@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.
- package/package.json +1 -1
- package/src/sap/fe/core/.library +4 -1
- package/src/sap/fe/core/ActionRuntime.js +48 -23
- package/src/sap/fe/core/ActionRuntime.ts +61 -35
- package/src/sap/fe/core/AppComponent.js +76 -6
- package/src/sap/fe/core/AppComponent.ts +94 -8
- package/src/sap/fe/core/AppStateHandler.js +9 -8
- package/src/sap/fe/core/AppStateHandler.ts +13 -9
- package/src/sap/fe/core/BaseController.js +8 -5
- package/src/sap/fe/core/BaseController.ts +6 -1
- package/src/sap/fe/core/CommonUtils.js +4 -123
- package/src/sap/fe/core/CommonUtils.ts +3 -172
- package/src/sap/fe/core/ExtensionAPI.js +3 -10
- package/src/sap/fe/core/ExtensionAPI.ts +2 -14
- package/src/sap/fe/core/PageController.js +64 -43
- package/src/sap/fe/core/PageController.ts +62 -47
- package/src/sap/fe/core/TemplateComponent.js +20 -1
- package/src/sap/fe/core/TemplateComponent.ts +24 -2
- package/src/sap/fe/core/buildingBlocks/BuildingBlock.js +37 -24
- package/src/sap/fe/core/buildingBlocks/BuildingBlock.ts +47 -31
- package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockSupport.js +1 -1
- package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockSupport.ts +4 -0
- package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplateProcessor.js +4 -1
- package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplateProcessor.ts +3 -0
- package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplatingBase.js +4 -1
- package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplatingBase.ts +4 -0
- package/src/sap/fe/core/controllerextensions/BaseControllerExtension.js +7 -5
- package/src/sap/fe/core/controllerextensions/BaseControllerExtension.ts +22 -2
- package/src/sap/fe/core/controllerextensions/CollaborativeDraft.js +82 -39
- package/src/sap/fe/core/controllerextensions/CollaborativeDraft.ts +91 -54
- package/src/sap/fe/core/controllerextensions/EditFlow.js +25 -3
- package/src/sap/fe/core/controllerextensions/EditFlow.ts +27 -3
- package/src/sap/fe/core/controllerextensions/InlineEditFlow.js +9 -7
- package/src/sap/fe/core/controllerextensions/InlineEditFlow.ts +17 -5
- package/src/sap/fe/core/controllerextensions/InternalRouting.js +37 -18
- package/src/sap/fe/core/controllerextensions/InternalRouting.ts +49 -17
- package/src/sap/fe/core/controllerextensions/KPIManagement.js +30 -15
- package/src/sap/fe/core/controllerextensions/KPIManagement.ts +32 -14
- package/src/sap/fe/core/controllerextensions/MessageHandler.js +9 -10
- package/src/sap/fe/core/controllerextensions/MessageHandler.ts +8 -9
- package/src/sap/fe/core/controllerextensions/Paginator.js +2 -2
- package/src/sap/fe/core/controllerextensions/Paginator.ts +1 -1
- package/src/sap/fe/core/controllerextensions/Placeholder.js +10 -2
- package/src/sap/fe/core/controllerextensions/Placeholder.ts +5 -1
- package/src/sap/fe/core/controllerextensions/Recommendations.js +3 -3
- package/src/sap/fe/core/controllerextensions/Recommendations.ts +2 -2
- package/src/sap/fe/core/controllerextensions/Routing.js +9 -5
- package/src/sap/fe/core/controllerextensions/Routing.ts +7 -7
- package/src/sap/fe/core/controllerextensions/Share.js +5 -5
- package/src/sap/fe/core/controllerextensions/Share.ts +4 -4
- package/src/sap/fe/core/controllerextensions/SideEffects.js +1 -1
- package/src/sap/fe/core/controllerextensions/SideEffects.ts +17 -2
- package/src/sap/fe/core/controllerextensions/collaboration/ActivityBase.js +2 -2
- package/src/sap/fe/core/controllerextensions/collaboration/ActivityBase.ts +1 -1
- package/src/sap/fe/core/controllerextensions/editFlow/NotApplicableContextDialog.js +3 -3
- package/src/sap/fe/core/controllerextensions/editFlow/NotApplicableContextDialog.tsx +3 -2
- package/src/sap/fe/core/controllerextensions/editFlow/TransactionHelper.js +33 -11
- package/src/sap/fe/core/controllerextensions/editFlow/TransactionHelper.ts +45 -14
- package/src/sap/fe/core/controllerextensions/editFlow/draft.js +37 -3
- package/src/sap/fe/core/controllerextensions/editFlow/draft.ts +41 -8
- package/src/sap/fe/core/controllerextensions/editFlow/draftDataLossPopup.js +10 -4
- package/src/sap/fe/core/controllerextensions/editFlow/draftDataLossPopup.ts +6 -1
- package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataOperation.js +7 -7
- package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataOperation.ts +6 -5
- package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataStrictHandling.js +2 -2
- package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataStrictHandling.ts +1 -1
- package/src/sap/fe/core/controllerextensions/editFlow/operations/OperationParameters.js +2 -1
- package/src/sap/fe/core/controllerextensions/editFlow/operations/OperationParameters.ts +1 -0
- package/src/sap/fe/core/controllerextensions/messageHandler/messageHandling.js +10 -6
- package/src/sap/fe/core/controllerextensions/messageHandler/messageHandling.ts +6 -5
- package/src/sap/fe/core/controllerextensions/routing/RouterProxy.js +11 -9
- package/src/sap/fe/core/controllerextensions/routing/RouterProxy.ts +22 -9
- package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DraftDataLossDialog.js +9 -4
- package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DraftDataLossDialog.tsx +10 -4
- package/src/sap/fe/core/controls/Recommendations/ConfirmRecommendationDialog.js +31 -2
- package/src/sap/fe/core/controls/Recommendations/ConfirmRecommendationDialog.tsx +34 -1
- package/src/sap/fe/core/converters/ManifestSettings.js +7 -1
- package/src/sap/fe/core/converters/ManifestSettings.ts +37 -0
- package/src/sap/fe/core/converters/ManifestWrapper.js +29 -9
- package/src/sap/fe/core/converters/ManifestWrapper.ts +29 -11
- package/src/sap/fe/core/converters/annotations/DataField.js +46 -19
- package/src/sap/fe/core/converters/annotations/DataField.ts +93 -19
- package/src/sap/fe/core/converters/common/AnnotationConverter.js +88 -35
- package/src/sap/fe/core/converters/controls/Common/Action.js +57 -20
- package/src/sap/fe/core/converters/controls/Common/Action.ts +71 -21
- package/src/sap/fe/core/converters/controls/Common/Chart.js +13 -3
- package/src/sap/fe/core/converters/controls/Common/Chart.ts +20 -4
- package/src/sap/fe/core/converters/controls/Common/Form.js +18 -3
- package/src/sap/fe/core/converters/controls/Common/Form.ts +23 -1
- package/src/sap/fe/core/converters/controls/Common/Table.js +89 -57
- package/src/sap/fe/core/converters/controls/Common/Table.ts +110 -56
- package/src/sap/fe/core/converters/controls/Common/filter/FilterRestrictions.js +243 -0
- package/src/sap/fe/core/converters/controls/Common/filter/FilterRestrictions.ts +309 -0
- package/src/sap/fe/core/converters/controls/Common/table/Columns.js +142 -58
- package/src/sap/fe/core/converters/controls/Common/table/Columns.ts +172 -78
- package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +12 -18
- package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +13 -27
- package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +7 -16
- package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +6 -17
- package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +16 -5
- package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +16 -5
- package/src/sap/fe/core/converters/helpers/Aggregation.js +12 -2
- package/src/sap/fe/core/converters/helpers/Aggregation.ts +11 -1
- package/src/sap/fe/core/converters/helpers/DataFieldHelper.js +27 -3
- package/src/sap/fe/core/converters/helpers/DataFieldHelper.ts +28 -1
- package/src/sap/fe/core/converters/helpers/ID.js +3 -1
- package/src/sap/fe/core/converters/helpers/ID.ts +1 -0
- package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +5 -2
- package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +7 -1
- package/src/sap/fe/core/converters/templates/ListReportConverter.js +11 -3
- package/src/sap/fe/core/converters/templates/ListReportConverter.ts +12 -4
- package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +19 -8
- package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +18 -7
- package/src/sap/fe/core/designtime/AnnotationBasedChanges.js +8 -3
- package/src/sap/fe/core/designtime/AnnotationBasedChanges.ts +7 -2
- package/src/sap/fe/core/formatters/FPMFormatter.js +2 -2
- package/src/sap/fe/core/formatters/FPMFormatter.ts +1 -1
- package/src/sap/fe/core/fpm/Component.js +8 -1
- package/src/sap/fe/core/fpm/Component.ts +8 -0
- package/src/sap/fe/core/fpm/manifest.json +1 -1
- package/src/sap/fe/core/helpers/AppStartupHelper.js +79 -25
- package/src/sap/fe/core/helpers/AppStartupHelper.ts +91 -32
- package/src/sap/fe/core/helpers/ManifestHelper.js +6 -3
- package/src/sap/fe/core/helpers/ManifestHelper.ts +3 -0
- package/src/sap/fe/core/helpers/MetaModelFunction.js +12 -3
- package/src/sap/fe/core/helpers/MetaModelFunction.ts +11 -3
- package/src/sap/fe/core/helpers/ModelHelper.js +48 -9
- package/src/sap/fe/core/helpers/ModelHelper.ts +55 -10
- package/src/sap/fe/core/helpers/TypeGuards.js +12 -2
- package/src/sap/fe/core/helpers/TypeGuards.ts +10 -1
- package/src/sap/fe/core/helpers/WebSocket.js +6 -7
- package/src/sap/fe/core/helpers/WebSocket.ts +10 -6
- package/src/sap/fe/core/library.js +30 -3
- package/src/sap/fe/core/library.ts +28 -1
- package/src/sap/fe/core/messagebundle.properties +8 -1
- package/src/sap/fe/core/messagebundle_ar.properties +7 -0
- package/src/sap/fe/core/messagebundle_bg.properties +10 -3
- package/src/sap/fe/core/messagebundle_ca.properties +7 -0
- package/src/sap/fe/core/messagebundle_cnr.properties +7 -0
- package/src/sap/fe/core/messagebundle_cs.properties +7 -0
- package/src/sap/fe/core/messagebundle_cy.properties +8 -1
- package/src/sap/fe/core/messagebundle_da.properties +7 -0
- package/src/sap/fe/core/messagebundle_de.properties +7 -0
- package/src/sap/fe/core/messagebundle_el.properties +7 -0
- package/src/sap/fe/core/messagebundle_en.properties +8 -1
- package/src/sap/fe/core/messagebundle_en_GB.properties +7 -0
- package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +5 -0
- package/src/sap/fe/core/messagebundle_es.properties +8 -1
- package/src/sap/fe/core/messagebundle_es_MX.properties +7 -0
- package/src/sap/fe/core/messagebundle_et.properties +7 -0
- package/src/sap/fe/core/messagebundle_fi.properties +7 -0
- package/src/sap/fe/core/messagebundle_fr.properties +16 -9
- package/src/sap/fe/core/messagebundle_fr_CA.properties +7 -0
- package/src/sap/fe/core/messagebundle_hi.properties +8 -1
- package/src/sap/fe/core/messagebundle_hr.properties +7 -0
- package/src/sap/fe/core/messagebundle_hu.properties +7 -0
- package/src/sap/fe/core/messagebundle_id.properties +7 -0
- package/src/sap/fe/core/messagebundle_it.properties +7 -0
- package/src/sap/fe/core/messagebundle_iw.properties +7 -0
- package/src/sap/fe/core/messagebundle_ja.properties +8 -1
- package/src/sap/fe/core/messagebundle_kk.properties +7 -0
- package/src/sap/fe/core/messagebundle_ko.properties +7 -0
- package/src/sap/fe/core/messagebundle_lt.properties +7 -0
- package/src/sap/fe/core/messagebundle_lv.properties +7 -0
- package/src/sap/fe/core/messagebundle_mk.properties +7 -0
- package/src/sap/fe/core/messagebundle_ms.properties +7 -0
- package/src/sap/fe/core/messagebundle_nl.properties +7 -0
- package/src/sap/fe/core/messagebundle_no.properties +7 -0
- package/src/sap/fe/core/messagebundle_pl.properties +7 -0
- package/src/sap/fe/core/messagebundle_pt.properties +7 -0
- package/src/sap/fe/core/messagebundle_pt_PT.properties +7 -0
- package/src/sap/fe/core/messagebundle_ro.properties +7 -0
- package/src/sap/fe/core/messagebundle_ru.properties +7 -0
- package/src/sap/fe/core/messagebundle_sh.properties +7 -0
- package/src/sap/fe/core/messagebundle_sk.properties +7 -0
- package/src/sap/fe/core/messagebundle_sl.properties +7 -0
- package/src/sap/fe/core/messagebundle_sr.properties +7 -0
- package/src/sap/fe/core/messagebundle_sv.properties +7 -0
- package/src/sap/fe/core/messagebundle_th.properties +7 -0
- package/src/sap/fe/core/messagebundle_tr.properties +7 -0
- package/src/sap/fe/core/messagebundle_uk.properties +7 -0
- package/src/sap/fe/core/messagebundle_vi.properties +7 -0
- package/src/sap/fe/core/messagebundle_zh_CN.properties +8 -1
- package/src/sap/fe/core/messagebundle_zh_TW.properties +7 -0
- package/src/sap/fe/core/rootView/Fcl.controller.js +21 -7
- package/src/sap/fe/core/rootView/Fcl.controller.ts +28 -6
- package/src/sap/fe/core/rootView/RootViewBaseController.js +96 -88
- package/src/sap/fe/core/rootView/RootViewBaseController.ts +106 -96
- package/src/sap/fe/core/services/EnvironmentServiceFactory.js +14 -10
- package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +15 -10
- package/src/sap/fe/core/services/RoutingServiceFactory.js +16 -7
- package/src/sap/fe/core/services/RoutingServiceFactory.ts +23 -10
- package/src/sap/fe/core/services/SideEffectsServiceFactory.js +9 -7
- package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +13 -8
- package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +62 -6
- package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +74 -11
- package/src/sap/fe/core/services/collaborativeDraftServiceFactory.js +33 -15
- package/src/sap/fe/core/services/collaborativeDraftServiceFactory.ts +31 -11
- package/src/sap/fe/core/templating/DisplayModeFormatter.js +4 -5
- package/src/sap/fe/core/templating/DisplayModeFormatter.ts +4 -6
- package/src/sap/fe/core/templating/UIFormatters.js +17 -2
- package/src/sap/fe/core/templating/UIFormatters.ts +25 -1
- package/src/sap/fe/core/types/sap.fe.core-auto-ext.d.js +10 -0
- package/src/sap/fe/core/types/sap.fe.core-auto-ext.d.ts +369 -0
- package/src/sap/fe/core/types/sap.fe.core-manual-ext.d.js +9 -0
- package/src/sap/fe/core/types/sap.fe.core-manual-ext.d.ts +49 -0
- 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;
|