@sapui5/sap.fe.core 1.141.2 → 1.142.1

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 +1 -1
  2. package/src/sap/fe/core/.library +4 -1
  3. package/src/sap/fe/core/ActionRuntime.js +48 -23
  4. package/src/sap/fe/core/ActionRuntime.ts +61 -35
  5. package/src/sap/fe/core/AppComponent.js +76 -6
  6. package/src/sap/fe/core/AppComponent.ts +94 -8
  7. package/src/sap/fe/core/AppStateHandler.js +9 -8
  8. package/src/sap/fe/core/AppStateHandler.ts +13 -9
  9. package/src/sap/fe/core/BaseController.js +8 -5
  10. package/src/sap/fe/core/BaseController.ts +6 -1
  11. package/src/sap/fe/core/CommonUtils.js +4 -123
  12. package/src/sap/fe/core/CommonUtils.ts +3 -172
  13. package/src/sap/fe/core/ExtensionAPI.js +3 -10
  14. package/src/sap/fe/core/ExtensionAPI.ts +2 -14
  15. package/src/sap/fe/core/PageController.js +64 -43
  16. package/src/sap/fe/core/PageController.ts +62 -47
  17. package/src/sap/fe/core/TemplateComponent.js +20 -1
  18. package/src/sap/fe/core/TemplateComponent.ts +24 -2
  19. package/src/sap/fe/core/buildingBlocks/BuildingBlock.js +37 -24
  20. package/src/sap/fe/core/buildingBlocks/BuildingBlock.ts +47 -31
  21. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockSupport.js +1 -1
  22. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockSupport.ts +4 -0
  23. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplateProcessor.js +4 -1
  24. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplateProcessor.ts +3 -0
  25. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplatingBase.js +4 -1
  26. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplatingBase.ts +4 -0
  27. package/src/sap/fe/core/controllerextensions/BaseControllerExtension.js +7 -5
  28. package/src/sap/fe/core/controllerextensions/BaseControllerExtension.ts +22 -2
  29. package/src/sap/fe/core/controllerextensions/CollaborativeDraft.js +82 -39
  30. package/src/sap/fe/core/controllerextensions/CollaborativeDraft.ts +91 -54
  31. package/src/sap/fe/core/controllerextensions/EditFlow.js +25 -3
  32. package/src/sap/fe/core/controllerextensions/EditFlow.ts +27 -3
  33. package/src/sap/fe/core/controllerextensions/InlineEditFlow.js +9 -7
  34. package/src/sap/fe/core/controllerextensions/InlineEditFlow.ts +17 -5
  35. package/src/sap/fe/core/controllerextensions/InternalRouting.js +37 -18
  36. package/src/sap/fe/core/controllerextensions/InternalRouting.ts +49 -17
  37. package/src/sap/fe/core/controllerextensions/KPIManagement.js +30 -15
  38. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +32 -14
  39. package/src/sap/fe/core/controllerextensions/MessageHandler.js +9 -10
  40. package/src/sap/fe/core/controllerextensions/MessageHandler.ts +8 -9
  41. package/src/sap/fe/core/controllerextensions/Paginator.js +2 -2
  42. package/src/sap/fe/core/controllerextensions/Paginator.ts +1 -1
  43. package/src/sap/fe/core/controllerextensions/Placeholder.js +10 -2
  44. package/src/sap/fe/core/controllerextensions/Placeholder.ts +5 -1
  45. package/src/sap/fe/core/controllerextensions/Recommendations.js +3 -3
  46. package/src/sap/fe/core/controllerextensions/Recommendations.ts +2 -2
  47. package/src/sap/fe/core/controllerextensions/Routing.js +9 -5
  48. package/src/sap/fe/core/controllerextensions/Routing.ts +7 -7
  49. package/src/sap/fe/core/controllerextensions/Share.js +5 -5
  50. package/src/sap/fe/core/controllerextensions/Share.ts +4 -4
  51. package/src/sap/fe/core/controllerextensions/SideEffects.js +1 -1
  52. package/src/sap/fe/core/controllerextensions/SideEffects.ts +17 -2
  53. package/src/sap/fe/core/controllerextensions/collaboration/ActivityBase.js +2 -2
  54. package/src/sap/fe/core/controllerextensions/collaboration/ActivityBase.ts +1 -1
  55. package/src/sap/fe/core/controllerextensions/editFlow/NotApplicableContextDialog.js +3 -3
  56. package/src/sap/fe/core/controllerextensions/editFlow/NotApplicableContextDialog.tsx +3 -2
  57. package/src/sap/fe/core/controllerextensions/editFlow/TransactionHelper.js +33 -11
  58. package/src/sap/fe/core/controllerextensions/editFlow/TransactionHelper.ts +45 -14
  59. package/src/sap/fe/core/controllerextensions/editFlow/draft.js +37 -3
  60. package/src/sap/fe/core/controllerextensions/editFlow/draft.ts +41 -8
  61. package/src/sap/fe/core/controllerextensions/editFlow/draftDataLossPopup.js +10 -4
  62. package/src/sap/fe/core/controllerextensions/editFlow/draftDataLossPopup.ts +6 -1
  63. package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataOperation.js +7 -7
  64. package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataOperation.ts +6 -5
  65. package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataStrictHandling.js +2 -2
  66. package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataStrictHandling.ts +1 -1
  67. package/src/sap/fe/core/controllerextensions/editFlow/operations/OperationParameters.js +2 -1
  68. package/src/sap/fe/core/controllerextensions/editFlow/operations/OperationParameters.ts +1 -0
  69. package/src/sap/fe/core/controllerextensions/messageHandler/messageHandling.js +10 -6
  70. package/src/sap/fe/core/controllerextensions/messageHandler/messageHandling.ts +6 -5
  71. package/src/sap/fe/core/controllerextensions/routing/RouterProxy.js +11 -9
  72. package/src/sap/fe/core/controllerextensions/routing/RouterProxy.ts +22 -9
  73. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DraftDataLossDialog.js +9 -4
  74. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DraftDataLossDialog.tsx +10 -4
  75. package/src/sap/fe/core/controls/Recommendations/ConfirmRecommendationDialog.js +31 -2
  76. package/src/sap/fe/core/controls/Recommendations/ConfirmRecommendationDialog.tsx +34 -1
  77. package/src/sap/fe/core/converters/ManifestSettings.js +7 -1
  78. package/src/sap/fe/core/converters/ManifestSettings.ts +37 -0
  79. package/src/sap/fe/core/converters/ManifestWrapper.js +29 -9
  80. package/src/sap/fe/core/converters/ManifestWrapper.ts +29 -11
  81. package/src/sap/fe/core/converters/annotations/DataField.js +46 -19
  82. package/src/sap/fe/core/converters/annotations/DataField.ts +93 -19
  83. package/src/sap/fe/core/converters/common/AnnotationConverter.js +88 -35
  84. package/src/sap/fe/core/converters/controls/Common/Action.js +57 -20
  85. package/src/sap/fe/core/converters/controls/Common/Action.ts +71 -21
  86. package/src/sap/fe/core/converters/controls/Common/Chart.js +13 -3
  87. package/src/sap/fe/core/converters/controls/Common/Chart.ts +20 -4
  88. package/src/sap/fe/core/converters/controls/Common/Form.js +18 -3
  89. package/src/sap/fe/core/converters/controls/Common/Form.ts +23 -1
  90. package/src/sap/fe/core/converters/controls/Common/Table.js +89 -57
  91. package/src/sap/fe/core/converters/controls/Common/Table.ts +110 -56
  92. package/src/sap/fe/core/converters/controls/Common/filter/FilterRestrictions.js +243 -0
  93. package/src/sap/fe/core/converters/controls/Common/filter/FilterRestrictions.ts +309 -0
  94. package/src/sap/fe/core/converters/controls/Common/table/Columns.js +142 -58
  95. package/src/sap/fe/core/converters/controls/Common/table/Columns.ts +172 -78
  96. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +12 -18
  97. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +13 -27
  98. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +7 -16
  99. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +6 -17
  100. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +16 -5
  101. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +16 -5
  102. package/src/sap/fe/core/converters/helpers/Aggregation.js +12 -2
  103. package/src/sap/fe/core/converters/helpers/Aggregation.ts +11 -1
  104. package/src/sap/fe/core/converters/helpers/DataFieldHelper.js +27 -3
  105. package/src/sap/fe/core/converters/helpers/DataFieldHelper.ts +28 -1
  106. package/src/sap/fe/core/converters/helpers/ID.js +3 -1
  107. package/src/sap/fe/core/converters/helpers/ID.ts +1 -0
  108. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +5 -2
  109. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +7 -1
  110. package/src/sap/fe/core/converters/templates/ListReportConverter.js +11 -3
  111. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +12 -4
  112. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +19 -8
  113. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +18 -7
  114. package/src/sap/fe/core/designtime/AnnotationBasedChanges.js +8 -3
  115. package/src/sap/fe/core/designtime/AnnotationBasedChanges.ts +7 -2
  116. package/src/sap/fe/core/formatters/FPMFormatter.js +2 -2
  117. package/src/sap/fe/core/formatters/FPMFormatter.ts +1 -1
  118. package/src/sap/fe/core/fpm/Component.js +8 -1
  119. package/src/sap/fe/core/fpm/Component.ts +8 -0
  120. package/src/sap/fe/core/fpm/manifest.json +1 -1
  121. package/src/sap/fe/core/helpers/AppStartupHelper.js +79 -25
  122. package/src/sap/fe/core/helpers/AppStartupHelper.ts +91 -32
  123. package/src/sap/fe/core/helpers/ManifestHelper.js +6 -3
  124. package/src/sap/fe/core/helpers/ManifestHelper.ts +3 -0
  125. package/src/sap/fe/core/helpers/MetaModelFunction.js +12 -3
  126. package/src/sap/fe/core/helpers/MetaModelFunction.ts +11 -3
  127. package/src/sap/fe/core/helpers/ModelHelper.js +48 -9
  128. package/src/sap/fe/core/helpers/ModelHelper.ts +55 -10
  129. package/src/sap/fe/core/helpers/TypeGuards.js +12 -2
  130. package/src/sap/fe/core/helpers/TypeGuards.ts +10 -1
  131. package/src/sap/fe/core/helpers/WebSocket.js +6 -7
  132. package/src/sap/fe/core/helpers/WebSocket.ts +10 -6
  133. package/src/sap/fe/core/library.js +30 -3
  134. package/src/sap/fe/core/library.ts +28 -1
  135. package/src/sap/fe/core/messagebundle.properties +8 -1
  136. package/src/sap/fe/core/messagebundle_ar.properties +7 -0
  137. package/src/sap/fe/core/messagebundle_bg.properties +10 -3
  138. package/src/sap/fe/core/messagebundle_ca.properties +7 -0
  139. package/src/sap/fe/core/messagebundle_cnr.properties +7 -0
  140. package/src/sap/fe/core/messagebundle_cs.properties +7 -0
  141. package/src/sap/fe/core/messagebundle_cy.properties +8 -1
  142. package/src/sap/fe/core/messagebundle_da.properties +7 -0
  143. package/src/sap/fe/core/messagebundle_de.properties +7 -0
  144. package/src/sap/fe/core/messagebundle_el.properties +7 -0
  145. package/src/sap/fe/core/messagebundle_en.properties +8 -1
  146. package/src/sap/fe/core/messagebundle_en_GB.properties +7 -0
  147. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +5 -0
  148. package/src/sap/fe/core/messagebundle_es.properties +8 -1
  149. package/src/sap/fe/core/messagebundle_es_MX.properties +7 -0
  150. package/src/sap/fe/core/messagebundle_et.properties +7 -0
  151. package/src/sap/fe/core/messagebundle_fi.properties +7 -0
  152. package/src/sap/fe/core/messagebundle_fr.properties +16 -9
  153. package/src/sap/fe/core/messagebundle_fr_CA.properties +7 -0
  154. package/src/sap/fe/core/messagebundle_hi.properties +8 -1
  155. package/src/sap/fe/core/messagebundle_hr.properties +7 -0
  156. package/src/sap/fe/core/messagebundle_hu.properties +7 -0
  157. package/src/sap/fe/core/messagebundle_id.properties +7 -0
  158. package/src/sap/fe/core/messagebundle_it.properties +7 -0
  159. package/src/sap/fe/core/messagebundle_iw.properties +7 -0
  160. package/src/sap/fe/core/messagebundle_ja.properties +8 -1
  161. package/src/sap/fe/core/messagebundle_kk.properties +7 -0
  162. package/src/sap/fe/core/messagebundle_ko.properties +7 -0
  163. package/src/sap/fe/core/messagebundle_lt.properties +7 -0
  164. package/src/sap/fe/core/messagebundle_lv.properties +7 -0
  165. package/src/sap/fe/core/messagebundle_mk.properties +7 -0
  166. package/src/sap/fe/core/messagebundle_ms.properties +7 -0
  167. package/src/sap/fe/core/messagebundle_nl.properties +7 -0
  168. package/src/sap/fe/core/messagebundle_no.properties +7 -0
  169. package/src/sap/fe/core/messagebundle_pl.properties +7 -0
  170. package/src/sap/fe/core/messagebundle_pt.properties +7 -0
  171. package/src/sap/fe/core/messagebundle_pt_PT.properties +7 -0
  172. package/src/sap/fe/core/messagebundle_ro.properties +7 -0
  173. package/src/sap/fe/core/messagebundle_ru.properties +7 -0
  174. package/src/sap/fe/core/messagebundle_sh.properties +7 -0
  175. package/src/sap/fe/core/messagebundle_sk.properties +7 -0
  176. package/src/sap/fe/core/messagebundle_sl.properties +7 -0
  177. package/src/sap/fe/core/messagebundle_sr.properties +7 -0
  178. package/src/sap/fe/core/messagebundle_sv.properties +7 -0
  179. package/src/sap/fe/core/messagebundle_th.properties +7 -0
  180. package/src/sap/fe/core/messagebundle_tr.properties +7 -0
  181. package/src/sap/fe/core/messagebundle_uk.properties +7 -0
  182. package/src/sap/fe/core/messagebundle_vi.properties +7 -0
  183. package/src/sap/fe/core/messagebundle_zh_CN.properties +8 -1
  184. package/src/sap/fe/core/messagebundle_zh_TW.properties +7 -0
  185. package/src/sap/fe/core/rootView/Fcl.controller.js +21 -7
  186. package/src/sap/fe/core/rootView/Fcl.controller.ts +28 -6
  187. package/src/sap/fe/core/rootView/RootViewBaseController.js +96 -88
  188. package/src/sap/fe/core/rootView/RootViewBaseController.ts +106 -96
  189. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +14 -10
  190. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +15 -10
  191. package/src/sap/fe/core/services/RoutingServiceFactory.js +16 -7
  192. package/src/sap/fe/core/services/RoutingServiceFactory.ts +23 -10
  193. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +9 -7
  194. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +13 -8
  195. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +62 -6
  196. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +74 -11
  197. package/src/sap/fe/core/services/collaborativeDraftServiceFactory.js +33 -15
  198. package/src/sap/fe/core/services/collaborativeDraftServiceFactory.ts +31 -11
  199. package/src/sap/fe/core/templating/DisplayModeFormatter.js +4 -5
  200. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +4 -6
  201. package/src/sap/fe/core/templating/UIFormatters.js +17 -2
  202. package/src/sap/fe/core/templating/UIFormatters.ts +25 -1
  203. package/src/sap/fe/core/types/sap.fe.core-auto-ext.d.js +10 -0
  204. package/src/sap/fe/core/types/sap.fe.core-auto-ext.d.ts +369 -0
  205. package/src/sap/fe/core/types/sap.fe.core-manual-ext.d.js +9 -0
  206. package/src/sap/fe/core/types/sap.fe.core-manual-ext.d.ts +49 -0
  207. package/ui5.yaml +2 -0
@@ -0,0 +1,243 @@
1
+ /*!
2
+ * SAP UI development toolkit for HTML5 (SAPUI5)
3
+ * (c) Copyright 2009-2025 SAP SE. All rights reserved
4
+ */
5
+ sap.ui.define(["sap/base/util/array/uniqueSort", "sap/base/util/merge", "sap/fe/core/helpers/TypeGuards"], function (uniqueSort, mergeObjects, TypeGuards) {
6
+ "use strict";
7
+
8
+ var isEntitySet = TypeGuards.isEntitySet;
9
+ /**
10
+ * Extracts property path string from a flexible path object used in converter or annotation inputs.
11
+ * The object may contain a 'value' field. Returns undefined if it is a non-empty string.
12
+ * @param ref Potential property reference object.
13
+ * @returns Property path string or undefined.
14
+ */
15
+ function extractPath(ref) {
16
+ if (!ref) {
17
+ return undefined;
18
+ }
19
+ return typeof ref.value === "string" ? ref.value : undefined;
20
+ }
21
+
22
+ /**
23
+ * Parses raw FilterRestrictionsType annotation into plain arrays of strings and a mapping of allowed expressions.
24
+ * This replaces previous two-step normalization + extraction logic and deliberately avoids introducing $PropertyPath objects.
25
+ * @param filterRestrictions Raw filter restrictions annotation (may be undefined).
26
+ * @returns Parsed filter restrictions with simple string collections.
27
+ */
28
+ function getFilterRestrictions(filterRestrictions) {
29
+ if (!filterRestrictions) {
30
+ return {
31
+ RequiredProperties: [],
32
+ NonFilterableProperties: [],
33
+ FilterAllowedExpressions: {}
34
+ };
35
+ }
36
+ const required = (filterRestrictions.RequiredProperties ?? []).map(p => extractPath(p)).filter(p => !!p);
37
+ const nonFilterable = (filterRestrictions.NonFilterableProperties ?? []).map(p => extractPath(p)).filter(p => !!p);
38
+ const allowed = {};
39
+ for (const expr of filterRestrictions.FilterExpressionRestrictions ?? []) {
40
+ const exprObj = expr;
41
+ const propPath = extractPath(exprObj.Property);
42
+ const allowedExp = typeof exprObj.AllowedExpressions === "string" ? exprObj.AllowedExpressions : undefined;
43
+ if (!propPath || !allowedExp) {
44
+ continue;
45
+ }
46
+ if (allowed[propPath] !== undefined) {
47
+ allowed[propPath].push(allowedExp);
48
+ } else {
49
+ allowed[propPath] = [allowedExp];
50
+ }
51
+ }
52
+ return {
53
+ RequiredProperties: required,
54
+ NonFilterableProperties: nonFilterable,
55
+ FilterAllowedExpressions: allowed
56
+ };
57
+ }
58
+ function _fetchPropertiesForNavPath(paths, navPath, props) {
59
+ const navPathPrefix = navPath + "/";
60
+ return paths.reduce((outPaths, pathToCheck) => {
61
+ if (pathToCheck.startsWith(navPathPrefix)) {
62
+ const outPath = pathToCheck.replace(navPathPrefix, "");
63
+ if (!outPaths.includes(outPath)) {
64
+ outPaths.push(outPath);
65
+ }
66
+ }
67
+ return outPaths;
68
+ }, props);
69
+ }
70
+
71
+ /**
72
+ * Initializes an empty filter restrictions object with default values.
73
+ * @returns The initialized filter restrictions object
74
+ */
75
+ function initializeFilterRestrictions() {
76
+ return {
77
+ RequiredProperties: [],
78
+ NonFilterableProperties: [],
79
+ FilterAllowedExpressions: {}
80
+ };
81
+ }
82
+
83
+ /**
84
+ * Determines if the entity set has a result context annotation.
85
+ * @param entitySet The entity set to check
86
+ * @returns True if the entity set has result context, false otherwise
87
+ */
88
+ function hasResultContext(entitySet) {
89
+ if (!entitySet?.annotations?.Common) {
90
+ return false;
91
+ }
92
+ return "ResultContext" in entitySet.annotations.Common ? entitySet.annotations.Common.ResultContext?.valueOf() === true : false;
93
+ }
94
+
95
+ /**
96
+ * Processes filter restrictions at entity set level (least priority).
97
+ * @param restrictions The current filter restrictions object
98
+ * @param filterRestrictions The filter restrictions annotation
99
+ * @param hasResultContextValue Whether the entity has result context
100
+ * @returns Updated filter restrictions object
101
+ */
102
+ function processEntitySetFilterRestrictions(restrictions, filterRestrictions, hasResultContextValue) {
103
+ const filterRestictions = getFilterRestrictions(filterRestrictions);
104
+ restrictions.RequiredProperties = filterRestictions.RequiredProperties;
105
+ if (!hasResultContextValue) {
106
+ restrictions.NonFilterableProperties = filterRestictions.NonFilterableProperties;
107
+ }
108
+ restrictions.FilterAllowedExpressions = filterRestictions.FilterAllowedExpressions;
109
+ return restrictions;
110
+ }
111
+
112
+ /**
113
+ * Processes property path filter restrictions (third highest priority).
114
+ * @param restrictions The current filter restrictions object
115
+ * @param filterRestrictions The parent filter restrictions
116
+ * @param navPath The navigation path
117
+ * @returns Updated filter restrictions object
118
+ */
119
+ function processPropertyPathFilterRestrictions(restrictions, filterRestrictions, navPath) {
120
+ if (!filterRestrictions || navPath.includes("%2F")) {
121
+ return restrictions;
122
+ }
123
+ const filterRestictions = getFilterRestrictions(filterRestrictions);
124
+ const navPrefix = navPath + "/";
125
+ const reqSubset = filterRestictions.RequiredProperties.filter(p => p.startsWith(navPrefix)).map(p => p.slice(navPrefix.length));
126
+ const nonFilterSubset = filterRestictions.NonFilterableProperties.filter(p => p.startsWith(navPrefix)).map(p => p.slice(navPrefix.length));
127
+ restrictions.RequiredProperties = _fetchPropertiesForNavPath(reqSubset, navPath, restrictions.RequiredProperties);
128
+ restrictions.NonFilterableProperties = _fetchPropertiesForNavPath(nonFilterSubset, navPath, restrictions.NonFilterableProperties);
129
+ const parentAllowedExpressions = Object.keys(filterRestictions.FilterAllowedExpressions).reduce((outProp, propPath) => {
130
+ if (propPath.startsWith(navPrefix)) {
131
+ const outPropPath = propPath.slice(navPrefix.length);
132
+ outProp[outPropPath] = filterRestictions.FilterAllowedExpressions[propPath];
133
+ }
134
+ return outProp;
135
+ }, {});
136
+ restrictions.FilterAllowedExpressions = mergeObjects({}, restrictions.FilterAllowedExpressions, parentAllowedExpressions);
137
+ return restrictions;
138
+ }
139
+
140
+ /**
141
+ * Processes navigation restrictions (second highest priority).
142
+ * @param restrictions The current filter restrictions object
143
+ * @param navigationRestrictions The navigation restrictions
144
+ * @returns Updated filter restrictions object
145
+ */
146
+ function processNavigationFilterRestrictions(restrictions, navigationRestrictions) {
147
+ const filterRestictions = getFilterRestrictions(navigationRestrictions);
148
+ restrictions.RequiredProperties = uniqueSort(restrictions.RequiredProperties.concat(filterRestictions.RequiredProperties));
149
+ restrictions.NonFilterableProperties = uniqueSort(restrictions.NonFilterableProperties.concat(filterRestictions.NonFilterableProperties));
150
+ restrictions.FilterAllowedExpressions = mergeObjects({}, restrictions.FilterAllowedExpressions, filterRestictions.FilterAllowedExpressions);
151
+ return restrictions;
152
+ }
153
+
154
+ /**
155
+ * Processes navigation association entity restrictions (highest priority).
156
+ * @param restrictions The current filter restrictions object
157
+ * @param associationRestrictions The association entity filter restrictions
158
+ * @returns Updated filter restrictions object
159
+ */
160
+ function processNavigationAssociationFilterRestrictions(restrictions, associationRestrictions) {
161
+ const filterRestictions = getFilterRestrictions(associationRestrictions);
162
+ restrictions.RequiredProperties = uniqueSort(restrictions.RequiredProperties.concat(filterRestictions.RequiredProperties));
163
+ restrictions.NonFilterableProperties = uniqueSort(restrictions.NonFilterableProperties.concat(filterRestictions.NonFilterableProperties));
164
+ restrictions.FilterAllowedExpressions = mergeObjects({}, restrictions.FilterAllowedExpressions, filterRestictions.FilterAllowedExpressions);
165
+ return restrictions;
166
+ }
167
+
168
+ /**
169
+ * Processes filter restrictions using converter context.
170
+ * @param dataModelObjectPath The data model object path
171
+ * @returns Processed filter restrictions
172
+ */
173
+ function processFilterRestrictionsFromConverter(dataModelObjectPath) {
174
+ const restrictions = initializeFilterRestrictions();
175
+ const isContainment = !isEntitySet(dataModelObjectPath.targetEntitySet);
176
+ const containmentNavPath = isContainment && dataModelObjectPath.navigationProperties[dataModelObjectPath.navigationProperties.length - 1]?.name;
177
+
178
+ // LEAST PRIORITY - Filter restrictions directly at Entity Set
179
+ if (!isContainment) {
180
+ const entitySetFilterRestrictions = dataModelObjectPath.targetEntitySet?.annotations?.Capabilities?.FilterRestrictions;
181
+ const hasResultContextValue = hasResultContext(dataModelObjectPath.targetEntitySet);
182
+ processEntitySetFilterRestrictions(restrictions, entitySetFilterRestrictions, hasResultContextValue);
183
+ }
184
+ if (dataModelObjectPath.navigationProperties.length > 0) {
185
+ const navPath = isContainment ? containmentNavPath : dataModelObjectPath.navigationProperties[dataModelObjectPath.navigationProperties.length - 1]?.name;
186
+
187
+ // THIRD HIGHEST PRIORITY - Property path restrictions at parent entity
188
+ const parentFilterRestrictions = dataModelObjectPath.startingEntitySet?.annotations?.Capabilities?.FilterRestrictions;
189
+ processPropertyPathFilterRestrictions(restrictions, parentFilterRestrictions, navPath);
190
+
191
+ // SECOND HIGHEST PRIORITY - Navigation restrictions from parent entity set
192
+ // Build the full navigation path dynamically
193
+ const navigationPathParts = dataModelObjectPath.navigationProperties.map(prop => prop.name);
194
+
195
+ // Check for navigation restrictions that match any part of our navigation path
196
+ const navigationRestrictions = dataModelObjectPath.startingEntitySet?.annotations?.Capabilities?.NavigationRestrictions?.RestrictedProperties?.find(navProp => {
197
+ const navPropPath = navProp.NavigationProperty.value;
198
+ if (!navPropPath) {
199
+ return false;
200
+ }
201
+
202
+ // Check if the navigation property path matches any of our navigation segments
203
+ // This handles both single level (e.g., "_PartnerItems") and multi-level (e.g., "Set/_PartnerItems") paths
204
+ const isPartialPathMatch = navigationPathParts.some((_, index) => {
205
+ const partialPath = navigationPathParts.slice(index).join("/");
206
+ return navPropPath === partialPath;
207
+ });
208
+
209
+ // Also check the full path
210
+ const fullPath = navigationPathParts.join("/");
211
+ return isPartialPathMatch || navPropPath === fullPath;
212
+ });
213
+ const navFilterRestrictions = navigationRestrictions?.FilterRestrictions;
214
+ processNavigationFilterRestrictions(restrictions, navFilterRestrictions);
215
+
216
+ // HIGHEST PRIORITY - Navigation association entity restrictions
217
+ const navigationAssociation = dataModelObjectPath.navigationProperties.find(navProp => navProp.name === navPath);
218
+ const associationFilterRestrictions = navigationAssociation?.annotations?.Capabilities?.FilterRestrictions;
219
+ processNavigationAssociationFilterRestrictions(restrictions, associationFilterRestrictions);
220
+ }
221
+ return restrictions;
222
+ }
223
+
224
+ /*** Fetches filter restrictions by entity path with proper priority handling and ensures correct processing order by following priority order:
225
+ * 1. LEAST PRIORITY: Filter restrictions directly at Entity Set
226
+ * 2. THIRD HIGHEST PRIORITY: Property path restrictions at parent entity
227
+ * 3. SECOND HIGHEST PRIORITY: Navigation restrictions
228
+ * 4. HIGHEST PRIORITY: Restrictions at navigation association entity
229
+ * @param converterContext Optional converter context for enhanced processing
230
+ * @returns Filter restrictions object containing required properties, non-filterable properties, and allowed expressions
231
+ */
232
+ function getFilterRestrictionsByDataModel(dataModelObjectPath) {
233
+ if (dataModelObjectPath) {
234
+ return processFilterRestrictionsFromConverter(dataModelObjectPath);
235
+ }
236
+ return initializeFilterRestrictions();
237
+ }
238
+ const FilterRestrictions = {
239
+ getFilterRestrictionsByDataModel
240
+ };
241
+ return FilterRestrictions;
242
+ }, false);
243
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJleHRyYWN0UGF0aCIsInJlZiIsInVuZGVmaW5lZCIsInZhbHVlIiwiZ2V0RmlsdGVyUmVzdHJpY3Rpb25zIiwiZmlsdGVyUmVzdHJpY3Rpb25zIiwiUmVxdWlyZWRQcm9wZXJ0aWVzIiwiTm9uRmlsdGVyYWJsZVByb3BlcnRpZXMiLCJGaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnMiLCJyZXF1aXJlZCIsIm1hcCIsInAiLCJmaWx0ZXIiLCJub25GaWx0ZXJhYmxlIiwiYWxsb3dlZCIsImV4cHIiLCJGaWx0ZXJFeHByZXNzaW9uUmVzdHJpY3Rpb25zIiwiZXhwck9iaiIsInByb3BQYXRoIiwiUHJvcGVydHkiLCJhbGxvd2VkRXhwIiwiQWxsb3dlZEV4cHJlc3Npb25zIiwicHVzaCIsIl9mZXRjaFByb3BlcnRpZXNGb3JOYXZQYXRoIiwicGF0aHMiLCJuYXZQYXRoIiwicHJvcHMiLCJuYXZQYXRoUHJlZml4IiwicmVkdWNlIiwib3V0UGF0aHMiLCJwYXRoVG9DaGVjayIsInN0YXJ0c1dpdGgiLCJvdXRQYXRoIiwicmVwbGFjZSIsImluY2x1ZGVzIiwiaW5pdGlhbGl6ZUZpbHRlclJlc3RyaWN0aW9ucyIsImhhc1Jlc3VsdENvbnRleHQiLCJlbnRpdHlTZXQiLCJhbm5vdGF0aW9ucyIsIkNvbW1vbiIsIlJlc3VsdENvbnRleHQiLCJ2YWx1ZU9mIiwicHJvY2Vzc0VudGl0eVNldEZpbHRlclJlc3RyaWN0aW9ucyIsInJlc3RyaWN0aW9ucyIsImhhc1Jlc3VsdENvbnRleHRWYWx1ZSIsImZpbHRlclJlc3RpY3Rpb25zIiwicHJvY2Vzc1Byb3BlcnR5UGF0aEZpbHRlclJlc3RyaWN0aW9ucyIsIm5hdlByZWZpeCIsInJlcVN1YnNldCIsInNsaWNlIiwibGVuZ3RoIiwibm9uRmlsdGVyU3Vic2V0IiwicGFyZW50QWxsb3dlZEV4cHJlc3Npb25zIiwiT2JqZWN0Iiwia2V5cyIsIm91dFByb3AiLCJvdXRQcm9wUGF0aCIsIm1lcmdlT2JqZWN0cyIsInByb2Nlc3NOYXZpZ2F0aW9uRmlsdGVyUmVzdHJpY3Rpb25zIiwibmF2aWdhdGlvblJlc3RyaWN0aW9ucyIsInVuaXF1ZVNvcnQiLCJjb25jYXQiLCJwcm9jZXNzTmF2aWdhdGlvbkFzc29jaWF0aW9uRmlsdGVyUmVzdHJpY3Rpb25zIiwiYXNzb2NpYXRpb25SZXN0cmljdGlvbnMiLCJwcm9jZXNzRmlsdGVyUmVzdHJpY3Rpb25zRnJvbUNvbnZlcnRlciIsImRhdGFNb2RlbE9iamVjdFBhdGgiLCJpc0NvbnRhaW5tZW50IiwiaXNFbnRpdHlTZXQiLCJ0YXJnZXRFbnRpdHlTZXQiLCJjb250YWlubWVudE5hdlBhdGgiLCJuYXZpZ2F0aW9uUHJvcGVydGllcyIsIm5hbWUiLCJlbnRpdHlTZXRGaWx0ZXJSZXN0cmljdGlvbnMiLCJDYXBhYmlsaXRpZXMiLCJGaWx0ZXJSZXN0cmljdGlvbnMiLCJwYXJlbnRGaWx0ZXJSZXN0cmljdGlvbnMiLCJzdGFydGluZ0VudGl0eVNldCIsIm5hdmlnYXRpb25QYXRoUGFydHMiLCJwcm9wIiwiTmF2aWdhdGlvblJlc3RyaWN0aW9ucyIsIlJlc3RyaWN0ZWRQcm9wZXJ0aWVzIiwiZmluZCIsIm5hdlByb3AiLCJuYXZQcm9wUGF0aCIsIk5hdmlnYXRpb25Qcm9wZXJ0eSIsImlzUGFydGlhbFBhdGhNYXRjaCIsInNvbWUiLCJfIiwiaW5kZXgiLCJwYXJ0aWFsUGF0aCIsImpvaW4iLCJmdWxsUGF0aCIsIm5hdkZpbHRlclJlc3RyaWN0aW9ucyIsIm5hdmlnYXRpb25Bc3NvY2lhdGlvbiIsImFzc29jaWF0aW9uRmlsdGVyUmVzdHJpY3Rpb25zIiwiZ2V0RmlsdGVyUmVzdHJpY3Rpb25zQnlEYXRhTW9kZWwiXSwic291cmNlUm9vdCI6Ii4iLCJzb3VyY2VzIjpbIkZpbHRlclJlc3RyaWN0aW9ucy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IEVudGl0eVNldCwgUHJvcGVydHlQYXRoIH0gZnJvbSBcIkBzYXAtdXgvdm9jYWJ1bGFyaWVzLXR5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IEZpbHRlclJlc3RyaWN0aW9uc1R5cGUgfSBmcm9tIFwiQHNhcC11eC92b2NhYnVsYXJpZXMtdHlwZXMvdm9jYWJ1bGFyaWVzL0NhcGFiaWxpdGllc1wiO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHlTZXRBbm5vdGF0aW9uc19DYXBhYmlsaXRpZXMgfSBmcm9tIFwiQHNhcC11eC92b2NhYnVsYXJpZXMtdHlwZXMvdm9jYWJ1bGFyaWVzL0NhcGFiaWxpdGllc19FZG1cIjtcbmltcG9ydCB1bmlxdWVTb3J0IGZyb20gXCJzYXAvYmFzZS91dGlsL2FycmF5L3VuaXF1ZVNvcnRcIjtcbmltcG9ydCBtZXJnZU9iamVjdHMgZnJvbSBcInNhcC9iYXNlL3V0aWwvbWVyZ2VcIjtcbmltcG9ydCB0eXBlIHsgUGFnZUNvbnRleHRQYXRoVGFyZ2V0IH0gZnJvbSBcInNhcC9mZS9jb3JlL2NvbnZlcnRlcnMvVGVtcGxhdGVDb252ZXJ0ZXJcIjtcbmltcG9ydCB7IGlzRW50aXR5U2V0IH0gZnJvbSBcInNhcC9mZS9jb3JlL2hlbHBlcnMvVHlwZUd1YXJkc1wiO1xuaW1wb3J0IHR5cGUgeyBEYXRhTW9kZWxPYmplY3RQYXRoIH0gZnJvbSBcInNhcC9mZS9jb3JlL3RlbXBsYXRpbmcvRGF0YU1vZGVsUGF0aEhlbHBlclwiO1xuXG50eXBlIF9GaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnMgPSBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT47XG5cbmV4cG9ydCB0eXBlIEZpbHRlclJlc3RyaWN0aW9ucyA9IHtcblx0UmVxdWlyZWRQcm9wZXJ0aWVzOiBzdHJpbmdbXTtcblx0Tm9uRmlsdGVyYWJsZVByb3BlcnRpZXM6IHN0cmluZ1tdO1xuXHRGaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnM6IF9GaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnM7XG59O1xuXG50eXBlIEZpbHRlckV4cHJlc3Npb25SZXN0cmljdGlvbiA9IHtcblx0UHJvcGVydHk/OiBQcm9wZXJ0eVBhdGg7XG5cdEFsbG93ZWRFeHByZXNzaW9ucz86IHN0cmluZztcbn07XG5cbi8qKlxuICogRXh0cmFjdHMgcHJvcGVydHkgcGF0aCBzdHJpbmcgZnJvbSBhIGZsZXhpYmxlIHBhdGggb2JqZWN0IHVzZWQgaW4gY29udmVydGVyIG9yIGFubm90YXRpb24gaW5wdXRzLlxuICogVGhlIG9iamVjdCBtYXkgY29udGFpbiBhICd2YWx1ZScgZmllbGQuIFJldHVybnMgdW5kZWZpbmVkIGlmIGl0IGlzIGEgbm9uLWVtcHR5IHN0cmluZy5cbiAqIEBwYXJhbSByZWYgUG90ZW50aWFsIHByb3BlcnR5IHJlZmVyZW5jZSBvYmplY3QuXG4gKiBAcmV0dXJucyBQcm9wZXJ0eSBwYXRoIHN0cmluZyBvciB1bmRlZmluZWQuXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RQYXRoKHJlZjogUHJvcGVydHlQYXRoIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcblx0aWYgKCFyZWYpIHtcblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cdHJldHVybiB0eXBlb2YgcmVmLnZhbHVlID09PSBcInN0cmluZ1wiID8gcmVmLnZhbHVlIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFBhcnNlcyByYXcgRmlsdGVyUmVzdHJpY3Rpb25zVHlwZSBhbm5vdGF0aW9uIGludG8gcGxhaW4gYXJyYXlzIG9mIHN0cmluZ3MgYW5kIGEgbWFwcGluZyBvZiBhbGxvd2VkIGV4cHJlc3Npb25zLlxuICogVGhpcyByZXBsYWNlcyBwcmV2aW91cyB0d28tc3RlcCBub3JtYWxpemF0aW9uICsgZXh0cmFjdGlvbiBsb2dpYyBhbmQgZGVsaWJlcmF0ZWx5IGF2b2lkcyBpbnRyb2R1Y2luZyAkUHJvcGVydHlQYXRoIG9iamVjdHMuXG4gKiBAcGFyYW0gZmlsdGVyUmVzdHJpY3Rpb25zIFJhdyBmaWx0ZXIgcmVzdHJpY3Rpb25zIGFubm90YXRpb24gKG1heSBiZSB1bmRlZmluZWQpLlxuICogQHJldHVybnMgUGFyc2VkIGZpbHRlciByZXN0cmljdGlvbnMgd2l0aCBzaW1wbGUgc3RyaW5nIGNvbGxlY3Rpb25zLlxuICovXG5mdW5jdGlvbiBnZXRGaWx0ZXJSZXN0cmljdGlvbnMoZmlsdGVyUmVzdHJpY3Rpb25zOiBGaWx0ZXJSZXN0cmljdGlvbnNUeXBlIHwgdW5kZWZpbmVkKTogRmlsdGVyUmVzdHJpY3Rpb25zIHtcblx0aWYgKCFmaWx0ZXJSZXN0cmljdGlvbnMpIHtcblx0XHRyZXR1cm4geyBSZXF1aXJlZFByb3BlcnRpZXM6IFtdLCBOb25GaWx0ZXJhYmxlUHJvcGVydGllczogW10sIEZpbHRlckFsbG93ZWRFeHByZXNzaW9uczoge30gfTtcblx0fVxuXG5cdGNvbnN0IHJlcXVpcmVkOiBzdHJpbmdbXSA9IChmaWx0ZXJSZXN0cmljdGlvbnMuUmVxdWlyZWRQcm9wZXJ0aWVzID8/IFtdKS5tYXAoKHApID0+IGV4dHJhY3RQYXRoKHApKS5maWx0ZXIoKHApOiBwIGlzIHN0cmluZyA9PiAhIXApO1xuXHRjb25zdCBub25GaWx0ZXJhYmxlOiBzdHJpbmdbXSA9IChmaWx0ZXJSZXN0cmljdGlvbnMuTm9uRmlsdGVyYWJsZVByb3BlcnRpZXMgPz8gW10pXG5cdFx0Lm1hcCgocCkgPT4gZXh0cmFjdFBhdGgocCkpXG5cdFx0LmZpbHRlcigocCk6IHAgaXMgc3RyaW5nID0+ICEhcCk7XG5cblx0Y29uc3QgYWxsb3dlZDogX0ZpbHRlckFsbG93ZWRFeHByZXNzaW9ucyA9IHt9O1xuXHRmb3IgKGNvbnN0IGV4cHIgb2YgZmlsdGVyUmVzdHJpY3Rpb25zLkZpbHRlckV4cHJlc3Npb25SZXN0cmljdGlvbnMgPz8gW10pIHtcblx0XHRjb25zdCBleHByT2JqID0gZXhwciBhcyBGaWx0ZXJFeHByZXNzaW9uUmVzdHJpY3Rpb247XG5cdFx0Y29uc3QgcHJvcFBhdGggPSBleHRyYWN0UGF0aChleHByT2JqLlByb3BlcnR5KTtcblx0XHRjb25zdCBhbGxvd2VkRXhwID0gdHlwZW9mIGV4cHJPYmouQWxsb3dlZEV4cHJlc3Npb25zID09PSBcInN0cmluZ1wiID8gZXhwck9iai5BbGxvd2VkRXhwcmVzc2lvbnMgOiB1bmRlZmluZWQ7XG5cdFx0aWYgKCFwcm9wUGF0aCB8fCAhYWxsb3dlZEV4cCkge1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXHRcdGlmIChhbGxvd2VkW3Byb3BQYXRoXSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRhbGxvd2VkW3Byb3BQYXRoXS5wdXNoKGFsbG93ZWRFeHApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhbGxvd2VkW3Byb3BQYXRoXSA9IFthbGxvd2VkRXhwXTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdFJlcXVpcmVkUHJvcGVydGllczogcmVxdWlyZWQsXG5cdFx0Tm9uRmlsdGVyYWJsZVByb3BlcnRpZXM6IG5vbkZpbHRlcmFibGUsXG5cdFx0RmlsdGVyQWxsb3dlZEV4cHJlc3Npb25zOiBhbGxvd2VkXG5cdH07XG59XG5cbmZ1bmN0aW9uIF9mZXRjaFByb3BlcnRpZXNGb3JOYXZQYXRoKHBhdGhzOiBzdHJpbmdbXSwgbmF2UGF0aDogc3RyaW5nLCBwcm9wczogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG5cdGNvbnN0IG5hdlBhdGhQcmVmaXggPSBuYXZQYXRoICsgXCIvXCI7XG5cdHJldHVybiBwYXRocy5yZWR1Y2UoKG91dFBhdGhzOiBzdHJpbmdbXSwgcGF0aFRvQ2hlY2s6IHN0cmluZykgPT4ge1xuXHRcdGlmIChwYXRoVG9DaGVjay5zdGFydHNXaXRoKG5hdlBhdGhQcmVmaXgpKSB7XG5cdFx0XHRjb25zdCBvdXRQYXRoID0gcGF0aFRvQ2hlY2sucmVwbGFjZShuYXZQYXRoUHJlZml4LCBcIlwiKTtcblx0XHRcdGlmICghb3V0UGF0aHMuaW5jbHVkZXMob3V0UGF0aCkpIHtcblx0XHRcdFx0b3V0UGF0aHMucHVzaChvdXRQYXRoKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIG91dFBhdGhzO1xuXHR9LCBwcm9wcyk7XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgYW4gZW1wdHkgZmlsdGVyIHJlc3RyaWN0aW9ucyBvYmplY3Qgd2l0aCBkZWZhdWx0IHZhbHVlcy5cbiAqIEByZXR1cm5zIFRoZSBpbml0aWFsaXplZCBmaWx0ZXIgcmVzdHJpY3Rpb25zIG9iamVjdFxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRmlsdGVyUmVzdHJpY3Rpb25zKCk6IEZpbHRlclJlc3RyaWN0aW9ucyB7XG5cdHJldHVybiB7XG5cdFx0UmVxdWlyZWRQcm9wZXJ0aWVzOiBbXSxcblx0XHROb25GaWx0ZXJhYmxlUHJvcGVydGllczogW10sXG5cdFx0RmlsdGVyQWxsb3dlZEV4cHJlc3Npb25zOiB7fVxuXHR9O1xufVxuXG4vKipcbiAqIERldGVybWluZXMgaWYgdGhlIGVudGl0eSBzZXQgaGFzIGEgcmVzdWx0IGNvbnRleHQgYW5ub3RhdGlvbi5cbiAqIEBwYXJhbSBlbnRpdHlTZXQgVGhlIGVudGl0eSBzZXQgdG8gY2hlY2tcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGVudGl0eSBzZXQgaGFzIHJlc3VsdCBjb250ZXh0LCBmYWxzZSBvdGhlcndpc2VcbiAqL1xuZnVuY3Rpb24gaGFzUmVzdWx0Q29udGV4dChlbnRpdHlTZXQ6IEVudGl0eVNldCB8IG51bGwgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcblx0aWYgKCFlbnRpdHlTZXQ/LmFubm90YXRpb25zPy5Db21tb24pIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0cmV0dXJuIFwiUmVzdWx0Q29udGV4dFwiIGluIGVudGl0eVNldC5hbm5vdGF0aW9ucy5Db21tb24gPyBlbnRpdHlTZXQuYW5ub3RhdGlvbnMuQ29tbW9uLlJlc3VsdENvbnRleHQ/LnZhbHVlT2YoKSA9PT0gdHJ1ZSA6IGZhbHNlO1xufVxuXG4vKipcbiAqIFByb2Nlc3NlcyBmaWx0ZXIgcmVzdHJpY3Rpb25zIGF0IGVudGl0eSBzZXQgbGV2ZWwgKGxlYXN0IHByaW9yaXR5KS5cbiAqIEBwYXJhbSByZXN0cmljdGlvbnMgVGhlIGN1cnJlbnQgZmlsdGVyIHJlc3RyaWN0aW9ucyBvYmplY3RcbiAqIEBwYXJhbSBmaWx0ZXJSZXN0cmljdGlvbnMgVGhlIGZpbHRlciByZXN0cmljdGlvbnMgYW5ub3RhdGlvblxuICogQHBhcmFtIGhhc1Jlc3VsdENvbnRleHRWYWx1ZSBXaGV0aGVyIHRoZSBlbnRpdHkgaGFzIHJlc3VsdCBjb250ZXh0XG4gKiBAcmV0dXJucyBVcGRhdGVkIGZpbHRlciByZXN0cmljdGlvbnMgb2JqZWN0XG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NFbnRpdHlTZXRGaWx0ZXJSZXN0cmljdGlvbnMoXG5cdHJlc3RyaWN0aW9uczogRmlsdGVyUmVzdHJpY3Rpb25zLFxuXHRmaWx0ZXJSZXN0cmljdGlvbnM6IEZpbHRlclJlc3RyaWN0aW9uc1R5cGUgfCB1bmRlZmluZWQsXG5cdGhhc1Jlc3VsdENvbnRleHRWYWx1ZTogYm9vbGVhblxuKTogRmlsdGVyUmVzdHJpY3Rpb25zIHtcblx0Y29uc3QgZmlsdGVyUmVzdGljdGlvbnMgPSBnZXRGaWx0ZXJSZXN0cmljdGlvbnMoZmlsdGVyUmVzdHJpY3Rpb25zKTtcblx0cmVzdHJpY3Rpb25zLlJlcXVpcmVkUHJvcGVydGllcyA9IGZpbHRlclJlc3RpY3Rpb25zLlJlcXVpcmVkUHJvcGVydGllcztcblx0aWYgKCFoYXNSZXN1bHRDb250ZXh0VmFsdWUpIHtcblx0XHRyZXN0cmljdGlvbnMuTm9uRmlsdGVyYWJsZVByb3BlcnRpZXMgPSBmaWx0ZXJSZXN0aWN0aW9ucy5Ob25GaWx0ZXJhYmxlUHJvcGVydGllcztcblx0fVxuXHRyZXN0cmljdGlvbnMuRmlsdGVyQWxsb3dlZEV4cHJlc3Npb25zID0gZmlsdGVyUmVzdGljdGlvbnMuRmlsdGVyQWxsb3dlZEV4cHJlc3Npb25zO1xuXHRyZXR1cm4gcmVzdHJpY3Rpb25zO1xufVxuXG4vKipcbiAqIFByb2Nlc3NlcyBwcm9wZXJ0eSBwYXRoIGZpbHRlciByZXN0cmljdGlvbnMgKHRoaXJkIGhpZ2hlc3QgcHJpb3JpdHkpLlxuICogQHBhcmFtIHJlc3RyaWN0aW9ucyBUaGUgY3VycmVudCBmaWx0ZXIgcmVzdHJpY3Rpb25zIG9iamVjdFxuICogQHBhcmFtIGZpbHRlclJlc3RyaWN0aW9ucyBUaGUgcGFyZW50IGZpbHRlciByZXN0cmljdGlvbnNcbiAqIEBwYXJhbSBuYXZQYXRoIFRoZSBuYXZpZ2F0aW9uIHBhdGhcbiAqIEByZXR1cm5zIFVwZGF0ZWQgZmlsdGVyIHJlc3RyaWN0aW9ucyBvYmplY3RcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc1Byb3BlcnR5UGF0aEZpbHRlclJlc3RyaWN0aW9ucyhcblx0cmVzdHJpY3Rpb25zOiBGaWx0ZXJSZXN0cmljdGlvbnMsXG5cdGZpbHRlclJlc3RyaWN0aW9uczogRmlsdGVyUmVzdHJpY3Rpb25zVHlwZSB8IHVuZGVmaW5lZCxcblx0bmF2UGF0aDogc3RyaW5nXG4pOiBGaWx0ZXJSZXN0cmljdGlvbnMge1xuXHRpZiAoIWZpbHRlclJlc3RyaWN0aW9ucyB8fCBuYXZQYXRoLmluY2x1ZGVzKFwiJTJGXCIpKSB7XG5cdFx0cmV0dXJuIHJlc3RyaWN0aW9ucztcblx0fVxuXHRjb25zdCBmaWx0ZXJSZXN0aWN0aW9ucyA9IGdldEZpbHRlclJlc3RyaWN0aW9ucyhmaWx0ZXJSZXN0cmljdGlvbnMpO1xuXG5cdGNvbnN0IG5hdlByZWZpeCA9IG5hdlBhdGggKyBcIi9cIjtcblx0Y29uc3QgcmVxU3Vic2V0ID0gZmlsdGVyUmVzdGljdGlvbnMuUmVxdWlyZWRQcm9wZXJ0aWVzLmZpbHRlcigocCkgPT4gcC5zdGFydHNXaXRoKG5hdlByZWZpeCkpLm1hcCgocCkgPT4gcC5zbGljZShuYXZQcmVmaXgubGVuZ3RoKSk7XG5cdGNvbnN0IG5vbkZpbHRlclN1YnNldCA9IGZpbHRlclJlc3RpY3Rpb25zLk5vbkZpbHRlcmFibGVQcm9wZXJ0aWVzLmZpbHRlcigocCkgPT4gcC5zdGFydHNXaXRoKG5hdlByZWZpeCkpLm1hcCgocCkgPT5cblx0XHRwLnNsaWNlKG5hdlByZWZpeC5sZW5ndGgpXG5cdCk7XG5cdHJlc3RyaWN0aW9ucy5SZXF1aXJlZFByb3BlcnRpZXMgPSBfZmV0Y2hQcm9wZXJ0aWVzRm9yTmF2UGF0aChyZXFTdWJzZXQsIG5hdlBhdGgsIHJlc3RyaWN0aW9ucy5SZXF1aXJlZFByb3BlcnRpZXMpO1xuXHRyZXN0cmljdGlvbnMuTm9uRmlsdGVyYWJsZVByb3BlcnRpZXMgPSBfZmV0Y2hQcm9wZXJ0aWVzRm9yTmF2UGF0aChub25GaWx0ZXJTdWJzZXQsIG5hdlBhdGgsIHJlc3RyaWN0aW9ucy5Ob25GaWx0ZXJhYmxlUHJvcGVydGllcyk7XG5cblx0Y29uc3QgcGFyZW50QWxsb3dlZEV4cHJlc3Npb25zID0gT2JqZWN0LmtleXMoZmlsdGVyUmVzdGljdGlvbnMuRmlsdGVyQWxsb3dlZEV4cHJlc3Npb25zKS5yZWR1Y2UoXG5cdFx0KG91dFByb3A6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiwgcHJvcFBhdGg6IHN0cmluZykgPT4ge1xuXHRcdFx0aWYgKHByb3BQYXRoLnN0YXJ0c1dpdGgobmF2UHJlZml4KSkge1xuXHRcdFx0XHRjb25zdCBvdXRQcm9wUGF0aCA9IHByb3BQYXRoLnNsaWNlKG5hdlByZWZpeC5sZW5ndGgpO1xuXHRcdFx0XHRvdXRQcm9wW291dFByb3BQYXRoXSA9IGZpbHRlclJlc3RpY3Rpb25zLkZpbHRlckFsbG93ZWRFeHByZXNzaW9uc1twcm9wUGF0aF07XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gb3V0UHJvcDtcblx0XHR9LFxuXHRcdHt9IGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPlxuXHQpO1xuXG5cdHJlc3RyaWN0aW9ucy5GaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnMgPSBtZXJnZU9iamVjdHMoe30sIHJlc3RyaWN0aW9ucy5GaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnMsIHBhcmVudEFsbG93ZWRFeHByZXNzaW9ucykgYXMgUmVjb3JkPFxuXHRcdHN0cmluZyxcblx0XHRzdHJpbmdbXVxuXHQ+O1xuXHRyZXR1cm4gcmVzdHJpY3Rpb25zO1xufVxuXG4vKipcbiAqIFByb2Nlc3NlcyBuYXZpZ2F0aW9uIHJlc3RyaWN0aW9ucyAoc2Vjb25kIGhpZ2hlc3QgcHJpb3JpdHkpLlxuICogQHBhcmFtIHJlc3RyaWN0aW9ucyBUaGUgY3VycmVudCBmaWx0ZXIgcmVzdHJpY3Rpb25zIG9iamVjdFxuICogQHBhcmFtIG5hdmlnYXRpb25SZXN0cmljdGlvbnMgVGhlIG5hdmlnYXRpb24gcmVzdHJpY3Rpb25zXG4gKiBAcmV0dXJucyBVcGRhdGVkIGZpbHRlciByZXN0cmljdGlvbnMgb2JqZWN0XG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NOYXZpZ2F0aW9uRmlsdGVyUmVzdHJpY3Rpb25zKFxuXHRyZXN0cmljdGlvbnM6IEZpbHRlclJlc3RyaWN0aW9ucyxcblx0bmF2aWdhdGlvblJlc3RyaWN0aW9uczogRmlsdGVyUmVzdHJpY3Rpb25zVHlwZSB8IHVuZGVmaW5lZFxuKTogRmlsdGVyUmVzdHJpY3Rpb25zIHtcblx0Y29uc3QgZmlsdGVyUmVzdGljdGlvbnMgPSBnZXRGaWx0ZXJSZXN0cmljdGlvbnMobmF2aWdhdGlvblJlc3RyaWN0aW9ucyk7XG5cdHJlc3RyaWN0aW9ucy5SZXF1aXJlZFByb3BlcnRpZXMgPSB1bmlxdWVTb3J0KHJlc3RyaWN0aW9ucy5SZXF1aXJlZFByb3BlcnRpZXMuY29uY2F0KGZpbHRlclJlc3RpY3Rpb25zLlJlcXVpcmVkUHJvcGVydGllcykpO1xuXHRyZXN0cmljdGlvbnMuTm9uRmlsdGVyYWJsZVByb3BlcnRpZXMgPSB1bmlxdWVTb3J0KFxuXHRcdHJlc3RyaWN0aW9ucy5Ob25GaWx0ZXJhYmxlUHJvcGVydGllcy5jb25jYXQoZmlsdGVyUmVzdGljdGlvbnMuTm9uRmlsdGVyYWJsZVByb3BlcnRpZXMpXG5cdCk7XG5cdHJlc3RyaWN0aW9ucy5GaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnMgPSBtZXJnZU9iamVjdHMoXG5cdFx0e30sXG5cdFx0cmVzdHJpY3Rpb25zLkZpbHRlckFsbG93ZWRFeHByZXNzaW9ucyxcblx0XHRmaWx0ZXJSZXN0aWN0aW9ucy5GaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnNcblx0KSBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT47XG5cdHJldHVybiByZXN0cmljdGlvbnM7XG59XG5cbi8qKlxuICogUHJvY2Vzc2VzIG5hdmlnYXRpb24gYXNzb2NpYXRpb24gZW50aXR5IHJlc3RyaWN0aW9ucyAoaGlnaGVzdCBwcmlvcml0eSkuXG4gKiBAcGFyYW0gcmVzdHJpY3Rpb25zIFRoZSBjdXJyZW50IGZpbHRlciByZXN0cmljdGlvbnMgb2JqZWN0XG4gKiBAcGFyYW0gYXNzb2NpYXRpb25SZXN0cmljdGlvbnMgVGhlIGFzc29jaWF0aW9uIGVudGl0eSBmaWx0ZXIgcmVzdHJpY3Rpb25zXG4gKiBAcmV0dXJucyBVcGRhdGVkIGZpbHRlciByZXN0cmljdGlvbnMgb2JqZWN0XG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NOYXZpZ2F0aW9uQXNzb2NpYXRpb25GaWx0ZXJSZXN0cmljdGlvbnMoXG5cdHJlc3RyaWN0aW9uczogRmlsdGVyUmVzdHJpY3Rpb25zLFxuXHRhc3NvY2lhdGlvblJlc3RyaWN0aW9uczogRmlsdGVyUmVzdHJpY3Rpb25zVHlwZSB8IHVuZGVmaW5lZFxuKTogRmlsdGVyUmVzdHJpY3Rpb25zIHtcblx0Y29uc3QgZmlsdGVyUmVzdGljdGlvbnMgPSBnZXRGaWx0ZXJSZXN0cmljdGlvbnMoYXNzb2NpYXRpb25SZXN0cmljdGlvbnMpO1xuXHRyZXN0cmljdGlvbnMuUmVxdWlyZWRQcm9wZXJ0aWVzID0gdW5pcXVlU29ydChyZXN0cmljdGlvbnMuUmVxdWlyZWRQcm9wZXJ0aWVzLmNvbmNhdChmaWx0ZXJSZXN0aWN0aW9ucy5SZXF1aXJlZFByb3BlcnRpZXMpKTtcblx0cmVzdHJpY3Rpb25zLk5vbkZpbHRlcmFibGVQcm9wZXJ0aWVzID0gdW5pcXVlU29ydChcblx0XHRyZXN0cmljdGlvbnMuTm9uRmlsdGVyYWJsZVByb3BlcnRpZXMuY29uY2F0KGZpbHRlclJlc3RpY3Rpb25zLk5vbkZpbHRlcmFibGVQcm9wZXJ0aWVzKVxuXHQpO1xuXHRyZXN0cmljdGlvbnMuRmlsdGVyQWxsb3dlZEV4cHJlc3Npb25zID0gbWVyZ2VPYmplY3RzKFxuXHRcdHt9LFxuXHRcdHJlc3RyaWN0aW9ucy5GaWx0ZXJBbGxvd2VkRXhwcmVzc2lvbnMsXG5cdFx0ZmlsdGVyUmVzdGljdGlvbnMuRmlsdGVyQWxsb3dlZEV4cHJlc3Npb25zXG5cdCkgYXMgX0ZpbHRlckFsbG93ZWRFeHByZXNzaW9ucztcblx0cmV0dXJuIHJlc3RyaWN0aW9ucztcbn1cblxuLyoqXG4gKiBQcm9jZXNzZXMgZmlsdGVyIHJlc3RyaWN0aW9ucyB1c2luZyBjb252ZXJ0ZXIgY29udGV4dC5cbiAqIEBwYXJhbSBkYXRhTW9kZWxPYmplY3RQYXRoIFRoZSBkYXRhIG1vZGVsIG9iamVjdCBwYXRoXG4gKiBAcmV0dXJucyBQcm9jZXNzZWQgZmlsdGVyIHJlc3RyaWN0aW9uc1xuICovXG5mdW5jdGlvbiBwcm9jZXNzRmlsdGVyUmVzdHJpY3Rpb25zRnJvbUNvbnZlcnRlcihkYXRhTW9kZWxPYmplY3RQYXRoOiBEYXRhTW9kZWxPYmplY3RQYXRoPFBhZ2VDb250ZXh0UGF0aFRhcmdldD4pOiBGaWx0ZXJSZXN0cmljdGlvbnMge1xuXHRjb25zdCByZXN0cmljdGlvbnMgPSBpbml0aWFsaXplRmlsdGVyUmVzdHJpY3Rpb25zKCk7XG5cdGNvbnN0IGlzQ29udGFpbm1lbnQgPSAhaXNFbnRpdHlTZXQoZGF0YU1vZGVsT2JqZWN0UGF0aC50YXJnZXRFbnRpdHlTZXQpO1xuXHRjb25zdCBjb250YWlubWVudE5hdlBhdGggPVxuXHRcdGlzQ29udGFpbm1lbnQgJiYgZGF0YU1vZGVsT2JqZWN0UGF0aC5uYXZpZ2F0aW9uUHJvcGVydGllc1tkYXRhTW9kZWxPYmplY3RQYXRoLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLmxlbmd0aCAtIDFdPy5uYW1lO1xuXG5cdC8vIExFQVNUIFBSSU9SSVRZIC0gRmlsdGVyIHJlc3RyaWN0aW9ucyBkaXJlY3RseSBhdCBFbnRpdHkgU2V0XG5cdGlmICghaXNDb250YWlubWVudCkge1xuXHRcdGNvbnN0IGVudGl0eVNldEZpbHRlclJlc3RyaWN0aW9ucyA9IChcblx0XHRcdGRhdGFNb2RlbE9iamVjdFBhdGgudGFyZ2V0RW50aXR5U2V0Py5hbm5vdGF0aW9ucz8uQ2FwYWJpbGl0aWVzIGFzIEVudGl0eVNldEFubm90YXRpb25zX0NhcGFiaWxpdGllc1xuXHRcdCk/LkZpbHRlclJlc3RyaWN0aW9ucztcblx0XHRjb25zdCBoYXNSZXN1bHRDb250ZXh0VmFsdWUgPSBoYXNSZXN1bHRDb250ZXh0KGRhdGFNb2RlbE9iamVjdFBhdGgudGFyZ2V0RW50aXR5U2V0IGFzIEVudGl0eVNldCB8IG51bGwgfCB1bmRlZmluZWQpO1xuXG5cdFx0cHJvY2Vzc0VudGl0eVNldEZpbHRlclJlc3RyaWN0aW9ucyhyZXN0cmljdGlvbnMsIGVudGl0eVNldEZpbHRlclJlc3RyaWN0aW9ucywgaGFzUmVzdWx0Q29udGV4dFZhbHVlKTtcblx0fVxuXG5cdGlmIChkYXRhTW9kZWxPYmplY3RQYXRoLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLmxlbmd0aCA+IDApIHtcblx0XHRjb25zdCBuYXZQYXRoID0gaXNDb250YWlubWVudFxuXHRcdFx0PyAoY29udGFpbm1lbnROYXZQYXRoIGFzIHN0cmluZylcblx0XHRcdDogZGF0YU1vZGVsT2JqZWN0UGF0aC5uYXZpZ2F0aW9uUHJvcGVydGllc1tkYXRhTW9kZWxPYmplY3RQYXRoLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLmxlbmd0aCAtIDFdPy5uYW1lO1xuXG5cdFx0Ly8gVEhJUkQgSElHSEVTVCBQUklPUklUWSAtIFByb3BlcnR5IHBhdGggcmVzdHJpY3Rpb25zIGF0IHBhcmVudCBlbnRpdHlcblx0XHRjb25zdCBwYXJlbnRGaWx0ZXJSZXN0cmljdGlvbnMgPSAoXG5cdFx0XHRkYXRhTW9kZWxPYmplY3RQYXRoLnN0YXJ0aW5nRW50aXR5U2V0Py5hbm5vdGF0aW9ucz8uQ2FwYWJpbGl0aWVzIGFzIEVudGl0eVNldEFubm90YXRpb25zX0NhcGFiaWxpdGllc1xuXHRcdCk/LkZpbHRlclJlc3RyaWN0aW9ucztcblx0XHRwcm9jZXNzUHJvcGVydHlQYXRoRmlsdGVyUmVzdHJpY3Rpb25zKHJlc3RyaWN0aW9ucywgcGFyZW50RmlsdGVyUmVzdHJpY3Rpb25zLCBuYXZQYXRoKTtcblxuXHRcdC8vIFNFQ09ORCBISUdIRVNUIFBSSU9SSVRZIC0gTmF2aWdhdGlvbiByZXN0cmljdGlvbnMgZnJvbSBwYXJlbnQgZW50aXR5IHNldFxuXHRcdC8vIEJ1aWxkIHRoZSBmdWxsIG5hdmlnYXRpb24gcGF0aCBkeW5hbWljYWxseVxuXHRcdGNvbnN0IG5hdmlnYXRpb25QYXRoUGFydHMgPSBkYXRhTW9kZWxPYmplY3RQYXRoLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLm1hcCgocHJvcCkgPT4gcHJvcC5uYW1lKTtcblxuXHRcdC8vIENoZWNrIGZvciBuYXZpZ2F0aW9uIHJlc3RyaWN0aW9ucyB0aGF0IG1hdGNoIGFueSBwYXJ0IG9mIG91ciBuYXZpZ2F0aW9uIHBhdGhcblx0XHRjb25zdCBuYXZpZ2F0aW9uUmVzdHJpY3Rpb25zID1cblx0XHRcdGRhdGFNb2RlbE9iamVjdFBhdGguc3RhcnRpbmdFbnRpdHlTZXQ/LmFubm90YXRpb25zPy5DYXBhYmlsaXRpZXM/Lk5hdmlnYXRpb25SZXN0cmljdGlvbnM/LlJlc3RyaWN0ZWRQcm9wZXJ0aWVzPy5maW5kKFxuXHRcdFx0XHQobmF2UHJvcCkgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IG5hdlByb3BQYXRoID0gbmF2UHJvcC5OYXZpZ2F0aW9uUHJvcGVydHkudmFsdWU7XG5cdFx0XHRcdFx0aWYgKCFuYXZQcm9wUGF0aCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIENoZWNrIGlmIHRoZSBuYXZpZ2F0aW9uIHByb3BlcnR5IHBhdGggbWF0Y2hlcyBhbnkgb2Ygb3VyIG5hdmlnYXRpb24gc2VnbWVudHNcblx0XHRcdFx0XHQvLyBUaGlzIGhhbmRsZXMgYm90aCBzaW5nbGUgbGV2ZWwgKGUuZy4sIFwiX1BhcnRuZXJJdGVtc1wiKSBhbmQgbXVsdGktbGV2ZWwgKGUuZy4sIFwiU2V0L19QYXJ0bmVySXRlbXNcIikgcGF0aHNcblx0XHRcdFx0XHRjb25zdCBpc1BhcnRpYWxQYXRoTWF0Y2ggPSBuYXZpZ2F0aW9uUGF0aFBhcnRzLnNvbWUoKF8sIGluZGV4KSA9PiB7XG5cdFx0XHRcdFx0XHRjb25zdCBwYXJ0aWFsUGF0aCA9IG5hdmlnYXRpb25QYXRoUGFydHMuc2xpY2UoaW5kZXgpLmpvaW4oXCIvXCIpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIG5hdlByb3BQYXRoID09PSBwYXJ0aWFsUGF0aDtcblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdC8vIEFsc28gY2hlY2sgdGhlIGZ1bGwgcGF0aFxuXHRcdFx0XHRcdGNvbnN0IGZ1bGxQYXRoID0gbmF2aWdhdGlvblBhdGhQYXJ0cy5qb2luKFwiL1wiKTtcblx0XHRcdFx0XHRyZXR1cm4gaXNQYXJ0aWFsUGF0aE1hdGNoIHx8IG5hdlByb3BQYXRoID09PSBmdWxsUGF0aDtcblx0XHRcdFx0fVxuXHRcdFx0KTtcblxuXHRcdGNvbnN0IG5hdkZpbHRlclJlc3RyaWN0aW9ucyA9IG5hdmlnYXRpb25SZXN0cmljdGlvbnM/LkZpbHRlclJlc3RyaWN0aW9ucztcblx0XHRwcm9jZXNzTmF2aWdhdGlvbkZpbHRlclJlc3RyaWN0aW9ucyhyZXN0cmljdGlvbnMsIG5hdkZpbHRlclJlc3RyaWN0aW9ucyk7XG5cblx0XHQvLyBISUdIRVNUIFBSSU9SSVRZIC0gTmF2aWdhdGlvbiBhc3NvY2lhdGlvbiBlbnRpdHkgcmVzdHJpY3Rpb25zXG5cdFx0Y29uc3QgbmF2aWdhdGlvbkFzc29jaWF0aW9uID0gZGF0YU1vZGVsT2JqZWN0UGF0aC5uYXZpZ2F0aW9uUHJvcGVydGllcy5maW5kKChuYXZQcm9wKSA9PiBuYXZQcm9wLm5hbWUgPT09IG5hdlBhdGgpO1xuXHRcdGNvbnN0IGFzc29jaWF0aW9uRmlsdGVyUmVzdHJpY3Rpb25zID0gKG5hdmlnYXRpb25Bc3NvY2lhdGlvbj8uYW5ub3RhdGlvbnM/LkNhcGFiaWxpdGllcyBhcyBFbnRpdHlTZXRBbm5vdGF0aW9uc19DYXBhYmlsaXRpZXMpXG5cdFx0XHQ/LkZpbHRlclJlc3RyaWN0aW9ucztcblx0XHRwcm9jZXNzTmF2aWdhdGlvbkFzc29jaWF0aW9uRmlsdGVyUmVzdHJpY3Rpb25zKHJlc3RyaWN0aW9ucywgYXNzb2NpYXRpb25GaWx0ZXJSZXN0cmljdGlvbnMpO1xuXHR9XG5cblx0cmV0dXJuIHJlc3RyaWN0aW9ucztcbn1cblxuLyoqKiBGZXRjaGVzIGZpbHRlciByZXN0cmljdGlvbnMgYnkgZW50aXR5IHBhdGggd2l0aCBwcm9wZXIgcHJpb3JpdHkgaGFuZGxpbmcgYW5kIGVuc3VyZXMgY29ycmVjdCBwcm9jZXNzaW5nIG9yZGVyIGJ5IGZvbGxvd2luZyBwcmlvcml0eSBvcmRlcjpcbiAqIDEuIExFQVNUIFBSSU9SSVRZOiBGaWx0ZXIgcmVzdHJpY3Rpb25zIGRpcmVjdGx5IGF0IEVudGl0eSBTZXRcbiAqIDIuIFRISVJEIEhJR0hFU1QgUFJJT1JJVFk6IFByb3BlcnR5IHBhdGggcmVzdHJpY3Rpb25zIGF0IHBhcmVudCBlbnRpdHlcbiAqIDMuIFNFQ09ORCBISUdIRVNUIFBSSU9SSVRZOiBOYXZpZ2F0aW9uIHJlc3RyaWN0aW9uc1xuICogNC4gSElHSEVTVCBQUklPUklUWTogUmVzdHJpY3Rpb25zIGF0IG5hdmlnYXRpb24gYXNzb2NpYXRpb24gZW50aXR5XG4gKiBAcGFyYW0gY29udmVydGVyQ29udGV4dCBPcHRpb25hbCBjb252ZXJ0ZXIgY29udGV4dCBmb3IgZW5oYW5jZWQgcHJvY2Vzc2luZ1xuICogQHJldHVybnMgRmlsdGVyIHJlc3RyaWN0aW9ucyBvYmplY3QgY29udGFpbmluZyByZXF1aXJlZCBwcm9wZXJ0aWVzLCBub24tZmlsdGVyYWJsZSBwcm9wZXJ0aWVzLCBhbmQgYWxsb3dlZCBleHByZXNzaW9uc1xuICovXG5mdW5jdGlvbiBnZXRGaWx0ZXJSZXN0cmljdGlvbnNCeURhdGFNb2RlbChkYXRhTW9kZWxPYmplY3RQYXRoPzogRGF0YU1vZGVsT2JqZWN0UGF0aDxQYWdlQ29udGV4dFBhdGhUYXJnZXQ+KTogRmlsdGVyUmVzdHJpY3Rpb25zIHtcblx0aWYgKGRhdGFNb2RlbE9iamVjdFBhdGgpIHtcblx0XHRyZXR1cm4gcHJvY2Vzc0ZpbHRlclJlc3RyaWN0aW9uc0Zyb21Db252ZXJ0ZXIoZGF0YU1vZGVsT2JqZWN0UGF0aCk7XG5cdH1cblx0cmV0dXJuIGluaXRpYWxpemVGaWx0ZXJSZXN0cmljdGlvbnMoKTtcbn1cblxuY29uc3QgRmlsdGVyUmVzdHJpY3Rpb25zID0geyBnZXRGaWx0ZXJSZXN0cmljdGlvbnNCeURhdGFNb2RlbCB9O1xuXG5leHBvcnQgZGVmYXVsdCBGaWx0ZXJSZXN0cmljdGlvbnM7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0VBc0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNBLFNBQVNBLFdBQVdBLENBQUNDLEdBQTZCLEVBQXNCO0lBQ3ZFLElBQUksQ0FBQ0EsR0FBRyxFQUFFO01BQ1QsT0FBT0MsU0FBUztJQUNqQjtJQUNBLE9BQU8sT0FBT0QsR0FBRyxDQUFDRSxLQUFLLEtBQUssUUFBUSxHQUFHRixHQUFHLENBQUNFLEtBQUssR0FBR0QsU0FBUztFQUM3RDs7RUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDQSxTQUFTRSxxQkFBcUJBLENBQUNDLGtCQUFzRCxFQUFzQjtJQUMxRyxJQUFJLENBQUNBLGtCQUFrQixFQUFFO01BQ3hCLE9BQU87UUFBRUMsa0JBQWtCLEVBQUUsRUFBRTtRQUFFQyx1QkFBdUIsRUFBRSxFQUFFO1FBQUVDLHdCQUF3QixFQUFFLENBQUM7TUFBRSxDQUFDO0lBQzdGO0lBRUEsTUFBTUMsUUFBa0IsR0FBRyxDQUFDSixrQkFBa0IsQ0FBQ0Msa0JBQWtCLElBQUksRUFBRSxFQUFFSSxHQUFHLENBQUVDLENBQUMsSUFBS1gsV0FBVyxDQUFDVyxDQUFDLENBQUMsQ0FBQyxDQUFDQyxNQUFNLENBQUVELENBQUMsSUFBa0IsQ0FBQyxDQUFDQSxDQUFDLENBQUM7SUFDbkksTUFBTUUsYUFBdUIsR0FBRyxDQUFDUixrQkFBa0IsQ0FBQ0UsdUJBQXVCLElBQUksRUFBRSxFQUMv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
@@ -0,0 +1,309 @@
1
+ import type { EntitySet, PropertyPath } from "@sap-ux/vocabularies-types";
2
+ import type { FilterRestrictionsType } from "@sap-ux/vocabularies-types/vocabularies/Capabilities";
3
+ import type { EntitySetAnnotations_Capabilities } from "@sap-ux/vocabularies-types/vocabularies/Capabilities_Edm";
4
+ import uniqueSort from "sap/base/util/array/uniqueSort";
5
+ import mergeObjects from "sap/base/util/merge";
6
+ import type { PageContextPathTarget } from "sap/fe/core/converters/TemplateConverter";
7
+ import { isEntitySet } from "sap/fe/core/helpers/TypeGuards";
8
+ import type { DataModelObjectPath } from "sap/fe/core/templating/DataModelPathHelper";
9
+
10
+ type _FilterAllowedExpressions = Record<string, string[]>;
11
+
12
+ export type FilterRestrictions = {
13
+ RequiredProperties: string[];
14
+ NonFilterableProperties: string[];
15
+ FilterAllowedExpressions: _FilterAllowedExpressions;
16
+ };
17
+
18
+ type FilterExpressionRestriction = {
19
+ Property?: PropertyPath;
20
+ AllowedExpressions?: string;
21
+ };
22
+
23
+ /**
24
+ * Extracts property path string from a flexible path object used in converter or annotation inputs.
25
+ * The object may contain a 'value' field. Returns undefined if it is a non-empty string.
26
+ * @param ref Potential property reference object.
27
+ * @returns Property path string or undefined.
28
+ */
29
+ function extractPath(ref: PropertyPath | undefined): string | undefined {
30
+ if (!ref) {
31
+ return undefined;
32
+ }
33
+ return typeof ref.value === "string" ? ref.value : undefined;
34
+ }
35
+
36
+ /**
37
+ * Parses raw FilterRestrictionsType annotation into plain arrays of strings and a mapping of allowed expressions.
38
+ * This replaces previous two-step normalization + extraction logic and deliberately avoids introducing $PropertyPath objects.
39
+ * @param filterRestrictions Raw filter restrictions annotation (may be undefined).
40
+ * @returns Parsed filter restrictions with simple string collections.
41
+ */
42
+ function getFilterRestrictions(filterRestrictions: FilterRestrictionsType | undefined): FilterRestrictions {
43
+ if (!filterRestrictions) {
44
+ return { RequiredProperties: [], NonFilterableProperties: [], FilterAllowedExpressions: {} };
45
+ }
46
+
47
+ const required: string[] = (filterRestrictions.RequiredProperties ?? []).map((p) => extractPath(p)).filter((p): p is string => !!p);
48
+ const nonFilterable: string[] = (filterRestrictions.NonFilterableProperties ?? [])
49
+ .map((p) => extractPath(p))
50
+ .filter((p): p is string => !!p);
51
+
52
+ const allowed: _FilterAllowedExpressions = {};
53
+ for (const expr of filterRestrictions.FilterExpressionRestrictions ?? []) {
54
+ const exprObj = expr as FilterExpressionRestriction;
55
+ const propPath = extractPath(exprObj.Property);
56
+ const allowedExp = typeof exprObj.AllowedExpressions === "string" ? exprObj.AllowedExpressions : undefined;
57
+ if (!propPath || !allowedExp) {
58
+ continue;
59
+ }
60
+ if (allowed[propPath] !== undefined) {
61
+ allowed[propPath].push(allowedExp);
62
+ } else {
63
+ allowed[propPath] = [allowedExp];
64
+ }
65
+ }
66
+
67
+ return {
68
+ RequiredProperties: required,
69
+ NonFilterableProperties: nonFilterable,
70
+ FilterAllowedExpressions: allowed
71
+ };
72
+ }
73
+
74
+ function _fetchPropertiesForNavPath(paths: string[], navPath: string, props: string[]): string[] {
75
+ const navPathPrefix = navPath + "/";
76
+ return paths.reduce((outPaths: string[], pathToCheck: string) => {
77
+ if (pathToCheck.startsWith(navPathPrefix)) {
78
+ const outPath = pathToCheck.replace(navPathPrefix, "");
79
+ if (!outPaths.includes(outPath)) {
80
+ outPaths.push(outPath);
81
+ }
82
+ }
83
+ return outPaths;
84
+ }, props);
85
+ }
86
+
87
+ /**
88
+ * Initializes an empty filter restrictions object with default values.
89
+ * @returns The initialized filter restrictions object
90
+ */
91
+ function initializeFilterRestrictions(): FilterRestrictions {
92
+ return {
93
+ RequiredProperties: [],
94
+ NonFilterableProperties: [],
95
+ FilterAllowedExpressions: {}
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Determines if the entity set has a result context annotation.
101
+ * @param entitySet The entity set to check
102
+ * @returns True if the entity set has result context, false otherwise
103
+ */
104
+ function hasResultContext(entitySet: EntitySet | null | undefined): boolean {
105
+ if (!entitySet?.annotations?.Common) {
106
+ return false;
107
+ }
108
+ return "ResultContext" in entitySet.annotations.Common ? entitySet.annotations.Common.ResultContext?.valueOf() === true : false;
109
+ }
110
+
111
+ /**
112
+ * Processes filter restrictions at entity set level (least priority).
113
+ * @param restrictions The current filter restrictions object
114
+ * @param filterRestrictions The filter restrictions annotation
115
+ * @param hasResultContextValue Whether the entity has result context
116
+ * @returns Updated filter restrictions object
117
+ */
118
+ function processEntitySetFilterRestrictions(
119
+ restrictions: FilterRestrictions,
120
+ filterRestrictions: FilterRestrictionsType | undefined,
121
+ hasResultContextValue: boolean
122
+ ): FilterRestrictions {
123
+ const filterRestictions = getFilterRestrictions(filterRestrictions);
124
+ restrictions.RequiredProperties = filterRestictions.RequiredProperties;
125
+ if (!hasResultContextValue) {
126
+ restrictions.NonFilterableProperties = filterRestictions.NonFilterableProperties;
127
+ }
128
+ restrictions.FilterAllowedExpressions = filterRestictions.FilterAllowedExpressions;
129
+ return restrictions;
130
+ }
131
+
132
+ /**
133
+ * Processes property path filter restrictions (third highest priority).
134
+ * @param restrictions The current filter restrictions object
135
+ * @param filterRestrictions The parent filter restrictions
136
+ * @param navPath The navigation path
137
+ * @returns Updated filter restrictions object
138
+ */
139
+ function processPropertyPathFilterRestrictions(
140
+ restrictions: FilterRestrictions,
141
+ filterRestrictions: FilterRestrictionsType | undefined,
142
+ navPath: string
143
+ ): FilterRestrictions {
144
+ if (!filterRestrictions || navPath.includes("%2F")) {
145
+ return restrictions;
146
+ }
147
+ const filterRestictions = getFilterRestrictions(filterRestrictions);
148
+
149
+ const navPrefix = navPath + "/";
150
+ const reqSubset = filterRestictions.RequiredProperties.filter((p) => p.startsWith(navPrefix)).map((p) => p.slice(navPrefix.length));
151
+ const nonFilterSubset = filterRestictions.NonFilterableProperties.filter((p) => p.startsWith(navPrefix)).map((p) =>
152
+ p.slice(navPrefix.length)
153
+ );
154
+ restrictions.RequiredProperties = _fetchPropertiesForNavPath(reqSubset, navPath, restrictions.RequiredProperties);
155
+ restrictions.NonFilterableProperties = _fetchPropertiesForNavPath(nonFilterSubset, navPath, restrictions.NonFilterableProperties);
156
+
157
+ const parentAllowedExpressions = Object.keys(filterRestictions.FilterAllowedExpressions).reduce(
158
+ (outProp: Record<string, string[]>, propPath: string) => {
159
+ if (propPath.startsWith(navPrefix)) {
160
+ const outPropPath = propPath.slice(navPrefix.length);
161
+ outProp[outPropPath] = filterRestictions.FilterAllowedExpressions[propPath];
162
+ }
163
+ return outProp;
164
+ },
165
+ {} as Record<string, string[]>
166
+ );
167
+
168
+ restrictions.FilterAllowedExpressions = mergeObjects({}, restrictions.FilterAllowedExpressions, parentAllowedExpressions) as Record<
169
+ string,
170
+ string[]
171
+ >;
172
+ return restrictions;
173
+ }
174
+
175
+ /**
176
+ * Processes navigation restrictions (second highest priority).
177
+ * @param restrictions The current filter restrictions object
178
+ * @param navigationRestrictions The navigation restrictions
179
+ * @returns Updated filter restrictions object
180
+ */
181
+ function processNavigationFilterRestrictions(
182
+ restrictions: FilterRestrictions,
183
+ navigationRestrictions: FilterRestrictionsType | undefined
184
+ ): FilterRestrictions {
185
+ const filterRestictions = getFilterRestrictions(navigationRestrictions);
186
+ restrictions.RequiredProperties = uniqueSort(restrictions.RequiredProperties.concat(filterRestictions.RequiredProperties));
187
+ restrictions.NonFilterableProperties = uniqueSort(
188
+ restrictions.NonFilterableProperties.concat(filterRestictions.NonFilterableProperties)
189
+ );
190
+ restrictions.FilterAllowedExpressions = mergeObjects(
191
+ {},
192
+ restrictions.FilterAllowedExpressions,
193
+ filterRestictions.FilterAllowedExpressions
194
+ ) as Record<string, string[]>;
195
+ return restrictions;
196
+ }
197
+
198
+ /**
199
+ * Processes navigation association entity restrictions (highest priority).
200
+ * @param restrictions The current filter restrictions object
201
+ * @param associationRestrictions The association entity filter restrictions
202
+ * @returns Updated filter restrictions object
203
+ */
204
+ function processNavigationAssociationFilterRestrictions(
205
+ restrictions: FilterRestrictions,
206
+ associationRestrictions: FilterRestrictionsType | undefined
207
+ ): FilterRestrictions {
208
+ const filterRestictions = getFilterRestrictions(associationRestrictions);
209
+ restrictions.RequiredProperties = uniqueSort(restrictions.RequiredProperties.concat(filterRestictions.RequiredProperties));
210
+ restrictions.NonFilterableProperties = uniqueSort(
211
+ restrictions.NonFilterableProperties.concat(filterRestictions.NonFilterableProperties)
212
+ );
213
+ restrictions.FilterAllowedExpressions = mergeObjects(
214
+ {},
215
+ restrictions.FilterAllowedExpressions,
216
+ filterRestictions.FilterAllowedExpressions
217
+ ) as _FilterAllowedExpressions;
218
+ return restrictions;
219
+ }
220
+
221
+ /**
222
+ * Processes filter restrictions using converter context.
223
+ * @param dataModelObjectPath The data model object path
224
+ * @returns Processed filter restrictions
225
+ */
226
+ function processFilterRestrictionsFromConverter(dataModelObjectPath: DataModelObjectPath<PageContextPathTarget>): FilterRestrictions {
227
+ const restrictions = initializeFilterRestrictions();
228
+ const isContainment = !isEntitySet(dataModelObjectPath.targetEntitySet);
229
+ const containmentNavPath =
230
+ isContainment && dataModelObjectPath.navigationProperties[dataModelObjectPath.navigationProperties.length - 1]?.name;
231
+
232
+ // LEAST PRIORITY - Filter restrictions directly at Entity Set
233
+ if (!isContainment) {
234
+ const entitySetFilterRestrictions = (
235
+ dataModelObjectPath.targetEntitySet?.annotations?.Capabilities as EntitySetAnnotations_Capabilities
236
+ )?.FilterRestrictions;
237
+ const hasResultContextValue = hasResultContext(dataModelObjectPath.targetEntitySet as EntitySet | null | undefined);
238
+
239
+ processEntitySetFilterRestrictions(restrictions, entitySetFilterRestrictions, hasResultContextValue);
240
+ }
241
+
242
+ if (dataModelObjectPath.navigationProperties.length > 0) {
243
+ const navPath = isContainment
244
+ ? (containmentNavPath as string)
245
+ : dataModelObjectPath.navigationProperties[dataModelObjectPath.navigationProperties.length - 1]?.name;
246
+
247
+ // THIRD HIGHEST PRIORITY - Property path restrictions at parent entity
248
+ const parentFilterRestrictions = (
249
+ dataModelObjectPath.startingEntitySet?.annotations?.Capabilities as EntitySetAnnotations_Capabilities
250
+ )?.FilterRestrictions;
251
+ processPropertyPathFilterRestrictions(restrictions, parentFilterRestrictions, navPath);
252
+
253
+ // SECOND HIGHEST PRIORITY - Navigation restrictions from parent entity set
254
+ // Build the full navigation path dynamically
255
+ const navigationPathParts = dataModelObjectPath.navigationProperties.map((prop) => prop.name);
256
+
257
+ // Check for navigation restrictions that match any part of our navigation path
258
+ const navigationRestrictions =
259
+ dataModelObjectPath.startingEntitySet?.annotations?.Capabilities?.NavigationRestrictions?.RestrictedProperties?.find(
260
+ (navProp) => {
261
+ const navPropPath = navProp.NavigationProperty.value;
262
+ if (!navPropPath) {
263
+ return false;
264
+ }
265
+
266
+ // Check if the navigation property path matches any of our navigation segments
267
+ // This handles both single level (e.g., "_PartnerItems") and multi-level (e.g., "Set/_PartnerItems") paths
268
+ const isPartialPathMatch = navigationPathParts.some((_, index) => {
269
+ const partialPath = navigationPathParts.slice(index).join("/");
270
+ return navPropPath === partialPath;
271
+ });
272
+
273
+ // Also check the full path
274
+ const fullPath = navigationPathParts.join("/");
275
+ return isPartialPathMatch || navPropPath === fullPath;
276
+ }
277
+ );
278
+
279
+ const navFilterRestrictions = navigationRestrictions?.FilterRestrictions;
280
+ processNavigationFilterRestrictions(restrictions, navFilterRestrictions);
281
+
282
+ // HIGHEST PRIORITY - Navigation association entity restrictions
283
+ const navigationAssociation = dataModelObjectPath.navigationProperties.find((navProp) => navProp.name === navPath);
284
+ const associationFilterRestrictions = (navigationAssociation?.annotations?.Capabilities as EntitySetAnnotations_Capabilities)
285
+ ?.FilterRestrictions;
286
+ processNavigationAssociationFilterRestrictions(restrictions, associationFilterRestrictions);
287
+ }
288
+
289
+ return restrictions;
290
+ }
291
+
292
+ /*** Fetches filter restrictions by entity path with proper priority handling and ensures correct processing order by following priority order:
293
+ * 1. LEAST PRIORITY: Filter restrictions directly at Entity Set
294
+ * 2. THIRD HIGHEST PRIORITY: Property path restrictions at parent entity
295
+ * 3. SECOND HIGHEST PRIORITY: Navigation restrictions
296
+ * 4. HIGHEST PRIORITY: Restrictions at navigation association entity
297
+ * @param converterContext Optional converter context for enhanced processing
298
+ * @returns Filter restrictions object containing required properties, non-filterable properties, and allowed expressions
299
+ */
300
+ function getFilterRestrictionsByDataModel(dataModelObjectPath?: DataModelObjectPath<PageContextPathTarget>): FilterRestrictions {
301
+ if (dataModelObjectPath) {
302
+ return processFilterRestrictionsFromConverter(dataModelObjectPath);
303
+ }
304
+ return initializeFilterRestrictions();
305
+ }
306
+
307
+ const FilterRestrictions = { getFilterRestrictionsByDataModel };
308
+
309
+ export default FilterRestrictions;