@sapui5/sap.fe.core 1.97.0 → 1.99.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 +5 -4
- package/src/sap/fe/core/.library +1 -1
- package/src/sap/fe/core/AnnotationHelper.js +377 -405
- package/src/sap/fe/core/AnnotationHelper.ts +385 -0
- package/src/sap/fe/core/AppComponent.js +6 -3
- package/src/sap/fe/core/AppStateHandler.js +229 -181
- package/src/sap/fe/core/AppStateHandler.ts +171 -0
- package/src/sap/fe/core/BaseController.js +3 -2
- package/src/sap/fe/core/BusyLocker.js +105 -121
- package/src/sap/fe/core/BusyLocker.ts +98 -0
- package/src/sap/fe/core/CommonUtils.js +2073 -2379
- package/src/sap/fe/core/CommonUtils.ts +2078 -0
- package/src/sap/fe/core/ExtensionAPI.js +16 -7
- package/src/sap/fe/core/PageController.js +84 -119
- package/src/sap/fe/core/PageController.ts +101 -0
- package/src/sap/fe/core/RouterProxy.js +986 -807
- package/src/sap/fe/core/RouterProxy.ts +838 -0
- package/src/sap/fe/core/Synchronization.js +51 -35
- package/src/sap/fe/core/Synchronization.ts +29 -0
- package/src/sap/fe/core/TemplateComponent.js +173 -155
- package/src/sap/fe/core/TemplateComponent.ts +166 -0
- package/src/sap/fe/core/TemplateModel.js +97 -54
- package/src/sap/fe/core/TemplateModel.ts +64 -0
- package/src/sap/fe/core/TransactionHelper.js +1576 -1579
- package/src/sap/fe/core/TransactionHelper.ts +1706 -0
- package/src/sap/fe/core/actions/draft.js +560 -581
- package/src/sap/fe/core/actions/draft.ts +594 -0
- package/src/sap/fe/core/actions/messageHandling.js +545 -511
- package/src/sap/fe/core/actions/messageHandling.ts +532 -0
- package/src/sap/fe/core/actions/nonDraft.js +17 -19
- package/src/sap/fe/core/actions/nonDraft.ts +12 -0
- package/src/sap/fe/core/actions/operations.js +1074 -1211
- package/src/sap/fe/core/actions/operations.ts +1162 -0
- package/src/sap/fe/core/actions/sticky.js +102 -105
- package/src/sap/fe/core/actions/sticky.ts +102 -0
- package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +3 -2
- package/src/sap/fe/core/controllerextensions/EditFlow.js +229 -260
- package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +3 -2
- package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +288 -13
- package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +27 -23
- package/src/sap/fe/core/controllerextensions/InternalRouting.js +82 -46
- package/src/sap/fe/core/controllerextensions/KPIManagement.js +113 -25
- package/src/sap/fe/core/controllerextensions/KPIManagement.ts +135 -44
- package/src/sap/fe/core/controllerextensions/MassEdit.js +172 -0
- package/src/sap/fe/core/controllerextensions/MessageHandler.js +22 -9
- package/src/sap/fe/core/controllerextensions/PageReady.js +3 -3
- package/src/sap/fe/core/controllerextensions/PageReady.ts +12 -8
- package/src/sap/fe/core/controllerextensions/Paginator.js +37 -9
- package/src/sap/fe/core/controllerextensions/Placeholder.js +8 -4
- package/src/sap/fe/core/controllerextensions/Routing.js +25 -5
- package/src/sap/fe/core/controllerextensions/RoutingListener.js +3 -2
- package/src/sap/fe/core/controllerextensions/Share.js +22 -8
- package/src/sap/fe/core/controllerextensions/SideEffects.js +9 -9
- package/src/sap/fe/core/controllerextensions/SideEffects.ts +22 -21
- package/src/sap/fe/core/controllerextensions/ViewState.js +3 -2
- package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +2 -1
- package/src/sap/fe/core/controls/CommandExecution.js +3 -2
- package/src/sap/fe/core/controls/ConditionalWrapper.js +3 -2
- package/src/sap/fe/core/controls/CustomQuickViewPage.js +3 -2
- package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +9 -5
- package/src/sap/fe/core/controls/FieldWrapper.js +18 -23
- package/src/sap/fe/core/controls/FilterBar.js +3 -2
- package/src/sap/fe/core/controls/FormElementWrapper.js +3 -7
- package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +3 -2
- package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +2 -1
- package/src/sap/fe/core/controls/filterbar/FilterContainer.js +3 -2
- package/src/sap/fe/core/controls/filterbar/VisualFilter.js +5 -4
- package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +3 -2
- package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +3 -2
- package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
- package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +79 -0
- package/src/sap/fe/core/converters/ConverterContext.js +14 -2
- package/src/sap/fe/core/converters/ConverterContext.ts +14 -3
- package/src/sap/fe/core/converters/ManifestSettings.js +1 -1
- package/src/sap/fe/core/converters/ManifestSettings.ts +4 -0
- package/src/sap/fe/core/converters/ManifestWrapper.js +56 -32
- package/src/sap/fe/core/converters/ManifestWrapper.ts +24 -6
- package/src/sap/fe/core/converters/MetaModelConverter.js +67 -6
- package/src/sap/fe/core/converters/MetaModelConverter.ts +70 -14
- package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
- package/src/sap/fe/core/converters/TemplateConverter.ts +2 -2
- package/src/sap/fe/core/converters/annotations/DataField.js +3 -3
- package/src/sap/fe/core/converters/annotations/DataField.ts +1 -1
- package/src/sap/fe/core/converters/common/AnnotationConverter.js +33 -21
- package/src/sap/fe/core/converters/controls/Common/Action.js +11 -2
- package/src/sap/fe/core/converters/controls/Common/Action.ts +8 -2
- package/src/sap/fe/core/converters/controls/Common/Chart.js +5 -3
- package/src/sap/fe/core/converters/controls/Common/Chart.ts +11 -3
- package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +3 -3
- package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +2 -2
- package/src/sap/fe/core/converters/controls/Common/Form.js +20 -10
- package/src/sap/fe/core/converters/controls/Common/Form.ts +24 -4
- package/src/sap/fe/core/converters/controls/Common/KPI.js +69 -4
- package/src/sap/fe/core/converters/controls/Common/KPI.ts +72 -0
- package/src/sap/fe/core/converters/controls/Common/Table.js +390 -398
- package/src/sap/fe/core/converters/controls/Common/Table.ts +497 -484
- package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +527 -0
- package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +655 -0
- package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +489 -37
- package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +506 -58
- package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
- package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
- package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +17 -9
- package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +24 -9
- package/src/sap/fe/core/converters/helpers/Aggregation.js +18 -3
- package/src/sap/fe/core/converters/helpers/Aggregation.ts +28 -5
- package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -1
- package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -0
- package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +4 -4
- package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +3 -3
- package/src/sap/fe/core/converters/templates/ListReportConverter.js +13 -6
- package/src/sap/fe/core/converters/templates/ListReportConverter.ts +26 -15
- package/src/sap/fe/core/designtime/AppComponent.designtime.js +11 -2
- package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
- package/src/sap/fe/core/formatters/CriticalityFormatter.ts +1 -1
- package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
- package/src/sap/fe/core/formatters/FPMFormatter.ts +4 -10
- package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
- package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -1
- package/src/sap/fe/core/formatters/TableFormatter.js +39 -28
- package/src/sap/fe/core/formatters/TableFormatter.ts +43 -28
- package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
- package/src/sap/fe/core/formatters/ValueFormatter.ts +30 -7
- package/src/sap/fe/core/fpm/Component.js +3 -2
- package/src/sap/fe/core/helpers/AppStartupHelper.js +359 -0
- package/src/sap/fe/core/helpers/AppStartupHelper.ts +391 -0
- package/src/sap/fe/core/helpers/BindingExpression.js +484 -437
- package/src/sap/fe/core/helpers/BindingExpression.ts +480 -463
- package/src/sap/fe/core/helpers/ClassSupport.js +27 -15
- package/src/sap/fe/core/helpers/ClassSupport.ts +31 -20
- package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +63 -59
- package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +56 -0
- package/src/sap/fe/core/helpers/EditState.js +81 -84
- package/src/sap/fe/core/helpers/EditState.ts +81 -0
- package/src/sap/fe/core/helpers/ExcelFormatHelper.js +62 -48
- package/src/sap/fe/core/helpers/ExcelFormatHelper.ts +49 -0
- package/src/sap/fe/core/helpers/FPMHelper.js +52 -56
- package/src/sap/fe/core/helpers/FPMHelper.ts +62 -0
- package/src/sap/fe/core/helpers/KeepAliveHelper.js +4 -5
- package/src/sap/fe/core/helpers/KeepAliveHelper.ts +10 -10
- package/src/sap/fe/core/helpers/MassEditHelper.js +687 -0
- package/src/sap/fe/core/helpers/ModelHelper.js +229 -225
- package/src/sap/fe/core/helpers/ModelHelper.ts +227 -0
- package/src/sap/fe/core/helpers/PasteHelper.js +210 -132
- package/src/sap/fe/core/helpers/PasteHelper.ts +196 -0
- package/src/sap/fe/core/helpers/SemanticDateOperators.js +332 -313
- package/src/sap/fe/core/helpers/SemanticDateOperators.ts +330 -0
- package/src/sap/fe/core/helpers/SemanticKeyHelper.js +66 -67
- package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +73 -0
- package/src/sap/fe/core/helpers/StableIdHelper.js +4 -7
- package/src/sap/fe/core/helpers/StableIdHelper.ts +2 -6
- package/src/sap/fe/core/jsx-runtime/jsx.js +1 -1
- package/src/sap/fe/core/jsx-runtime/jsx.ts +1 -1
- package/src/sap/fe/core/library.js +30 -3
- package/src/sap/fe/core/library.support.js +12 -5
- package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +62 -0
- package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +66 -0
- package/src/sap/fe/core/messagebundle.properties +61 -13
- package/src/sap/fe/core/messagebundle_ar.properties +33 -2
- package/src/sap/fe/core/messagebundle_bg.properties +33 -2
- package/src/sap/fe/core/messagebundle_ca.properties +33 -2
- package/src/sap/fe/core/messagebundle_cs.properties +34 -3
- package/src/sap/fe/core/messagebundle_cy.properties +33 -2
- package/src/sap/fe/core/messagebundle_da.properties +33 -2
- package/src/sap/fe/core/messagebundle_de.properties +33 -2
- package/src/sap/fe/core/messagebundle_el.properties +33 -2
- package/src/sap/fe/core/messagebundle_en.properties +32 -1
- package/src/sap/fe/core/messagebundle_en_GB.properties +32 -1
- package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +36 -1
- package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +33 -2
- package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +33 -2
- package/src/sap/fe/core/messagebundle_es.properties +33 -2
- package/src/sap/fe/core/messagebundle_es_MX.properties +33 -2
- package/src/sap/fe/core/messagebundle_et.properties +33 -2
- package/src/sap/fe/core/messagebundle_fi.properties +34 -3
- package/src/sap/fe/core/messagebundle_fr.properties +38 -7
- package/src/sap/fe/core/messagebundle_fr_CA.properties +33 -2
- package/src/sap/fe/core/messagebundle_hi.properties +33 -2
- package/src/sap/fe/core/messagebundle_hr.properties +33 -2
- package/src/sap/fe/core/messagebundle_hu.properties +34 -3
- package/src/sap/fe/core/messagebundle_id.properties +36 -5
- package/src/sap/fe/core/messagebundle_it.properties +33 -2
- package/src/sap/fe/core/messagebundle_iw.properties +33 -2
- package/src/sap/fe/core/messagebundle_ja.properties +33 -2
- package/src/sap/fe/core/messagebundle_kk.properties +33 -2
- package/src/sap/fe/core/messagebundle_ko.properties +33 -2
- package/src/sap/fe/core/messagebundle_lt.properties +33 -2
- package/src/sap/fe/core/messagebundle_lv.properties +33 -2
- package/src/sap/fe/core/messagebundle_ms.properties +33 -2
- package/src/sap/fe/core/messagebundle_nl.properties +33 -2
- package/src/sap/fe/core/messagebundle_no.properties +33 -2
- package/src/sap/fe/core/messagebundle_pl.properties +33 -2
- package/src/sap/fe/core/messagebundle_pt.properties +34 -3
- package/src/sap/fe/core/messagebundle_pt_PT.properties +33 -2
- package/src/sap/fe/core/messagebundle_ro.properties +33 -2
- package/src/sap/fe/core/messagebundle_ru.properties +33 -2
- package/src/sap/fe/core/messagebundle_sh.properties +33 -2
- package/src/sap/fe/core/messagebundle_sk.properties +33 -2
- package/src/sap/fe/core/messagebundle_sl.properties +33 -2
- package/src/sap/fe/core/messagebundle_sv.properties +34 -3
- package/src/sap/fe/core/messagebundle_th.properties +33 -2
- package/src/sap/fe/core/messagebundle_tr.properties +33 -2
- package/src/sap/fe/core/messagebundle_uk.properties +33 -2
- package/src/sap/fe/core/messagebundle_vi.properties +33 -2
- package/src/sap/fe/core/messagebundle_zh_CN.properties +33 -2
- package/src/sap/fe/core/messagebundle_zh_TW.properties +33 -2
- package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +2 -2
- package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -1
- package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +269 -202
- package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +212 -0
- package/src/sap/fe/core/services/EnvironmentServiceFactory.js +4 -3
- package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +9 -5
- package/src/sap/fe/core/services/NavigationServiceFactory.js +406 -300
- package/src/sap/fe/core/services/NavigationServiceFactory.ts +316 -0
- package/src/sap/fe/core/services/ResourceModelServiceFactory.js +149 -81
- package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +80 -0
- package/src/sap/fe/core/services/RoutingServiceFactory.js +987 -1152
- package/src/sap/fe/core/services/RoutingServiceFactory.ts +898 -0
- package/src/sap/fe/core/services/ShellServicesFactory.js +31 -2
- package/src/sap/fe/core/services/ShellServicesFactory.ts +45 -11
- package/src/sap/fe/core/services/SideEffectsServiceFactory.js +42 -85
- package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +57 -100
- package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +461 -478
- package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +453 -0
- package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +10 -8
- package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +8 -0
- package/src/sap/fe/core/support/AnnotationIssue.support.js +15 -3
- package/src/sap/fe/core/support/AnnotationIssue.support.ts +16 -2
- package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -2
- package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.ts +1 -1
- package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
- package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
- package/src/sap/fe/core/templating/DataModelPathHelper.js +10 -48
- package/src/sap/fe/core/templating/DataModelPathHelper.ts +14 -46
- package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
- package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
- package/src/sap/fe/core/templating/FieldControlHelper.js +8 -8
- package/src/sap/fe/core/templating/FieldControlHelper.ts +25 -7
- package/src/sap/fe/core/templating/FilterHelper.js +139 -70
- package/src/sap/fe/core/templating/FilterHelper.ts +140 -70
- package/src/sap/fe/core/templating/PropertyHelper.js +2 -2
- package/src/sap/fe/core/templating/PropertyHelper.ts +1 -1
- package/src/sap/fe/core/templating/UIFormatters.js +45 -110
- package/src/sap/fe/core/templating/UIFormatters.ts +39 -75
- package/src/sap/fe/core/type/Email.js +1 -1
- package/src/sap/fe/core/type/Email.ts +4 -6
- package/ui5.yaml +0 -3
- package/src/sap/fe/core/controls/filterbar.d.js +0 -8
- package/src/sap/fe/core/controls/filterbar.d.ts +0 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* SAP UI development toolkit for HTML5 (SAPUI5)
|
|
3
|
+
* (c) Copyright 2009-2021 SAP SE. All rights reserved
|
|
4
|
+
*/
|
|
5
|
+
sap.ui.define(["sap/ui/model/Filter", "sap/ui/model/FilterOperator", "./ModelHelper"], function (Filter, FilterOperator, ModelHelper) {
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Retrieves a set of key values from startup parameters.
|
|
10
|
+
*
|
|
11
|
+
* @param aKeyNames The array of key names
|
|
12
|
+
* @param oStartupParameters The startup parameters
|
|
13
|
+
* @returns An array of pairs {name, value} if all key values could be found in the startup parameters, undefined otherwise
|
|
14
|
+
*/
|
|
15
|
+
function _getKeysFromStartupParams(aKeyNames, oStartupParameters) {
|
|
16
|
+
var bAllFound = true;
|
|
17
|
+
var aKeys = aKeyNames.map(function (name) {
|
|
18
|
+
if (oStartupParameters[name] && oStartupParameters[name].length === 1) {
|
|
19
|
+
return {
|
|
20
|
+
name: name,
|
|
21
|
+
value: oStartupParameters[name][0]
|
|
22
|
+
};
|
|
23
|
+
} else {
|
|
24
|
+
// A unique key value couldn't be found in the startup parameters
|
|
25
|
+
bAllFound = false;
|
|
26
|
+
return {
|
|
27
|
+
name: name,
|
|
28
|
+
value: ""
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return bAllFound ? aKeys : undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a filter from a list of key values.
|
|
36
|
+
*
|
|
37
|
+
* @param aKeys Array of semantic keys or technical keys (with values)
|
|
38
|
+
* @param bDraftMode True if the entity supports draft mode
|
|
39
|
+
* @param oMetaModel The metamodel
|
|
40
|
+
* @returns The filter
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
function _createFilterFromKeys(aKeys, bDraftMode, oMetaModel) {
|
|
45
|
+
var bFilterCaseSensitive = ModelHelper.isFilteringCaseSensitive(oMetaModel);
|
|
46
|
+
var bFilterOnActiveEntity = false;
|
|
47
|
+
var aFilters = aKeys.map(function (key) {
|
|
48
|
+
if (key.name === "IsActiveEntity") {
|
|
49
|
+
bFilterOnActiveEntity = true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return new Filter({
|
|
53
|
+
path: key.name,
|
|
54
|
+
operator: FilterOperator.EQ,
|
|
55
|
+
value1: key.value,
|
|
56
|
+
caseSensitive: bFilterCaseSensitive
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (bDraftMode && !bFilterOnActiveEntity) {
|
|
61
|
+
var oDraftFilter = new Filter({
|
|
62
|
+
filters: [new Filter("IsActiveEntity", "EQ", false), new Filter("SiblingEntity/IsActiveEntity", "EQ", null)],
|
|
63
|
+
and: false
|
|
64
|
+
});
|
|
65
|
+
aFilters.push(oDraftFilter);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return new Filter(aFilters, true);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Loads all contexts for a list of page infos.
|
|
72
|
+
*
|
|
73
|
+
* @param aStartupPages The list of page infos
|
|
74
|
+
* @param oModel The model used to load the contexts
|
|
75
|
+
* @returns A Promise for all contexts
|
|
76
|
+
*/
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
function _requestObjectsFromParameters(aStartupPages, oModel) {
|
|
80
|
+
// Load the respective objects for all object pages found in aExternallyNavigablePages
|
|
81
|
+
var aContextPromises = aStartupPages.map(function (pageInfo) {
|
|
82
|
+
var aKeys = pageInfo.semanticKeys || pageInfo.technicalKeys || [];
|
|
83
|
+
|
|
84
|
+
var oFilter = _createFilterFromKeys(aKeys, pageInfo.draftMode, oModel.getMetaModel()); // only request a minimum of fields to boost backend performance since this is only used to check if an object exists
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
var oListBind = oModel.bindList(pageInfo.contextPath, undefined, undefined, oFilter, {
|
|
88
|
+
"$select": aKeys.map(function (key) {
|
|
89
|
+
return key.name;
|
|
90
|
+
}).join(",")
|
|
91
|
+
});
|
|
92
|
+
return oListBind.requestContexts(0, 2);
|
|
93
|
+
});
|
|
94
|
+
return Promise.all(aContextPromises);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Returns the list of all pages that allow deeplink and that can be reached using the startup parameters.
|
|
98
|
+
*
|
|
99
|
+
* @param oManifestRouting The routing information from the app manifest
|
|
100
|
+
* @param oStartupParameters The startup parameters
|
|
101
|
+
* @param oMetaModel The metamodel
|
|
102
|
+
* @returns
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
function _getReachablePages(oManifestRouting, oStartupParameters, oMetaModel) {
|
|
107
|
+
var aRoutes = oManifestRouting.routes;
|
|
108
|
+
var mPagesByLevel = {};
|
|
109
|
+
aRoutes.forEach(function (oRoute) {
|
|
110
|
+
var sPattern = oRoute.pattern.replace(":?query:", "");
|
|
111
|
+
|
|
112
|
+
if (sPattern.endsWith("/")) {
|
|
113
|
+
sPattern = sPattern.substr(0, sPattern.length - 1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (sPattern) {
|
|
117
|
+
var _oTarget$options, _oTarget$options$sett;
|
|
118
|
+
|
|
119
|
+
// Ignore level-0 routes (ListReport)
|
|
120
|
+
sPattern = sPattern.replace(/\(\{[^\}]*\}\)/g, "(#)"); // Replace keys with #
|
|
121
|
+
// Get the rightmost target for this route
|
|
122
|
+
|
|
123
|
+
var sTargetName = Array.isArray(oRoute.target) ? oRoute.target[oRoute.target.length - 1] : oRoute.target;
|
|
124
|
+
var oTarget = oManifestRouting.targets[sTargetName];
|
|
125
|
+
var aPatternSegments = sPattern.split("/");
|
|
126
|
+
var pageLevel = aPatternSegments.length - 1; // The first level of object page allows deep linking by default.
|
|
127
|
+
// Otherwise, the target must allow deep linking explicitely in the manifest
|
|
128
|
+
|
|
129
|
+
if (pageLevel === 0 || oTarget !== null && oTarget !== void 0 && (_oTarget$options = oTarget.options) !== null && _oTarget$options !== void 0 && (_oTarget$options$sett = _oTarget$options.settings) !== null && _oTarget$options$sett !== void 0 && _oTarget$options$sett.allowDeepLinking) {
|
|
130
|
+
var sContextPath = oTarget.options.settings.contextPath || oTarget.options.settings.entitySet && "/" + oTarget.options.settings.entitySet;
|
|
131
|
+
var oEntityType = sContextPath && oMetaModel.getObject("/$EntityContainer" + sContextPath + "/");
|
|
132
|
+
|
|
133
|
+
if (oEntityType) {
|
|
134
|
+
// Get the semantic key values for the entity
|
|
135
|
+
var aSemanticKeyNames = oMetaModel.getObject("/$EntityContainer" + sContextPath + "/@com.sap.vocabularies.Common.v1.SemanticKey");
|
|
136
|
+
var aSemantickKeys = aSemanticKeyNames ? _getKeysFromStartupParams(aSemanticKeyNames.map(function (semKey) {
|
|
137
|
+
return semKey.$PropertyPath;
|
|
138
|
+
}), oStartupParameters) : undefined; // Get the technical keys only if we couldn't find the semantic key values, and on first level OP
|
|
139
|
+
|
|
140
|
+
var aTechnicalKeys = !aSemantickKeys && pageLevel === 0 ? _getKeysFromStartupParams(oEntityType["$Key"], oStartupParameters) : undefined;
|
|
141
|
+
|
|
142
|
+
if (aSemantickKeys || aTechnicalKeys) {
|
|
143
|
+
// The startup parameters contain values for all semantic keys (or technical keys) --> we can store the page info in the corresponding level
|
|
144
|
+
var draftMode = oMetaModel.getObject("/$EntityContainer" + sContextPath + "@com.sap.vocabularies.Common.v1.DraftRoot") || oMetaModel.getObject("/$EntityContainer" + sContextPath + "@com.sap.vocabularies.Common.v1.DraftNode") ? true : false;
|
|
145
|
+
|
|
146
|
+
if (!mPagesByLevel[pageLevel]) {
|
|
147
|
+
mPagesByLevel[pageLevel] = [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
mPagesByLevel[pageLevel].push({
|
|
151
|
+
pattern: sPattern,
|
|
152
|
+
contextPath: sContextPath,
|
|
153
|
+
draftMode: draftMode,
|
|
154
|
+
technicalKeys: aTechnicalKeys,
|
|
155
|
+
semanticKeys: aSemantickKeys,
|
|
156
|
+
target: sTargetName
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}); // A page is reachable only if all its parents are also reachable
|
|
163
|
+
// So if we couldn't find any pages for a given level, all pages with a higher level won't be reachable anyway
|
|
164
|
+
|
|
165
|
+
var aReachablePages = [];
|
|
166
|
+
var level = 0;
|
|
167
|
+
|
|
168
|
+
while (mPagesByLevel[level]) {
|
|
169
|
+
aReachablePages.push(mPagesByLevel[level]);
|
|
170
|
+
level++;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return aReachablePages;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get the list of startup pages.
|
|
177
|
+
*
|
|
178
|
+
* @param oManifestRouting The routing information from the app manifest
|
|
179
|
+
* @param oStartupParameters The startup parameters
|
|
180
|
+
* @param oMetaModel The metamodel
|
|
181
|
+
* @returns An array of startup page infos
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
function _getStartupPagesFromStartupParams(oManifestRouting, oStartupParameters, oMetaModel) {
|
|
186
|
+
// Find all pages that can be reached with the startup parameters
|
|
187
|
+
var aReachablePages = _getReachablePages(oManifestRouting, oStartupParameters, oMetaModel);
|
|
188
|
+
|
|
189
|
+
if (aReachablePages.length === 0) {
|
|
190
|
+
return [];
|
|
191
|
+
} // Find the longest sequence of pages that can be reached (recursively)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
var result = [];
|
|
195
|
+
var current = [];
|
|
196
|
+
|
|
197
|
+
function findRecursive(level) {
|
|
198
|
+
var aCurrentLevelPages = aReachablePages[level];
|
|
199
|
+
var lastPage = current.length ? current[current.length - 1] : undefined;
|
|
200
|
+
|
|
201
|
+
if (aCurrentLevelPages) {
|
|
202
|
+
aCurrentLevelPages.forEach(function (nextPage) {
|
|
203
|
+
if (!lastPage || nextPage.pattern.indexOf(lastPage.pattern) === 0) {
|
|
204
|
+
// We only consider pages that can be reached from the page at the previous level,
|
|
205
|
+
// --> their pattern must be the pattern of the previous page with another segment appended
|
|
206
|
+
current.push(nextPage);
|
|
207
|
+
findRecursive(level + 1);
|
|
208
|
+
current.pop();
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (current.length > result.length) {
|
|
214
|
+
result = current.slice(); // We have found a sequence longer than our previous best --> store it as the new longest
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
findRecursive(0);
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Creates the startup object from the list of pages and contexts.
|
|
223
|
+
*
|
|
224
|
+
* @param aStartupPages The pages
|
|
225
|
+
* @param aContexts The contexts
|
|
226
|
+
* @returns An object containing either a hash or a context to navigate to, or an empty object if no deep link was found
|
|
227
|
+
*/
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
function _getDeepLinkObject(aStartupPages, aContexts) {
|
|
231
|
+
if (aContexts.length === 1) {
|
|
232
|
+
return {
|
|
233
|
+
context: aContexts[0]
|
|
234
|
+
};
|
|
235
|
+
} else if (aContexts.length > 1) {
|
|
236
|
+
// Navigation to a deeper level --> use the pattern of the deepest object page
|
|
237
|
+
// and replace the parameters by the ID from the contexts
|
|
238
|
+
var hash = aStartupPages[aStartupPages.length - 1].pattern;
|
|
239
|
+
aContexts.forEach(function (oContext) {
|
|
240
|
+
hash = hash.replace("(#)", "(" + oContext.getPath().split("(")[1]);
|
|
241
|
+
});
|
|
242
|
+
return {
|
|
243
|
+
hash: hash
|
|
244
|
+
};
|
|
245
|
+
} else {
|
|
246
|
+
return {};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Calculates startup parameters for a deeplink case, from startup parameters and routing infoirmation.
|
|
251
|
+
*
|
|
252
|
+
* @param oManifestRouting The routing information from the app manifest
|
|
253
|
+
* @param oStartupParameters The startup parameters
|
|
254
|
+
* @param oModel The OData model
|
|
255
|
+
* @returns An object containing either a hash or a context to navigate to, or an empty object if no deep link was found
|
|
256
|
+
*/
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
function getDeepLinkStartupHash(oManifestRouting, oStartupParameters, oModel) {
|
|
260
|
+
var aStartupPages;
|
|
261
|
+
return oModel.getMetaModel().requestObject("/$EntityContainer/").then(function () {
|
|
262
|
+
// Check if semantic keys are present in url parameters for every object page at each level
|
|
263
|
+
aStartupPages = _getStartupPagesFromStartupParams(oManifestRouting, oStartupParameters, oModel.getMetaModel());
|
|
264
|
+
return _requestObjectsFromParameters(aStartupPages, oModel);
|
|
265
|
+
}).then(function (aValues) {
|
|
266
|
+
if (aValues.length) {
|
|
267
|
+
// Make sure we only get 1 context per promise, and flatten the array
|
|
268
|
+
var aContexts = [];
|
|
269
|
+
aValues.forEach(function (aFoundContexts) {
|
|
270
|
+
if (aFoundContexts.length === 1) {
|
|
271
|
+
aContexts.push(aFoundContexts[0]);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
return aContexts.length === aValues.length ? _getDeepLinkObject(aStartupPages, aContexts) : {};
|
|
275
|
+
} else {
|
|
276
|
+
return {};
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Calculates the new hash based on the startup parameters.
|
|
282
|
+
*
|
|
283
|
+
* @param oStartupParameters The startup parameter values (map parameter name -> array of values)
|
|
284
|
+
* @param sContextPath The context path for the startup of the app (generally the path to the main entity set)
|
|
285
|
+
* @param oRouter The router instance
|
|
286
|
+
* @param oMetaModel The meta model
|
|
287
|
+
* @returns A promise containing the hash to navigate to, or an empty string if there's no need to navigate
|
|
288
|
+
*/
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
function getCreateStartupHash(oStartupParameters, sContextPath, oRouter, oMetaModel) {
|
|
292
|
+
return oMetaModel.requestObject(sContextPath + "@").then(function (oEntitySetAnnotations) {
|
|
293
|
+
var sMetaPath = "";
|
|
294
|
+
var bCreatable = true;
|
|
295
|
+
|
|
296
|
+
if (oEntitySetAnnotations["@com.sap.vocabularies.Common.v1.DraftRoot"] && oEntitySetAnnotations["@com.sap.vocabularies.Common.v1.DraftRoot"]["NewAction"]) {
|
|
297
|
+
sMetaPath = sContextPath + "@com.sap.vocabularies.Common.v1.DraftRoot/NewAction@Org.OData.Core.V1.OperationAvailable";
|
|
298
|
+
} else if (oEntitySetAnnotations["@com.sap.vocabularies.Session.v1.StickySessionSupported"] && oEntitySetAnnotations["@com.sap.vocabularies.Session.v1.StickySessionSupported"]["NewAction"]) {
|
|
299
|
+
sMetaPath = sContextPath + "@com.sap.vocabularies.Session.v1.StickySessionSupported/NewAction@Org.OData.Core.V1.OperationAvailable";
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (sMetaPath) {
|
|
303
|
+
var bNewActionOperationAvailable = oMetaModel.getObject(sMetaPath);
|
|
304
|
+
|
|
305
|
+
if (bNewActionOperationAvailable === false) {
|
|
306
|
+
bCreatable = false;
|
|
307
|
+
}
|
|
308
|
+
} else {
|
|
309
|
+
var oInsertRestrictions = oEntitySetAnnotations["@Org.OData.Capabilities.V1.InsertRestrictions"];
|
|
310
|
+
|
|
311
|
+
if (oInsertRestrictions && oInsertRestrictions.Insertable === false) {
|
|
312
|
+
bCreatable = false;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (bCreatable) {
|
|
317
|
+
return getDefaultCreateHash(oStartupParameters, sContextPath, oRouter);
|
|
318
|
+
} else {
|
|
319
|
+
return "";
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Calculates the hash to create a new object.
|
|
325
|
+
*
|
|
326
|
+
* @param oStartupParameters The startup parameter values (map parameter name -> array of values)
|
|
327
|
+
* @param sContextPath The context path of the entity set to be used for the creation
|
|
328
|
+
* @param oRouter The router instance
|
|
329
|
+
* @returns The hash
|
|
330
|
+
*/
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
function getDefaultCreateHash(oStartupParameters, sContextPath, oRouter) {
|
|
334
|
+
var sDefaultCreateHash = oStartupParameters && oStartupParameters.preferredMode ? oStartupParameters.preferredMode[0] : "create";
|
|
335
|
+
var sHash = "";
|
|
336
|
+
sDefaultCreateHash = sDefaultCreateHash.indexOf(":") !== -1 && sDefaultCreateHash.length > sDefaultCreateHash.indexOf(":") + 1 ? sDefaultCreateHash.substr(0, sDefaultCreateHash.indexOf(":")) : "create";
|
|
337
|
+
sHash = sContextPath.substring(1) + "(...)?i-action=" + sDefaultCreateHash;
|
|
338
|
+
|
|
339
|
+
if (oRouter.getRouteInfoByHash(sHash)) {
|
|
340
|
+
return sHash;
|
|
341
|
+
} else {
|
|
342
|
+
throw new Error("No route match for creating a new " + sContextPath.substring(1));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
var AppStartupHelper = {
|
|
347
|
+
_getKeysFromStartupParams: _getKeysFromStartupParams,
|
|
348
|
+
_createFilterFromKeys: _createFilterFromKeys,
|
|
349
|
+
_requestObjectsFromParameters: _requestObjectsFromParameters,
|
|
350
|
+
_getReachablePages: _getReachablePages,
|
|
351
|
+
_getStartupPagesFromStartupParams: _getStartupPagesFromStartupParams,
|
|
352
|
+
_getDeepLinkObject: _getDeepLinkObject,
|
|
353
|
+
getDeepLinkStartupHash: getDeepLinkStartupHash,
|
|
354
|
+
getCreateStartupHash: getCreateStartupHash,
|
|
355
|
+
getDefaultCreateHash: getDefaultCreateHash
|
|
356
|
+
};
|
|
357
|
+
return AppStartupHelper;
|
|
358
|
+
}, false);
|
|
359
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkFwcFN0YXJ0dXBIZWxwZXIudHMiXSwibmFtZXMiOlsiX2dldEtleXNGcm9tU3RhcnR1cFBhcmFtcyIsImFLZXlOYW1lcyIsIm9TdGFydHVwUGFyYW1ldGVycyIsImJBbGxGb3VuZCIsImFLZXlzIiwibWFwIiwibmFtZSIsImxlbmd0aCIsInZhbHVlIiwidW5kZWZpbmVkIiwiX2NyZWF0ZUZpbHRlckZyb21LZXlzIiwiYkRyYWZ0TW9kZSIsIm9NZXRhTW9kZWwiLCJiRmlsdGVyQ2FzZVNlbnNpdGl2ZSIsIk1vZGVsSGVscGVyIiwiaXNGaWx0ZXJpbmdDYXNlU2Vuc2l0aXZlIiwiYkZpbHRlck9uQWN0aXZlRW50aXR5IiwiYUZpbHRlcnMiLCJrZXkiLCJGaWx0ZXIiLCJwYXRoIiwib3BlcmF0b3IiLCJGaWx0ZXJPcGVyYXRvciIsIkVRIiwidmFsdWUxIiwiY2FzZVNlbnNpdGl2ZSIsIm9EcmFmdEZpbHRlciIsImZpbHRlcnMiLCJhbmQiLCJwdXNoIiwiX3JlcXVlc3RPYmplY3RzRnJvbVBhcmFtZXRlcnMiLCJhU3RhcnR1cFBhZ2VzIiwib01vZGVsIiwiYUNvbnRleHRQcm9taXNlcyIsInBhZ2VJbmZvIiwic2VtYW50aWNLZXlzIiwidGVjaG5pY2FsS2V5cyIsIm9GaWx0ZXIiLCJkcmFmdE1vZGUiLCJnZXRNZXRhTW9kZWwiLCJvTGlzdEJpbmQiLCJiaW5kTGlzdCIsImNvbnRleHRQYXRoIiwiam9pbiIsInJlcXVlc3RDb250ZXh0cyIsIlByb21pc2UiLCJhbGwiLCJfZ2V0UmVhY2hhYmxlUGFnZXMiLCJvTWFuaWZlc3RSb3V0aW5nIiwiYVJvdXRlcyIsInJvdXRlcyIsIm1QYWdlc0J5TGV2ZWwiLCJmb3JFYWNoIiwib1JvdXRlIiwic1BhdHRlcm4iLCJwYXR0ZXJuIiwicmVwbGFjZSIsImVuZHNXaXRoIiwic3Vic3RyIiwic1RhcmdldE5hbWUiLCJBcnJheSIsImlzQXJyYXkiLCJ0YXJnZXQiLCJvVGFyZ2V0IiwidGFyZ2V0cyIsImFQYXR0ZXJuU2VnbWVudHMiLCJzcGxpdCIsInBhZ2VMZXZlbCIsIm9wdGlvbnMiLCJzZXR0aW5ncyIsImFsbG93RGVlcExpbmtpbmciLCJzQ29udGV4dFBhdGgiLCJlbnRpdHlTZXQiLCJvRW50aXR5VHlwZSIsImdldE9iamVjdCIsImFTZW1hbnRpY0tleU5hbWVzIiwiYVNlbWFudGlja0tleXMiLCJzZW1LZXkiLCIkUHJvcGVydHlQYXRoIiwiYVRlY2huaWNhbEtleXMiLCJhUmVhY2hhYmxlUGFnZXMiLCJsZXZlbCIsIl9nZXRTdGFydHVwUGFnZXNGcm9tU3RhcnR1cFBhcmFtcyIsInJlc3VsdCIsImN1cnJlbnQiLCJmaW5kUmVjdXJzaXZlIiwiYUN1cnJlbnRMZXZlbFBhZ2VzIiwibGFzdFBhZ2UiLCJuZXh0UGFnZSIsImluZGV4T2YiLCJwb3AiLCJzbGljZSIsIl9nZXREZWVwTGlua09iamVjdCIsImFDb250ZXh0cyIsImNvbnRleHQiLCJoYXNoIiwib0NvbnRleHQiLCJnZXRQYXRoIiwiZ2V0RGVlcExpbmtTdGFydHVwSGFzaCIsInJlcXVlc3RPYmplY3QiLCJ0aGVuIiwiYVZhbHVlcyIsImFGb3VuZENvbnRleHRzIiwiZ2V0Q3JlYXRlU3RhcnR1cEhhc2giLCJvUm91dGVyIiwib0VudGl0eVNldEFubm90YXRpb25zIiwic01ldGFQYXRoIiwiYkNyZWF0YWJsZSIsImJOZXdBY3Rpb25PcGVyYXRpb25BdmFpbGFibGUiLCJvSW5zZXJ0UmVzdHJpY3Rpb25zIiwiSW5zZXJ0YWJsZSIsImdldERlZmF1bHRDcmVhdGVIYXNoIiwic0RlZmF1bHRDcmVhdGVIYXNoIiwicHJlZmVycmVkTW9kZSIsInNIYXNoIiwic3Vic3RyaW5nIiwiZ2V0Um91dGVJbmZvQnlIYXNoIiwiRXJyb3IiLCJBcHBTdGFydHVwSGVscGVyIl0sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBOzs7O0FBb0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBU0EseUJBQVQsQ0FBbUNDLFNBQW5DLEVBQXdEQyxrQkFBeEQsRUFBMEc7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a0IsRUFBbEJBLGtCQUp3QjtBQUt4Qm1DLElBQUFBLGlDQUFpQyxFQUFqQ0EsaUNBTHdCO0FBTXhCVSxJQUFBQSxrQkFBa0IsRUFBbEJBLGtCQU53QjtBQU94Qk0sSUFBQUEsc0JBQXNCLEVBQXRCQSxzQkFQd0I7QUFReEJLLElBQUFBLG9CQUFvQixFQUFwQkEsb0JBUndCO0FBU3hCUSxJQUFBQSxvQkFBb0IsRUFBcEJBO0FBVHdCLEdBQXpCO1NBWWVPLGdCIiwic291cmNlUm9vdCI6Ii4iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgT0RhdGFNZXRhTW9kZWwgZnJvbSBcInNhcC91aS9tb2RlbC9vZGF0YS92NC9PRGF0YU1ldGFNb2RlbFwiO1xuaW1wb3J0IE9EYXRhTW9kZWwgZnJvbSBcInNhcC91aS9tb2RlbC9vZGF0YS92NC9PRGF0YU1vZGVsXCI7XG5pbXBvcnQgQ29udGV4dCBmcm9tIFwic2FwL3VpL21vZGVsL29kYXRhL3Y0L0NvbnRleHRcIjtcbmltcG9ydCBGaWx0ZXIgZnJvbSBcInNhcC91aS9tb2RlbC9GaWx0ZXJcIjtcbmltcG9ydCBGaWx0ZXJPcGVyYXRvciBmcm9tIFwic2FwL3VpL21vZGVsL0ZpbHRlck9wZXJhdG9yXCI7XG5pbXBvcnQgUm91dGVyIGZyb20gXCJzYXAvdWkvY29yZS9yb3V0aW5nL1JvdXRlclwiO1xuaW1wb3J0IE1vZGVsSGVscGVyIGZyb20gXCIuL01vZGVsSGVscGVyXCI7XG5cbnR5cGUgVmFsdWVkS2V5ID0ge1xuXHRuYW1lOiBzdHJpbmc7XG5cdHZhbHVlOiBzdHJpbmc7XG59O1xuXG50eXBlIFBhZ2VJbmZvID0ge1xuXHRwYXR0ZXJuOiBzdHJpbmc7XG5cdGNvbnRleHRQYXRoOiBzdHJpbmc7XG5cdGRyYWZ0TW9kZTogQm9vbGVhbjtcblx0dGVjaG5pY2FsS2V5czogVmFsdWVkS2V5W10gfCB1bmRlZmluZWQ7XG5cdHNlbWFudGljS2V5czogVmFsdWVkS2V5W10gfCB1bmRlZmluZWQ7XG5cdHRhcmdldDogc3RyaW5nO1xufTtcblxuLyoqXG4gKiBSZXRyaWV2ZXMgYSBzZXQgb2Yga2V5IHZhbHVlcyBmcm9tIHN0YXJ0dXAgcGFyYW1ldGVycy5cbiAqXG4gKiBAcGFyYW0gYUtleU5hbWVzIFRoZSBhcnJheSBvZiBrZXkgbmFtZXNcbiAqIEBwYXJhbSBvU3RhcnR1cFBhcmFtZXRlcnMgVGhlIHN0YXJ0dXAgcGFyYW1ldGVyc1xuICogQHJldHVybnMgQW4gYXJyYXkgb2YgcGFpcnMge25hbWUsIHZhbHVlfSBpZiBhbGwga2V5IHZhbHVlcyBjb3VsZCBiZSBmb3VuZCBpbiB0aGUgc3RhcnR1cCBwYXJhbWV0ZXJzLCB1bmRlZmluZWQgb3RoZXJ3aXNlXG4gKi9cbmZ1bmN0aW9uIF9nZXRLZXlzRnJvbVN0YXJ0dXBQYXJhbXMoYUtleU5hbWVzOiBzdHJpbmdbXSwgb1N0YXJ0dXBQYXJhbWV0ZXJzOiBhbnkpOiBWYWx1ZWRLZXlbXSB8IHVuZGVmaW5lZCB7XG5cdGxldCBiQWxsRm91bmQgPSB0cnVlO1xuXHRjb25zdCBhS2V5cyA9IGFLZXlOYW1lcy5tYXAobmFtZSA9PiB7XG5cdFx0aWYgKG9TdGFydHVwUGFyYW1ldGVyc1tuYW1lXSAmJiBvU3RhcnR1cFBhcmFtZXRlcnNbbmFtZV0ubGVuZ3RoID09PSAxKSB7XG5cdFx0XHRyZXR1cm4geyBuYW1lLCB2YWx1ZTogb1N0YXJ0dXBQYXJhbWV0ZXJzW25hbWVdWzBdIGFzIHN0cmluZyB9O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBBIHVuaXF1ZSBrZXkgdmFsdWUgY291bGRuJ3QgYmUgZm91bmQgaW4gdGhlIHN0YXJ0dXAgcGFyYW1ldGVyc1xuXHRcdFx0YkFsbEZvdW5kID0gZmFsc2U7XG5cdFx0XHRyZXR1cm4geyBuYW1lLCB2YWx1ZTogXCJcIiB9O1xuXHRcdH1cblx0fSk7XG5cblx0cmV0dXJuIGJBbGxGb3VuZCA/IGFLZXlzIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBmaWx0ZXIgZnJvbSBhIGxpc3Qgb2Yga2V5IHZhbHVlcy5cbiAqXG4gKiBAcGFyYW0gYUtleXMgQXJyYXkgb2Ygc2VtYW50aWMga2V5cyBvciB0ZWNobmljYWwga2V5cyAod2l0aCB2YWx1ZXMpXG4gKiBAcGFyYW0gYkRyYWZ0TW9kZSBUcnVlIGlmIHRoZSBlbnRpdHkgc3VwcG9ydHMgZHJhZnQgbW9kZVxuICogQHBhcmFtIG9NZXRhTW9kZWwgVGhlIG1ldGFtb2RlbFxuICogQHJldHVybnMgVGhlIGZpbHRlclxuICovXG5mdW5jdGlvbiBfY3JlYXRlRmlsdGVyRnJvbUtleXMoYUtleXM6IFZhbHVlZEtleVtdLCBiRHJhZnRNb2RlOiBCb29sZWFuLCBvTWV0YU1vZGVsOiBPRGF0YU1ldGFNb2RlbCk6IEZpbHRlciB7XG5cdGNvbnN0IGJGaWx0ZXJDYXNlU2Vuc2l0aXZlID0gTW9kZWxIZWxwZXIuaXNGaWx0ZXJpbmdDYXNlU2Vuc2l0aXZlKG9NZXRhTW9kZWwpO1xuXG5cdGxldCBiRmlsdGVyT25BY3RpdmVFbnRpdHkgPSBmYWxzZTtcblx0Y29uc3QgYUZpbHRlcnMgPSBhS2V5cy5tYXAoa2V5ID0+IHtcblx0XHRpZiAoa2V5Lm5hbWUgPT09IFwiSXNBY3RpdmVFbnRpdHlcIikge1xuXHRcdFx0YkZpbHRlck9uQWN0aXZlRW50aXR5ID0gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIG5ldyBGaWx0ZXIoe1xuXHRcdFx0cGF0aDoga2V5Lm5hbWUsXG5cdFx0XHRvcGVyYXRvcjogRmlsdGVyT3BlcmF0b3IuRVEsXG5cdFx0XHR2YWx1ZTE6IGtleS52YWx1ZSxcblx0XHRcdGNhc2VTZW5zaXRpdmU6IGJGaWx0ZXJDYXNlU2Vuc2l0aXZlXG5cdFx0fSk7XG5cdH0pO1xuXHRpZiAoYkRyYWZ0TW9kZSAmJiAhYkZpbHRlck9uQWN0aXZlRW50aXR5KSB7XG5cdFx0Y29uc3Qgb0RyYWZ0RmlsdGVyID0gbmV3IEZpbHRlcih7XG5cdFx0XHRmaWx0ZXJzOiBbbmV3IEZpbHRlcihcIklzQWN0aXZlRW50aXR5XCIsIFwiRVFcIiwgZmFsc2UpLCBuZXcgRmlsdGVyKFwiU2libGluZ0VudGl0eS9Jc0FjdGl2ZUVudGl0eVwiLCBcIkVRXCIsIG51bGwpXSxcblx0XHRcdGFuZDogZmFsc2Vcblx0XHR9KTtcblx0XHRhRmlsdGVycy5wdXNoKG9EcmFmdEZpbHRlcik7XG5cdH1cblxuXHRyZXR1cm4gbmV3IEZpbHRlcihhRmlsdGVycywgdHJ1ZSk7XG59XG5cbi8qKlxuICogTG9hZHMgYWxsIGNvbnRleHRzIGZvciBhIGxpc3Qgb2YgcGFnZSBpbmZvcy5cbiAqXG4gKiBAcGFyYW0gYVN0YXJ0dXBQYWdlcyBUaGUgbGlzdCBvZiBwYWdlIGluZm9zXG4gKiBAcGFyYW0gb01vZGVsIFRoZSBtb2RlbCB1c2VkIHRvIGxvYWQgdGhlIGNvbnRleHRzXG4gKiBAcmV0dXJucyBBIFByb21pc2UgZm9yIGFsbCBjb250ZXh0c1xuICovXG5mdW5jdGlvbiBfcmVxdWVzdE9iamVjdHNGcm9tUGFyYW1ldGVycyhhU3RhcnR1cFBhZ2VzOiBQYWdlSW5mb1tdLCBvTW9kZWw6IE9EYXRhTW9kZWwpOiBQcm9taXNlPENvbnRleHRbXVtdPiB7XG5cdC8vIExvYWQgdGhlIHJlc3BlY3RpdmUgb2JqZWN0cyBmb3IgYWxsIG9iamVjdCBwYWdlcyBmb3VuZCBpbiBhRXh0ZXJuYWxseU5hdmlnYWJsZVBhZ2VzXG5cdGNvbnN0IGFDb250ZXh0UHJvbWlzZXMgPSBhU3RhcnR1cFBhZ2VzLm1hcChwYWdlSW5mbyA9PiB7XG5cdFx0Y29uc3QgYUtleXMgPSBwYWdlSW5mby5zZW1hbnRpY0tleXMgfHwgcGFnZUluZm8udGVjaG5pY2FsS2V5cyB8fCBbXTtcblx0XHRjb25zdCBvRmlsdGVyID0gX2NyZWF0ZUZpbHRlckZyb21LZXlzKGFLZXlzLCBwYWdlSW5mby5kcmFmdE1vZGUsIG9Nb2RlbC5nZXRNZXRhTW9kZWwoKSk7XG5cblx0XHQvLyBvbmx5IHJlcXVlc3QgYSBtaW5pbXVtIG9mIGZpZWxkcyB0byBib29zdCBiYWNrZW5kIHBlcmZvcm1hbmNlIHNpbmNlIHRoaXMgaXMgb25seSB1c2VkIHRvIGNoZWNrIGlmIGFuIG9iamVjdCBleGlzdHNcblx0XHRjb25zdCBvTGlzdEJpbmQgPSBvTW9kZWwuYmluZExpc3QocGFnZUluZm8uY29udGV4dFBhdGgsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBvRmlsdGVyLCB7XG5cdFx0XHRcIiRzZWxlY3RcIjogYUtleXNcblx0XHRcdFx0Lm1hcChrZXkgPT4ge1xuXHRcdFx0XHRcdHJldHVybiBrZXkubmFtZTtcblx0XHRcdFx0fSlcblx0XHRcdFx0LmpvaW4oXCIsXCIpXG5cdFx0fSBhcyBhbnkpO1xuXHRcdHJldHVybiBvTGlzdEJpbmQucmVxdWVzdENvbnRleHRzKDAsIDIpO1xuXHR9KTtcblxuXHRyZXR1cm4gUHJvbWlzZS5hbGwoYUNvbnRleHRQcm9taXNlcyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbGlzdCBvZiBhbGwgcGFnZXMgdGhhdCBhbGxvdyBkZWVwbGluayBhbmQgdGhhdCBjYW4gYmUgcmVhY2hlZCB1c2luZyB0aGUgc3RhcnR1cCBwYXJhbWV0ZXJzLlxuICpcbiAqIEBwYXJhbSBvTWFuaWZlc3RSb3V0aW5nIFRoZSByb3V0aW5nIGluZm9ybWF0aW9uIGZyb20gdGhlIGFwcCBtYW5pZmVzdFxuICogQHBhcmFtIG9TdGFydHVwUGFyYW1ldGVycyBUaGUgc3RhcnR1cCBwYXJhbWV0ZXJzXG4gKiBAcGFyYW0gb01ldGFNb2RlbCBUaGUgbWV0YW1vZGVsXG4gKiBAcmV0dXJuc1xuICovXG5mdW5jdGlvbiBfZ2V0UmVhY2hhYmxlUGFnZXMob01hbmlmZXN0Um91dGluZzogYW55LCBvU3RhcnR1cFBhcmFtZXRlcnM6IGFueSwgb01ldGFNb2RlbDogT0RhdGFNZXRhTW9kZWwpOiBQYWdlSW5mb1tdW10ge1xuXHRjb25zdCBhUm91dGVzOiBhbnlbXSA9IG9NYW5pZmVzdFJvdXRpbmcucm91dGVzO1xuXHRjb25zdCBtUGFnZXNCeUxldmVsOiBSZWNvcmQ8bnVtYmVyLCBQYWdlSW5mb1tdPiA9IHt9O1xuXG5cdGFSb3V0ZXMuZm9yRWFjaChvUm91dGUgPT4ge1xuXHRcdGxldCBzUGF0dGVybjogc3RyaW5nID0gb1JvdXRlLnBhdHRlcm4ucmVwbGFjZShcIjo/cXVlcnk6XCIsIFwiXCIpO1xuXHRcdGlmIChzUGF0dGVybi5lbmRzV2l0aChcIi9cIikpIHtcblx0XHRcdHNQYXR0ZXJuID0gc1BhdHRlcm4uc3Vic3RyKDAsIHNQYXR0ZXJuLmxlbmd0aCAtIDEpO1xuXHRcdH1cblxuXHRcdGlmIChzUGF0dGVybikge1xuXHRcdFx0Ly8gSWdub3JlIGxldmVsLTAgcm91dGVzIChMaXN0UmVwb3J0KVxuXHRcdFx0c1BhdHRlcm4gPSBzUGF0dGVybi5yZXBsYWNlKC9cXChcXHtbXlxcfV0qXFx9XFwpL2csIFwiKCMpXCIpOyAvLyBSZXBsYWNlIGtleXMgd2l0aCAjXG5cblx0XHRcdC8vIEdldCB0aGUgcmlnaHRtb3N0IHRhcmdldCBmb3IgdGhpcyByb3V0ZVxuXHRcdFx0Y29uc3Qgc1RhcmdldE5hbWU6IHN0cmluZyA9IEFycmF5LmlzQXJyYXkob1JvdXRlLnRhcmdldCkgPyBvUm91dGUudGFyZ2V0W29Sb3V0ZS50YXJnZXQubGVuZ3RoIC0gMV0gOiBvUm91dGUudGFyZ2V0O1xuXHRcdFx0Y29uc3Qgb1RhcmdldCA9IG9NYW5pZmVzdFJvdXRpbmcudGFyZ2V0c1tzVGFyZ2V0TmFtZV07XG5cblx0XHRcdGNvbnN0IGFQYXR0ZXJuU2VnbWVudHMgPSBzUGF0dGVybi5zcGxpdChcIi9cIik7XG5cdFx0XHRjb25zdCBwYWdlTGV2ZWwgPSBhUGF0dGVyblNlZ21lbnRzLmxlbmd0aCAtIDE7XG5cblx0XHRcdC8vIFRoZSBmaXJzdCBsZXZlbCBvZiBvYmplY3QgcGFnZSBhbGxvd3MgZGVlcCBsaW5raW5nIGJ5IGRlZmF1bHQuXG5cdFx0XHQvLyBPdGhlcndpc2UsIHRoZSB0YXJnZXQgbXVzdCBhbGxvdyBkZWVwIGxpbmtpbmcgZXhwbGljaXRlbHkgaW4gdGhlIG1hbmlmZXN0XG5cdFx0XHRpZiAocGFnZUxldmVsID09PSAwIHx8IG9UYXJnZXQ/Lm9wdGlvbnM/LnNldHRpbmdzPy5hbGxvd0RlZXBMaW5raW5nKSB7XG5cdFx0XHRcdGNvbnN0IHNDb250ZXh0UGF0aDogc3RyaW5nID1cblx0XHRcdFx0XHRvVGFyZ2V0Lm9wdGlvbnMuc2V0dGluZ3MuY29udGV4dFBhdGggfHxcblx0XHRcdFx0XHQob1RhcmdldC5vcHRpb25zLnNldHRpbmdzLmVudGl0eVNldCAmJiBcIi9cIiArIG9UYXJnZXQub3B0aW9ucy5zZXR0aW5ncy5lbnRpdHlTZXQpO1xuXHRcdFx0XHRjb25zdCBvRW50aXR5VHlwZSA9IHNDb250ZXh0UGF0aCAmJiBvTWV0YU1vZGVsLmdldE9iamVjdChcIi8kRW50aXR5Q29udGFpbmVyXCIgKyBzQ29udGV4dFBhdGggKyBcIi9cIik7XG5cblx0XHRcdFx0aWYgKG9FbnRpdHlUeXBlKSB7XG5cdFx0XHRcdFx0Ly8gR2V0IHRoZSBzZW1hbnRpYyBrZXkgdmFsdWVzIGZvciB0aGUgZW50aXR5XG5cdFx0XHRcdFx0Y29uc3QgYVNlbWFudGljS2V5TmFtZXM6IGFueSA9IG9NZXRhTW9kZWwuZ2V0T2JqZWN0KFxuXHRcdFx0XHRcdFx0XCIvJEVudGl0eUNvbnRhaW5lclwiICsgc0NvbnRleHRQYXRoICsgXCIvQGNvbS5zYXAudm9jYWJ1bGFyaWVzLkNvbW1vbi52MS5TZW1hbnRpY0tleVwiXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRjb25zdCBhU2VtYW50aWNrS2V5cyA9IGFTZW1hbnRpY0tleU5hbWVzXG5cdFx0XHRcdFx0XHQ/IF9nZXRLZXlzRnJvbVN0YXJ0dXBQYXJhbXMoXG5cdFx0XHRcdFx0XHRcdFx0YVNlbWFudGljS2V5TmFtZXMubWFwKChzZW1LZXk6IGFueSkgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuIHNlbUtleS4kUHJvcGVydHlQYXRoIGFzIHN0cmluZztcblx0XHRcdFx0XHRcdFx0XHR9KSxcblx0XHRcdFx0XHRcdFx0XHRvU3RhcnR1cFBhcmFtZXRlcnNcblx0XHRcdFx0XHRcdCAgKVxuXHRcdFx0XHRcdFx0OiB1bmRlZmluZWQ7XG5cblx0XHRcdFx0XHQvLyBHZXQgdGhlIHRlY2huaWNhbCBrZXlzIG9ubHkgaWYgd2UgY291bGRuJ3QgZmluZCB0aGUgc2VtYW50aWMga2V5IHZhbHVlcywgYW5kIG9uIGZpcnN0IGxldmVsIE9QXG5cdFx0XHRcdFx0Y29uc3QgYVRlY2huaWNhbEtleXMgPVxuXHRcdFx0XHRcdFx0IWFTZW1hbnRpY2tLZXlzICYmIHBhZ2VMZXZlbCA9PT0gMCA/IF9nZXRLZXlzRnJvbVN0YXJ0dXBQYXJhbXMob0VudGl0eVR5cGVbXCIkS2V5XCJdLCBvU3RhcnR1cFBhcmFtZXRlcnMpIDogdW5kZWZpbmVkO1xuXG5cdFx0XHRcdFx0aWYgKGFTZW1hbnRpY2tLZXlzIHx8IGFUZWNobmljYWxLZXlzKSB7XG5cdFx0XHRcdFx0XHQvLyBUaGUgc3RhcnR1cCBwYXJhbWV0ZXJzIGNvbnRhaW4gdmFsdWVzIGZvciBhbGwgc2VtYW50aWMga2V5cyAob3IgdGVjaG5pY2FsIGtleXMpIC0tPiB3ZSBjYW4gc3RvcmUgdGhlIHBhZ2UgaW5mbyBpbiB0aGUgY29ycmVzcG9uZGluZyBsZXZlbFxuXHRcdFx0XHRcdFx0Y29uc3QgZHJhZnRNb2RlID1cblx0XHRcdFx0XHRcdFx0b01ldGFNb2RlbC5nZXRPYmplY3QoXCIvJEVudGl0eUNvbnRhaW5lclwiICsgc0NvbnRleHRQYXRoICsgXCJAY29tLnNhcC52b2NhYnVsYXJpZXMuQ29tbW9uLnYxLkRyYWZ0Um9vdFwiKSB8fFxuXHRcdFx0XHRcdFx0XHRvTWV0YU1vZGVsLmdldE9iamVjdChcIi8kRW50aXR5Q29udGFpbmVyXCIgKyBzQ29udGV4dFBhdGggKyBcIkBjb20uc2FwLnZvY2FidWxhcmllcy5Db21tb24udjEuRHJhZnROb2RlXCIpXG5cdFx0XHRcdFx0XHRcdFx0PyB0cnVlXG5cdFx0XHRcdFx0XHRcdFx0OiBmYWxzZTtcblxuXHRcdFx0XHRcdFx0aWYgKCFtUGFnZXNCeUxldmVsW3BhZ2VMZXZlbF0pIHtcblx0XHRcdFx0XHRcdFx0bVBhZ2VzQnlMZXZlbFtwYWdlTGV2ZWxdID0gW107XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRtUGFnZXNCeUxldmVsW3BhZ2VMZXZlbF0ucHVzaCh7XG5cdFx0XHRcdFx0XHRcdHBhdHRlcm46IHNQYXR0ZXJuLFxuXHRcdFx0XHRcdFx0XHRjb250ZXh0UGF0aDogc0NvbnRleHRQYXRoLFxuXHRcdFx0XHRcdFx0XHRkcmFmdE1vZGUsXG5cdFx0XHRcdFx0XHRcdHRlY2huaWNhbEtleXM6IGFUZWNobmljYWxLZXlzLFxuXHRcdFx0XHRcdFx0XHRzZW1hbnRpY0tleXM6IGFTZW1hbnRpY2tLZXlzLFxuXHRcdFx0XHRcdFx0XHR0YXJnZXQ6IHNUYXJnZXROYW1lXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXG5cdC8vIEEgcGFnZSBpcyByZWFjaGFibGUgb25seSBpZiBhbGwgaXRzIHBhcmVudHMgYXJlIGFsc28gcmVhY2hhYmxlXG5cdC8vIFNvIGlmIHdlIGNvdWxkbid0IGZpbmQgYW55IHBhZ2VzIGZvciBhIGdpdmVuIGxldmVsLCBhbGwgcGFnZXMgd2l0aCBhIGhpZ2hlciBsZXZlbCB3b24ndCBiZSByZWFjaGFibGUgYW55d2F5XG5cdGNvbnN0IGFSZWFjaGFibGVQYWdlczogUGFnZUluZm9bXVtdID0gW107XG5cdGxldCBsZXZlbCA9IDA7XG5cdHdoaWxlIChtUGFnZXNCeUxldmVsW2xldmVsXSkge1xuXHRcdGFSZWFjaGFibGVQYWdlcy5wdXNoKG1QYWdlc0J5TGV2ZWxbbGV2ZWxdKTtcblx0XHRsZXZlbCsrO1xuXHR9XG5cblx0cmV0dXJuIGFSZWFjaGFibGVQYWdlcztcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGxpc3Qgb2Ygc3RhcnR1cCBwYWdlcy5cbiAqXG4gKiBAcGFyYW0gb01hbmlmZXN0Um91dGluZyBUaGUgcm91dGluZyBpbmZvcm1hdGlvbiBmcm9tIHRoZSBhcHAgbWFuaWZlc3RcbiAqIEBwYXJhbSBvU3RhcnR1cFBhcmFtZXRlcnMgVGhlIHN0YXJ0dXAgcGFyYW1ldGVyc1xuICogQHBhcmFtIG9NZXRhTW9kZWwgVGhlIG1ldGFtb2RlbFxuICogQHJldHVybnMgQW4gYXJyYXkgb2Ygc3RhcnR1cCBwYWdlIGluZm9zXG4gKi9cbmZ1bmN0aW9uIF9nZXRTdGFydHVwUGFnZXNGcm9tU3RhcnR1cFBhcmFtcyhvTWFuaWZlc3RSb3V0aW5nOiBhbnksIG9TdGFydHVwUGFyYW1ldGVyczogYW55LCBvTWV0YU1vZGVsOiBPRGF0YU1ldGFNb2RlbCk6IFBhZ2VJbmZvW10ge1xuXHQvLyBGaW5kIGFsbCBwYWdlcyB0aGF0IGNhbiBiZSByZWFjaGVkIHdpdGggdGhlIHN0YXJ0dXAgcGFyYW1ldGVyc1xuXHRjb25zdCBhUmVhY2hhYmxlUGFnZXMgPSBfZ2V0UmVhY2hhYmxlUGFnZXMob01hbmlmZXN0Um91dGluZywgb1N0YXJ0dXBQYXJhbWV0ZXJzLCBvTWV0YU1vZGVsKTtcblxuXHRpZiAoYVJlYWNoYWJsZVBhZ2VzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHJldHVybiBbXTtcblx0fVxuXG5cdC8vIEZpbmQgdGhlIGxvbmdlc3Qgc2VxdWVuY2Ugb2YgcGFnZXMgdGhhdCBjYW4gYmUgcmVhY2hlZCAocmVjdXJzaXZlbHkpXG5cdGxldCByZXN1bHQ6IFBhZ2VJbmZvW10gPSBbXTtcblx0Y29uc3QgY3VycmVudDogUGFnZUluZm9bXSA9IFtdO1xuXG5cdGZ1bmN0aW9uIGZpbmRSZWN1cnNpdmUobGV2ZWw6IG51bWJlcikge1xuXHRcdGNvbnN0IGFDdXJyZW50TGV2ZWxQYWdlcyA9IGFSZWFjaGFibGVQYWdlc1tsZXZlbF07XG5cdFx0Y29uc3QgbGFzdFBhZ2UgPSBjdXJyZW50Lmxlbmd0aCA/IGN1cnJlbnRbY3VycmVudC5sZW5ndGggLSAxXSA6IHVuZGVmaW5lZDtcblxuXHRcdGlmIChhQ3VycmVudExldmVsUGFnZXMpIHtcblx0XHRcdGFDdXJyZW50TGV2ZWxQYWdlcy5mb3JFYWNoKGZ1bmN0aW9uKG5leHRQYWdlKSB7XG5cdFx0XHRcdGlmICghbGFzdFBhZ2UgfHwgbmV4dFBhZ2UucGF0dGVybi5pbmRleE9mKGxhc3RQYWdlLnBhdHRlcm4pID09PSAwKSB7XG5cdFx0XHRcdFx0Ly8gV2Ugb25seSBjb25zaWRlciBwYWdlcyB0aGF0IGNhbiBiZSByZWFjaGVkIGZyb20gdGhlIHBhZ2UgYXQgdGhlIHByZXZpb3VzIGxldmVsLFxuXHRcdFx0XHRcdC8vIC0tPiB0aGVpciBwYXR0ZXJuIG11c3QgYmUgdGhlIHBhdHRlcm4gb2YgdGhlIHByZXZpb3VzIHBhZ2Ugd2l0aCBhbm90aGVyIHNlZ21lbnQgYXBwZW5kZWRcblx0XHRcdFx0XHRjdXJyZW50LnB1c2gobmV4dFBhZ2UpO1xuXHRcdFx0XHRcdGZpbmRSZWN1cnNpdmUobGV2ZWwgKyAxKTtcblx0XHRcdFx0XHRjdXJyZW50LnBvcCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdFx0aWYgKGN1cnJlbnQubGVuZ3RoID4gcmVzdWx0Lmxlbmd0aCkge1xuXHRcdFx0cmVzdWx0ID0gY3VycmVudC5zbGljZSgpOyAvLyBXZSBoYXZlIGZvdW5kIGEgc2VxdWVuY2UgbG9uZ2VyIHRoYW4gb3VyIHByZXZpb3VzIGJlc3QgLS0+IHN0b3JlIGl0IGFzIHRoZSBuZXcgbG9uZ2VzdFxuXHRcdH1cblx0fVxuXG5cdGZpbmRSZWN1cnNpdmUoMCk7XG5cblx0cmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBzdGFydHVwIG9iamVjdCBmcm9tIHRoZSBsaXN0IG9mIHBhZ2VzIGFuZCBjb250ZXh0cy5cbiAqXG4gKiBAcGFyYW0gYVN0YXJ0dXBQYWdlcyBUaGUgcGFnZXNcbiAqIEBwYXJhbSBhQ29udGV4dHMgVGhlIGNvbnRleHRzXG4gKiBAcmV0dXJucyBBbiBvYmplY3QgY29udGFpbmluZyBlaXRoZXIgYSBoYXNoIG9yIGEgY29udGV4dCB0byBuYXZpZ2F0ZSB0bywgb3IgYW4gZW1wdHkgb2JqZWN0IGlmIG5vIGRlZXAgbGluayB3YXMgZm91bmRcbiAqL1xuZnVuY3Rpb24gX2dldERlZXBMaW5rT2JqZWN0KGFTdGFydHVwUGFnZXM6IFBhZ2VJbmZvW10sIGFDb250ZXh0czogQ29udGV4dFtdKTogeyBoYXNoPzogc3RyaW5nOyBjb250ZXh0PzogQ29udGV4dCB9IHtcblx0aWYgKGFDb250ZXh0cy5sZW5ndGggPT09IDEpIHtcblx0XHRyZXR1cm4geyBjb250ZXh0OiBhQ29udGV4dHNbMF0gfTtcblx0fSBlbHNlIGlmIChhQ29udGV4dHMubGVuZ3RoID4gMSkge1xuXHRcdC8vIE5hdmlnYXRpb24gdG8gYSBkZWVwZXIgbGV2ZWwgLS0+IHVzZSB0aGUgcGF0dGVybiBvZiB0aGUgZGVlcGVzdCBvYmplY3QgcGFnZVxuXHRcdC8vIGFuZCByZXBsYWNlIHRoZSBwYXJhbWV0ZXJzIGJ5IHRoZSBJRCBmcm9tIHRoZSBjb250ZXh0c1xuXHRcdGxldCBoYXNoID0gYVN0YXJ0dXBQYWdlc1thU3RhcnR1cFBhZ2VzLmxlbmd0aCAtIDFdLnBhdHRlcm47XG5cdFx0YUNvbnRleHRzLmZvckVhY2goZnVuY3Rpb24ob0NvbnRleHQpIHtcblx0XHRcdGhhc2ggPSBoYXNoLnJlcGxhY2UoXCIoIylcIiwgXCIoXCIgKyBvQ29udGV4dC5nZXRQYXRoKCkuc3BsaXQoXCIoXCIpWzFdKTtcblx0XHR9KTtcblxuXHRcdHJldHVybiB7IGhhc2ggfTtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4ge307XG5cdH1cbn1cblxuLyoqXG4gKiBDYWxjdWxhdGVzIHN0YXJ0dXAgcGFyYW1ldGVycyBmb3IgYSBkZWVwbGluayBjYXNlLCBmcm9tIHN0YXJ0dXAgcGFyYW1ldGVycyBhbmQgcm91dGluZyBpbmZvaXJtYXRpb24uXG4gKlxuICogQHBhcmFtIG9NYW5pZmVzdFJvdXRpbmcgVGhlIHJvdXRpbmcgaW5mb3JtYXRpb24gZnJvbSB0aGUgYXBwIG1hbmlmZXN0XG4gKiBAcGFyYW0gb1N0YXJ0dXBQYXJhbWV0ZXJzIFRoZSBzdGFydHVwIHBhcmFtZXRlcnNcbiAqIEBwYXJhbSBvTW9kZWwgVGhlIE9EYXRhIG1vZGVsXG4gKiBAcmV0dXJucyBBbiBvYmplY3QgY29udGFpbmluZyBlaXRoZXIgYSBoYXNoIG9yIGEgY29udGV4dCB0byBuYXZpZ2F0ZSB0bywgb3IgYW4gZW1wdHkgb2JqZWN0IGlmIG5vIGRlZXAgbGluayB3YXMgZm91bmRcbiAqL1xuZnVuY3Rpb24gZ2V0RGVlcExpbmtTdGFydHVwSGFzaChcblx0b01hbmlmZXN0Um91dGluZzogYW55LFxuXHRvU3RhcnR1cFBhcmFtZXRlcnM6IGFueSxcblx0b01vZGVsOiBPRGF0YU1vZGVsXG4pOiBQcm9taXNlPHsgaGFzaD86IHN0cmluZzsgY29udGV4dD86IENvbnRleHQgfT4ge1xuXHRsZXQgYVN0YXJ0dXBQYWdlczogUGFnZUluZm9bXTtcblxuXHRyZXR1cm4gb01vZGVsXG5cdFx0LmdldE1ldGFNb2RlbCgpXG5cdFx0LnJlcXVlc3RPYmplY3QoXCIvJEVudGl0eUNvbnRhaW5lci9cIilcblx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHQvLyBDaGVjayBpZiBzZW1hbnRpYyBrZXlzIGFyZSBwcmVzZW50IGluIHVybCBwYXJhbWV0ZXJzIGZvciBldmVyeSBvYmplY3QgcGFnZSBhdCBlYWNoIGxldmVsXG5cdFx0XHRhU3RhcnR1cFBhZ2VzID0gX2dldFN0YXJ0dXBQYWdlc0Zyb21TdGFydHVwUGFyYW1zKG9NYW5pZmVzdFJvdXRpbmcsIG9TdGFydHVwUGFyYW1ldGVycywgb01vZGVsLmdldE1ldGFNb2RlbCgpKTtcblxuXHRcdFx0cmV0dXJuIF9yZXF1ZXN0T2JqZWN0c0Zyb21QYXJhbWV0ZXJzKGFTdGFydHVwUGFnZXMsIG9Nb2RlbCk7XG5cdFx0fSlcblx0XHQudGhlbigoYVZhbHVlczogQ29udGV4dFtdW10pID0+IHtcblx0XHRcdGlmIChhVmFsdWVzLmxlbmd0aCkge1xuXHRcdFx0XHQvLyBNYWtlIHN1cmUgd2Ugb25seSBnZXQgMSBjb250ZXh0IHBlciBwcm9taXNlLCBhbmQgZmxhdHRlbiB0aGUgYXJyYXlcblx0XHRcdFx0Y29uc3QgYUNvbnRleHRzOiBDb250ZXh0W10gPSBbXTtcblx0XHRcdFx0YVZhbHVlcy5mb3JFYWNoKGZ1bmN0aW9uKGFGb3VuZENvbnRleHRzKSB7XG5cdFx0XHRcdFx0aWYgKGFGb3VuZENvbnRleHRzLmxlbmd0aCA9PT0gMSkge1xuXHRcdFx0XHRcdFx0YUNvbnRleHRzLnB1c2goYUZvdW5kQ29udGV4dHNbMF0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0cmV0dXJuIGFDb250ZXh0cy5sZW5ndGggPT09IGFWYWx1ZXMubGVuZ3RoID8gX2dldERlZXBMaW5rT2JqZWN0KGFTdGFydHVwUGFnZXMsIGFDb250ZXh0cykgOiB7fTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiB7fTtcblx0XHRcdH1cblx0XHR9KTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBuZXcgaGFzaCBiYXNlZCBvbiB0aGUgc3RhcnR1cCBwYXJhbWV0ZXJzLlxuICpcbiAqIEBwYXJhbSBvU3RhcnR1cFBhcmFtZXRlcnMgVGhlIHN0YXJ0dXAgcGFyYW1ldGVyIHZhbHVlcyAobWFwIHBhcmFtZXRlciBuYW1lIC0+IGFycmF5IG9mIHZhbHVlcylcbiAqIEBwYXJhbSBzQ29udGV4dFBhdGggVGhlIGNvbnRleHQgcGF0aCBmb3IgdGhlIHN0YXJ0dXAgb2YgdGhlIGFwcCAoZ2VuZXJhbGx5IHRoZSBwYXRoIHRvIHRoZSBtYWluIGVudGl0eSBzZXQpXG4gKiBAcGFyYW0gb1JvdXRlciBUaGUgcm91dGVyIGluc3RhbmNlXG4gKiBAcGFyYW0gb01ldGFNb2RlbCBUaGUgbWV0YSBtb2RlbFxuICogQHJldHVybnMgQSBwcm9taXNlIGNvbnRhaW5pbmcgdGhlIGhhc2ggdG8gbmF2aWdhdGUgdG8sIG9yIGFuIGVtcHR5IHN0cmluZyBpZiB0aGVyZSdzIG5vIG5lZWQgdG8gbmF2aWdhdGVcbiAqL1xuZnVuY3Rpb24gZ2V0Q3JlYXRlU3RhcnR1cEhhc2gob1N0YXJ0dXBQYXJhbWV0ZXJzOiBhbnksIHNDb250ZXh0UGF0aDogc3RyaW5nLCBvUm91dGVyOiBSb3V0ZXIsIG9NZXRhTW9kZWw6IE9EYXRhTWV0YU1vZGVsKTogUHJvbWlzZTxTdHJpbmc+IHtcblx0cmV0dXJuIG9NZXRhTW9kZWwucmVxdWVzdE9iamVjdChzQ29udGV4dFBhdGggKyBcIkBcIikudGhlbihmdW5jdGlvbihvRW50aXR5U2V0QW5ub3RhdGlvbnM6IGFueSkge1xuXHRcdGxldCBzTWV0YVBhdGggPSBcIlwiO1xuXHRcdGxldCBiQ3JlYXRhYmxlID0gdHJ1ZTtcblxuXHRcdGlmIChcblx0XHRcdG9FbnRpdHlTZXRBbm5vdGF0aW9uc1tcIkBjb20uc2FwLnZvY2FidWxhcmllcy5Db21tb24udjEuRHJhZnRSb290XCJdICYmXG5cdFx0XHRvRW50aXR5U2V0QW5ub3RhdGlvbnNbXCJAY29tLnNhcC52b2NhYnVsYXJpZXMuQ29tbW9uLnYxLkRyYWZ0Um9vdFwiXVtcIk5ld0FjdGlvblwiXVxuXHRcdCkge1xuXHRcdFx0c01ldGFQYXRoID0gc0NvbnRleHRQYXRoICsgXCJAY29tLnNhcC52b2NhYnVsYXJpZXMuQ29tbW9uLnYxLkRyYWZ0Um9vdC9OZXdBY3Rpb25AT3JnLk9EYXRhLkNvcmUuVjEuT3BlcmF0aW9uQXZhaWxhYmxlXCI7XG5cdFx0fSBlbHNlIGlmIChcblx0XHRcdG9FbnRpdHlTZXRBbm5vdGF0aW9uc1tcIkBjb20uc2FwLnZvY2FidWxhcmllcy5TZXNzaW9uLnYxLlN0aWNreVNlc3Npb25TdXBwb3J0ZWRcIl0gJiZcblx0XHRcdG9FbnRpdHlTZXRBbm5vdGF0aW9uc1tcIkBjb20uc2FwLnZvY2FidWxhcmllcy5TZXNzaW9uLnYxLlN0aWNreVNlc3Npb25TdXBwb3J0ZWRcIl1bXCJOZXdBY3Rpb25cIl1cblx0XHQpIHtcblx0XHRcdHNNZXRhUGF0aCA9XG5cdFx0XHRcdHNDb250ZXh0UGF0aCArIFwiQGNvbS5zYXAudm9jYWJ1bGFyaWVzLlNlc3Npb24udjEuU3RpY2t5U2Vzc2lvblN1cHBvcnRlZC9OZXdBY3Rpb25AT3JnLk9EYXRhLkNvcmUuVjEuT3BlcmF0aW9uQXZhaWxhYmxlXCI7XG5cdFx0fVxuXG5cdFx0aWYgKHNNZXRhUGF0aCkge1xuXHRcdFx0Y29uc3QgYk5ld0FjdGlvbk9wZXJhdGlvbkF2YWlsYWJsZSA9IG9NZXRhTW9kZWwuZ2V0T2JqZWN0KHNNZXRhUGF0aCk7XG5cdFx0XHRpZiAoYk5ld0FjdGlvbk9wZXJhdGlvbkF2YWlsYWJsZSA9PT0gZmFsc2UpIHtcblx0XHRcdFx0YkNyZWF0YWJsZSA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zdCBvSW5zZXJ0UmVzdHJpY3Rpb25zID0gb0VudGl0eVNldEFubm90YXRpb25zW1wiQE9yZy5PRGF0YS5DYXBhYmlsaXRpZXMuVjEuSW5zZXJ0UmVzdHJpY3Rpb25zXCJdO1xuXHRcdFx0aWYgKG9JbnNlcnRSZXN0cmljdGlvbnMgJiYgb0luc2VydFJlc3RyaWN0aW9ucy5JbnNlcnRhYmxlID09PSBmYWxzZSkge1xuXHRcdFx0XHRiQ3JlYXRhYmxlID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmIChiQ3JlYXRhYmxlKSB7XG5cdFx0XHRyZXR1cm4gZ2V0RGVmYXVsdENyZWF0ZUhhc2gob1N0YXJ0dXBQYXJhbWV0ZXJzLCBzQ29udGV4dFBhdGgsIG9Sb3V0ZXIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gXCJcIjtcblx0XHR9XG5cdH0pO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGhhc2ggdG8gY3JlYXRlIGEgbmV3IG9iamVjdC5cbiAqXG4gKiBAcGFyYW0gb1N0YXJ0dXBQYXJhbWV0ZXJzIFRoZSBzdGFydHVwIHBhcmFtZXRlciB2YWx1ZXMgKG1hcCBwYXJhbWV0ZXIgbmFtZSAtPiBhcnJheSBvZiB2YWx1ZXMpXG4gKiBAcGFyYW0gc0NvbnRleHRQYXRoIFRoZSBjb250ZXh0IHBhdGggb2YgdGhlIGVudGl0eSBzZXQgdG8gYmUgdXNlZCBmb3IgdGhlIGNyZWF0aW9uXG4gKiBAcGFyYW0gb1JvdXRlciBUaGUgcm91dGVyIGluc3RhbmNlXG4gKiBAcmV0dXJucyBUaGUgaGFzaFxuICovXG5mdW5jdGlvbiBnZXREZWZhdWx0Q3JlYXRlSGFzaChvU3RhcnR1cFBhcmFtZXRlcnM6IGFueSwgc0NvbnRleHRQYXRoOiBzdHJpbmcsIG9Sb3V0ZXI6IFJvdXRlcik6IHN0cmluZyB7XG5cdGxldCBzRGVmYXVsdENyZWF0ZUhhc2ggPVxuXHRcdG9TdGFydHVwUGFyYW1ldGVycyAmJiBvU3RhcnR1cFBhcmFtZXRlcnMucHJlZmVycmVkTW9kZSA/IChvU3RhcnR1cFBhcmFtZXRlcnMucHJlZmVycmVkTW9kZVswXSBhcyBzdHJpbmcpIDogXCJjcmVhdGVcIjtcblx0bGV0IHNIYXNoID0gXCJcIjtcblxuXHRzRGVmYXVsdENyZWF0ZUhhc2ggPVxuXHRcdHNEZWZhdWx0Q3JlYXRlSGFzaC5pbmRleE9mKFwiOlwiKSAhPT0gLTEgJiYgc0RlZmF1bHRDcmVhdGVIYXNoLmxlbmd0aCA+IHNEZWZhdWx0Q3JlYXRlSGFzaC5pbmRleE9mKFwiOlwiKSArIDFcblx0XHRcdD8gc0RlZmF1bHRDcmVhdGVIYXNoLnN1YnN0cigwLCBzRGVmYXVsdENyZWF0ZUhhc2guaW5kZXhPZihcIjpcIikpXG5cdFx0XHQ6IFwiY3JlYXRlXCI7XG5cdHNIYXNoID0gc0NvbnRleHRQYXRoLnN1YnN0cmluZygxKSArIFwiKC4uLik/aS1hY3Rpb249XCIgKyBzRGVmYXVsdENyZWF0ZUhhc2g7XG5cdGlmIChvUm91dGVyLmdldFJvdXRlSW5mb0J5SGFzaChzSGFzaCkpIHtcblx0XHRyZXR1cm4gc0hhc2g7XG5cdH0gZWxzZSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiTm8gcm91dGUgbWF0Y2ggZm9yIGNyZWF0aW5nIGEgbmV3IFwiICsgc0NvbnRleHRQYXRoLnN1YnN0cmluZygxKSk7XG5cdH1cbn1cblxuY29uc3QgQXBwU3RhcnR1cEhlbHBlciA9IHtcblx0X2dldEtleXNGcm9tU3RhcnR1cFBhcmFtcyxcblx0X2NyZWF0ZUZpbHRlckZyb21LZXlzLFxuXHRfcmVxdWVzdE9iamVjdHNGcm9tUGFyYW1ldGVycyxcblx0X2dldFJlYWNoYWJsZVBhZ2VzLFxuXHRfZ2V0U3RhcnR1cFBhZ2VzRnJvbVN0YXJ0dXBQYXJhbXMsXG5cdF9nZXREZWVwTGlua09iamVjdCxcblx0Z2V0RGVlcExpbmtTdGFydHVwSGFzaCxcblx0Z2V0Q3JlYXRlU3RhcnR1cEhhc2gsXG5cdGdldERlZmF1bHRDcmVhdGVIYXNoXG59O1xuXG5leHBvcnQgZGVmYXVsdCBBcHBTdGFydHVwSGVscGVyO1xuIl19
|