@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.
Files changed (249) hide show
  1. package/package.json +5 -4
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +377 -405
  4. package/src/sap/fe/core/AnnotationHelper.ts +385 -0
  5. package/src/sap/fe/core/AppComponent.js +6 -3
  6. package/src/sap/fe/core/AppStateHandler.js +229 -181
  7. package/src/sap/fe/core/AppStateHandler.ts +171 -0
  8. package/src/sap/fe/core/BaseController.js +3 -2
  9. package/src/sap/fe/core/BusyLocker.js +105 -121
  10. package/src/sap/fe/core/BusyLocker.ts +98 -0
  11. package/src/sap/fe/core/CommonUtils.js +2073 -2379
  12. package/src/sap/fe/core/CommonUtils.ts +2078 -0
  13. package/src/sap/fe/core/ExtensionAPI.js +16 -7
  14. package/src/sap/fe/core/PageController.js +84 -119
  15. package/src/sap/fe/core/PageController.ts +101 -0
  16. package/src/sap/fe/core/RouterProxy.js +986 -807
  17. package/src/sap/fe/core/RouterProxy.ts +838 -0
  18. package/src/sap/fe/core/Synchronization.js +51 -35
  19. package/src/sap/fe/core/Synchronization.ts +29 -0
  20. package/src/sap/fe/core/TemplateComponent.js +173 -155
  21. package/src/sap/fe/core/TemplateComponent.ts +166 -0
  22. package/src/sap/fe/core/TemplateModel.js +97 -54
  23. package/src/sap/fe/core/TemplateModel.ts +64 -0
  24. package/src/sap/fe/core/TransactionHelper.js +1576 -1579
  25. package/src/sap/fe/core/TransactionHelper.ts +1706 -0
  26. package/src/sap/fe/core/actions/draft.js +560 -581
  27. package/src/sap/fe/core/actions/draft.ts +594 -0
  28. package/src/sap/fe/core/actions/messageHandling.js +545 -511
  29. package/src/sap/fe/core/actions/messageHandling.ts +532 -0
  30. package/src/sap/fe/core/actions/nonDraft.js +17 -19
  31. package/src/sap/fe/core/actions/nonDraft.ts +12 -0
  32. package/src/sap/fe/core/actions/operations.js +1074 -1211
  33. package/src/sap/fe/core/actions/operations.ts +1162 -0
  34. package/src/sap/fe/core/actions/sticky.js +102 -105
  35. package/src/sap/fe/core/actions/sticky.ts +102 -0
  36. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +3 -2
  37. package/src/sap/fe/core/controllerextensions/EditFlow.js +229 -260
  38. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +3 -2
  39. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +288 -13
  40. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +27 -23
  41. package/src/sap/fe/core/controllerextensions/InternalRouting.js +82 -46
  42. package/src/sap/fe/core/controllerextensions/KPIManagement.js +113 -25
  43. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +135 -44
  44. package/src/sap/fe/core/controllerextensions/MassEdit.js +172 -0
  45. package/src/sap/fe/core/controllerextensions/MessageHandler.js +22 -9
  46. package/src/sap/fe/core/controllerextensions/PageReady.js +3 -3
  47. package/src/sap/fe/core/controllerextensions/PageReady.ts +12 -8
  48. package/src/sap/fe/core/controllerextensions/Paginator.js +37 -9
  49. package/src/sap/fe/core/controllerextensions/Placeholder.js +8 -4
  50. package/src/sap/fe/core/controllerextensions/Routing.js +25 -5
  51. package/src/sap/fe/core/controllerextensions/RoutingListener.js +3 -2
  52. package/src/sap/fe/core/controllerextensions/Share.js +22 -8
  53. package/src/sap/fe/core/controllerextensions/SideEffects.js +9 -9
  54. package/src/sap/fe/core/controllerextensions/SideEffects.ts +22 -21
  55. package/src/sap/fe/core/controllerextensions/ViewState.js +3 -2
  56. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +2 -1
  57. package/src/sap/fe/core/controls/CommandExecution.js +3 -2
  58. package/src/sap/fe/core/controls/ConditionalWrapper.js +3 -2
  59. package/src/sap/fe/core/controls/CustomQuickViewPage.js +3 -2
  60. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +9 -5
  61. package/src/sap/fe/core/controls/FieldWrapper.js +18 -23
  62. package/src/sap/fe/core/controls/FilterBar.js +3 -2
  63. package/src/sap/fe/core/controls/FormElementWrapper.js +3 -7
  64. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +3 -2
  65. package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +2 -1
  66. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +3 -2
  67. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +5 -4
  68. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +3 -2
  69. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +3 -2
  70. package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
  71. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +79 -0
  72. package/src/sap/fe/core/converters/ConverterContext.js +14 -2
  73. package/src/sap/fe/core/converters/ConverterContext.ts +14 -3
  74. package/src/sap/fe/core/converters/ManifestSettings.js +1 -1
  75. package/src/sap/fe/core/converters/ManifestSettings.ts +4 -0
  76. package/src/sap/fe/core/converters/ManifestWrapper.js +56 -32
  77. package/src/sap/fe/core/converters/ManifestWrapper.ts +24 -6
  78. package/src/sap/fe/core/converters/MetaModelConverter.js +67 -6
  79. package/src/sap/fe/core/converters/MetaModelConverter.ts +70 -14
  80. package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
  81. package/src/sap/fe/core/converters/TemplateConverter.ts +2 -2
  82. package/src/sap/fe/core/converters/annotations/DataField.js +3 -3
  83. package/src/sap/fe/core/converters/annotations/DataField.ts +1 -1
  84. package/src/sap/fe/core/converters/common/AnnotationConverter.js +33 -21
  85. package/src/sap/fe/core/converters/controls/Common/Action.js +11 -2
  86. package/src/sap/fe/core/converters/controls/Common/Action.ts +8 -2
  87. package/src/sap/fe/core/converters/controls/Common/Chart.js +5 -3
  88. package/src/sap/fe/core/converters/controls/Common/Chart.ts +11 -3
  89. package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +3 -3
  90. package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +2 -2
  91. package/src/sap/fe/core/converters/controls/Common/Form.js +20 -10
  92. package/src/sap/fe/core/converters/controls/Common/Form.ts +24 -4
  93. package/src/sap/fe/core/converters/controls/Common/KPI.js +69 -4
  94. package/src/sap/fe/core/converters/controls/Common/KPI.ts +72 -0
  95. package/src/sap/fe/core/converters/controls/Common/Table.js +390 -398
  96. package/src/sap/fe/core/converters/controls/Common/Table.ts +497 -484
  97. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +527 -0
  98. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +655 -0
  99. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +489 -37
  100. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +506 -58
  101. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
  102. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
  103. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +17 -9
  104. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +24 -9
  105. package/src/sap/fe/core/converters/helpers/Aggregation.js +18 -3
  106. package/src/sap/fe/core/converters/helpers/Aggregation.ts +28 -5
  107. package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -1
  108. package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -0
  109. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +4 -4
  110. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +3 -3
  111. package/src/sap/fe/core/converters/templates/ListReportConverter.js +13 -6
  112. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +26 -15
  113. package/src/sap/fe/core/designtime/AppComponent.designtime.js +11 -2
  114. package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
  115. package/src/sap/fe/core/formatters/CriticalityFormatter.ts +1 -1
  116. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  117. package/src/sap/fe/core/formatters/FPMFormatter.ts +4 -10
  118. package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
  119. package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -1
  120. package/src/sap/fe/core/formatters/TableFormatter.js +39 -28
  121. package/src/sap/fe/core/formatters/TableFormatter.ts +43 -28
  122. package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
  123. package/src/sap/fe/core/formatters/ValueFormatter.ts +30 -7
  124. package/src/sap/fe/core/fpm/Component.js +3 -2
  125. package/src/sap/fe/core/helpers/AppStartupHelper.js +359 -0
  126. package/src/sap/fe/core/helpers/AppStartupHelper.ts +391 -0
  127. package/src/sap/fe/core/helpers/BindingExpression.js +484 -437
  128. package/src/sap/fe/core/helpers/BindingExpression.ts +480 -463
  129. package/src/sap/fe/core/helpers/ClassSupport.js +27 -15
  130. package/src/sap/fe/core/helpers/ClassSupport.ts +31 -20
  131. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +63 -59
  132. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +56 -0
  133. package/src/sap/fe/core/helpers/EditState.js +81 -84
  134. package/src/sap/fe/core/helpers/EditState.ts +81 -0
  135. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +62 -48
  136. package/src/sap/fe/core/helpers/ExcelFormatHelper.ts +49 -0
  137. package/src/sap/fe/core/helpers/FPMHelper.js +52 -56
  138. package/src/sap/fe/core/helpers/FPMHelper.ts +62 -0
  139. package/src/sap/fe/core/helpers/KeepAliveHelper.js +4 -5
  140. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +10 -10
  141. package/src/sap/fe/core/helpers/MassEditHelper.js +687 -0
  142. package/src/sap/fe/core/helpers/ModelHelper.js +229 -225
  143. package/src/sap/fe/core/helpers/ModelHelper.ts +227 -0
  144. package/src/sap/fe/core/helpers/PasteHelper.js +210 -132
  145. package/src/sap/fe/core/helpers/PasteHelper.ts +196 -0
  146. package/src/sap/fe/core/helpers/SemanticDateOperators.js +332 -313
  147. package/src/sap/fe/core/helpers/SemanticDateOperators.ts +330 -0
  148. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +66 -67
  149. package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +73 -0
  150. package/src/sap/fe/core/helpers/StableIdHelper.js +4 -7
  151. package/src/sap/fe/core/helpers/StableIdHelper.ts +2 -6
  152. package/src/sap/fe/core/jsx-runtime/jsx.js +1 -1
  153. package/src/sap/fe/core/jsx-runtime/jsx.ts +1 -1
  154. package/src/sap/fe/core/library.js +30 -3
  155. package/src/sap/fe/core/library.support.js +12 -5
  156. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +62 -0
  157. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +66 -0
  158. package/src/sap/fe/core/messagebundle.properties +61 -13
  159. package/src/sap/fe/core/messagebundle_ar.properties +33 -2
  160. package/src/sap/fe/core/messagebundle_bg.properties +33 -2
  161. package/src/sap/fe/core/messagebundle_ca.properties +33 -2
  162. package/src/sap/fe/core/messagebundle_cs.properties +34 -3
  163. package/src/sap/fe/core/messagebundle_cy.properties +33 -2
  164. package/src/sap/fe/core/messagebundle_da.properties +33 -2
  165. package/src/sap/fe/core/messagebundle_de.properties +33 -2
  166. package/src/sap/fe/core/messagebundle_el.properties +33 -2
  167. package/src/sap/fe/core/messagebundle_en.properties +32 -1
  168. package/src/sap/fe/core/messagebundle_en_GB.properties +32 -1
  169. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +36 -1
  170. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +33 -2
  171. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +33 -2
  172. package/src/sap/fe/core/messagebundle_es.properties +33 -2
  173. package/src/sap/fe/core/messagebundle_es_MX.properties +33 -2
  174. package/src/sap/fe/core/messagebundle_et.properties +33 -2
  175. package/src/sap/fe/core/messagebundle_fi.properties +34 -3
  176. package/src/sap/fe/core/messagebundle_fr.properties +38 -7
  177. package/src/sap/fe/core/messagebundle_fr_CA.properties +33 -2
  178. package/src/sap/fe/core/messagebundle_hi.properties +33 -2
  179. package/src/sap/fe/core/messagebundle_hr.properties +33 -2
  180. package/src/sap/fe/core/messagebundle_hu.properties +34 -3
  181. package/src/sap/fe/core/messagebundle_id.properties +36 -5
  182. package/src/sap/fe/core/messagebundle_it.properties +33 -2
  183. package/src/sap/fe/core/messagebundle_iw.properties +33 -2
  184. package/src/sap/fe/core/messagebundle_ja.properties +33 -2
  185. package/src/sap/fe/core/messagebundle_kk.properties +33 -2
  186. package/src/sap/fe/core/messagebundle_ko.properties +33 -2
  187. package/src/sap/fe/core/messagebundle_lt.properties +33 -2
  188. package/src/sap/fe/core/messagebundle_lv.properties +33 -2
  189. package/src/sap/fe/core/messagebundle_ms.properties +33 -2
  190. package/src/sap/fe/core/messagebundle_nl.properties +33 -2
  191. package/src/sap/fe/core/messagebundle_no.properties +33 -2
  192. package/src/sap/fe/core/messagebundle_pl.properties +33 -2
  193. package/src/sap/fe/core/messagebundle_pt.properties +34 -3
  194. package/src/sap/fe/core/messagebundle_pt_PT.properties +33 -2
  195. package/src/sap/fe/core/messagebundle_ro.properties +33 -2
  196. package/src/sap/fe/core/messagebundle_ru.properties +33 -2
  197. package/src/sap/fe/core/messagebundle_sh.properties +33 -2
  198. package/src/sap/fe/core/messagebundle_sk.properties +33 -2
  199. package/src/sap/fe/core/messagebundle_sl.properties +33 -2
  200. package/src/sap/fe/core/messagebundle_sv.properties +34 -3
  201. package/src/sap/fe/core/messagebundle_th.properties +33 -2
  202. package/src/sap/fe/core/messagebundle_tr.properties +33 -2
  203. package/src/sap/fe/core/messagebundle_uk.properties +33 -2
  204. package/src/sap/fe/core/messagebundle_vi.properties +33 -2
  205. package/src/sap/fe/core/messagebundle_zh_CN.properties +33 -2
  206. package/src/sap/fe/core/messagebundle_zh_TW.properties +33 -2
  207. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +2 -2
  208. package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -1
  209. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +269 -202
  210. package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +212 -0
  211. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +4 -3
  212. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +9 -5
  213. package/src/sap/fe/core/services/NavigationServiceFactory.js +406 -300
  214. package/src/sap/fe/core/services/NavigationServiceFactory.ts +316 -0
  215. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +149 -81
  216. package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +80 -0
  217. package/src/sap/fe/core/services/RoutingServiceFactory.js +987 -1152
  218. package/src/sap/fe/core/services/RoutingServiceFactory.ts +898 -0
  219. package/src/sap/fe/core/services/ShellServicesFactory.js +31 -2
  220. package/src/sap/fe/core/services/ShellServicesFactory.ts +45 -11
  221. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +42 -85
  222. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +57 -100
  223. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +461 -478
  224. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +453 -0
  225. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +10 -8
  226. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +8 -0
  227. package/src/sap/fe/core/support/AnnotationIssue.support.js +15 -3
  228. package/src/sap/fe/core/support/AnnotationIssue.support.ts +16 -2
  229. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -2
  230. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.ts +1 -1
  231. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
  232. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
  233. package/src/sap/fe/core/templating/DataModelPathHelper.js +10 -48
  234. package/src/sap/fe/core/templating/DataModelPathHelper.ts +14 -46
  235. package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
  236. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
  237. package/src/sap/fe/core/templating/FieldControlHelper.js +8 -8
  238. package/src/sap/fe/core/templating/FieldControlHelper.ts +25 -7
  239. package/src/sap/fe/core/templating/FilterHelper.js +139 -70
  240. package/src/sap/fe/core/templating/FilterHelper.ts +140 -70
  241. package/src/sap/fe/core/templating/PropertyHelper.js +2 -2
  242. package/src/sap/fe/core/templating/PropertyHelper.ts +1 -1
  243. package/src/sap/fe/core/templating/UIFormatters.js +45 -110
  244. package/src/sap/fe/core/templating/UIFormatters.ts +39 -75
  245. package/src/sap/fe/core/type/Email.js +1 -1
  246. package/src/sap/fe/core/type/Email.ts +4 -6
  247. package/ui5.yaml +0 -3
  248. package/src/sap/fe/core/controls/filterbar.d.js +0 -8
  249. package/src/sap/fe/core/controls/filterbar.d.ts +0 -0
@@ -1,1154 +1,989 @@
1
1
  /*!
2
- * SAPUI5
3
- * (c) Copyright 2009-2021 SAP SE. All rights reserved.
2
+ * SAP UI development toolkit for HTML5 (SAPUI5)
3
+ * (c) Copyright 2009-2021 SAP SE. All rights reserved
4
4
  */
5
- sap.ui.define(
6
- [
7
- "sap/ui/core/service/Service",
8
- "sap/ui/core/service/ServiceFactory",
9
- "sap/ui/core/Component",
10
- "sap/ui/base/BindingParser",
11
- "sap/fe/core/helpers/SemanticKeyHelper",
12
- "sap/ui/model/Filter",
13
- "sap/ui/model/FilterOperator",
14
- "sap/base/Log",
15
- "sap/ui/base/EventProvider",
16
- "sap/fe/core/BusyLocker",
17
- "sap/fe/core/helpers/ModelHelper",
18
- "sap/fe/core/helpers/EditState",
19
- "sap/fe/core/actions/messageHandling",
20
- "sap/fe/core/controllerextensions/Placeholder"
21
- ],
22
- function(
23
- Service,
24
- ServiceFactory,
25
- Component,
26
- BindingParser,
27
- SemanticKeyHelper,
28
- Filter,
29
- FilterOperator,
30
- Log,
31
- EventProvider,
32
- BusyLocker,
33
- ModelHelper,
34
- EditState,
35
- MessageHandling,
36
- Placeholder
37
- ) {
38
- "use strict";
39
-
40
- var RoutingServiceEventing = EventProvider.extend("sap.fe.core.services.RoutingServiceEventing", {
41
- metadata: {
42
- events: {
43
- "routeMatched": {},
44
- "afterRouteMatched": {}
45
- }
46
- }
47
- });
48
-
49
- var RoutingService = Service.extend("sap.fe.core.services.RoutingService", {
50
- /**
51
- * Initialize the routing service.
52
- */
53
- init: function() {
54
- var that = this;
55
- var oContext = this.getContext();
56
- if (oContext.scopeType === "component") {
57
- this.oAppComponent = oContext.scopeObject;
58
- this.oModel = this.oAppComponent.getModel();
59
- this.oMetaModel = this.oModel.getMetaModel();
60
- this.oRouter = this.oAppComponent.getRouter();
61
- this.oRouterProxy = this.oAppComponent.getRouterProxy();
62
- this.eventProvider = new RoutingServiceEventing();
63
-
64
- var oRoutingConfig = this.oAppComponent.getManifestEntry("/sap.ui5/routing");
65
- var oRootViewConfig = this.oAppComponent.getManifestEntry("/sap.ui5/rootView");
66
- this._parseRoutingConfiguration(oRoutingConfig, oRootViewConfig);
67
-
68
- var oAppConfig = this.oAppComponent.getManifestEntry("/sap.app");
69
- this.outbounds = oAppConfig && oAppConfig.crossNavigation && oAppConfig.crossNavigation.outbounds;
70
- }
71
-
72
- this.initPromise = Promise.resolve(that);
73
- },
74
-
75
- exit: function() {
76
- this.oRouter.detachRouteMatched(this._fnOnRouteMatched);
77
- this.eventProvider.fireEvent("routeMatched", {});
78
- this.eventProvider.destroy();
79
- },
80
-
81
- /**
82
- * Parse a manifest routing configuration for internal usage.
83
- *
84
- * @param {object} oRoutingConfig The routing configuration from the manifest
85
- * @param {object} oRootViewConfig The root view configuration from the manifest
86
- * @private
87
- */
88
- _parseRoutingConfiguration: function(oRoutingConfig, oRootViewConfig) {
89
- var that = this,
90
- isFCL = oRootViewConfig && oRootViewConfig.viewName === "sap.fe.templates.RootContainer.view.Fcl";
91
-
92
- // Information of targets
93
- this._mTargets = {};
94
- Object.keys(oRoutingConfig.targets).forEach(function(sTargetName) {
95
- that._mTargets[sTargetName] = Object.assign({ targetName: sTargetName }, oRoutingConfig.targets[sTargetName]);
96
-
97
- // View level for FCL cases is calculated from the target pattern
98
- if (that._mTargets[sTargetName].contextPattern !== undefined) {
99
- that._mTargets[sTargetName].viewLevel = that._getViewLevelFromPattern(
100
- that._mTargets[sTargetName].contextPattern,
101
- 0
102
- );
103
- }
104
- });
105
-
106
- // Information of routes
107
- this._mRoutes = {};
108
- for (var sRouteKey in oRoutingConfig.routes) {
109
- var oRouteManifestInfo = oRoutingConfig.routes[sRouteKey],
110
- aRouteTargets = Array.isArray(oRouteManifestInfo.target) ? oRouteManifestInfo.target : [oRouteManifestInfo.target],
111
- sRouteName = Array.isArray(oRoutingConfig.routes) ? oRouteManifestInfo.name : sRouteKey,
112
- sRoutePattern = oRouteManifestInfo.pattern;
113
-
114
- // Check route pattern: all patterns need to end with ':?query:', that we use for parameters
115
- if (sRoutePattern.length < 8 || sRoutePattern.indexOf(":?query:") !== sRoutePattern.length - 8) {
116
- Log.error("Pattern for route " + sRouteName + " doesn't end with ':?query:' : " + sRoutePattern);
117
- }
118
- var iRouteLevel = that._getViewLevelFromPattern(sRoutePattern, 0);
119
- that._mRoutes[sRouteName] = {
120
- name: sRouteName,
121
- pattern: sRoutePattern,
122
- targets: aRouteTargets,
123
- routeLevel: iRouteLevel
124
- };
125
-
126
- // Add the parent targets in the list of targets for the route
127
- for (var i = 0; i < aRouteTargets.length; i++) {
128
- var sParentTargetName = that._mTargets[aRouteTargets[i]].parent;
129
- if (sParentTargetName) {
130
- aRouteTargets.push(sParentTargetName);
131
- }
132
- }
133
-
134
- if (!isFCL) {
135
- // View level for non-FCL cases is calculated from the route pattern
136
- if (
137
- that._mTargets[aRouteTargets[0]].viewLevel === undefined ||
138
- that._mTargets[aRouteTargets[0]].viewLevel < iRouteLevel
139
- ) {
140
- // There are cases when different routes point to the same target. We take the
141
- // largest viewLevel in that case.
142
- that._mTargets[aRouteTargets[0]].viewLevel = iRouteLevel;
143
- }
144
-
145
- // FCL level for non-FCL cases is equal to -1
146
- that._mTargets[aRouteTargets[0]].FCLLevel = -1;
147
- } else if (aRouteTargets.length === 1 && that._mTargets[aRouteTargets[0]].controlAggregation !== "beginColumnPages") {
148
- // We're in the case where there's only 1 target for the route, and it's not in the first column
149
- // --> this is a fullscreen column after all columns in the FCL have been used
150
- that._mTargets[aRouteTargets[0]].FCLLevel = 3;
151
- } else {
152
- // Other FCL cases
153
- aRouteTargets.forEach(function(sTargetName) {
154
- switch (that._mTargets[sTargetName].controlAggregation) {
155
- case "beginColumnPages":
156
- that._mTargets[sTargetName].FCLLevel = 0;
157
- break;
158
-
159
- case "midColumnPages":
160
- that._mTargets[sTargetName].FCLLevel = 1;
161
- break;
162
-
163
- default:
164
- that._mTargets[sTargetName].FCLLevel = 2;
165
- }
166
- });
167
- }
168
- }
169
-
170
- // Propagate viewLevel, contextPattern, FCLLevel and controlAggregation to parent targets
171
- Object.keys(that._mTargets).forEach(function(sTargetName) {
172
- while (that._mTargets[sTargetName].parent) {
173
- var sParentTargetName = that._mTargets[sTargetName].parent;
174
- that._mTargets[sParentTargetName].viewLevel =
175
- that._mTargets[sParentTargetName].viewLevel || that._mTargets[sTargetName].viewLevel;
176
- that._mTargets[sParentTargetName].contextPattern =
177
- that._mTargets[sParentTargetName].contextPattern || that._mTargets[sTargetName].contextPattern;
178
- that._mTargets[sParentTargetName].FCLLevel =
179
- that._mTargets[sParentTargetName].FCLLevel || that._mTargets[sTargetName].FCLLevel;
180
- that._mTargets[sParentTargetName].controlAggregation =
181
- that._mTargets[sParentTargetName].controlAggregation || that._mTargets[sTargetName].controlAggregation;
182
- sTargetName = sParentTargetName;
183
- }
184
- });
185
-
186
- // Determine the root entity for the app
187
- var aLevel0RouteNames = [],
188
- aLevel1RouteNames = [],
189
- sDefaultRouteName;
190
-
191
- for (var sName in that._mRoutes) {
192
- var iLevel = that._mRoutes[sName].routeLevel;
193
- if (iLevel === 0) {
194
- aLevel0RouteNames.push(sName);
195
- } else if (iLevel === 1) {
196
- aLevel1RouteNames.push(sName);
197
- }
198
- }
199
-
200
- if (aLevel0RouteNames.length === 1) {
201
- sDefaultRouteName = aLevel0RouteNames[0];
202
- } else if (aLevel1RouteNames.length === 1) {
203
- sDefaultRouteName = aLevel1RouteNames[0];
204
- }
205
-
206
- if (sDefaultRouteName) {
207
- var sDefaultTargetName = that._mRoutes[sDefaultRouteName].targets.slice(-1)[0];
208
- that.sContextPath = "";
209
- if (that._mTargets[sDefaultTargetName].options && that._mTargets[sDefaultTargetName].options.settings) {
210
- var oSettings = that._mTargets[sDefaultTargetName].options.settings;
211
- that.sContextPath = oSettings.contextPath || "/" + oSettings.entitySet;
212
- }
213
- if (!that.sContextPath) {
214
- Log.error(
215
- "Cannot determine default contextPath: contextPath or entitySet missing in default target: " +
216
- sDefaultTargetName
217
- );
218
- }
219
- } else {
220
- Log.error("Cannot determine default contextPath: no default route found.");
221
- }
222
-
223
- // We need to establish the correct path to the different pages, including the navigation properties
224
- Object.keys(that._mTargets)
225
- .map(function(sTargetKey) {
226
- return that._mTargets[sTargetKey];
227
- })
228
- .sort(function(a, b) {
229
- return a.viewLevel < b.viewLevel ? -1 : 1;
230
- })
231
- .forEach(function(target) {
232
- // After sorting the targets per level we can then go through their navigation object and update the paths accordingly.
233
- if (target.options) {
234
- var settings = target.options.settings;
235
- var sContextPath = settings.contextPath || (settings.entitySet ? "/" + settings.entitySet : "");
236
- if (!settings.fullContextPath && sContextPath) {
237
- if (target.viewLevel === 0 || target.viewLevel === undefined) {
238
- settings.fullContextPath = "/";
239
- } else {
240
- settings.fullContextPath = sContextPath + "/";
241
- }
242
- }
243
- Object.keys(settings.navigation || {}).forEach(function(sNavName) {
244
- // Check if it's a navigation property
245
- var targetRoute = that._mRoutes[settings.navigation[sNavName].detail.route];
246
- if (targetRoute && targetRoute.targets) {
247
- targetRoute.targets.forEach(function(sTargetName) {
248
- if (
249
- that._mTargets[sTargetName].options &&
250
- that._mTargets[sTargetName].options.settings &&
251
- !that._mTargets[sTargetName].options.settings.fullContextPath
252
- ) {
253
- var targetNav;
254
- if (sNavName.startsWith("/")) {
255
- targetNav = sNavName;
256
- } else {
257
- targetNav = settings.fullContextPath + sNavName;
258
- }
259
- that._mTargets[sTargetName].options.settings.fullContextPath = targetNav + "/";
260
- }
261
- });
262
- }
263
- });
264
- }
265
- });
266
- },
267
-
268
- /**
269
- * Calculates a view level from a pattern by counting the number of segments.
270
- *
271
- * @param {string} sPattern The pattern
272
- * @param {number} viewLevel The current level of view
273
- * @returns {number} The level
274
- */
275
- _getViewLevelFromPattern: function(sPattern, viewLevel) {
276
- sPattern = sPattern.replace(":?query:", "");
277
- var regex = new RegExp("/[^/]*$");
278
- if (sPattern && sPattern[0] !== "/" && sPattern[0] !== "?") {
279
- sPattern = "/" + sPattern;
280
- }
281
- if (sPattern.length) {
282
- sPattern = sPattern.replace(regex, "");
283
- if (this.oRouter.match(sPattern) || sPattern === "") {
284
- return this._getViewLevelFromPattern(sPattern, ++viewLevel);
285
- } else {
286
- return this._getViewLevelFromPattern(sPattern, viewLevel);
287
- }
288
- } else {
289
- return viewLevel;
290
- }
291
- },
292
-
293
- _getRouteInformation: function(sRouteName) {
294
- return this._mRoutes[sRouteName];
295
- },
296
-
297
- _getTargetInformation: function(sTargetName) {
298
- return this._mTargets[sTargetName];
299
- },
300
-
301
- _getComponentId: function(sOwnerId, sComponentId) {
302
- if (sComponentId.indexOf(sOwnerId + "---") === 0) {
303
- return sComponentId.substr(sOwnerId.length + 3);
304
- }
305
- return sComponentId;
306
- },
307
-
308
- /**
309
- * Get target information for a given component.
310
- *
311
- * @param {object} oComponentInstance Instance of the component
312
- * @returns {object} The configuration for the target
313
- */
314
- getTargetInformationFor: function(oComponentInstance) {
315
- var sTargetComponentId = this._getComponentId(oComponentInstance._sOwnerId, oComponentInstance.getId());
316
- var that = this;
317
- var sCorrectTargetName = null;
318
- Object.keys(this._mTargets).forEach(function(sTargetName) {
319
- if (
320
- that._mTargets[sTargetName].id === sTargetComponentId ||
321
- that._mTargets[sTargetName].viewId === sTargetComponentId
322
- ) {
323
- sCorrectTargetName = sTargetName;
324
- }
325
- });
326
- return this._getTargetInformation(sCorrectTargetName);
327
- },
328
-
329
- getLastSemanticMapping: function() {
330
- return this.oLastSemanticMapping;
331
- },
332
-
333
- setLastSemanticMapping: function(oMapping) {
334
- this.oLastSemanticMapping = oMapping;
335
- },
336
-
337
- navigateTo: function(oContext, sRouteName, mParameterMapping, bPreserveHistory) {
338
- var sTargetURLPromise;
339
- if (!mParameterMapping) {
340
- // if there is no parameter mapping define this mean we rely entirely on the binding context path
341
- sTargetURLPromise = Promise.resolve(SemanticKeyHelper.getSemanticPath(oContext));
342
- } else {
343
- sTargetURLPromise = this.prepareParameters(mParameterMapping, sRouteName, oContext).then(
344
- function(mParameters) {
345
- return this.oRouter.getURL(sRouteName, mParameters);
346
- }.bind(this)
347
- );
348
- }
349
- return sTargetURLPromise.then(
350
- function(sTargetURL) {
351
- this.oRouterProxy.navToHash(sTargetURL, bPreserveHistory);
352
- }.bind(this)
353
- );
354
- },
355
-
356
- /**
357
- * Method to return a map of routing target parameters where the binding syntax is resolved to the current model.
358
- *
359
- * @param {object} mParameters Parameters map in the format [k: string] : ComplexBindingSyntax
360
- * @param {string} sTargetRoute Name of the target route
361
- * @param {object} oContext The instance of the binding context
362
- * @returns {Promise} A promise which resolves to the routing target parameters
363
- */
364
- prepareParameters: function(mParameters, sTargetRoute, oContext) {
365
- var oParametersPromise;
366
- try {
367
- var sContextPath = oContext.getPath();
368
- var aContextPathParts = sContextPath.split("/");
369
- var aAllResolvedParameterPromises = Object.keys(mParameters).map(
370
- function(sParameterKey) {
371
- var sParameterMappingExpression = mParameters[sParameterKey];
372
- // We assume the defined parameters will be compatible with a binding expression
373
- var oParsedExpression = BindingParser.complexParser(sParameterMappingExpression);
374
- var aParts = oParsedExpression.parts || [oParsedExpression];
375
- var aResolvedParameterPromises = aParts.map(function(oPathPart) {
376
- var aRelativeParts = oPathPart.path.split("../");
377
- // We go up the current context path as many times as necessary
378
- var aLocalParts = aContextPathParts.slice(0, aContextPathParts.length - aRelativeParts.length + 1);
379
- aLocalParts.push(aRelativeParts[aRelativeParts.length - 1]);
380
- return oContext.requestProperty(aLocalParts.join("/"));
381
- });
382
-
383
- return Promise.all(aResolvedParameterPromises).then(
384
- function(aResolvedParameters) {
385
- var value = oParsedExpression.formatter
386
- ? oParsedExpression.formatter.apply(this, aResolvedParameters)
387
- : aResolvedParameters.join("");
388
- return { key: sParameterKey, value: value };
389
- }.bind(this)
390
- );
391
- }.bind(this)
392
- );
393
-
394
- oParametersPromise = Promise.all(aAllResolvedParameterPromises).then(function(aAllResolvedParameters) {
395
- var oParameters = {};
396
- aAllResolvedParameters.forEach(function(oResolvedParameter) {
397
- oParameters[oResolvedParameter.key] = oResolvedParameter.value;
398
- });
399
- return oParameters;
400
- });
401
- } catch (oError) {
402
- Log.error("Could not parse the parameters for the navigation to route " + sTargetRoute);
403
- oParametersPromise = Promise.resolve(undefined);
404
- }
405
- return oParametersPromise;
406
- },
407
-
408
- _fireRouteMatchEvents: function(mParameters) {
409
- this.eventProvider.fireEvent("routeMatched", mParameters);
410
- this.eventProvider.fireEvent("afterRouteMatched", mParameters);
411
-
412
- EditState.cleanProcessedEditState(); // Reset UI state when all bindings have been refreshed
413
- },
414
-
415
- /**
416
- * Navigates to a context.
417
- *
418
- * @param {sap.ui.model.odata.v4.Context} oContext The Context to be navigated to
419
- * @param {object} [mParameters] Optional, map containing the following attributes:
420
- * @param {boolean} [mParameters.checkNoHashChange] Navigate to the context without changing the URL
421
- * @param {Promise} [mParameters.asyncContext] The context is created async, navigate to (...) and
422
- * wait for Promise to be resolved and then navigate into the context
423
- * @param {boolean} [mParameters.bDeferredContext] The context shall be created deferred at the target page
424
- * @param {boolean} [mParameters.editable] The target page shall be immediately in the edit mode to avoid flickering
425
- * @param {boolean} [mParameters.bPersistOPScroll] The bPersistOPScroll will be used for scrolling to first tab
426
- * @param {number} [mParameters.updateFCLLevel] `+1` if we add a column in FCL, `-1` to remove a column, 0 to stay on the same column
427
- * @param {boolean} [mParameters.noPreservationCache] Do navigation without taking into account the preserved cache mechanism
428
- * @param {boolean} [mParameters.bRecreateContext] Force re-creation of the context instead of using the one passed as parameter
429
- * @param {boolean} [mParameters.bForceFocus] Forces focus selection after navigation
430
- * @param {object} [oViewData] View data
431
- * @param {object} [oCurrentTargetInfo] The target information from which the navigation is triggered
432
- * @returns {Promise} Promise which is resolved once the navigation is triggered
433
- *
434
- * @ui5-restricted
435
- * @final
436
- */
437
- navigateToContext: function(oContext, mParameters, oViewData, oCurrentTargetInfo) {
438
- var sTargetRoute, oRouteParametersPromise;
439
-
440
- // Manage parameter mapping
441
- if (mParameters.targetPath && oViewData && oViewData.navigation) {
442
- var oRouteDetail = oViewData.navigation[mParameters.targetPath].detail;
443
- sTargetRoute = oRouteDetail.route;
444
-
445
- if (oRouteDetail.parameters) {
446
- oRouteParametersPromise = this.prepareParameters(oRouteDetail.parameters, sTargetRoute, oContext);
447
- }
448
- }
449
-
450
- var sTargetPath = this._getPathFromContext(oContext, mParameters);
451
- // If the path is empty, we're supposed to navigate to the first page of the app
452
- // Check if we need to exit from the app instead
453
- if (sTargetPath.length === 0 && this.bExitOnNavigateBackToRoot) {
454
- return this.oRouterProxy.exitFromApp();
455
- }
456
-
457
- // If the context is deferred or async, we add (...) to the path
458
- if (mParameters.asyncContext || mParameters.bDeferredContext) {
459
- sTargetPath += "(...)";
460
- }
461
-
462
- // Add layout parameter if needed
463
- var sLayout = this._calculateLayout(sTargetPath, mParameters);
464
- if (sLayout) {
465
- sTargetPath += "?layout=" + sLayout;
466
- }
467
-
468
- // Navigation parameters for later usage
469
- var oNavigationInfo = {
470
- oAsyncContext: mParameters.asyncContext,
471
- bDeferredContext: mParameters.bDeferredContext,
472
- bTargetEditable: mParameters.editable,
473
- bPersistOPScroll: mParameters.bPersistOPScroll,
474
- useContext: mParameters.updateFCLLevel === -1 || mParameters.bRecreateContext ? undefined : oContext,
475
- bDraftNavigation: mParameters.bDraftNavigation,
476
- bShowPlaceholder: mParameters.showPlaceholder !== undefined ? mParameters.showPlaceholder : true
477
- };
478
-
479
- if (mParameters.checkNoHashChange) {
480
- // Check if the new hash is different from the current one
481
- var sCurrentHashNoAppState = this.oRouterProxy.getHash().replace(/[&?]{1}sap-iapp-state=[A-Z0-9]+/, "");
482
- if (sTargetPath === sCurrentHashNoAppState) {
483
- // The hash doesn't change, but we fire the routeMatch event to trigger page refresh / binding
484
- var mEventParameters = this.oRouter.getRouteInfoByHash(this.oRouterProxy.getHash());
485
- mEventParameters.navigationInfo = oNavigationInfo;
486
- mEventParameters.routeInformation = this._getRouteInformation(this.sCurrentRouteName);
487
- mEventParameters.routePattern = this.sCurrentRoutePattern;
488
- mEventParameters.views = this.aCurrentViews;
489
- this.oRouterProxy.setFocusForced(mParameters.bForceFocus);
490
-
491
- this._fireRouteMatchEvents(mEventParameters);
492
-
493
- return Promise.resolve();
494
- }
495
- }
496
-
497
- if (mParameters.transient && mParameters.editable == true && sTargetPath.indexOf("(...)") === -1) {
498
- if (sTargetPath.indexOf("?") > -1) {
499
- sTargetPath += "&i-action=create";
500
- } else {
501
- sTargetPath += "?i-action=create";
502
- }
503
- }
504
-
505
- // Clear unbound messages upon navigating from LR to OP
506
- // This is to ensure stale error messages from LR are not shown to the user after navigation to OP.
507
- if (oCurrentTargetInfo && oCurrentTargetInfo.name === "sap.fe.templates.ListReport") {
508
- var oRouteInfo = this.oRouter.getRouteInfoByHash(sTargetPath);
509
- if (oRouteInfo) {
510
- var oRoute = this._getRouteInformation(oRouteInfo.name);
511
- if (oRoute && oRoute.targets && oRoute.targets.length > 0) {
512
- var sLastTargetName = oRoute.targets[oRoute.targets.length - 1];
513
- var oTarget = this._getTargetInformation(sLastTargetName);
514
- if (oTarget && oTarget.name === "sap.fe.templates.ObjectPage") {
515
- MessageHandling.removeUnboundTransitionMessages();
516
- }
517
- }
518
- }
519
- }
520
-
521
- // Add the navigation parameters in the queue
522
- this.navigationInfoQueue.push(oNavigationInfo);
523
-
524
- if (sTargetRoute && oRouteParametersPromise) {
525
- return oRouteParametersPromise.then(
526
- function(oRouteParameters) {
527
- this.oRouter.navTo(sTargetRoute, oRouteParameters);
528
- return Promise.resolve();
529
- }.bind(this)
530
- );
531
- }
532
- return this.oRouterProxy.navToHash(sTargetPath, false, mParameters.noPreservationCache, mParameters.bForceFocus);
533
- },
534
-
535
- /**
536
- * Checks if one of the current views on the screen is bound to a given context.
537
- *
538
- * @param {sap.ui.model.odata.v4.Context} oContext The context
539
- * @returns {boolean} `true` or `false` if the current state is impacted or not
540
- */
541
- isCurrentStateImpactedBy: function(oContext) {
542
- var sPath = oContext.getPath();
543
-
544
- // First, check with the technical path. We have to try it, because for level > 1, we
545
- // uses technical keys even if Semantic keys are enabled
546
- if (this.oRouterProxy.isCurrentStateImpactedBy(sPath)) {
547
- return true;
548
- } else if (/^[^\(\)]+\([^\(\)]+\)$/.test(sPath)) {
549
- // If the current path can be semantic (i.e. is like xxx(yyy))
550
- // check with the semantic path if we can find it
551
- var sSemanticPath;
552
- if (this.oLastSemanticMapping && this.oLastSemanticMapping.technicalPath === sPath) {
553
- // We have already resolved this semantic path
554
- sSemanticPath = this.oLastSemanticMapping.semanticPath;
555
- } else {
556
- sSemanticPath = SemanticKeyHelper.getSemanticPath(oContext);
557
- }
558
-
559
- return sSemanticPath != sPath ? this.oRouterProxy.isCurrentStateImpactedBy(sSemanticPath) : false;
560
- } else {
561
- return false;
562
- }
563
- },
564
-
565
- _findPathToNavigate: function(sPath) {
566
- var regex = new RegExp("/[^/]*$");
567
- sPath = sPath.replace(regex, "");
568
- if (this.oRouter.match(sPath) || sPath === "") {
569
- return sPath;
570
- } else {
571
- return this._findPathToNavigate(sPath);
572
- }
573
- },
574
-
575
- _checkContextForSemanticPath: function(oContext) {
576
- var sPath = oContext.getPath();
577
-
578
- // First, check if this is a level-1 object (path = /aaa(bbb))
579
- if (!/^\/[^\(]+\([^\)]+\)$/.test(sPath)) {
580
- return false;
581
- }
582
-
583
- // Then check if the entity has semantic keys
584
- var oMetaModel = oContext.getModel().getMetaModel(),
585
- sEntitySetName = oMetaModel.getMetaContext(oContext.getPath()).getObject("@sapui.name");
586
- if (!SemanticKeyHelper.getSemanticKeys(oMetaModel, sEntitySetName)) {
587
- return false;
588
- }
589
-
590
- // Then check the entity is draft-enabled
591
- return ModelHelper.isDraftSupported(oMetaModel, sPath);
592
- },
593
-
594
- _getPathFromContext: function(oContext, mParameters) {
595
- var sPath;
596
-
597
- if (oContext.isA("sap.ui.model.odata.v4.ODataListBinding") && oContext.isRelative()) {
598
- sPath = oContext.getHeaderContext().getPath();
599
- } else {
600
- sPath = oContext.getPath();
601
- }
602
-
603
- if (mParameters.updateFCLLevel === -1) {
604
- // When navigating back from a context, we need to remove the last component of the path
605
- sPath = this._findPathToNavigate(sPath);
606
-
607
- // Check if we're navigating back to a semantic path that was previously resolved
608
- if (this.oLastSemanticMapping && this.oLastSemanticMapping.technicalPath === sPath) {
609
- sPath = this.oLastSemanticMapping.semanticPath;
610
- }
611
- } else if (this._checkContextForSemanticPath(oContext)) {
612
- // We check if we have to use a semantic path
613
- var sSemanticPath = SemanticKeyHelper.getSemanticPath(oContext, true);
614
-
615
- if (!sSemanticPath) {
616
- // We were not able to build the semantic path --> Use the technical path and
617
- // clear the previous mapping, otherwise the old mapping is used in EditFlow#updateDocument
618
- // and it leads to unwanted page reloads
619
- this.setLastSemanticMapping(undefined);
620
- } else if (sSemanticPath !== sPath) {
621
- // Store the mapping technical <-> semantic path to avoid recalculating it later
622
- // and use the semantic path instead of the technical one
623
- this.setLastSemanticMapping({ technicalPath: sPath, semanticPath: sSemanticPath });
624
- sPath = sSemanticPath;
625
- }
626
- }
627
-
628
- // remove extra '/' at the beginning of path
629
- if (sPath[0] === "/") {
630
- sPath = sPath.substring(1);
631
- }
632
-
633
- return sPath;
634
- },
635
-
636
- _calculateLayout: function(sPath, mParameters) {
637
- var FCLLevel = mParameters.FCLLevel;
638
- if (mParameters.updateFCLLevel) {
639
- FCLLevel += mParameters.updateFCLLevel;
640
- if (FCLLevel < 0) {
641
- FCLLevel = 0;
642
- }
643
- }
644
-
645
- return this.oAppComponent.getRootViewController().calculateLayout(FCLLevel, sPath, mParameters.sLayout);
646
- },
647
-
648
- /**
649
- * Event handler before a route is matched.
650
- * Displays a busy indicator.
651
- *
652
- * @param {object} oEvent The event
653
- */
654
- _beforeRouteMatched: function(oEvent) {
655
- var bPlaceholderEnabled = new Placeholder().isPlaceholderEnabled();
656
- if (!bPlaceholderEnabled) {
657
- var oRootView = this.oAppComponent.getRootControl();
658
- BusyLocker.lock(oRootView);
659
- }
660
- },
661
-
662
- /**
663
- * Event handler when a route is matched.
664
- * Hides the busy indicator and fires its own 'routematched' event.
665
- *
666
- * @param {object} oEvent The event
667
- */
668
- _onRouteMatched: function(oEvent) {
669
- var oAppStateHandler = this.oAppComponent.getAppStateHandler(),
670
- oRootView = this.oAppComponent.getRootControl(),
671
- that = this;
672
- var bPlaceholderEnabled = new Placeholder().isPlaceholderEnabled();
673
- if (BusyLocker.isLocked(oRootView) && !bPlaceholderEnabled) {
674
- BusyLocker.unlock(oRootView);
675
- }
676
- var mParameters = oEvent.getParameters();
677
- if (this.navigationInfoQueue.length) {
678
- mParameters.navigationInfo = this.navigationInfoQueue[0];
679
- this.navigationInfoQueue = this.navigationInfoQueue.slice(1);
680
- } else {
681
- mParameters.navigationInfo = {};
682
- }
683
- if (oAppStateHandler.checkIfRouteChangedByIApp()) {
684
- mParameters.navigationInfo.bReasonIsIappState = true;
685
- oAppStateHandler.resetRouteChangedByIApp();
686
- }
687
-
688
- this.sCurrentRouteName = oEvent.getParameter("name");
689
- this.sCurrentRoutePattern = oEvent.getParameters().config.pattern;
690
- this.aCurrentViews = oEvent.getParameter("views");
691
-
692
- mParameters.routeInformation = this._getRouteInformation(this.sCurrentRouteName);
693
- mParameters.routePattern = this.sCurrentRoutePattern;
694
-
695
- this._fireRouteMatchEvents(mParameters);
696
-
697
- // Check if current hash has been set by the routerProxy.navToHash function
698
- // If not, rebuild history properly (both in the browser and the RouterProxy)
699
- if (!history.state || history.state.feLevel === undefined) {
700
- this.oRouterProxy
701
- .restoreHistory()
702
- .then(function() {
703
- that.oRouterProxy.resolveRouteMatch();
704
- })
705
- .catch(function(oError) {
706
- Log.error("Error while restoring history", oError);
707
- });
708
- } else {
709
- this.oRouterProxy.resolveRouteMatch();
710
- }
711
- },
712
-
713
- attachRouteMatched: function(oData, fnFunction, oListener) {
714
- this.eventProvider.attachEvent("routeMatched", oData, fnFunction, oListener);
715
- },
716
- detachRouteMatched: function(fnFunction, oListener) {
717
- this.eventProvider.detachEvent("routeMatched", fnFunction, oListener);
718
- },
719
- attachAfterRouteMatched: function(oData, fnFunction, oListener) {
720
- this.eventProvider.attachEvent("afterRouteMatched", oData, fnFunction, oListener);
721
- },
722
- detachAfterRouteMatched: function(fnFunction, oListener) {
723
- this.eventProvider.detachEvent("afterRouteMatched", fnFunction, oListener);
724
- },
725
-
726
- getRouteFromHash: function(oRouter, oAppComponent) {
727
- var sHash = oRouter.getHashChanger().hash;
728
- var oRouteInfo = oRouter.getRouteInfoByHash(sHash);
729
- return oAppComponent
730
- .getMetadata()
731
- .getManifestEntry("/sap.ui5/routing/routes")
732
- .filter(function(oRoute) {
733
- return oRoute.name === oRouteInfo.name;
734
- })[0];
735
- },
736
- getTargetsFromRoute: function(oRoute, oAppComponent) {
737
- var oTarget = oRoute.target;
738
- var that = this;
739
- if (typeof oTarget === "string") {
740
- return [this._mTargets[oTarget]];
741
- } else {
742
- var aTarget = [];
743
- oTarget.forEach(function(sTarget) {
744
- aTarget.push(that._mTargets[sTarget]);
745
- });
746
- return aTarget;
747
- }
748
- },
749
-
750
- initializeRouting: function() {
751
- var that = this;
752
-
753
- // Attach router handlers
754
- this._fnOnRouteMatched = this._onRouteMatched.bind(this);
755
- this.oRouter.attachRouteMatched(this._fnOnRouteMatched);
756
- var bPlaceholderEnabled = new Placeholder().isPlaceholderEnabled();
757
- if (!bPlaceholderEnabled) {
758
- this.oRouter.attachBeforeRouteMatched(this._beforeRouteMatched.bind(this));
759
- }
760
- // Reset internal state
761
- this.navigationInfoQueue = [];
762
- EditState.resetEditState();
763
- this.bExitOnNavigateBackToRoot = !this.oRouter.match("");
764
-
765
- var bIsIappState =
766
- that.oRouter
767
- .getHashChanger()
768
- .getHash()
769
- .indexOf("sap-iapp-state") !== -1;
770
- var initPromise = that.oAppComponent
771
- .getStartupParameters()
772
- .then(function(oStartupParameters) {
773
- var bHasStartUpParameters = oStartupParameters !== undefined && Object.keys(oStartupParameters).length !== 0;
774
- // Manage startup parameters (in case of no iapp-state)
775
- if (!bIsIappState && bHasStartUpParameters) {
776
- var sHash = that.oRouter.getHashChanger().getHash();
777
- if (
778
- oStartupParameters.preferredMode &&
779
- oStartupParameters.preferredMode[0].indexOf("create") !== -1 &&
780
- !sHash
781
- ) {
782
- // Logic for create mode
783
- return that._managePreferredModeCreateStartup(oStartupParameters);
784
- } else {
785
- return that._manageDeeplinkStartup(oStartupParameters);
786
- }
787
- }
788
- })
789
- .catch(function(oError) {
790
- Log.error("Error during routing initialization", oError);
791
- });
792
-
793
- return initPromise;
794
- },
795
-
796
- getDefaultCreateHash: function(oStartupParameters) {
797
- var sContextPath = this.getContextPath(),
798
- sDefaultCreateHash =
799
- oStartupParameters && oStartupParameters.preferredMode ? oStartupParameters.preferredMode[0] : "create",
800
- sHash;
801
-
802
- sDefaultCreateHash =
803
- sDefaultCreateHash.indexOf(":") !== -1 && sDefaultCreateHash.length > sDefaultCreateHash.indexOf(":") + 1
804
- ? sDefaultCreateHash.substr(0, sDefaultCreateHash.indexOf(":"))
805
- : "create";
806
- sHash = sContextPath.substring(1) + "(...)?i-action=" + sDefaultCreateHash;
807
- if (this.oRouter.getRouteInfoByHash(sHash)) {
808
- return sHash;
809
- } else {
810
- throw new Error("No route match for creating a new " + sContextPath.substring(1));
811
- }
812
- },
813
-
814
- _managePreferredModeCreateStartup: function(oStartupParameters) {
815
- var that = this;
816
- return this.oMetaModel
817
- .requestObject(this.getContextPath() + "@")
818
- .then(function(oEntitySetAnnotations) {
819
- var sMetaPath,
820
- bCreatable = true;
821
- if (
822
- oEntitySetAnnotations["@com.sap.vocabularies.Common.v1.DraftRoot"] &&
823
- oEntitySetAnnotations["@com.sap.vocabularies.Common.v1.DraftRoot"]["NewAction"]
824
- ) {
825
- sMetaPath =
826
- that.getContextPath() +
827
- "@com.sap.vocabularies.Common.v1.DraftRoot/NewAction@Org.OData.Core.V1.OperationAvailable";
828
- } else if (
829
- oEntitySetAnnotations["@com.sap.vocabularies.Session.v1.StickySessionSupported"] &&
830
- oEntitySetAnnotations["@com.sap.vocabularies.Session.v1.StickySessionSupported"]["NewAction"]
831
- ) {
832
- sMetaPath =
833
- that.getContextPath() +
834
- "@com.sap.vocabularies.Session.v1.StickySessionSupported/NewAction@Org.OData.Core.V1.OperationAvailable";
835
- }
836
- if (sMetaPath) {
837
- var bNewActionOperationAvailable = that.oMetaModel.getObject(sMetaPath);
838
- if (bNewActionOperationAvailable === false) {
839
- bCreatable = false;
840
- }
841
- } else {
842
- var oInsertRestrictions = oEntitySetAnnotations["@Org.OData.Capabilities.V1.InsertRestrictions"];
843
- if (oInsertRestrictions && oInsertRestrictions.Insertable === false) {
844
- bCreatable = false;
845
- }
846
- }
847
- if (bCreatable) {
848
- var sPath = that.getDefaultCreateHash(oStartupParameters);
849
- that.oRouter.getHashChanger().replaceHash(sPath);
850
- that.bExitOnNavigateBackToRoot = true;
851
- }
852
- })
853
- .catch(function() {
854
- Log.error("Cannot fetch the Annotations");
855
- });
856
- },
857
-
858
- _requestObjectsFromParameters: function(oStartUpParameters, aExternallyNavigablePages) {
859
- var that = this;
860
-
861
- // Load the respective objects for all object pages found in aExternallyNavigablePages
862
- var aContextPromises = aExternallyNavigablePages.map(function(oPage) {
863
- var oCompleteFilter, oListBind;
864
- if (oPage.isSemanticKeyNavigation) {
865
- oCompleteFilter = that._createFilter(oPage.draft, oPage.semanticKeys, oStartUpParameters);
866
- } else {
867
- oCompleteFilter = that._createFilter(oPage.draft, oPage.technicalKeys, oStartUpParameters);
868
- }
869
- // only request a minimum of fields to boost backend performance since this is only used to check if an object exists
870
- oListBind = that.oModel.bindList(oPage.contextPath, undefined, undefined, oCompleteFilter, {
871
- "$select": oPage.isSemanticKeyNavigation
872
- ? oPage.semanticKeys.map(function(key) {
873
- return key.$PropertyPath;
874
- })
875
- : oPage.technicalKeys
876
- });
877
- return oListBind.requestContexts(0, 2);
878
- });
879
-
880
- return Promise.all(aContextPromises);
881
- },
882
-
883
- _manageDeeplinkStartup: function(oStartUpParameters) {
884
- var that = this,
885
- aExternallyNavigablePages;
886
-
887
- // Need to preload the entity set informations in the metamodel
888
- return this.oMetaModel
889
- .requestObject("/$EntityContainer/")
890
- .then(function() {
891
- // Check if semantic keys are present in url parameters for every object page at each level
892
- var oLevelOfObjectPages = that._getNavigablePages(that.oAppComponent.getManifest()["sap.ui5"].routing);
893
-
894
- aExternallyNavigablePages = that._findTargetPagesFromStartupParams(oLevelOfObjectPages, oStartUpParameters);
895
-
896
- return that._requestObjectsFromParameters(oStartUpParameters, aExternallyNavigablePages);
897
- })
898
- .then(function(aValues) {
899
- if (aValues.length) {
900
- // Make sure we only get 1 context per promise, and flatten the array
901
- var aContexts = [];
902
- aValues.forEach(function(aFoundContexts) {
903
- if (aFoundContexts.length === 1) {
904
- aContexts.push(aFoundContexts[0]);
905
- }
906
- });
907
-
908
- // Keep hash if navigation has been done, navigation takes precedence over Startup parameters
909
- if (aContexts.length === aValues.length && !that.oRouter.getHashChanger().getHash()) {
910
- var sHash = that._buildStartupHash(aExternallyNavigablePages, aContexts);
911
- if (sHash) {
912
- //Replace the hash with newly created hash
913
- that.oRouter.getHashChanger().replaceHash(sHash);
914
- }
915
- }
916
- }
917
- })
918
- .catch(function(error) {
919
- Log.info("Could not find results for list bind: " + error);
920
- });
921
- },
922
-
923
- _getNavigablePages: function(oRouting) {
924
- var aRoutes = oRouting.routes,
925
- oTargets = oRouting.targets,
926
- mPageMap = {};
927
- for (var i = 0; i < aRoutes.length; i++) {
928
- var oPage = {},
929
- sPattern = aRoutes[i].pattern,
930
- sTarget = aRoutes[i].target,
931
- iLevel = sPattern.split("/").length - 1;
932
- oPage["pattern"] = sPattern;
933
- if (sPattern === ":?query:" || sPattern === "") {
934
- continue;
935
- }
936
- if (iLevel === 1 && sPattern.split("/")[iLevel] === ":?query:") {
937
- iLevel = 0;
938
- }
939
- oPage["level"] = iLevel;
940
- if (Array.isArray(sTarget)) {
941
- //target is Array in case of FCL
942
- oPage["target"] = sTarget[sTarget.length - 1];
943
- } else {
944
- oPage["target"] = sTarget;
945
- }
946
- if (oTargets[oPage.target].options && oTargets[oPage.target].options.settings) {
947
- oPage["allowDeepLinking"] = oTargets[oPage.target].options.settings.allowDeepLinking;
948
- var sContextPath =
949
- oTargets[oPage.target].options.settings.contextPath ||
950
- (oTargets[oPage.target].options.settings.entitySet && "/" + oTargets[oPage.target].options.settings.entitySet);
951
- oPage["contextPath"] = sContextPath;
952
- }
953
- if (!oPage["allowDeepLinking"] && oPage["level"] !== 0) {
954
- continue;
955
- } else if (!mPageMap[oPage.level]) {
956
- mPageMap[oPage.level] = [];
957
- }
958
- mPageMap[oPage.level].push(oPage);
959
- }
960
- return mPageMap;
961
- },
962
-
963
- /**
964
- * For each level (starting at 0), find the first object page corresponding to an object
965
- * that can be determined with the keys passed as startup parameters.
966
- * Stop when no OP that can be can be found for a given level.
967
- *
968
- * @param {object} mPagesByLevel A map (level --> array of pages at that level)
969
- * @param {object} oStartupParameters The startup parameters of the application
970
- * @returns {Array} Array of all pages that can be reached with the provided parameters
971
- */
972
- _findTargetPagesFromStartupParams: function(mPagesByLevel, oStartupParameters) {
973
- var iLevel = 0,
974
- aReachablePages = [],
975
- bFound = true;
976
-
977
- while (bFound && iLevel in mPagesByLevel) {
978
- var aObjectPages = mPagesByLevel[iLevel];
979
-
980
- // loop through pages at each level
981
- // use for-loop to break early
982
- bFound = false;
983
- for (var i = 0; i < aObjectPages.length; ++i) {
984
- var oObjectPage = aObjectPages[i];
985
- if (!oObjectPage.contextPath && oObjectPage.level === 0) {
986
- oObjectPage.contextPath = this.getContextPath();
987
- }
988
- if (!oObjectPage.contextPath) {
989
- continue;
990
- }
991
-
992
- oObjectPage.entityType = this.oMetaModel.getObject("/$EntityContainer" + oObjectPage.contextPath + "/");
993
- oObjectPage.draft =
994
- this.oMetaModel.getObject(
995
- "/$EntityContainer" + oObjectPage.contextPath + "@com.sap.vocabularies.Common.v1.DraftRoot"
996
- ) ||
997
- this.oMetaModel.getObject(
998
- "/$EntityContainer" + oObjectPage.contextPath + "@com.sap.vocabularies.Common.v1.DraftNode"
999
- );
1000
- oObjectPage.technicalKeys = oObjectPage.entityType["$Key"];
1001
- oObjectPage.semanticKeys = this.oMetaModel.getObject(
1002
- "/$EntityContainer" + oObjectPage.contextPath + "/@com.sap.vocabularies.Common.v1.SemanticKey"
1003
- );
1004
-
1005
- if (this._checkForKeys(oObjectPage.semanticKeys, oStartupParameters)) {
1006
- // make record if semantic keys are available in URL params
1007
- oObjectPage.isSemanticKeyNavigation = true;
1008
- aReachablePages.push(oObjectPage);
1009
- bFound = true;
1010
- break;
1011
- } else if (oObjectPage.level === 0 && this._checkForKeys(oObjectPage.technicalKeys, oStartupParameters)) {
1012
- // Support for Technical Keys for root level object page
1013
- oObjectPage.isSemanticKeyNavigation = false;
1014
- aReachablePages.push(oObjectPage);
1015
- bFound = true;
1016
- break;
1017
- }
1018
- }
1019
-
1020
- ++iLevel;
1021
- }
1022
-
1023
- return aReachablePages;
1024
- },
1025
-
1026
- /**
1027
- * Creates the filter for the entity set.
1028
- *
1029
- * @param {object} oDraftDetail The details of draft node
1030
- * @param {Array} aKeys Array of semantic keys or technical keys of the page
1031
- * @param {object} oStartUpParameters URL parameters
1032
- * @returns {object} Filters for the entity set
1033
- */
1034
- _createFilter: function(oDraftDetail, aKeys, oStartUpParameters) {
1035
- var aFilters = [],
1036
- bFilteringCaseSensitive = ModelHelper.isFilteringCaseSensitive(this.oMetaModel);
1037
-
1038
- for (var j = 0; j < aKeys.length; j++) {
1039
- var sProperty = aKeys[j].$PropertyPath;
1040
- if (!sProperty) {
1041
- // Technical Keys Scenario
1042
- sProperty = aKeys[j];
1043
- if (sProperty === "IsActiveEntity") {
1044
- oDraftDetail = false;
1045
- }
1046
- }
1047
- var sValue = oStartUpParameters[sProperty][0];
1048
- if (sValue) {
1049
- aFilters.push(
1050
- new Filter({
1051
- path: sProperty,
1052
- operator: FilterOperator.EQ,
1053
- value1: sValue,
1054
- caseSensitive: bFilteringCaseSensitive
1055
- })
1056
- );
1057
- } else {
1058
- return undefined;
1059
- }
1060
- }
1061
- if (oDraftDetail) {
1062
- var oDraftFilter = new Filter({
1063
- filters: [new Filter("IsActiveEntity", "EQ", false), new Filter("SiblingEntity/IsActiveEntity", "EQ", null)],
1064
- and: false
1065
- });
1066
- aFilters.push(oDraftFilter);
1067
- }
1068
- var oCompleteFilter = new Filter(aFilters, true);
1069
- return oCompleteFilter;
1070
- },
1071
-
1072
- /**
1073
- * Check for Semantic Keys/ Technical Keys in the URL.
1074
- *
1075
- * @param {Array} aKeys Array of semantic keys or technical keys of the page
1076
- * @param {object} oParameters URL parameters
1077
- * @returns {boolean} True if Semantic Keys are available in URL
1078
- */
1079
- _checkForKeys: function(aKeys, oParameters) {
1080
- if (aKeys && aKeys.length) {
1081
- for (var j = 0; j < aKeys.length; j++) {
1082
- var sPropertyPath = aKeys[j].$PropertyPath;
1083
- if (!sPropertyPath) {
1084
- // Technical Keys do not require $ProperyPath
1085
- sPropertyPath = aKeys[j];
1086
- }
1087
- var aPropertyValue = oParameters[sPropertyPath];
1088
- if (!aPropertyValue || (aPropertyValue && aPropertyValue.length > 1)) {
1089
- return false;
1090
- }
1091
- }
1092
- return true;
1093
- }
1094
- return false;
1095
- },
1096
-
1097
- _buildStartupHash: function(aReachablePages, aContexts) {
1098
- var sHash;
1099
-
1100
- if (aContexts.length === 1) {
1101
- // Navigation to first-level object page
1102
- // We check if we have to use a semantic path
1103
- var sTechnicalPath = aContexts[0].getPath(),
1104
- sSemanticPath = SemanticKeyHelper.getSemanticPath(aContexts[0]);
1105
-
1106
- if (sSemanticPath !== sTechnicalPath) {
1107
- // Store the mapping technical <-> semantic path to avoid recalculating it later
1108
- // and use the semantic path instead of the technical one
1109
- this.setLastSemanticMapping({ technicalPath: sTechnicalPath, semanticPath: sSemanticPath });
1110
- }
1111
-
1112
- sHash = sSemanticPath.substring(1); // To remove the leading '/'
1113
- } else if (aContexts.length > 1) {
1114
- // Navigation to a deeper level --> use the pattern of the deepest object page
1115
- // and replace the parameters by the ID from the contexts
1116
- var aParts = aReachablePages[aReachablePages.length - 1].pattern.split("/");
1117
-
1118
- sHash = aParts
1119
- .map(function(sPart, iIndex) {
1120
- var sKey = sPart.split("(")[0];
1121
- var sValue = aContexts[iIndex].getPath().split("(")[1];
1122
- return sKey + "(" + sValue; // sValue contains the closing ')'
1123
- })
1124
- .join("/");
1125
- }
1126
-
1127
- return sHash;
1128
- },
1129
-
1130
- getOutbounds: function() {
1131
- return this.outbounds;
1132
- },
1133
-
1134
- /**
1135
- * Gets the name of the Draft root entity set or the sticky-enabled entity set.
1136
- *
1137
- * @returns {string} The name of the root EntitySet
1138
- *
1139
- * @ui5-restricted
1140
- */
1141
- getContextPath: function() {
1142
- return this.sContextPath;
1143
- }
1144
- });
1145
-
1146
- return ServiceFactory.extend("sap.fe.core.services.RoutingServiceFactory", {
1147
- createInstance: function(oServiceContext) {
1148
- var oRoutingService = new RoutingService(oServiceContext);
1149
- return oRoutingService.initPromise;
1150
- }
1151
- });
1152
- },
1153
- true
1154
- );
5
+ sap.ui.define(["sap/ui/core/service/Service", "sap/ui/core/service/ServiceFactory", "sap/ui/base/BindingParser", "sap/fe/core/helpers/SemanticKeyHelper", "sap/base/Log", "sap/ui/base/EventProvider", "sap/fe/core/BusyLocker", "sap/fe/core/helpers/ModelHelper", "sap/fe/core/helpers/EditState", "sap/fe/core/actions/messageHandling", "sap/fe/core/controllerextensions/Placeholder", "sap/fe/core/helpers/AppStartupHelper", "sap/ui/model/odata/v4/ODataUtils"], function (Service, ServiceFactory, BindingParser, SemanticKeyHelper, Log, EventProvider, BusyLocker, ModelHelper, EditState, messageHandling, Placeholder, AppStartupHelper, ODataUtils) {
6
+ "use strict";
7
+
8
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
9
+
10
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
11
+
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
13
+
14
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
15
+
16
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
17
+
18
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
19
+
20
+ function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
21
+
22
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
23
+
24
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
25
+
26
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
27
+
28
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
29
+
30
+ var RoutingServiceEventing = EventProvider.extend("sap.fe.core.services.RoutingServiceEventing", {
31
+ metadata: {
32
+ events: {
33
+ "routeMatched": {},
34
+ "afterRouteMatched": {}
35
+ }
36
+ }
37
+ });
38
+
39
+ var RoutingService = /*#__PURE__*/function (_Service) {
40
+ _inherits(RoutingService, _Service);
41
+
42
+ var _super = _createSuper(RoutingService);
43
+
44
+ function RoutingService() {
45
+ var _this;
46
+
47
+ _classCallCheck(this, RoutingService);
48
+
49
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
50
+ args[_key] = arguments[_key];
51
+ }
52
+
53
+ _this = _super.call.apply(_super, [this].concat(args));
54
+
55
+ _defineProperty(_assertThisInitialized(_this), "navigationInfoQueue", []);
56
+
57
+ return _this;
58
+ }
59
+
60
+ _createClass(RoutingService, [{
61
+ key: "init",
62
+ value: function init() {
63
+ var oContext = this.getContext();
64
+
65
+ if (oContext.scopeType === "component") {
66
+ this.oAppComponent = oContext.scopeObject;
67
+ this.oModel = this.oAppComponent.getModel();
68
+ this.oMetaModel = this.oModel.getMetaModel();
69
+ this.oRouter = this.oAppComponent.getRouter();
70
+ this.oRouterProxy = this.oAppComponent.getRouterProxy();
71
+ this.eventProvider = new RoutingServiceEventing();
72
+ var oRoutingConfig = this.oAppComponent.getManifestEntry("/sap.ui5/routing");
73
+ var oRootViewConfig = this.oAppComponent.getManifestEntry("/sap.ui5/rootView");
74
+
75
+ this._parseRoutingConfiguration(oRoutingConfig, oRootViewConfig);
76
+
77
+ var oAppConfig = this.oAppComponent.getManifestEntry("/sap.app");
78
+ this.outbounds = oAppConfig && oAppConfig.crossNavigation && oAppConfig.crossNavigation.outbounds;
79
+ }
80
+
81
+ this.initPromise = Promise.resolve(this);
82
+ }
83
+ }, {
84
+ key: "beforeExit",
85
+ value: function beforeExit() {
86
+ this.oRouter.detachRouteMatched(this._fnOnRouteMatched, this);
87
+ this.eventProvider.fireEvent("routeMatched", {});
88
+ }
89
+ }, {
90
+ key: "exit",
91
+ value: function exit() {
92
+ this.eventProvider.destroy();
93
+ }
94
+ /**
95
+ * Parse a manifest routing configuration for internal usage.
96
+ *
97
+ * @param {object} oRoutingConfig The routing configuration from the manifest
98
+ * @param {object} oRootViewConfig The root view configuration from the manifest
99
+ * @private
100
+ */
101
+
102
+ }, {
103
+ key: "_parseRoutingConfiguration",
104
+ value: function _parseRoutingConfiguration(oRoutingConfig, oRootViewConfig) {
105
+ var _this2 = this;
106
+
107
+ var isFCL = oRootViewConfig && oRootViewConfig.viewName === "sap.fe.templates.RootContainer.view.Fcl"; // Information of targets
108
+
109
+ this._mTargets = {};
110
+ Object.keys(oRoutingConfig.targets).forEach(function (sTargetName) {
111
+ _this2._mTargets[sTargetName] = Object.assign({
112
+ targetName: sTargetName
113
+ }, oRoutingConfig.targets[sTargetName]); // View level for FCL cases is calculated from the target pattern
114
+
115
+ if (_this2._mTargets[sTargetName].contextPattern !== undefined) {
116
+ _this2._mTargets[sTargetName].viewLevel = _this2._getViewLevelFromPattern(_this2._mTargets[sTargetName].contextPattern, 0);
117
+ }
118
+ }); // Information of routes
119
+
120
+ this._mRoutes = {};
121
+
122
+ for (var sRouteKey in oRoutingConfig.routes) {
123
+ var oRouteManifestInfo = oRoutingConfig.routes[sRouteKey],
124
+ aRouteTargets = Array.isArray(oRouteManifestInfo.target) ? oRouteManifestInfo.target : [oRouteManifestInfo.target],
125
+ sRouteName = Array.isArray(oRoutingConfig.routes) ? oRouteManifestInfo.name : sRouteKey,
126
+ sRoutePattern = oRouteManifestInfo.pattern; // Check route pattern: all patterns need to end with ':?query:', that we use for parameters
127
+
128
+ if (sRoutePattern.length < 8 || sRoutePattern.indexOf(":?query:") !== sRoutePattern.length - 8) {
129
+ Log.warning("Pattern for route " + sRouteName + " doesn't end with ':?query:' : " + sRoutePattern);
130
+ }
131
+
132
+ var iRouteLevel = this._getViewLevelFromPattern(sRoutePattern, 0);
133
+
134
+ this._mRoutes[sRouteName] = {
135
+ name: sRouteName,
136
+ pattern: sRoutePattern,
137
+ targets: aRouteTargets,
138
+ routeLevel: iRouteLevel
139
+ }; // Add the parent targets in the list of targets for the route
140
+
141
+ for (var i = 0; i < aRouteTargets.length; i++) {
142
+ var sParentTargetName = this._mTargets[aRouteTargets[i]].parent;
143
+
144
+ if (sParentTargetName) {
145
+ aRouteTargets.push(sParentTargetName);
146
+ }
147
+ }
148
+
149
+ if (!isFCL) {
150
+ // View level for non-FCL cases is calculated from the route pattern
151
+ if (this._mTargets[aRouteTargets[0]].viewLevel === undefined || this._mTargets[aRouteTargets[0]].viewLevel < iRouteLevel) {
152
+ // There are cases when different routes point to the same target. We take the
153
+ // largest viewLevel in that case.
154
+ this._mTargets[aRouteTargets[0]].viewLevel = iRouteLevel;
155
+ } // FCL level for non-FCL cases is equal to -1
156
+
157
+
158
+ this._mTargets[aRouteTargets[0]].FCLLevel = -1;
159
+ } else if (aRouteTargets.length === 1 && this._mTargets[aRouteTargets[0]].controlAggregation !== "beginColumnPages") {
160
+ // We're in the case where there's only 1 target for the route, and it's not in the first column
161
+ // --> this is a fullscreen column after all columns in the FCL have been used
162
+ this._mTargets[aRouteTargets[0]].FCLLevel = 3;
163
+ } else {
164
+ // Other FCL cases
165
+ aRouteTargets.forEach(function (sTargetName) {
166
+ switch (_this2._mTargets[sTargetName].controlAggregation) {
167
+ case "beginColumnPages":
168
+ _this2._mTargets[sTargetName].FCLLevel = 0;
169
+ break;
170
+
171
+ case "midColumnPages":
172
+ _this2._mTargets[sTargetName].FCLLevel = 1;
173
+ break;
174
+
175
+ default:
176
+ _this2._mTargets[sTargetName].FCLLevel = 2;
177
+ }
178
+ });
179
+ }
180
+ } // Propagate viewLevel, contextPattern, FCLLevel and controlAggregation to parent targets
181
+
182
+
183
+ Object.keys(this._mTargets).forEach(function (sTargetName) {
184
+ while (_this2._mTargets[sTargetName].parent) {
185
+ var _sParentTargetName = _this2._mTargets[sTargetName].parent;
186
+ _this2._mTargets[_sParentTargetName].viewLevel = _this2._mTargets[_sParentTargetName].viewLevel || _this2._mTargets[sTargetName].viewLevel;
187
+ _this2._mTargets[_sParentTargetName].contextPattern = _this2._mTargets[_sParentTargetName].contextPattern || _this2._mTargets[sTargetName].contextPattern;
188
+ _this2._mTargets[_sParentTargetName].FCLLevel = _this2._mTargets[_sParentTargetName].FCLLevel || _this2._mTargets[sTargetName].FCLLevel;
189
+ _this2._mTargets[_sParentTargetName].controlAggregation = _this2._mTargets[_sParentTargetName].controlAggregation || _this2._mTargets[sTargetName].controlAggregation;
190
+ sTargetName = _sParentTargetName;
191
+ }
192
+ }); // Determine the root entity for the app
193
+
194
+ var aLevel0RouteNames = [];
195
+ var aLevel1RouteNames = [];
196
+ var sDefaultRouteName;
197
+
198
+ for (var sName in this._mRoutes) {
199
+ var iLevel = this._mRoutes[sName].routeLevel;
200
+
201
+ if (iLevel === 0) {
202
+ aLevel0RouteNames.push(sName);
203
+ } else if (iLevel === 1) {
204
+ aLevel1RouteNames.push(sName);
205
+ }
206
+ }
207
+
208
+ if (aLevel0RouteNames.length === 1) {
209
+ sDefaultRouteName = aLevel0RouteNames[0];
210
+ } else if (aLevel1RouteNames.length === 1) {
211
+ sDefaultRouteName = aLevel1RouteNames[0];
212
+ }
213
+
214
+ if (sDefaultRouteName) {
215
+ var sDefaultTargetName = this._mRoutes[sDefaultRouteName].targets.slice(-1)[0];
216
+
217
+ this.sContextPath = "";
218
+
219
+ if (this._mTargets[sDefaultTargetName].options && this._mTargets[sDefaultTargetName].options.settings) {
220
+ var oSettings = this._mTargets[sDefaultTargetName].options.settings;
221
+ this.sContextPath = oSettings.contextPath || "/" + oSettings.entitySet;
222
+ }
223
+
224
+ if (!this.sContextPath) {
225
+ Log.warning("Cannot determine default contextPath: contextPath or entitySet missing in default target: " + sDefaultTargetName);
226
+ }
227
+ } else {
228
+ Log.warning("Cannot determine default contextPath: no default route found.");
229
+ } // We need to establish the correct path to the different pages, including the navigation properties
230
+
231
+
232
+ Object.keys(this._mTargets).map(function (sTargetKey) {
233
+ return _this2._mTargets[sTargetKey];
234
+ }).sort(function (a, b) {
235
+ return a.viewLevel < b.viewLevel ? -1 : 1;
236
+ }).forEach(function (target) {
237
+ // After sorting the targets per level we can then go through their navigation object and update the paths accordingly.
238
+ if (target.options) {
239
+ var settings = target.options.settings;
240
+ var sContextPath = settings.contextPath || (settings.entitySet ? "/" + settings.entitySet : "");
241
+
242
+ if (!settings.fullContextPath && sContextPath) {
243
+ settings.fullContextPath = sContextPath + "/";
244
+ }
245
+
246
+ Object.keys(settings.navigation || {}).forEach(function (sNavName) {
247
+ // Check if it's a navigation property
248
+ var targetRoute = _this2._mRoutes[settings.navigation[sNavName].detail.route];
249
+
250
+ if (targetRoute && targetRoute.targets) {
251
+ targetRoute.targets.forEach(function (sTargetName) {
252
+ if (_this2._mTargets[sTargetName].options && _this2._mTargets[sTargetName].options.settings && !_this2._mTargets[sTargetName].options.settings.fullContextPath) {
253
+ if (target.viewLevel === 0) {
254
+ _this2._mTargets[sTargetName].options.settings.fullContextPath = "/" + sNavName + "/";
255
+ } else {
256
+ _this2._mTargets[sTargetName].options.settings.fullContextPath = settings.fullContextPath + sNavName + "/";
257
+ }
258
+ }
259
+ });
260
+ }
261
+ });
262
+ }
263
+ });
264
+ }
265
+ /**
266
+ * Calculates a view level from a pattern by counting the number of segments.
267
+ *
268
+ * @param {string} sPattern The pattern
269
+ * @param {number} viewLevel The current level of view
270
+ * @returns {number} The level
271
+ */
272
+
273
+ }, {
274
+ key: "_getViewLevelFromPattern",
275
+ value: function _getViewLevelFromPattern(sPattern, viewLevel) {
276
+ sPattern = sPattern.replace(":?query:", "");
277
+ var regex = new RegExp("/[^/]*$");
278
+
279
+ if (sPattern && sPattern[0] !== "/" && sPattern[0] !== "?") {
280
+ sPattern = "/" + sPattern;
281
+ }
282
+
283
+ if (sPattern.length) {
284
+ sPattern = sPattern.replace(regex, "");
285
+
286
+ if (this.oRouter.match(sPattern) || sPattern === "") {
287
+ return this._getViewLevelFromPattern(sPattern, ++viewLevel);
288
+ } else {
289
+ return this._getViewLevelFromPattern(sPattern, viewLevel);
290
+ }
291
+ } else {
292
+ return viewLevel;
293
+ }
294
+ }
295
+ }, {
296
+ key: "_getRouteInformation",
297
+ value: function _getRouteInformation(sRouteName) {
298
+ return this._mRoutes[sRouteName];
299
+ }
300
+ }, {
301
+ key: "_getTargetInformation",
302
+ value: function _getTargetInformation(sTargetName) {
303
+ return this._mTargets[sTargetName];
304
+ }
305
+ }, {
306
+ key: "_getComponentId",
307
+ value: function _getComponentId(sOwnerId, sComponentId) {
308
+ if (sComponentId.indexOf(sOwnerId + "---") === 0) {
309
+ return sComponentId.substr(sOwnerId.length + 3);
310
+ }
311
+
312
+ return sComponentId;
313
+ }
314
+ /**
315
+ * Get target information for a given component.
316
+ *
317
+ * @param {object} oComponentInstance Instance of the component
318
+ * @returns {object} The configuration for the target
319
+ */
320
+
321
+ }, {
322
+ key: "getTargetInformationFor",
323
+ value: function getTargetInformationFor(oComponentInstance) {
324
+ var _this3 = this;
325
+
326
+ var sTargetComponentId = this._getComponentId(oComponentInstance._sOwnerId, oComponentInstance.getId());
327
+
328
+ var sCorrectTargetName = null;
329
+ Object.keys(this._mTargets).forEach(function (sTargetName) {
330
+ if (_this3._mTargets[sTargetName].id === sTargetComponentId || _this3._mTargets[sTargetName].viewId === sTargetComponentId) {
331
+ sCorrectTargetName = sTargetName;
332
+ }
333
+ });
334
+ return this._getTargetInformation(sCorrectTargetName);
335
+ }
336
+ }, {
337
+ key: "getLastSemanticMapping",
338
+ value: function getLastSemanticMapping() {
339
+ return this.oLastSemanticMapping;
340
+ }
341
+ }, {
342
+ key: "setLastSemanticMapping",
343
+ value: function setLastSemanticMapping(oMapping) {
344
+ this.oLastSemanticMapping = oMapping;
345
+ }
346
+ }, {
347
+ key: "navigateTo",
348
+ value: function navigateTo(oContext, sRouteName, mParameterMapping, bPreserveHistory) {
349
+ var _this4 = this;
350
+
351
+ var sTargetURLPromise, bIsStickyMode;
352
+
353
+ if (oContext.getModel() && oContext.getModel().getMetaModel) {
354
+ bIsStickyMode = ModelHelper.isStickySessionSupported(oContext.getModel().getMetaModel());
355
+ }
356
+
357
+ if (!mParameterMapping) {
358
+ // if there is no parameter mapping define this mean we rely entirely on the binding context path
359
+ sTargetURLPromise = Promise.resolve(SemanticKeyHelper.getSemanticPath(oContext));
360
+ } else {
361
+ sTargetURLPromise = this.prepareParameters(mParameterMapping, sRouteName, oContext).then(function (mParameters) {
362
+ return _this4.oRouter.getURL(sRouteName, mParameters);
363
+ });
364
+ }
365
+
366
+ return sTargetURLPromise.then(function (sTargetURL) {
367
+ _this4.oRouterProxy.navToHash(sTargetURL, bPreserveHistory, false, false, !bIsStickyMode);
368
+ });
369
+ }
370
+ /**
371
+ * Method to return a map of routing target parameters where the binding syntax is resolved to the current model.
372
+ *
373
+ * @param {object} mParameters Parameters map in the format [k: string] : ComplexBindingSyntax
374
+ * @param {string} sTargetRoute Name of the target route
375
+ * @param {object} oContext The instance of the binding context
376
+ * @returns {Promise} A promise which resolves to the routing target parameters
377
+ */
378
+
379
+ }, {
380
+ key: "prepareParameters",
381
+ value: function prepareParameters(mParameters, sTargetRoute, oContext) {
382
+ var _this5 = this;
383
+
384
+ var oParametersPromise;
385
+
386
+ try {
387
+ var sContextPath = oContext.getPath();
388
+ var oMetaModel = oContext.getModel().getMetaModel();
389
+ var aContextPathParts = sContextPath.split("/");
390
+ var aAllResolvedParameterPromises = Object.keys(mParameters).map(function (sParameterKey) {
391
+ var sParameterMappingExpression = mParameters[sParameterKey]; // We assume the defined parameters will be compatible with a binding expression
392
+
393
+ var oParsedExpression = BindingParser.complexParser(sParameterMappingExpression);
394
+ var aParts = oParsedExpression.parts || [oParsedExpression];
395
+ var aResolvedParameterPromises = aParts.map(function (oPathPart) {
396
+ var aRelativeParts = oPathPart.path.split("../"); // We go up the current context path as many times as necessary
397
+
398
+ var aLocalParts = aContextPathParts.slice(0, aContextPathParts.length - aRelativeParts.length + 1);
399
+ aLocalParts.push(aRelativeParts[aRelativeParts.length - 1]);
400
+ var sPropertyPath = aLocalParts.join("/");
401
+ var oMetaContext = oMetaModel.getMetaContext(sPropertyPath);
402
+ return oContext.requestProperty(sPropertyPath).then(function (oValue) {
403
+ var oPropertyInfo = oMetaContext.getObject();
404
+ var sEdmType = oPropertyInfo.$Type;
405
+ return ODataUtils.formatLiteral(oValue, sEdmType);
406
+ });
407
+ });
408
+ return Promise.all(aResolvedParameterPromises).then(function (aResolvedParameters) {
409
+ var value = oParsedExpression.formatter ? oParsedExpression.formatter.apply(_this5, aResolvedParameters) : aResolvedParameters.join("");
410
+ return {
411
+ key: sParameterKey,
412
+ value: value
413
+ };
414
+ });
415
+ });
416
+ oParametersPromise = Promise.all(aAllResolvedParameterPromises).then(function (aAllResolvedParameters) {
417
+ var oParameters = {};
418
+ aAllResolvedParameters.forEach(function (oResolvedParameter) {
419
+ oParameters[oResolvedParameter.key] = oResolvedParameter.value;
420
+ });
421
+ return oParameters;
422
+ });
423
+ } catch (oError) {
424
+ Log.error("Could not parse the parameters for the navigation to route " + sTargetRoute);
425
+ oParametersPromise = Promise.resolve(undefined);
426
+ }
427
+
428
+ return oParametersPromise;
429
+ }
430
+ }, {
431
+ key: "_fireRouteMatchEvents",
432
+ value: function _fireRouteMatchEvents(mParameters) {
433
+ this.eventProvider.fireEvent("routeMatched", mParameters);
434
+ this.eventProvider.fireEvent("afterRouteMatched", mParameters);
435
+ EditState.cleanProcessedEditState(); // Reset UI state when all bindings have been refreshed
436
+ }
437
+ /**
438
+ * Navigates to a context.
439
+ *
440
+ * @param {sap.ui.model.odata.v4.Context} oContext The Context to be navigated to
441
+ * @param {object} [mParameters] Optional, map containing the following attributes:
442
+ * @param {boolean} [mParameters.checkNoHashChange] Navigate to the context without changing the URL
443
+ * @param {Promise} [mParameters.asyncContext] The context is created async, navigate to (...) and
444
+ * wait for Promise to be resolved and then navigate into the context
445
+ * @param {boolean} [mParameters.bDeferredContext] The context shall be created deferred at the target page
446
+ * @param {boolean} [mParameters.editable] The target page shall be immediately in the edit mode to avoid flickering
447
+ * @param {boolean} [mParameters.bPersistOPScroll] The bPersistOPScroll will be used for scrolling to first tab
448
+ * @param {number} [mParameters.updateFCLLevel] `+1` if we add a column in FCL, `-1` to remove a column, 0 to stay on the same column
449
+ * @param {boolean} [mParameters.noPreservationCache] Do navigation without taking into account the preserved cache mechanism
450
+ * @param {boolean} [mParameters.bRecreateContext] Force re-creation of the context instead of using the one passed as parameter
451
+ * @param {boolean} [mParameters.bForceFocus] Forces focus selection after navigation
452
+ * @param {object} [oViewData] View data
453
+ * @param {object} [oCurrentTargetInfo] The target information from which the navigation is triggered
454
+ * @returns {Promise} Promise which is resolved once the navigation is triggered
455
+ *
456
+ * @ui5-restricted
457
+ * @final
458
+ */
459
+
460
+ }, {
461
+ key: "navigateToContext",
462
+ value: function navigateToContext(oContext, mParameters, oViewData, oCurrentTargetInfo) {
463
+ var _this6 = this;
464
+
465
+ var sTargetRoute = "",
466
+ oRouteParametersPromise,
467
+ bIsStickyMode = false;
468
+
469
+ if (oContext.getModel() && oContext.getModel().getMetaModel) {
470
+ bIsStickyMode = ModelHelper.isStickySessionSupported(oContext.getModel().getMetaModel());
471
+ } // Manage parameter mapping
472
+
473
+
474
+ if (mParameters && mParameters.targetPath && oViewData && oViewData.navigation) {
475
+ var oRouteDetail = oViewData.navigation[mParameters.targetPath].detail;
476
+ sTargetRoute = oRouteDetail.route;
477
+
478
+ if (oRouteDetail.parameters) {
479
+ oRouteParametersPromise = this.prepareParameters(oRouteDetail.parameters, sTargetRoute, oContext);
480
+ }
481
+ }
482
+
483
+ var sTargetPath = this._getPathFromContext(oContext, mParameters); // If the path is empty, we're supposed to navigate to the first page of the app
484
+ // Check if we need to exit from the app instead
485
+
486
+
487
+ if (sTargetPath.length === 0 && this.bExitOnNavigateBackToRoot) {
488
+ return this.oRouterProxy.exitFromApp();
489
+ } // If the context is deferred or async, we add (...) to the path
490
+
491
+
492
+ if (mParameters !== null && mParameters !== void 0 && mParameters.asyncContext || mParameters !== null && mParameters !== void 0 && mParameters.bDeferredContext) {
493
+ sTargetPath += "(...)";
494
+ } // Add layout parameter if needed
495
+
496
+
497
+ var sLayout = this._calculateLayout(sTargetPath, mParameters);
498
+
499
+ if (sLayout) {
500
+ sTargetPath += "?layout=" + sLayout;
501
+ } // Navigation parameters for later usage
502
+
503
+
504
+ var oNavigationInfo = {
505
+ oAsyncContext: mParameters === null || mParameters === void 0 ? void 0 : mParameters.asyncContext,
506
+ bDeferredContext: mParameters === null || mParameters === void 0 ? void 0 : mParameters.bDeferredContext,
507
+ bTargetEditable: mParameters === null || mParameters === void 0 ? void 0 : mParameters.editable,
508
+ bPersistOPScroll: mParameters === null || mParameters === void 0 ? void 0 : mParameters.bPersistOPScroll,
509
+ useContext: (mParameters === null || mParameters === void 0 ? void 0 : mParameters.updateFCLLevel) === -1 || mParameters !== null && mParameters !== void 0 && mParameters.bRecreateContext ? undefined : oContext,
510
+ bDraftNavigation: mParameters === null || mParameters === void 0 ? void 0 : mParameters.bDraftNavigation,
511
+ bShowPlaceholder: (mParameters === null || mParameters === void 0 ? void 0 : mParameters.showPlaceholder) !== undefined ? mParameters === null || mParameters === void 0 ? void 0 : mParameters.showPlaceholder : true
512
+ };
513
+
514
+ if (mParameters !== null && mParameters !== void 0 && mParameters.checkNoHashChange) {
515
+ // Check if the new hash is different from the current one
516
+ var sCurrentHashNoAppState = this.oRouterProxy.getHash().replace(/[&?]{1}sap-iapp-state=[A-Z0-9]+/, "");
517
+
518
+ if (sTargetPath === sCurrentHashNoAppState) {
519
+ // The hash doesn't change, but we fire the routeMatch event to trigger page refresh / binding
520
+ var mEventParameters = this.oRouter.getRouteInfoByHash(this.oRouterProxy.getHash());
521
+
522
+ if (mEventParameters) {
523
+ mEventParameters.navigationInfo = oNavigationInfo;
524
+ mEventParameters.routeInformation = this._getRouteInformation(this.sCurrentRouteName);
525
+ mEventParameters.routePattern = this.sCurrentRoutePattern;
526
+ mEventParameters.views = this.aCurrentViews;
527
+ }
528
+
529
+ this.oRouterProxy.setFocusForced(!!mParameters.bForceFocus);
530
+
531
+ this._fireRouteMatchEvents(mEventParameters);
532
+
533
+ return Promise.resolve();
534
+ }
535
+ }
536
+
537
+ if (mParameters !== null && mParameters !== void 0 && mParameters.transient && mParameters.editable == true && sTargetPath.indexOf("(...)") === -1) {
538
+ if (sTargetPath.indexOf("?") > -1) {
539
+ sTargetPath += "&i-action=create";
540
+ } else {
541
+ sTargetPath += "?i-action=create";
542
+ }
543
+ } // Clear unbound messages upon navigating from LR to OP
544
+ // This is to ensure stale error messages from LR are not shown to the user after navigation to OP.
545
+
546
+
547
+ if (oCurrentTargetInfo && oCurrentTargetInfo.name === "sap.fe.templates.ListReport") {
548
+ var oRouteInfo = this.oRouter.getRouteInfoByHash(sTargetPath);
549
+
550
+ if (oRouteInfo) {
551
+ var oRoute = this._getRouteInformation(oRouteInfo.name);
552
+
553
+ if (oRoute && oRoute.targets && oRoute.targets.length > 0) {
554
+ var sLastTargetName = oRoute.targets[oRoute.targets.length - 1];
555
+
556
+ var oTarget = this._getTargetInformation(sLastTargetName);
557
+
558
+ if (oTarget && oTarget.name === "sap.fe.templates.ObjectPage") {
559
+ messageHandling.removeUnboundTransitionMessages();
560
+ }
561
+ }
562
+ }
563
+ } // Add the navigation parameters in the queue
564
+
565
+
566
+ this.navigationInfoQueue.push(oNavigationInfo);
567
+
568
+ if (sTargetRoute && oRouteParametersPromise) {
569
+ return oRouteParametersPromise.then(function (oRouteParameters) {
570
+ oRouteParameters.bIsStickyMode = bIsStickyMode;
571
+
572
+ _this6.oRouter.navTo(sTargetRoute, oRouteParameters);
573
+
574
+ return Promise.resolve();
575
+ });
576
+ }
577
+
578
+ return this.oRouterProxy.navToHash(sTargetPath, false, mParameters === null || mParameters === void 0 ? void 0 : mParameters.noPreservationCache, mParameters === null || mParameters === void 0 ? void 0 : mParameters.bForceFocus, !bIsStickyMode).then(function (bNavigated) {
579
+ if (!bNavigated) {
580
+ // The navigation did not happen --> remove the navigation parameters from the queue as they shouldn't be used
581
+ _this6.navigationInfoQueue.pop();
582
+ }
583
+ });
584
+ }
585
+ /**
586
+ * Navigates to a route.
587
+ *
588
+ * @function
589
+ * @name sap.fe.core.controllerextensions.Routing#navigateToRoute
590
+ * @memberof sap.fe.core.controllerextensions.Routing
591
+ * @static
592
+ * @param {string} [sTargetRouteName] Name of the target route
593
+ * @param {object} [oRouteParameters] Parameters to be used with route to create the target hash
594
+ * @returns {Promise} Promise that is resolved when the navigation is finalized
595
+ *
596
+ * @ui5-restricted
597
+ * @final
598
+ */
599
+
600
+ }, {
601
+ key: "navigateToRoute",
602
+ value: function navigateToRoute(sTargetRouteName, oRouteParameters) {
603
+ var sTargetURL = this.oRouter.getURL(sTargetRouteName, oRouteParameters);
604
+ return this.oRouterProxy.navToHash(sTargetURL, undefined, undefined, undefined, !oRouteParameters.bIsStickyMode);
605
+ }
606
+ /**
607
+ * Checks if one of the current views on the screen is bound to a given context.
608
+ *
609
+ * @param {sap.ui.model.odata.v4.Context} oContext The context
610
+ * @returns {boolean} `true` or `false` if the current state is impacted or not
611
+ */
612
+
613
+ }, {
614
+ key: "isCurrentStateImpactedBy",
615
+ value: function isCurrentStateImpactedBy(oContext) {
616
+ var sPath = oContext.getPath(); // First, check with the technical path. We have to try it, because for level > 1, we
617
+ // uses technical keys even if Semantic keys are enabled
618
+
619
+ if (this.oRouterProxy.isCurrentStateImpactedBy(sPath)) {
620
+ return true;
621
+ } else if (/^[^\(\)]+\([^\(\)]+\)$/.test(sPath)) {
622
+ // If the current path can be semantic (i.e. is like xxx(yyy))
623
+ // check with the semantic path if we can find it
624
+ var sSemanticPath;
625
+
626
+ if (this.oLastSemanticMapping && this.oLastSemanticMapping.technicalPath === sPath) {
627
+ // We have already resolved this semantic path
628
+ sSemanticPath = this.oLastSemanticMapping.semanticPath;
629
+ } else {
630
+ sSemanticPath = SemanticKeyHelper.getSemanticPath(oContext);
631
+ }
632
+
633
+ return sSemanticPath != sPath ? this.oRouterProxy.isCurrentStateImpactedBy(sSemanticPath) : false;
634
+ } else {
635
+ return false;
636
+ }
637
+ }
638
+ }, {
639
+ key: "_findPathToNavigate",
640
+ value: function _findPathToNavigate(sPath) {
641
+ var regex = new RegExp("/[^/]*$");
642
+ sPath = sPath.replace(regex, "");
643
+
644
+ if (this.oRouter.match(sPath) || sPath === "") {
645
+ return sPath;
646
+ } else {
647
+ return this._findPathToNavigate(sPath);
648
+ }
649
+ }
650
+ }, {
651
+ key: "_checkContextForSemanticPath",
652
+ value: function _checkContextForSemanticPath(oContext) {
653
+ var sPath = oContext.getPath(); // First, check if this is a level-1 object (path = /aaa(bbb))
654
+
655
+ if (!/^\/[^\(]+\([^\)]+\)$/.test(sPath)) {
656
+ return false;
657
+ } // Then check if the entity has semantic keys
658
+
659
+
660
+ var oMetaModel = oContext.getModel().getMetaModel(),
661
+ sEntitySetName = oMetaModel.getMetaContext(oContext.getPath()).getObject("@sapui.name");
662
+
663
+ if (!SemanticKeyHelper.getSemanticKeys(oMetaModel, sEntitySetName)) {
664
+ return false;
665
+ } // Then check the entity is draft-enabled
666
+
667
+
668
+ return ModelHelper.isDraftSupported(oMetaModel, sPath);
669
+ }
670
+ }, {
671
+ key: "_getPathFromContext",
672
+ value: function _getPathFromContext(oContext, mParameters) {
673
+ var sPath;
674
+
675
+ if (oContext.isA("sap.ui.model.odata.v4.ODataListBinding") && oContext.isRelative()) {
676
+ sPath = oContext.getHeaderContext().getPath();
677
+ } else {
678
+ sPath = oContext.getPath();
679
+ }
680
+
681
+ if (mParameters.updateFCLLevel === -1) {
682
+ // When navigating back from a context, we need to remove the last component of the path
683
+ sPath = this._findPathToNavigate(sPath); // Check if we're navigating back to a semantic path that was previously resolved
684
+
685
+ if (this.oLastSemanticMapping && this.oLastSemanticMapping.technicalPath === sPath) {
686
+ sPath = this.oLastSemanticMapping.semanticPath;
687
+ }
688
+ } else if (this._checkContextForSemanticPath(oContext)) {
689
+ // We check if we have to use a semantic path
690
+ var sSemanticPath = SemanticKeyHelper.getSemanticPath(oContext, true);
691
+
692
+ if (!sSemanticPath) {
693
+ // We were not able to build the semantic path --> Use the technical path and
694
+ // clear the previous mapping, otherwise the old mapping is used in EditFlow#updateDocument
695
+ // and it leads to unwanted page reloads
696
+ this.setLastSemanticMapping(undefined);
697
+ } else if (sSemanticPath !== sPath) {
698
+ // Store the mapping technical <-> semantic path to avoid recalculating it later
699
+ // and use the semantic path instead of the technical one
700
+ this.setLastSemanticMapping({
701
+ technicalPath: sPath,
702
+ semanticPath: sSemanticPath
703
+ });
704
+ sPath = sSemanticPath;
705
+ }
706
+ } // remove extra '/' at the beginning of path
707
+
708
+
709
+ if (sPath[0] === "/") {
710
+ sPath = sPath.substring(1);
711
+ }
712
+
713
+ return sPath;
714
+ }
715
+ }, {
716
+ key: "_calculateLayout",
717
+ value: function _calculateLayout(sPath, mParameters) {
718
+ var FCLLevel = mParameters.FCLLevel;
719
+
720
+ if (mParameters.updateFCLLevel) {
721
+ FCLLevel += mParameters.updateFCLLevel;
722
+
723
+ if (FCLLevel < 0) {
724
+ FCLLevel = 0;
725
+ }
726
+ }
727
+
728
+ return this.oAppComponent.getRootViewController().calculateLayout(FCLLevel, sPath, mParameters.sLayout);
729
+ }
730
+ /**
731
+ * Event handler before a route is matched.
732
+ * Displays a busy indicator.
733
+ *
734
+ */
735
+
736
+ }, {
737
+ key: "_beforeRouteMatched",
738
+ value: function
739
+ /*oEvent: Event*/
740
+ _beforeRouteMatched() {
741
+ var bPlaceholderEnabled = new Placeholder().isPlaceholderEnabled();
742
+
743
+ if (!bPlaceholderEnabled) {
744
+ var oRootView = this.oAppComponent.getRootControl();
745
+ BusyLocker.lock(oRootView);
746
+ }
747
+ }
748
+ /**
749
+ * Event handler when a route is matched.
750
+ * Hides the busy indicator and fires its own 'routematched' event.
751
+ *
752
+ * @param {object} oEvent The event
753
+ */
754
+
755
+ }, {
756
+ key: "_onRouteMatched",
757
+ value: function _onRouteMatched(oEvent) {
758
+ var _this7 = this;
759
+
760
+ var oAppStateHandler = this.oAppComponent.getAppStateHandler(),
761
+ oRootView = this.oAppComponent.getRootControl();
762
+ var bPlaceholderEnabled = new Placeholder().isPlaceholderEnabled();
763
+
764
+ if (BusyLocker.isLocked(oRootView) && !bPlaceholderEnabled) {
765
+ BusyLocker.unlock(oRootView);
766
+ }
767
+
768
+ var mParameters = oEvent.getParameters();
769
+
770
+ if (this.navigationInfoQueue.length) {
771
+ mParameters.navigationInfo = this.navigationInfoQueue[0];
772
+ this.navigationInfoQueue = this.navigationInfoQueue.slice(1);
773
+ } else {
774
+ mParameters.navigationInfo = {};
775
+ }
776
+
777
+ if (oAppStateHandler.checkIfRouteChangedByIApp()) {
778
+ mParameters.navigationInfo.bReasonIsIappState = true;
779
+ oAppStateHandler.resetRouteChangedByIApp();
780
+ }
781
+
782
+ this.sCurrentRouteName = oEvent.getParameter("name");
783
+ this.sCurrentRoutePattern = mParameters.config.pattern;
784
+ this.aCurrentViews = oEvent.getParameter("views");
785
+ mParameters.routeInformation = this._getRouteInformation(this.sCurrentRouteName);
786
+ mParameters.routePattern = this.sCurrentRoutePattern;
787
+
788
+ this._fireRouteMatchEvents(mParameters); // Check if current hash has been set by the routerProxy.navToHash function
789
+ // If not, rebuild history properly (both in the browser and the RouterProxy)
790
+
791
+
792
+ if (!history.state || history.state.feLevel === undefined) {
793
+ this.oRouterProxy.restoreHistory().then(function () {
794
+ _this7.oRouterProxy.resolveRouteMatch();
795
+ }).catch(function (oError) {
796
+ Log.error("Error while restoring history", oError);
797
+ });
798
+ } else {
799
+ this.oRouterProxy.resolveRouteMatch();
800
+ }
801
+ }
802
+ }, {
803
+ key: "attachRouteMatched",
804
+ value: function attachRouteMatched(oData, fnFunction, oListener) {
805
+ this.eventProvider.attachEvent("routeMatched", oData, fnFunction, oListener);
806
+ }
807
+ }, {
808
+ key: "detachRouteMatched",
809
+ value: function detachRouteMatched(fnFunction, oListener) {
810
+ this.eventProvider.detachEvent("routeMatched", fnFunction, oListener);
811
+ }
812
+ }, {
813
+ key: "attachAfterRouteMatched",
814
+ value: function attachAfterRouteMatched(oData, fnFunction, oListener) {
815
+ this.eventProvider.attachEvent("afterRouteMatched", oData, fnFunction, oListener);
816
+ }
817
+ }, {
818
+ key: "detachAfterRouteMatched",
819
+ value: function detachAfterRouteMatched(fnFunction, oListener) {
820
+ this.eventProvider.detachEvent("afterRouteMatched", fnFunction, oListener);
821
+ }
822
+ }, {
823
+ key: "getRouteFromHash",
824
+ value: function getRouteFromHash(oRouter, oAppComponent) {
825
+ var sHash = oRouter.getHashChanger().hash;
826
+ var oRouteInfo = oRouter.getRouteInfoByHash(sHash);
827
+ return oAppComponent.getMetadata().getManifestEntry("/sap.ui5/routing/routes").filter(function (oRoute) {
828
+ return oRoute.name === oRouteInfo.name;
829
+ })[0];
830
+ }
831
+ }, {
832
+ key: "getTargetsFromRoute",
833
+ value: function getTargetsFromRoute(oRoute) {
834
+ var _this8 = this;
835
+
836
+ var oTarget = oRoute.target;
837
+
838
+ if (typeof oTarget === "string") {
839
+ return [this._mTargets[oTarget]];
840
+ } else {
841
+ var aTarget = [];
842
+ oTarget.forEach(function (sTarget) {
843
+ aTarget.push(_this8._mTargets[sTarget]);
844
+ });
845
+ return aTarget;
846
+ }
847
+ }
848
+ }, {
849
+ key: "initializeRouting",
850
+ value: function initializeRouting() {
851
+ var _this9 = this;
852
+
853
+ // Attach router handlers
854
+ this._fnOnRouteMatched = this._onRouteMatched.bind(this);
855
+ this.oRouter.attachRouteMatched(this._fnOnRouteMatched, this);
856
+ var bPlaceholderEnabled = new Placeholder().isPlaceholderEnabled();
857
+
858
+ if (!bPlaceholderEnabled) {
859
+ this.oRouter.attachBeforeRouteMatched(this._beforeRouteMatched.bind(this));
860
+ } // Reset internal state
861
+
862
+
863
+ this.navigationInfoQueue = [];
864
+ EditState.resetEditState();
865
+ this.bExitOnNavigateBackToRoot = !this.oRouter.match("");
866
+ var bIsIappState = this.oRouter.getHashChanger().getHash().indexOf("sap-iapp-state") !== -1;
867
+ var initPromise = this.oAppComponent.getStartupParameters().then(function (oStartupParameters) {
868
+ var bHasStartUpParameters = oStartupParameters !== undefined && Object.keys(oStartupParameters).length !== 0;
869
+
870
+ var sHash = _this9.oRouter.getHashChanger().getHash(); // Manage startup parameters (in case of no iapp-state)
871
+
872
+
873
+ if (!bIsIappState && bHasStartUpParameters && !sHash) {
874
+ if (oStartupParameters.preferredMode && oStartupParameters.preferredMode[0].indexOf("create") !== -1) {
875
+ // Create mode
876
+ return _this9._manageCreateStartup(oStartupParameters);
877
+ } else {
878
+ // Deep link
879
+ return _this9._manageDeepLinkStartup(oStartupParameters);
880
+ }
881
+ }
882
+ }).catch(function (oError) {
883
+ Log.error("Error during routing initialization", oError);
884
+ });
885
+ return initPromise;
886
+ }
887
+ }, {
888
+ key: "getDefaultCreateHash",
889
+ value: function getDefaultCreateHash(oStartupParameters) {
890
+ return AppStartupHelper.getDefaultCreateHash(oStartupParameters, this.getContextPath(), this.oRouter);
891
+ }
892
+ }, {
893
+ key: "_manageCreateStartup",
894
+ value: function _manageCreateStartup(oStartupParameters) {
895
+ var _this10 = this;
896
+
897
+ return AppStartupHelper.getCreateStartupHash(oStartupParameters, this.getContextPath(), this.oRouter, this.oMetaModel).then(function (sNewHash) {
898
+ if (sNewHash) {
899
+ _this10.oRouter.getHashChanger().replaceHash(sNewHash);
900
+
901
+ _this10.bExitOnNavigateBackToRoot = true;
902
+ }
903
+ });
904
+ }
905
+ }, {
906
+ key: "_manageDeepLinkStartup",
907
+ value: function _manageDeepLinkStartup(oStartupParameters) {
908
+ var _this11 = this;
909
+
910
+ return AppStartupHelper.getDeepLinkStartupHash(this.oAppComponent.getManifest()["sap.ui5"].routing, oStartupParameters, this.oModel).then(function (oDeepLink) {
911
+ var sHash;
912
+
913
+ if (oDeepLink.context) {
914
+ var sTechnicalPath = oDeepLink.context.getPath(),
915
+ sSemanticPath = SemanticKeyHelper.getSemanticPath(oDeepLink.context);
916
+
917
+ if (sSemanticPath !== sTechnicalPath) {
918
+ // Store the mapping technical <-> semantic path to avoid recalculating it later
919
+ // and use the semantic path instead of the technical one
920
+ _this11.setLastSemanticMapping({
921
+ technicalPath: sTechnicalPath,
922
+ semanticPath: sSemanticPath
923
+ });
924
+ }
925
+
926
+ sHash = sSemanticPath.substring(1); // To remove the leading '/'
927
+ } else if (oDeepLink.hash) {
928
+ sHash = oDeepLink.hash;
929
+ }
930
+
931
+ if (sHash) {
932
+ //Replace the hash with newly created hash
933
+ _this11.oRouter.getHashChanger().replaceHash(sHash);
934
+ }
935
+ });
936
+ }
937
+ }, {
938
+ key: "getOutbounds",
939
+ value: function getOutbounds() {
940
+ return this.outbounds;
941
+ }
942
+ /**
943
+ * Gets the name of the Draft root entity set or the sticky-enabled entity set.
944
+ *
945
+ * @returns {string} The name of the root EntitySet
946
+ *
947
+ * @ui5-restricted
948
+ */
949
+
950
+ }, {
951
+ key: "getContextPath",
952
+ value: function getContextPath() {
953
+ return this.sContextPath;
954
+ }
955
+ }, {
956
+ key: "getInterface",
957
+ value: function getInterface() {
958
+ return this;
959
+ }
960
+ }]);
961
+
962
+ return RoutingService;
963
+ }(Service);
964
+
965
+ var RoutingServiceFactory = /*#__PURE__*/function (_ServiceFactory) {
966
+ _inherits(RoutingServiceFactory, _ServiceFactory);
967
+
968
+ var _super2 = _createSuper(RoutingServiceFactory);
969
+
970
+ function RoutingServiceFactory() {
971
+ _classCallCheck(this, RoutingServiceFactory);
972
+
973
+ return _super2.apply(this, arguments);
974
+ }
975
+
976
+ _createClass(RoutingServiceFactory, [{
977
+ key: "createInstance",
978
+ value: function createInstance(oServiceContext) {
979
+ var oRoutingService = new RoutingService(oServiceContext);
980
+ return oRoutingService.initPromise;
981
+ }
982
+ }]);
983
+
984
+ return RoutingServiceFactory;
985
+ }(ServiceFactory);
986
+
987
+ return RoutingServiceFactory;
988
+ }, false);
989
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlJvdXRpbmdTZXJ2aWNlRmFjdG9yeS50cyJdLCJuYW1lcyI6WyJSb3V0aW5nU2VydmljZUV2ZW50aW5nIiwiRXZlbnRQcm92aWRlciIsImV4dGVuZCIsIm1ldGFkYXRhIiwiZXZlbnRzIiwiUm91dGluZ1NlcnZpY2UiLCJvQ29udGV4dCIsImdldENvbnRleHQiLCJzY29wZVR5cGUiLCJvQXBwQ29tcG9uZW50Iiwic2NvcGVPYmplY3QiLCJvTW9kZWwiLCJnZXRNb2RlbCIsIm9NZXRhTW9kZWwiLCJnZXRNZXRhTW9kZWwiLCJvUm91dGVyIiwiZ2V0Um91dGVyIiwib1JvdXRlclByb3h5IiwiZ2V0Um91dGVyUHJveHkiLCJldmVudFByb3ZpZGVyIiwib1JvdXRpbmdDb25maWciLCJnZXRNYW5pZmVzdEVudHJ5Iiwib1Jvb3RWaWV3Q29uZmlnIiwiX3BhcnNlUm91dGluZ0NvbmZpZ3VyYXRpb24iLCJvQXBwQ29uZmlnIiwib3V0Ym91bmRzIiwiY3Jvc3NOYXZpZ2F0aW9uIiwiaW5pdFByb21pc2UiLCJQcm9taXNlIiwicmVzb2x2ZSIsImRldGFjaFJvdXRlTWF0Y2hlZCIsIl9mbk9uUm91dGVNYXRjaGVkIiwiZmlyZUV2ZW50IiwiZGVzdHJveSIsImlzRkNMIiwidmlld05hbWUiLCJfbVRhcmdldHMiLCJPYmplY3QiLCJrZXlzIiwidGFyZ2V0cyIsImZvckVhY2giLCJzVGFyZ2V0TmFtZSIsImFzc2lnbiIsInRhcmdldE5hbWUiLCJjb250ZXh0UGF0dGVybiIsInVuZGVmaW5lZCIsInZpZXdMZXZlbCIsIl9nZXRWaWV3TGV2ZWxGcm9tUGF0dGVybiIsIl9tUm91dGVzIiwic1JvdXRlS2V5Iiwicm91dGVzIiwib1JvdXRlTWFuaWZlc3RJbmZvIiwiYVJvdXRlVGFyZ2V0cyIsIkFycmF5IiwiaXNBcnJheSIsInRhcmdldCIsInNSb3V0ZU5hbWUiLCJuYW1lIiwic1JvdXRlUGF0dGVybiIsInBhdHRlcm4iLCJsZW5ndGgiLCJpbmRleE9mIiwiTG9nIiwid2FybmluZyIsImlSb3V0ZUxldmVsIiwicm91dGVMZXZlbCIsImkiLCJzUGFyZW50VGFyZ2V0TmFtZSIsInBhcmVudCIsInB1c2giLCJGQ0xMZXZlbCIsImNvbnRyb2xBZ2dyZWdhdGlvbiIsImFMZXZlbDBSb3V0ZU5hbWVzIiwiYUxldmVsMVJvdXRlTmFtZXMiLCJzRGVmYXVsdFJvdXRlTmFtZSIsInNOYW1lIiwiaUxldmVsIiwic0RlZmF1bHRUYXJnZXROYW1lIiwic2xpY2UiLCJzQ29udGV4dFBhdGgiLCJvcHRpb25zIiwic2V0dGluZ3MiLCJvU2V0dGluZ3MiLCJjb250ZXh0UGF0aCIsImVudGl0eVNldCIsIm1hcCIsInNUYXJnZXRLZXkiLCJzb3J0IiwiYSIsImIiLCJmdWxsQ29udGV4dFBhdGgiLCJuYXZpZ2F0aW9uIiwic05hdk5hbWUiLCJ0YXJnZXRSb3V0ZSIsImRldGFpbCIsInJvdXRlIiwic1BhdHRlcm4iLCJyZXBsYWNlIiwicmVnZXgiLCJSZWdFeHAiLCJtYXRjaCIsInNPd25lcklkIiwic0NvbXBvbmVudElkIiwic3Vic3RyIiwib0NvbXBvbmVudEluc3RhbmNlIiwic1RhcmdldENvbXBvbmVudElkIiwiX2dldENvbXBvbmVudElkIiwiX3NPd25lcklkIiwiZ2V0SWQiLCJzQ29ycmVjdFRhcmdldE5hbWUiLCJpZCIsInZpZXdJZCIsIl9nZXRUYXJnZXRJbmZvcm1hdGlvbiIsIm9MYXN0U2VtYW50aWNNYXBwaW5nIiwib01hcHBpbmciLCJtUGFyYW1ldGVyTWFwcGluZyIsImJQcmVzZXJ2ZUhpc3RvcnkiLCJzVGFyZ2V0VVJMUHJvbWlzZSIsImJJc1N0aWNreU1vZGUiLCJNb2RlbEhlbHBlciIsImlzU3RpY2t5U2Vzc2lvblN1cHBvcnRlZCIsIlNlbWFudGljS2V5SGVscGVyIiwiZ2V0U2VtYW50aWNQYXRoIiwicHJlcGFyZVBhcmFtZXRlcnMiLCJ0aGVuIiwibVBhcmFtZXRlcnMiLCJnZXRVUkwiLCJzVGFyZ2V0VVJMIiwibmF2VG9IYXNoIiwic1RhcmdldFJvdXRlIiwib1BhcmFtZXRlcnNQcm9taXNlIiwiZ2V0UGF0aCIsImFDb250ZXh0UGF0aFBhcnRzIiwic3BsaXQiLCJhQWxsUmVzb2x2ZWRQYXJhbWV0ZXJQcm9taXNlcyIsInNQYXJhbWV0ZXJLZXkiLCJzUGFyYW1ldGVyTWFwcGluZ0V4cHJlc3Npb24iLCJvUGFyc2VkRXhwcmVzc2lvbiIsIkJpbmRpbmdQYXJzZXIiLCJjb21wbGV4UGFyc2VyIiwiYVBhcnRzIiwicGFydHMiLCJhUmVzb2x2ZWRQYXJhbWV0ZXJQcm9taXNlcyIsIm9QYXRoUGFydCIsImFSZWxhdGl2ZVBhcnRzIiwicGF0aCIsImFMb2NhbFBhcnRzIiwic1Byb3BlcnR5UGF0aCIsImpvaW4iLCJvTWV0YUNvbnRleHQiLCJnZXRNZXRhQ29udGV4dCIsInJlcXVlc3RQcm9wZXJ0eSIsIm9WYWx1ZSIsIm9Qcm9wZXJ0eUluZm8iLCJnZXRPYmplY3QiLCJzRWRtVHlwZSIsIiRUeXBlIiwiT0RhdGFVdGlscyIsImZvcm1hdExpdGVyYWwiLCJhbGwiLCJhUmVzb2x2ZWRQYXJhbWV0ZXJzIiwidmFsdWUiLCJmb3JtYXR0ZXIiLCJhcHBseSIsImtleSIsImFBbGxSZXNvbHZlZFBhcmFtZXRlcnMiLCJvUGFyYW1ldGVycyIsIm9SZXNvbHZlZFBhcmFtZXRlciIsIm9FcnJvciIsImVycm9yIiwiRWRpdFN0YXRlIiwiY2xlYW5Qcm9jZXNzZWRFZGl0U3RhdGUiLCJvVmlld0RhdGEiLCJvQ3VycmVudFRhcmdldEluZm8iLCJvUm91dGVQYXJhbWV0ZXJzUHJvbWlzZSIsInRhcmdldFBhdGgiLCJvUm91dGVEZXRhaWwiLCJwYXJhbWV0ZXJzIiwic1RhcmdldFBhdGgiLCJfZ2V0UGF0aEZyb21Db250ZXh0IiwiYkV4aXRPbk5hdmlnYXRlQmFja1RvUm9vdCIsImV4aXRGcm9tQXBwIiwiYXN5bmNDb250ZXh0IiwiYkRlZmVycmVkQ29udGV4dCIsInNMYXlvdXQiLCJfY2FsY3VsYXRlTGF5b3V0Iiwib05hdmlnYXRpb25JbmZvIiwib0FzeW5jQ29udGV4dCIsImJUYXJnZXRFZGl0YWJsZSIsImVkaXRhYmxlIiwiYlBlcnNpc3RPUFNjcm9sbCIsInVzZUNvbnRleHQiLCJ1cGRhdGVGQ0xMZXZlbCIsImJSZWNyZWF0ZUNvbnRleHQiLCJiRHJhZnROYXZpZ2F0aW9uIiwiYlNob3dQbGFjZWhvbGRlciIsInNob3dQbGFjZWhvbGRlciIsImNoZWNrTm9IYXNoQ2hhbmdlIiwic0N1cnJlbnRIYXNoTm9BcHBTdGF0ZSIsImdldEhhc2giLCJtRXZlbnRQYXJhbWV0ZXJzIiwiZ2V0Um91dGVJbmZvQnlIYXNoIiwibmF2aWdhdGlvbkluZm8iLCJyb3V0ZUluZm9ybWF0aW9uIiwiX2dldFJvdXRlSW5mb3JtYXRpb24iLCJzQ3VycmVudFJvdXRlTmFtZSIsInJvdXRlUGF0dGVybiIsInNDdXJyZW50Um91dGVQYXR0ZXJuIiwidmlld3MiLCJhQ3VycmVudFZpZXdzIiwic2V0Rm9jdXNGb3JjZWQiLCJiRm9yY2VGb2N1cyIsIl9maXJlUm91dGVNYXRjaEV2ZW50cyIsInRyYW5zaWVudCIsIm9Sb3V0ZUluZm8iLCJvUm91dGUiLCJzTGFzdFRhcmdldE5hbWUiLCJvVGFyZ2V0IiwibWVzc2FnZUhhbmRsaW5nIiwicmVtb3ZlVW5ib3VuZFRyYW5zaXRpb25NZXNzYWdlcyIsIm5hdmlnYXRpb25JbmZvUXVldWUiLCJvUm91dGVQYXJhbWV0ZXJzIiwibmF2VG8iLCJub1ByZXNlcnZhdGlvbkNhY2hlIiwiYk5hdmlnYXRlZCIsInBvcCIsInNUYXJnZXRSb3V0ZU5hbWUiLCJzUGF0aCIsImlzQ3VycmVudFN0YXRlSW1wYWN0ZWRCeSIsInRlc3QiLCJzU2VtYW50aWNQYXRoIiwidGVjaG5pY2FsUGF0aCIsInNlbWFudGljUGF0aCIsIl9maW5kUGF0aFRvTmF2aWdhdGUiLCJzRW50aXR5U2V0TmFtZSIsImdldFNlbWFudGljS2V5cyIsImlzRHJhZnRTdXBwb3J0ZWQiLCJpc0EiLCJpc1JlbGF0aXZlIiwiZ2V0SGVhZGVyQ29udGV4dCIsIl9jaGVja0NvbnRleHRGb3JTZW1hbnRpY1BhdGgiLCJzZXRMYXN0U2VtYW50aWNNYXBwaW5nIiwic3Vic3RyaW5nIiwiZ2V0Um9vdFZpZXdDb250cm9sbGVyIiwiY2FsY3VsYXRlTGF5b3V0IiwiYlBsYWNlaG9sZGVyRW5hYmxlZCIsIlBsYWNlaG9sZGVyIiwiaXNQbGFjZWhvbGRlckVuYWJsZWQiLCJvUm9vdFZpZXciLCJnZXRSb290Q29udHJvbCIsIkJ1c3lMb2NrZXIiLCJsb2NrIiwib0V2ZW50Iiwib0FwcFN0YXRlSGFuZGxlciIsImdldEFwcFN0YXRlSGFuZGxlciIsImlzTG9ja2VkIiwidW5sb2NrIiwiZ2V0UGFyYW1ldGVycyIsImNoZWNrSWZSb3V0ZUNoYW5nZWRCeUlBcHAiLCJiUmVhc29uSXNJYXBwU3RhdGUiLCJyZXNldFJvdXRlQ2hhbmdlZEJ5SUFwcCIsImdldFBhcmFtZXRlciIsImNvbmZpZyIsImhpc3RvcnkiLCJzdGF0ZSIsImZlTGV2ZWwiLCJyZXN0b3JlSGlzdG9yeSIsInJlc29sdmVSb3V0ZU1hdGNoIiwiY2F0Y2giLCJvRGF0YSIsImZuRnVuY3Rpb24iLCJvTGlzdGVuZXIiLCJhdHRhY2hFdmVudCIsImRldGFjaEV2ZW50Iiwic0hhc2giLCJnZXRIYXNoQ2hhbmdlciIsImhhc2giLCJnZXRNZXRhZGF0YSIsImZpbHRlciIsImFUYXJnZXQiLCJzVGFyZ2V0IiwiX29uUm91dGVNYXRjaGVkIiwiYmluZCIsImF0dGFjaFJvdXRlTWF0Y2hlZCIsImF0dGFjaEJlZm9yZVJvdXRlTWF0Y2hlZCIsIl9iZWZvcmVSb3V0ZU1hdGNoZWQiLCJyZXNldEVkaXRTdGF0ZSIsImJJc0lhcHBTdGF0ZSIsImdldFN0YXJ0dXBQYXJhbWV0ZXJzIiwib1N0YXJ0dXBQYXJhbWV0ZXJzIiwiYkhhc1N0YXJ0VXBQYXJhbWV0ZXJzIiwicHJlZmVycmVkTW9kZSIsIl9tYW5hZ2VDcmVhdGVTdGFydHVwIiwiX21hbmFnZURlZXBMaW5rU3RhcnR1cCIsIkFwcFN0YXJ0dXBIZWxwZXIiLCJnZXREZWZhdWx0Q3JlYXRlSGFzaCIsImdldENvbnRleHRQYXRoIiwiZ2V0Q3JlYXRlU3RhcnR1cEhhc2giLCJzTmV3SGFzaCIsInJlcGxhY2VIYXNoIiwiZ2V0RGVlcExpbmtTdGFydHVwSGFzaCIsImdldE1hbmlmZXN0Iiwicm91dGluZyIsIm9EZWVwTGluayIsImNvbnRleHQiLCJzVGVjaG5pY2FsUGF0aCIsIlNlcnZpY2UiLCJSb3V0aW5nU2VydmljZUZhY3RvcnkiLCJvU2VydmljZUNvbnRleHQiLCJvUm91dGluZ1NlcnZpY2UiLCJTZXJ2aWNlRmFjdG9yeSJdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkEsTUFBTUEsc0JBQXNCLEdBQUdDLGFBQWEsQ0FBQ0MsTUFBZCxDQUFxQiw2Q0FBckIsRUFBb0U7QUFDbEdDLElBQUFBLFFBQVEsRUFBRTtBQUNUQyxNQUFBQSxNQUFNLEVBQUU7QUFDUCx3QkFBZ0IsRUFEVDtBQUVQLDZCQUFxQjtBQUZkO0FBREM7QUFEd0YsR0FBcEUsQ0FBL0I7O01BUU1DLGM7Ozs7Ozs7Ozs7Ozs7Ozs7NEVBZ0J3QixFOzs7Ozs7O2FBRzdCLGdCQUFPO0FBQ04sWUFBTUMsUUFBUSxHQUFHLEtBQUtDLFVBQUwsRUFBakI7O0FBQ0EsWUFBSUQsUUFBUSxDQUFDRSxTQUFULEtBQXVCLFdBQTNCLEVBQXdDO0FBQ3ZDLGVBQUtDLGFBQUwsR0FBcUJILFFBQVEsQ0FBQ0ksV0FBOUI7QUFDQSxlQUFLQyxNQUFMLEdBQWMsS0FBS0YsYUFBTCxDQUFtQkcsUUFBbkIsRUFBZDtBQUNBLGVBQUtDLFVBQUwsR0FBa0IsS0FBS0YsTUFBTCxDQUFZRyxZQUFaLEVBQWxCO0FBQ0EsZUFBS0MsT0FBTCxHQUFlLEtBQUtOLGFBQUwsQ0FBbUJPLFNBQW5CLEVBQWY7QUFDQSxlQUFLQyxZQUFMLEdBQW9CLEtBQUtSLGFBQUwsQ0FBbUJTLGNBQW5CLEVBQXBCO0FBQ0EsZUFBS0MsYUFBTCxHQUFxQixJQUFLbkIsc0JBQUwsRUFBckI7QUFFQSxjQUFNb0IsY0FBYyxHQUFHLEtBQUtYLGFBQUwsQ0FBbUJZLGdCQUFuQixDQUFvQyxrQkFBcEMs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Q0E7O0FBRUQ0QyxZQUFBQSxLQUFLLEdBQUc1QyxhQUFhLENBQUNZLFNBQWQsQ0FBd0IsQ0FBeEIsQ0FBUixDQVZzQixDQVVjO0FBQ3BDLFdBWEQsTUFXTyxJQUFJNkQsU0FBUyxDQUFDM0IsSUFBZCxFQUFvQjtBQUMxQkYsWUFBQUEsS0FBSyxHQUFHNkIsU0FBUyxDQUFDM0IsSUFBbEI7QUFDQTs7QUFFRCxjQUFJRixLQUFKLEVBQVc7QUFDVjtBQUNDLFlBQUEsT0FBSSxDQUFDblEsT0FBTCxDQUFhb1EsY0FBYixHQUE4QndCLFdBQS9CLENBQW1EekIsS0FBbkQ7QUFDQTtBQUNELFNBekJNLENBQVA7QUEwQkE7OzthQUVELHdCQUFlO0FBQ2QsZUFBTyxLQUFLelAsU0FBWjtBQUNBO0FBRUQ7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7YUFDQywwQkFBaUI7QUFDaEIsZUFBTyxLQUFLc0QsWUFBWjtBQUNBOzs7YUFDRCx3QkFBb0I7QUFDbkIsZUFBTyxJQUFQO0FBQ0E7Ozs7SUF6MUIyQm1PLE87O01BNDFCdkJDLHFCOzs7Ozs7Ozs7Ozs7O2FBQ0wsd0JBQWVDLGVBQWYsRUFBd0U7QUFDdkUsWUFBTUMsZUFBZSxHQUFHLElBQUloVCxjQUFKLENBQW1CK1MsZUFBbkIsQ0FBeEI7QUFDQSxlQUFPQyxlQUFlLENBQUMxUixXQUF2QjtBQUNBOzs7O0lBSmtDMlIsYzs7U0FPckJILHFCIiwic291cmNlUm9vdCI6Ii4iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRXZlbnQgZnJvbSBcInNhcC91aS9iYXNlL0V2ZW50XCI7XG5pbXBvcnQgU2VydmljZSBmcm9tIFwic2FwL3VpL2NvcmUvc2VydmljZS9TZXJ2aWNlXCI7XG5pbXBvcnQgU2VydmljZUZhY3RvcnkgZnJvbSBcInNhcC91aS9jb3JlL3NlcnZpY2UvU2VydmljZUZhY3RvcnlcIjtcbmltcG9ydCBCaW5kaW5nUGFyc2VyIGZyb20gXCJzYXAvdWkvYmFzZS9CaW5kaW5nUGFyc2VyXCI7XG5pbXBvcnQgU2VtYW50aWNLZXlIZWxwZXIgZnJvbSBcInNhcC9mZS9jb3JlL2hlbHBlcnMvU2VtYW50aWNLZXlIZWxwZXJcIjtcbmltcG9ydCBMb2cgZnJvbSBcInNhcC9iYXNlL0xvZ1wiO1xuaW1wb3J0IEV2ZW50UHJvdmlkZXIgZnJvbSBcInNhcC91aS9iYXNlL0V2ZW50UHJvdmlkZXJcIjtcbmltcG9ydCBCdXN5TG9ja2VyIGZyb20gXCJzYXAvZmUvY29yZS9CdXN5TG9ja2VyXCI7XG5pbXBvcnQgTW9kZWxIZWxwZXIgZnJvbSBcInNhcC9mZS9jb3JlL2hlbHBlcnMvTW9kZWxIZWxwZXJcIjtcbmltcG9ydCBFZGl0U3RhdGUgZnJvbSBcInNhcC9mZS9jb3JlL2hlbHBlcnMvRWRpdFN0YXRlXCI7XG5pbXBvcnQgbWVzc2FnZUhhbmRsaW5nIGZyb20gXCJzYXAvZmUvY29yZS9hY3Rpb25zL21lc3NhZ2VIYW5kbGluZ1wiO1xuaW1wb3J0IHsgUGxhY2Vob2xkZXIgfSBmcm9tIFwic2FwL2ZlL2NvcmUvY29udHJvbGxlcmV4dGVuc2lvbnNcIjtcbmltcG9ydCBBcHBTdGFydHVwSGVscGVyIGZyb20gXCJzYXAvZmUvY29yZS9oZWxwZXJzL0FwcFN0YXJ0dXBIZWxwZXJcIjtcbmltcG9ydCBPRGF0YVV0aWxzIGZyb20gXCJzYXAvdWkvbW9kZWwvb2RhdGEvdjQvT0RhdGFVdGlsc1wiO1xuaW1wb3J0IHsgU2VydmljZUNvbnRleHQgfSBmcm9tIFwic2FwL3VpL2NvcmUvc2VydmljZVwiO1xuaW1wb3J0IHsgQXBwQ29tcG9uZW50IH0gZnJvbSBcInNhcC9mZS9jb3JlXCI7XG5pbXBvcnQgT0RhdGFNb2RlbCBmcm9tIFwic2FwL3VpL21vZGVsL29kYXRhL3Y0L09EYXRhTW9kZWxcIjtcbmltcG9ydCBPRGF0YU1ldGFNb2RlbCBmcm9tIFwic2FwL3VpL21vZGVsL29kYXRhL3Y0L09EYXRhTWV0YU1vZGVsXCI7XG5pbXBvcnQgUm91dGVyIGZyb20gXCJzYXAvdWkvY29yZS9yb3V0aW5nL1JvdXRlclwiO1xuaW1wb3J0IFJvdXRlclByb3h5IGZyb20gXCJzYXAvZmUvY29yZS9Sb3V0ZXJQcm94eVwiO1xuaW1wb3J0IENvbnRleHQgZnJvbSBcInNhcC91aS9tb2RlbC9vZGF0YS92NC9Db250ZXh0XCI7XG50eXBlIFJvdXRpbmdTZXJ2aWNlU2V0dGluZ3MgPSB7fTtcbmNvbnN0IFJvdXRpbmdTZXJ2aWNlRXZlbnRpbmcgPSBFdmVudFByb3ZpZGVyLmV4dGVuZChcInNhcC5mZS5jb3JlLnNlcnZpY2VzLlJvdXRpbmdTZXJ2aWNlRXZlbnRpbmdcIiwge1xuXHRtZXRhZGF0YToge1xuXHRcdGV2ZW50czoge1xuXHRcdFx0XCJyb3V0ZU1hdGNoZWRcIjoge30sXG5cdFx0XHRcImFmdGVyUm91dGVNYXRjaGVkXCI6IHt9XG5cdFx0fVxuXHR9XG59KTtcbmNsYXNzIFJvdXRpbmdTZXJ2aWNlIGV4dGVuZHMgU2VydmljZTxSb3V0aW5nU2VydmljZVNldHRpbmdzPiB7XG5cdG9BcHBDb21wb25lbnQhOiBBcHBDb21wb25lbnQ7XG5cdG9Nb2RlbCE6IE9EYXRhTW9kZWw7XG5cdG9NZXRhTW9kZWwhOiBPRGF0YU1ldGFNb2RlbDtcblx0b1JvdXRlciE6IFJvdXRlcjtcblx0b1JvdXRlclByb3h5ITogUm91dGVyUHJveHk7XG5cdGV2ZW50UHJvdmlkZXIhOiBFdmVudFByb3ZpZGVyO1xuXHRpbml0UHJvbWlzZSE6IFByb21pc2U8YW55Pjtcblx0b3V0Ym91bmRzOiBhbnk7XG5cdF9tVGFyZ2V0czogYW55O1xuXHRfbVJvdXRlczogYW55O1xuXHRvTGFzdFNlbWFudGljTWFwcGluZzogYW55O1xuXHRiRXhpdE9uTmF2aWdhdGVCYWNrVG9Sb290PzogYm9vbGVhbjtcblx0c0N1cnJlbnRSb3V0ZU5hbWU/OiBzdHJpbmc7XG5cdHNDdXJyZW50Um91dGVQYXR0ZXJuPzogc3RyaW5nO1xuXHRhQ3VycmVudFZpZXdzPzogYW55W107XG5cdG5hdmlnYXRpb25JbmZvUXVldWU6IGFueVtdID0gW107XG5cdHNDb250ZXh0UGF0aCE6IHN0cmluZztcblx0X2ZuT25Sb3V0ZU1hdGNoZWQhOiBGdW5jdGlvbjtcblx0aW5pdCgpIHtcblx0XHRjb25zdCBvQ29udGV4dCA9IHRoaXMuZ2V0Q29udGV4dCgpO1xuXHRcdGlmIChvQ29udGV4dC5zY29wZVR5cGUgPT09IFwiY29tcG9uZW50XCIpIHtcblx0XHRcdHRoaXMub0FwcENvbXBvbmVudCA9IG9Db250ZXh0LnNjb3BlT2JqZWN0O1xuXHRcdFx0dGhpcy5vTW9kZWwgPSB0aGlzLm9BcHBDb21wb25lbnQuZ2V0TW9kZWwoKTtcblx0XHRcdHRoaXMub01ldGFNb2RlbCA9IHRoaXMub01vZGVsLmdldE1ldGFNb2RlbCgpO1xuXHRcdFx0dGhpcy5vUm91dGVyID0gdGhpcy5vQXBwQ29tcG9uZW50LmdldFJvdXRlcigpO1xuXHRcdFx0dGhpcy5vUm91dGVyUHJveHkgPSB0aGlzLm9BcHBDb21wb25lbnQuZ2V0Um91dGVyUHJveHkoKTtcblx0XHRcdHRoaXMuZXZlbnRQcm92aWRlciA9IG5ldyAoUm91dGluZ1NlcnZpY2VFdmVudGluZyBhcyBhbnkpKCk7XG5cblx0XHRcdGNvbnN0IG9Sb3V0aW5nQ29uZmlnID0gdGhpcy5vQXBwQ29tcG9uZW50LmdldE1hbmlmZXN0RW50cnkoXCIvc2FwLnVpNS9yb3V0aW5nXCIpO1xuXHRcdFx0Y29uc3Qgb1Jvb3RWaWV3Q29uZmlnID0gdGhpcy5vQXBwQ29tcG9uZW50LmdldE1hbmlmZXN0RW50cnkoXCIvc2FwLnVpNS9yb290Vmlld1wiKTtcblx0XHRcdHRoaXMuX3BhcnNlUm91dGluZ0NvbmZpZ3VyYXRpb24ob1JvdXRpbmdDb25maWcsIG9Sb290Vmlld0NvbmZpZyk7XG5cblx0XHRcdGNvbnN0IG9BcHBDb25maWcgPSB0aGlzLm9BcHBDb21wb25lbnQuZ2V0TWFuaWZlc3RFbnRyeShcIi9zYXAuYXBwXCIpO1xuXHRcdFx0dGhpcy5vdXRib3VuZHMgPSBvQXBwQ29uZmlnICYmIG9BcHBDb25maWcuY3Jvc3NOYXZpZ2F0aW9uICYmIG9BcHBDb25maWcuY3Jvc3NOYXZpZ2F0aW9uLm91dGJvdW5kcztcblx0XHR9XG5cblx0XHR0aGlzLmluaXRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKHRoaXMpO1xuXHR9XG5cdGJlZm9yZUV4aXQoKSB7XG5cdFx0dGhpcy5vUm91dGVyLmRldGFjaFJvdXRlTWF0Y2hlZCh0aGlzLl9mbk9uUm91dGVNYXRjaGVkLCB0aGlzKTtcblx0XHR0aGlzLmV2ZW50UHJvdmlkZXIuZmlyZUV2ZW50KFwicm91dGVNYXRjaGVkXCIsIHt9KTtcblx0fVxuXHRleGl0KCkge1xuXHRcdHRoaXMuZXZlbnRQcm92aWRlci5kZXN0cm95KCk7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2UgYSBtYW5pZmVzdCByb3V0aW5nIGNvbmZpZ3VyYXRpb24gZm9yIGludGVybmFsIHVzYWdlLlxuXHQgKlxuXHQgKiBAcGFyYW0ge29iamVjdH0gb1JvdXRpbmdDb25maWcgVGhlIHJvdXRpbmcgY29uZmlndXJhdGlvbiBmcm9tIHRoZSBtYW5pZmVzdFxuXHQgKiBAcGFyYW0ge29iamVjdH0gb1Jvb3RWaWV3Q29uZmlnIFRoZSByb290IHZpZXcgY29uZmlndXJhdGlvbiBmcm9tIHRoZSBtYW5pZmVzdFxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X3BhcnNlUm91dGluZ0NvbmZpZ3VyYXRpb24ob1JvdXRpbmdDb25maWc6IGFueSwgb1Jvb3RWaWV3Q29uZmlnOiBhbnkpIHtcblx0XHRjb25zdCBpc0ZDTCA9IG9Sb290Vmlld0NvbmZpZyAmJiBvUm9vdFZpZXdDb25maWcudmlld05hbWUgPT09IFwic2FwLmZlLnRlbXBsYXRlcy5Sb290Q29udGFpbmVyLnZpZXcuRmNsXCI7XG5cblx0XHQvLyBJbmZvcm1hdGlvbiBvZiB0YXJnZXRzXG5cdFx0dGhpcy5fbVRhcmdldHMgPSB7fTtcblx0XHRPYmplY3Qua2V5cyhvUm91dGluZ0NvbmZpZy50YXJnZXRzKS5mb3JFYWNoKChzVGFyZ2V0TmFtZTogc3RyaW5nKSA9PiB7XG5cdFx0XHR0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0gPSBPYmplY3QuYXNzaWduKHsgdGFyZ2V0TmFtZTogc1RhcmdldE5hbWUgfSwgb1JvdXRpbmdDb25maWcudGFyZ2V0c1tzVGFyZ2V0TmFtZV0pO1xuXG5cdFx0XHQvLyBWaWV3IGxldmVsIGZvciBGQ0wgY2FzZXMgaXMgY2FsY3VsYXRlZCBmcm9tIHRoZSB0YXJnZXQgcGF0dGVyblxuXHRcdFx0aWYgKHRoaXMuX21UYXJnZXRzW3NUYXJnZXROYW1lXS5jb250ZXh0UGF0dGVybiAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHRoaXMuX21UYXJnZXRzW3NUYXJnZXROYW1lXS52aWV3TGV2ZWwgPSB0aGlzLl9nZXRWaWV3TGV2ZWxGcm9tUGF0dGVybih0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0uY29udGV4dFBhdHRlcm4sIDApO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0Ly8gSW5mb3JtYXRpb24gb2Ygcm91dGVzXG5cdFx0dGhpcy5fbVJvdXRlcyA9IHt9O1xuXHRcdGZvciAoY29uc3Qgc1JvdXRlS2V5IGluIG9Sb3V0aW5nQ29uZmlnLnJvdXRlcykge1xuXHRcdFx0Y29uc3Qgb1JvdXRlTWFuaWZlc3RJbmZvID0gb1JvdXRpbmdDb25maWcucm91dGVzW3NSb3V0ZUtleV0sXG5cdFx0XHRcdGFSb3V0ZVRhcmdldHMgPSBBcnJheS5pc0FycmF5KG9Sb3V0ZU1hbmlmZXN0SW5mby50YXJnZXQpID8gb1JvdXRlTWFuaWZlc3RJbmZvLnRhcmdldCA6IFtvUm91dGVNYW5pZmVzdEluZm8udGFyZ2V0XSxcblx0XHRcdFx0c1JvdXRlTmFtZSA9IEFycmF5LmlzQXJyYXkob1JvdXRpbmdDb25maWcucm91dGVzKSA/IG9Sb3V0ZU1hbmlmZXN0SW5mby5uYW1lIDogc1JvdXRlS2V5LFxuXHRcdFx0XHRzUm91dGVQYXR0ZXJuID0gb1JvdXRlTWFuaWZlc3RJbmZvLnBhdHRlcm47XG5cblx0XHRcdC8vIENoZWNrIHJvdXRlIHBhdHRlcm46IGFsbCBwYXR0ZXJucyBuZWVkIHRvIGVuZCB3aXRoICc6P3F1ZXJ5OicsIHRoYXQgd2UgdXNlIGZvciBwYXJhbWV0ZXJzXG5cdFx0XHRpZiAoc1JvdXRlUGF0dGVybi5sZW5ndGggPCA4IHx8IHNSb3V0ZVBhdHRlcm4uaW5kZXhPZihcIjo/cXVlcnk6XCIpICE9PSBzUm91dGVQYXR0ZXJuLmxlbmd0aCAtIDgpIHtcblx0XHRcdFx0TG9nLndhcm5pbmcoXCJQYXR0ZXJuIGZvciByb3V0ZSBcIiArIHNSb3V0ZU5hbWUgKyBcIiBkb2Vzbid0IGVuZCB3aXRoICc6P3F1ZXJ5OicgOiBcIiArIHNSb3V0ZVBhdHRlcm4pO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgaVJvdXRlTGV2ZWwgPSB0aGlzLl9nZXRWaWV3TGV2ZWxGcm9tUGF0dGVybihzUm91dGVQYXR0ZXJuLCAwKTtcblx0XHRcdHRoaXMuX21Sb3V0ZXNbc1JvdXRlTmFtZV0gPSB7XG5cdFx0XHRcdG5hbWU6IHNSb3V0ZU5hbWUsXG5cdFx0XHRcdHBhdHRlcm46IHNSb3V0ZVBhdHRlcm4sXG5cdFx0XHRcdHRhcmdldHM6IGFSb3V0ZVRhcmdldHMsXG5cdFx0XHRcdHJvdXRlTGV2ZWw6IGlSb3V0ZUxldmVsXG5cdFx0XHR9O1xuXG5cdFx0XHQvLyBBZGQgdGhlIHBhcmVudCB0YXJnZXRzIGluIHRoZSBsaXN0IG9mIHRhcmdldHMgZm9yIHRoZSByb3V0ZVxuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBhUm91dGVUYXJnZXRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGNvbnN0IHNQYXJlbnRUYXJnZXROYW1lID0gdGhpcy5fbVRhcmdldHNbYVJvdXRlVGFyZ2V0c1tpXV0ucGFyZW50O1xuXHRcdFx0XHRpZiAoc1BhcmVudFRhcmdldE5hbWUpIHtcblx0XHRcdFx0XHRhUm91dGVUYXJnZXRzLnB1c2goc1BhcmVudFRhcmdldE5hbWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICghaXNGQ0wpIHtcblx0XHRcdFx0Ly8gVmlldyBsZXZlbCBmb3Igbm9uLUZDTCBjYXNlcyBpcyBjYWxjdWxhdGVkIGZyb20gdGhlIHJvdXRlIHBhdHRlcm5cblx0XHRcdFx0aWYgKHRoaXMuX21UYXJnZXRzW2FSb3V0ZVRhcmdldHNbMF1dLnZpZXdMZXZlbCA9PT0gdW5kZWZpbmVkIHx8IHRoaXMuX21UYXJnZXRzW2FSb3V0ZVRhcmdldHNbMF1dLnZpZXdMZXZlbCA8IGlSb3V0ZUxldmVsKSB7XG5cdFx0XHRcdFx0Ly8gVGhlcmUgYXJlIGNhc2VzIHdoZW4gZGlmZmVyZW50IHJvdXRlcyBwb2ludCB0byB0aGUgc2FtZSB0YXJnZXQuIFdlIHRha2UgdGhlXG5cdFx0XHRcdFx0Ly8gbGFyZ2VzdCB2aWV3TGV2ZWwgaW4gdGhhdCBjYXNlLlxuXHRcdFx0XHRcdHRoaXMuX21UYXJnZXRzW2FSb3V0ZVRhcmdldHNbMF1dLnZpZXdMZXZlbCA9IGlSb3V0ZUxldmVsO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gRkNMIGxldmVsIGZvciBub24tRkNMIGNhc2VzIGlzIGVxdWFsIHRvIC0xXG5cdFx0XHRcdHRoaXMuX21UYXJnZXRzW2FSb3V0ZVRhcmdldHNbMF1dLkZDTExldmVsID0gLTE7XG5cdFx0XHR9IGVsc2UgaWYgKGFSb3V0ZVRhcmdldHMubGVuZ3RoID09PSAxICYmIHRoaXMuX21UYXJnZXRzW2FSb3V0ZVRhcmdldHNbMF1dLmNvbnRyb2xBZ2dyZWdhdGlvbiAhPT0gXCJiZWdpbkNvbHVtblBhZ2VzXCIpIHtcblx0XHRcdFx0Ly8gV2UncmUgaW4gdGhlIGNhc2Ugd2hlcmUgdGhlcmUncyBvbmx5IDEgdGFyZ2V0IGZvciB0aGUgcm91dGUsIGFuZCBpdCdzIG5vdCBpbiB0aGUgZmlyc3QgY29sdW1uXG5cdFx0XHRcdC8vIC0tPiB0aGlzIGlzIGEgZnVsbHNjcmVlbiBjb2x1bW4gYWZ0ZXIgYWxsIGNvbHVtbnMgaW4gdGhlIEZDTCBoYXZlIGJlZW4gdXNlZFxuXHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1thUm91dGVUYXJnZXRzWzBdXS5GQ0xMZXZlbCA9IDM7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBPdGhlciBGQ0wgY2FzZXNcblx0XHRcdFx0YVJvdXRlVGFyZ2V0cy5mb3JFYWNoKChzVGFyZ2V0TmFtZTogYW55KSA9PiB7XG5cdFx0XHRcdFx0c3dpdGNoICh0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0uY29udHJvbEFnZ3JlZ2F0aW9uKSB7XG5cdFx0XHRcdFx0XHRjYXNlIFwiYmVnaW5Db2x1bW5QYWdlc1wiOlxuXHRcdFx0XHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0uRkNMTGV2ZWwgPSAwO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdFx0Y2FzZSBcIm1pZENvbHVtblBhZ2VzXCI6XG5cdFx0XHRcdFx0XHRcdHRoaXMuX21UYXJnZXRzW3NUYXJnZXROYW1lXS5GQ0xMZXZlbCA9IDE7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0uRkNMTGV2ZWwgPSAyO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUHJvcGFnYXRlIHZpZXdMZXZlbCwgY29udGV4dFBhdHRlcm4sIEZDTExldmVsIGFuZCBjb250cm9sQWdncmVnYXRpb24gdG8gcGFyZW50IHRhcmdldHNcblx0XHRPYmplY3Qua2V5cyh0aGlzLl9tVGFyZ2V0cykuZm9yRWFjaCgoc1RhcmdldE5hbWU6IHN0cmluZykgPT4ge1xuXHRcdFx0d2hpbGUgKHRoaXMuX21UYXJnZXRzW3NUYXJnZXROYW1lXS5wYXJlbnQpIHtcblx0XHRcdFx0Y29uc3Qgc1BhcmVudFRhcmdldE5hbWUgPSB0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0ucGFyZW50O1xuXHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzUGFyZW50VGFyZ2V0TmFtZV0udmlld0xldmVsID1cblx0XHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzUGFyZW50VGFyZ2V0TmFtZV0udmlld0xldmVsIHx8IHRoaXMuX21UYXJnZXRzW3NUYXJnZXROYW1lXS52aWV3TGV2ZWw7XG5cdFx0XHRcdHRoaXMuX21UYXJnZXRzW3NQYXJlbnRUYXJnZXROYW1lXS5jb250ZXh0UGF0dGVybiA9XG5cdFx0XHRcdFx0dGhpcy5fbVRhcmdldHNbc1BhcmVudFRhcmdldE5hbWVdLmNvbnRleHRQYXR0ZXJuIHx8IHRoaXMuX21UYXJnZXRzW3NUYXJnZXROYW1lXS5jb250ZXh0UGF0dGVybjtcblx0XHRcdFx0dGhpcy5fbVRhcmdldHNbc1BhcmVudFRhcmdldE5hbWVdLkZDTExldmVsID1cblx0XHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzUGFyZW50VGFyZ2V0TmFtZV0uRkNMTGV2ZWwgfHwgdGhpcy5fbVRhcmdldHNbc1RhcmdldE5hbWVdLkZDTExldmVsO1xuXHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzUGFyZW50VGFyZ2V0TmFtZV0uY29udHJvbEFnZ3JlZ2F0aW9uID1cblx0XHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzUGFyZW50VGFyZ2V0TmFtZV0uY29udHJvbEFnZ3JlZ2F0aW9uIHx8IHRoaXMuX21UYXJnZXRzW3NUYXJnZXROYW1lXS5jb250cm9sQWdncmVnYXRpb247XG5cdFx0XHRcdHNUYXJnZXROYW1lID0gc1BhcmVudFRhcmdldE5hbWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQvLyBEZXRlcm1pbmUgdGhlIHJvb3QgZW50aXR5IGZvciB0aGUgYXBwXG5cdFx0Y29uc3QgYUxldmVsMFJvdXRlTmFtZXMgPSBbXTtcblx0XHRjb25zdCBhTGV2ZWwxUm91dGVOYW1lcyA9IFtdO1xuXHRcdGxldCBzRGVmYXVsdFJvdXRlTmFtZTtcblxuXHRcdGZvciAoY29uc3Qgc05hbWUgaW4gdGhpcy5fbVJvdXRlcykge1xuXHRcdFx0Y29uc3QgaUxldmVsID0gdGhpcy5fbVJvdXRlc1tzTmFtZV0ucm91dGVMZXZlbDtcblx0XHRcdGlmIChpTGV2ZWwgPT09IDApIHtcblx0XHRcdFx0YUxldmVsMFJvdXRlTmFtZXMucHVzaChzTmFtZSk7XG5cdFx0XHR9IGVsc2UgaWYgKGlMZXZlbCA9PT0gMSkge1xuXHRcdFx0XHRhTGV2ZWwxUm91dGVOYW1lcy5wdXNoKHNOYW1lKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoYUxldmVsMFJvdXRlTmFtZXMubGVuZ3RoID09PSAxKSB7XG5cdFx0XHRzRGVmYXVsdFJvdXRlTmFtZSA9IGFMZXZlbDBSb3V0ZU5hbWVzWzBdO1xuXHRcdH0gZWxzZSBpZiAoYUxldmVsMVJvdXRlTmFtZXMubGVuZ3RoID09PSAxKSB7XG5cdFx0XHRzRGVmYXVsdFJvdXRlTmFtZSA9IGFMZXZlbDFSb3V0ZU5hbWVzWzBdO1xuXHRcdH1cblxuXHRcdGlmIChzRGVmYXVsdFJvdXRlTmFtZSkge1xuXHRcdFx0Y29uc3Qgc0RlZmF1bHRUYXJnZXROYW1lID0gdGhpcy5fbVJvdXRlc1tzRGVmYXVsdFJvdXRlTmFtZV0udGFyZ2V0cy5zbGljZSgtMSlbMF07XG5cdFx0XHR0aGlzLnNDb250ZXh0UGF0aCA9IFwiXCI7XG5cdFx0XHRpZiAodGhpcy5fbVRhcmdldHNbc0RlZmF1bHRUYXJnZXROYW1lXS5vcHRpb25zICYmIHRoaXMuX21UYXJnZXRzW3NEZWZhdWx0VGFyZ2V0TmFtZV0ub3B0aW9ucy5zZXR0aW5ncykge1xuXHRcdFx0XHRjb25zdCBvU2V0dGluZ3MgPSB0aGlzLl9tVGFyZ2V0c1tzRGVmYXVsdFRhcmdldE5hbWVdLm9wdGlvbnMuc2V0dGluZ3M7XG5cdFx0XHRcdHRoaXMuc0NvbnRleHRQYXRoID0gb1NldHRpbmdzLmNvbnRleHRQYXRoIHx8IFwiL1wiICsgb1NldHRpbmdzLmVudGl0eVNldDtcblx0XHRcdH1cblx0XHRcdGlmICghdGhpcy5zQ29udGV4dFBhdGgpIHtcblx0XHRcdFx0TG9nLndhcm5pbmcoXG5cdFx0XHRcdFx0XCJDYW5ub3QgZGV0ZXJtaW5lIGRlZmF1bHQgY29udGV4dFBhdGg6IGNvbnRleHRQYXRoIG9yIGVudGl0eVNldCBtaXNzaW5nIGluIGRlZmF1bHQgdGFyZ2V0OiBcIiArIHNEZWZhdWx0VGFyZ2V0TmFtZVxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRMb2cud2FybmluZyhcIkNhbm5vdCBkZXRlcm1pbmUgZGVmYXVsdCBjb250ZXh0UGF0aDogbm8gZGVmYXVsdCByb3V0ZSBmb3VuZC5cIik7XG5cdFx0fVxuXG5cdFx0Ly8gV2UgbmVlZCB0byBlc3RhYmxpc2ggdGhlIGNvcnJlY3QgcGF0aCB0byB0aGUgZGlmZmVyZW50IHBhZ2VzLCBpbmNsdWRpbmcgdGhlIG5hdmlnYXRpb24gcHJvcGVydGllc1xuXHRcdE9iamVjdC5rZXlzKHRoaXMuX21UYXJnZXRzKVxuXHRcdFx0Lm1hcCgoc1RhcmdldEtleTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0S2V5XTtcblx0XHRcdH0pXG5cdFx0XHQuc29ydCgoYTogYW55LCBiOiBhbnkpID0+IHtcblx0XHRcdFx0cmV0dXJuIGEudmlld0xldmVsIDwgYi52aWV3TGV2ZWwgPyAtMSA6IDE7XG5cdFx0XHR9KVxuXHRcdFx0LmZvckVhY2goKHRhcmdldDogYW55KSA9PiB7XG5cdFx0XHRcdC8vIEFmdGVyIHNvcnRpbmcgdGhlIHRhcmdldHMgcGVyIGxldmVsIHdlIGNhbiB0aGVuIGdvIHRocm91Z2ggdGhlaXIgbmF2aWdhdGlvbiBvYmplY3QgYW5kIHVwZGF0ZSB0aGUgcGF0aHMgYWNjb3JkaW5nbHkuXG5cdFx0XHRcdGlmICh0YXJnZXQub3B0aW9ucykge1xuXHRcdFx0XHRcdGNvbnN0IHNldHRpbmdzID0gdGFyZ2V0Lm9wdGlvbnMuc2V0dGluZ3M7XG5cdFx0XHRcdFx0Y29uc3Qgc0NvbnRleHRQYXRoID0gc2V0dGluZ3MuY29udGV4dFBhdGggfHwgKHNldHRpbmdzLmVudGl0eVNldCA/IFwiL1wiICsgc2V0dGluZ3MuZW50aXR5U2V0IDogXCJcIik7XG5cdFx0XHRcdFx0aWYgKCFzZXR0aW5ncy5mdWxsQ29udGV4dFBhdGggJiYgc0NvbnRleHRQYXRoKSB7XG5cdFx0XHRcdFx0XHRzZXR0aW5ncy5mdWxsQ29udGV4dFBhdGggPSBzQ29udGV4dFBhdGggKyBcIi9cIjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0T2JqZWN0LmtleXMoc2V0dGluZ3MubmF2aWdhdGlvbiB8fCB7fSkuZm9yRWFjaCgoc05hdk5hbWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0Ly8gQ2hlY2sgaWYgaXQncyBhIG5hdmlnYXRpb24gcHJvcGVydHlcblx0XHRcdFx0XHRcdGNvbnN0IHRhcmdldFJvdXRlID0gdGhpcy5fbVJvdXRlc1tzZXR0aW5ncy5uYXZpZ2F0aW9uW3NOYXZOYW1lXS5kZXRhaWwucm91dGVdO1xuXHRcdFx0XHRcdFx0aWYgKHRhcmdldFJvdXRlICYmIHRhcmdldFJvdXRlLnRhcmdldHMpIHtcblx0XHRcdFx0XHRcdFx0dGFyZ2V0Um91dGUudGFyZ2V0cy5mb3JFYWNoKChzVGFyZ2V0TmFtZTogYW55KSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKFxuXHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5fbVRhcmdldHNbc1RhcmdldE5hbWVdLm9wdGlvbnMgJiZcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMuX21UYXJnZXRzW3NUYXJnZXROYW1lXS5vcHRpb25zLnNldHRpbmdzICYmXG5cdFx0XHRcdFx0XHRcdFx0XHQhdGhpcy5fbVRhcmdldHNbc1RhcmdldE5hbWVdLm9wdGlvbnMuc2V0dGluZ3MuZnVsbENvbnRleHRQYXRoXG5cdFx0XHRcdFx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAodGFyZ2V0LnZpZXdMZXZlbCA9PT0gMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0ub3B0aW9ucy5zZXR0aW5ncy5mdWxsQ29udGV4dFBhdGggPSBcIi9cIiArIHNOYXZOYW1lICsgXCIvXCI7XG5cdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0ub3B0aW9ucy5zZXR0aW5ncy5mdWxsQ29udGV4dFBhdGggPVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLmZ1bGxDb250ZXh0UGF0aCArIHNOYXZOYW1lICsgXCIvXCI7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsY3VsYXRlcyBhIHZpZXcgbGV2ZWwgZnJvbSBhIHBhdHRlcm4gYnkgY291bnRpbmcgdGhlIG51bWJlciBvZiBzZWdtZW50cy5cblx0ICpcblx0ICogQHBhcmFtIHtzdHJpbmd9IHNQYXR0ZXJuIFRoZSBwYXR0ZXJuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSB2aWV3TGV2ZWwgVGhlIGN1cnJlbnQgbGV2ZWwgb2Ygdmlld1xuXHQgKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgbGV2ZWxcblx0ICovXG5cdF9nZXRWaWV3TGV2ZWxGcm9tUGF0dGVybihzUGF0dGVybjogc3RyaW5nLCB2aWV3TGV2ZWw6IG51bWJlcik6IG51bWJlciB7XG5cdFx0c1BhdHRlcm4gPSBzUGF0dGVybi5yZXBsYWNlKFwiOj9xdWVyeTpcIiwgXCJcIik7XG5cdFx0Y29uc3QgcmVnZXggPSBuZXcgUmVnRXhwKFwiL1teL10qJFwiKTtcblx0XHRpZiAoc1BhdHRlcm4gJiYgc1BhdHRlcm5bMF0gIT09IFwiL1wiICYmIHNQYXR0ZXJuWzBdICE9PSBcIj9cIikge1xuXHRcdFx0c1BhdHRlcm4gPSBcIi9cIiArIHNQYXR0ZXJuO1xuXHRcdH1cblx0XHRpZiAoc1BhdHRlcm4ubGVuZ3RoKSB7XG5cdFx0XHRzUGF0dGVybiA9IHNQYXR0ZXJuLnJlcGxhY2UocmVnZXgsIFwiXCIpO1xuXHRcdFx0aWYgKHRoaXMub1JvdXRlci5tYXRjaChzUGF0dGVybikgfHwgc1BhdHRlcm4gPT09IFwiXCIpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuX2dldFZpZXdMZXZlbEZyb21QYXR0ZXJuKHNQYXR0ZXJuLCArK3ZpZXdMZXZlbCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fZ2V0Vmlld0xldmVsRnJvbVBhdHRlcm4oc1BhdHRlcm4sIHZpZXdMZXZlbCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiB2aWV3TGV2ZWw7XG5cdFx0fVxuXHR9XG5cblx0X2dldFJvdXRlSW5mb3JtYXRpb24oc1JvdXRlTmFtZTogYW55KSB7XG5cdFx0cmV0dXJuIHRoaXMuX21Sb3V0ZXNbc1JvdXRlTmFtZV07XG5cdH1cblxuXHRfZ2V0VGFyZ2V0SW5mb3JtYXRpb24oc1RhcmdldE5hbWU6IGFueSkge1xuXHRcdHJldHVybiB0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV07XG5cdH1cblxuXHRfZ2V0Q29tcG9uZW50SWQoc093bmVySWQ6IGFueSwgc0NvbXBvbmVudElkOiBhbnkpIHtcblx0XHRpZiAoc0NvbXBvbmVudElkLmluZGV4T2Yoc093bmVySWQgKyBcIi0tLVwiKSA9PT0gMCkge1xuXHRcdFx0cmV0dXJuIHNDb21wb25lbnRJZC5zdWJzdHIoc093bmVySWQubGVuZ3RoICsgMyk7XG5cdFx0fVxuXHRcdHJldHVybiBzQ29tcG9uZW50SWQ7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHRhcmdldCBpbmZvcm1hdGlvbiBmb3IgYSBnaXZlbiBjb21wb25lbnQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBvQ29tcG9uZW50SW5zdGFuY2UgSW5zdGFuY2Ugb2YgdGhlIGNvbXBvbmVudFxuXHQgKiBAcmV0dXJucyB7b2JqZWN0fSBUaGUgY29uZmlndXJhdGlvbiBmb3IgdGhlIHRhcmdldFxuXHQgKi9cblx0Z2V0VGFyZ2V0SW5mb3JtYXRpb25Gb3Iob0NvbXBvbmVudEluc3RhbmNlOiBhbnkpIHtcblx0XHRjb25zdCBzVGFyZ2V0Q29tcG9uZW50SWQgPSB0aGlzLl9nZXRDb21wb25lbnRJZChvQ29tcG9uZW50SW5zdGFuY2UuX3NPd25lcklkLCBvQ29tcG9uZW50SW5zdGFuY2UuZ2V0SWQoKSk7XG5cdFx0bGV0IHNDb3JyZWN0VGFyZ2V0TmFtZSA9IG51bGw7XG5cdFx0T2JqZWN0LmtleXModGhpcy5fbVRhcmdldHMpLmZvckVhY2goKHNUYXJnZXROYW1lOiBzdHJpbmcpID0+IHtcblx0XHRcdGlmICh0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0uaWQgPT09IHNUYXJnZXRDb21wb25lbnRJZCB8fCB0aGlzLl9tVGFyZ2V0c1tzVGFyZ2V0TmFtZV0udmlld0lkID09PSBzVGFyZ2V0Q29tcG9uZW50SWQpIHtcblx0XHRcdFx0c0NvcnJlY3RUYXJnZXROYW1lID0gc1RhcmdldE5hbWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHRoaXMuX2dldFRhcmdldEluZm9ybWF0aW9uKHNDb3JyZWN0VGFyZ2V0TmFtZSk7XG5cdH1cblxuXHRnZXRMYXN0U2VtYW50aWNNYXBwaW5nKCkge1xuXHRcdHJldHVybiB0aGlzLm9MYXN0U2VtYW50aWNNYXBwaW5nO1xuXHR9XG5cblx0c2V0TGFzdFNlbWFudGljTWFwcGluZyhvTWFwcGluZzogYW55KSB7XG5cdFx0dGhpcy5vTGFzdFNlbWFudGljTWFwcGluZyA9IG9NYXBwaW5nO1xuXHR9XG5cblx0bmF2aWdhdGVUbyhvQ29udGV4dDogYW55LCBzUm91dGVOYW1lOiBhbnksIG1QYXJhbWV0ZXJNYXBwaW5nOiBhbnksIGJQcmVzZXJ2ZUhpc3Rvcnk6IGFueSkge1xuXHRcdGxldCBzVGFyZ2V0VVJMUHJvbWlzZSwgYklzU3RpY2t5TW9kZTogYm9vbGVhbjtcblx0XHRpZiAob0NvbnRleHQuZ2V0TW9kZWwoKSAmJiBvQ29udGV4dC5nZXRNb2RlbCgpLmdldE1ldGFNb2RlbCkge1xuXHRcdFx0YklzU3RpY2t5TW9kZSA9IE1vZGVsSGVscGVyLmlzU3RpY2t5U2Vzc2lvblN1cHBvcnRlZChvQ29udGV4dC5nZXRNb2RlbCgpLmdldE1ldGFNb2RlbCgpKTtcblx0XHR9XG5cdFx0aWYgKCFtUGFyYW1ldGVyTWFwcGluZykge1xuXHRcdFx0Ly8gaWYgdGhlcmUgaXMgbm8gcGFyYW1ldGVyIG1hcHBpbmcgZGVmaW5lIHRoaXMgbWVhbiB3ZSByZWx5IGVudGlyZWx5IG9uIHRoZSBiaW5kaW5nIGNvbnRleHQgcGF0aFxuXHRcdFx0c1RhcmdldFVSTFByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoU2VtYW50aWNLZXlIZWxwZXIuZ2V0U2VtYW50aWNQYXRoKG9Db250ZXh0KSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHNUYXJnZXRVUkxQcm9taXNlID0gdGhpcy5wcmVwYXJlUGFyYW1ldGVycyhtUGFyYW1ldGVyTWFwcGluZywgc1JvdXRlTmFtZSwgb0NvbnRleHQpLnRoZW4oKG1QYXJhbWV0ZXJzOiBhbnkpID0+IHtcblx0XHRcdFx0cmV0dXJuIHRoaXMub1JvdXRlci5nZXRVUkwoc1JvdXRlTmFtZSwgbVBhcmFtZXRlcnMpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdHJldHVybiBzVGFyZ2V0VVJMUHJvbWlzZS50aGVuKChzVGFyZ2V0VVJMOiBhbnkpID0+IHtcblx0XHRcdHRoaXMub1JvdXRlclByb3h5Lm5hdlRvSGFzaChzVGFyZ2V0VVJMLCBiUHJlc2VydmVIaXN0b3J5LCBmYWxzZSwgZmFsc2UsICFiSXNTdGlja3lNb2RlKTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNZXRob2QgdG8gcmV0dXJuIGEgbWFwIG9mIHJvdXRpbmcgdGFyZ2V0IHBhcmFtZXRlcnMgd2hlcmUgdGhlIGJpbmRpbmcgc3ludGF4IGlzIHJlc29sdmVkIHRvIHRoZSBjdXJyZW50IG1vZGVsLlxuXHQgKlxuXHQgKiBAcGFyYW0ge29iamVjdH0gbVBhcmFtZXRlcnMgUGFyYW1ldGVycyBtYXAgaW4gdGhlIGZvcm1hdCBbazogc3RyaW5nXSA6IENvbXBsZXhCaW5kaW5nU3ludGF4XG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzVGFyZ2V0Um91dGUgTmFtZSBvZiB0aGUgdGFyZ2V0IHJvdXRlXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBvQ29udGV4dCBUaGUgaW5zdGFuY2Ugb2YgdGhlIGJpbmRpbmcgY29udGV4dFxuXHQgKiBAcmV0dXJucyB7UHJvbWlzZX0gQSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHRvIHRoZSByb3V0aW5nIHRhcmdldCBwYXJhbWV0ZXJzXG5cdCAqL1xuXHRwcmVwYXJlUGFyYW1ldGVycyhtUGFyYW1ldGVyczogYW55LCBzVGFyZ2V0Um91dGU6IHN0cmluZywgb0NvbnRleHQ6IENvbnRleHQpIHtcblx0XHRsZXQgb1BhcmFtZXRlcnNQcm9taXNlO1xuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBzQ29udGV4dFBhdGggPSBvQ29udGV4dC5nZXRQYXRoKCk7XG5cdFx0XHRjb25zdCBvTWV0YU1vZGVsOiBPRGF0YU1ldGFNb2RlbCA9IG9Db250ZXh0LmdldE1vZGVsKCkuZ2V0TWV0YU1vZGVsKCkgYXMgT0RhdGFNZXRhTW9kZWw7XG5cdFx0XHRjb25zdCBhQ29udGV4dFBhdGhQYXJ0cyA9IHNDb250ZXh0UGF0aC5zcGxpdChcIi9cIik7XG5cdFx0XHRjb25zdCBhQWxsUmVzb2x2ZWRQYXJhbWV0ZXJQcm9taXNlcyA9IE9iamVjdC5rZXlzKG1QYXJhbWV0ZXJzKS5tYXAoKHNQYXJhbWV0ZXJLZXk6IGFueSkgPT4ge1xuXHRcdFx0XHRjb25zdCBzUGFyYW1ldGVyTWFwcGluZ0V4cHJlc3Npb24gPSBtUGFyYW1ldGVyc1tzUGFyYW1ldGVyS2V5XTtcblx0XHRcdFx0Ly8gV2UgYXNzdW1lIHRoZSBkZWZpbmVkIHBhcmFtZXRlcnMgd2lsbCBiZSBjb21wYXRpYmxlIHdpdGggYSBiaW5kaW5nIGV4cHJlc3Npb25cblx0XHRcdFx0Y29uc3Qgb1BhcnNlZEV4cHJlc3Npb24gPSBCaW5kaW5nUGFyc2VyLmNvbXBsZXhQYXJzZXIoc1BhcmFtZXRlck1hcHBpbmdFeHByZXNzaW9uKTtcblx0XHRcdFx0Y29uc3QgYVBhcnRzID0gb1BhcnNlZEV4cHJlc3Npb24ucGFydHMgfHwgW29QYXJzZWRFeHByZXNzaW9uXTtcblx0XHRcdFx0Y29uc3QgYVJlc29sdmVkUGFyYW1ldGVyUHJvbWlzZXMgPSBhUGFydHMubWFwKGZ1bmN0aW9uKG9QYXRoUGFydDogYW55KSB7XG5cdFx0XHRcdFx0Y29uc3QgYVJlbGF0aXZlUGFydHMgPSBvUGF0aFBhcnQucGF0aC5zcGxpdChcIi4uL1wiKTtcblx0XHRcdFx0XHQvLyBXZSBnbyB1cCB0aGUgY3VycmVudCBjb250ZXh0IHBhdGggYXMgbWFueSB0aW1lcyBhcyBuZWNlc3Nhcnlcblx0XHRcdFx0XHRjb25zdCBhTG9jYWxQYXJ0cyA9IGFDb250ZXh0UGF0aFBhcnRzLnNsaWNlKDAsIGFDb250ZXh0UGF0aFBhcnRzLmxlbmd0aCAtIGFSZWxhdGl2ZVBhcnRzLmxlbmd0aCArIDEpO1xuXHRcdFx0XHRcdGFMb2NhbFBhcnRzLnB1c2goYVJlbGF0aXZlUGFydHNbYVJlbGF0aXZlUGFydHMubGVuZ3RoIC0gMV0pO1xuXG5cdFx0XHRcdFx0Y29uc3Qgc1Byb3BlcnR5UGF0aCA9IGFMb2NhbFBhcnRzLmpvaW4oXCIvXCIpO1xuXHRcdFx0XHRcdGNvbnN0IG9NZXRhQ29udGV4dCA9IChvTWV0YU1vZGVsIGFzIGFueSkuZ2V0TWV0YUNvbnRleHQoc1Byb3BlcnR5UGF0aCk7XG5cdFx0XHRcdFx0cmV0dXJuIG9Db250ZXh0LnJlcXVlc3RQcm9wZXJ0eShzUHJvcGVydHlQYXRoKS50aGVuKGZ1bmN0aW9uKG9WYWx1ZTogYW55KSB7XG5cdFx0XHRcdFx0XHRjb25zdCBvUHJvcGVydHlJbmZvID0gb01ldGFDb250ZXh0LmdldE9iamVjdCgpO1xuXHRcdFx0XHRcdFx0Y29uc3Qgc0VkbVR5cGUgPSBvUHJvcGVydHlJbmZvLiRUeXBlO1xuXHRcdFx0XHRcdFx0cmV0dXJuIE9EYXRhVXRpbHMuZm9ybWF0TGl0ZXJhbChvVmFsdWUsIHNFZG1UeXBlKTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0cmV0dXJuIFByb21pc2UuYWxsKGFSZXNvbHZlZFBhcmFtZXRlclByb21pc2VzKS50aGVuKChhUmVzb2x2ZWRQYXJhbWV0ZXJzOiBhbnkpID0+IHtcblx0XHRcdFx0XHRjb25zdCB2YWx1ZSA9IG9QYXJzZWRFeHByZXNzaW9uLmZvcm1hdHRlclxuXHRcdFx0XHRcdFx0PyBvUGFyc2VkRXhwcmVzc2lvbi5mb3JtYXR0ZXIuYXBwbHkodGhpcywgYVJlc29sdmVkUGFyYW1ldGVycylcblx0XHRcdFx0XHRcdDogYVJlc29sdmVkUGFyYW1ldGVycy5qb2luKFwiXCIpO1xuXHRcdFx0XHRcdHJldHVybiB7IGtleTogc1BhcmFtZXRlcktleSwgdmFsdWU6IHZhbHVlIH07XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSk7XG5cblx0XHRcdG9QYXJhbWV0ZXJzUHJvbWlzZSA9IFByb21pc2UuYWxsKGFBbGxSZXNvbHZlZFBhcmFtZXRlclByb21pc2VzKS50aGVuKGZ1bmN0aW9uKFxuXHRcdFx0XHRhQWxsUmVzb2x2ZWRQYXJhbWV0ZXJzOiB7IGtleTogYW55OyB2YWx1ZTogYW55IH1bXVxuXHRcdFx0KSB7XG5cdFx0XHRcdGNvbnN0IG9QYXJhbWV0ZXJzOiBhbnkgPSB7fTtcblx0XHRcdFx0YUFsbFJlc29sdmVkUGFyYW1ldGVycy5mb3JFYWNoKGZ1bmN0aW9uKG9SZXNvbHZlZFBhcmFtZXRlcjogeyBrZXk6IGFueTsgdmFsdWU6IGFueSB9KSB7XG5cdFx0XHRcdFx0b1BhcmFtZXRlcnNbb1Jlc29sdmVkUGFyYW1ldGVyLmtleV0gPSBvUmVzb2x2ZWRQYXJhbWV0ZXIudmFsdWU7XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRyZXR1cm4gb1BhcmFtZXRlcnM7XG5cdFx0XHR9KTtcblx0XHR9IGNhdGNoIChvRXJyb3IpIHtcblx0XHRcdExvZy5lcnJvcihcIkNvdWxkIG5vdCBwYXJzZSB0aGUgcGFyYW1ldGVycyBmb3IgdGhlIG5hdmlnYXRpb24gdG8gcm91dGUgXCIgKyBzVGFyZ2V0Um91dGUpO1xuXHRcdFx0b1BhcmFtZXRlcnNQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKHVuZGVmaW5lZCk7XG5cdFx0fVxuXHRcdHJldHVybiBvUGFyYW1ldGVyc1Byb21pc2U7XG5cdH1cblxuXHRfZmlyZVJvdXRlTWF0Y2hFdmVudHMobVBhcmFtZXRlcnM6IGFueSkge1xuXHRcdHRoaXMuZXZlbnRQcm92aWRlci5maXJlRXZlbnQoXCJyb3V0ZU1hdGNoZWRcIiwgbVBhcmFtZXRlcnMpO1xuXHRcdHRoaXMuZXZlbnRQcm92aWRlci5maXJlRXZlbnQoXCJhZnRlclJvdXRlTWF0Y2hlZFwiLCBtUGFyYW1ldGVycyk7XG5cblx0XHRFZGl0U3RhdGUuY2xlYW5Qcm9jZXNzZWRFZGl0U3RhdGUoKTsgLy8gUmVzZXQgVUkgc3RhdGUgd2hlbiBhbGwgYmluZGluZ3MgaGF2ZSBiZWVuIHJlZnJlc2hlZFxuXHR9XG5cblx0LyoqXG5cdCAqIE5hdmlnYXRlcyB0byBhIGNvbnRleHQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7c2FwLnVpLm1vZGVsLm9kYXRhLnY0LkNvbnRleHR9IG9Db250ZXh0IFRoZSBDb250ZXh0IHRvIGJlIG5hdmlnYXRlZCB0b1xuXHQgKiBAcGFyYW0ge29iamVjdH0gW21QYXJhbWV0ZXJzXSBPcHRpb25hbCwgbWFwIGNvbnRhaW5pbmcgdGhlIGZvbGxvd2luZyBhdHRyaWJ1dGVzOlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IFttUGFyYW1ldGVycy5jaGVja05vSGFzaENoYW5nZV0gTmF2aWdhdGUgdG8gdGhlIGNvbnRleHQgd2l0aG91dCBjaGFuZ2luZyB0aGUgVVJMXG5cdCAqIEBwYXJhbSB7UHJvbWlzZX0gW21QYXJhbWV0ZXJzLmFzeW5jQ29udGV4dF0gVGhlIGNvbnRleHQgaXMgY3JlYXRlZCBhc3luYywgbmF2aWdhdGUgdG8gKC4uLikgYW5kXG5cdCAqICAgICAgICAgICAgICAgICAgICB3YWl0IGZvciBQcm9taXNlIHRvIGJlIHJlc29sdmVkIGFuZCB0aGVuIG5hdmlnYXRlIGludG8gdGhlIGNvbnRleHRcblx0ICogQHBhcmFtIHtib29sZWFufSBbbVBhcmFtZXRlcnMuYkRlZmVycmVkQ29udGV4dF0gVGhlIGNvbnRleHQgc2hhbGwgYmUgY3JlYXRlZCBkZWZlcnJlZCBhdCB0aGUgdGFyZ2V0IHBhZ2Vcblx0ICogQHBhcmFtIHtib29sZWFufSBbbVBhcmFtZXRlcnMuZWRpdGFibGVdIFRoZSB0YXJnZXQgcGFnZSBzaGFsbCBiZSBpbW1lZGlhdGVseSBpbiB0aGUgZWRpdCBtb2RlIHRvIGF2b2lkIGZsaWNrZXJpbmdcblx0ICogQHBhcmFtIHtib29sZWFufSBbbVBhcmFtZXRlcnMuYlBlcnNpc3RPUFNjcm9sbF0gVGhlIGJQZXJzaXN0T1BTY3JvbGwgd2lsbCBiZSB1c2VkIGZvciBzY3JvbGxpbmcgdG8gZmlyc3QgdGFiXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBbbVBhcmFtZXRlcnMudXBkYXRlRkNMTGV2ZWxdIGArMWAgaWYgd2UgYWRkIGEgY29sdW1uIGluIEZDTCwgYC0xYCB0byByZW1vdmUgYSBjb2x1bW4sIDAgdG8gc3RheSBvbiB0aGUgc2FtZSBjb2x1bW5cblx0ICogQHBhcmFtIHtib29sZWFufSBbbVBhcmFtZXRlcnMubm9QcmVzZXJ2YXRpb25DYWNoZV0gRG8gbmF2aWdhdGlvbiB3aXRob3V0IHRha2luZyBpbnRvIGFjY291bnQgdGhlIHByZXNlcnZlZCBjYWNoZSBtZWNoYW5pc21cblx0ICogQHBhcmFtIHtib29sZWFufSBbbVBhcmFtZXRlcnMuYlJlY3JlYXRlQ29udGV4dF0gRm9yY2UgcmUtY3JlYXRpb24gb2YgdGhlIGNvbnRleHQgaW5zdGVhZCBvZiB1c2luZyB0aGUgb25lIHBhc3NlZCBhcyBwYXJhbWV0ZXJcblx0ICogQHBhcmFtIHtib29sZWFufSBbbVBhcmFtZXRlcnMuYkZvcmNlRm9jdXNdIEZvcmNlcyBmb2N1cyBzZWxlY3Rpb24gYWZ0ZXIgbmF2aWdhdGlvblxuXHQgKiBAcGFyYW0ge29iamVjdH0gW29WaWV3RGF0YV0gVmlldyBkYXRhXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBbb0N1cnJlbnRUYXJnZXRJbmZvXSBUaGUgdGFyZ2V0IGluZm9ybWF0aW9uIGZyb20gd2hpY2ggdGhlIG5hdmlnYXRpb24gaXMgdHJpZ2dlcmVkXG5cdCAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIHdoaWNoIGlzIHJlc29sdmVkIG9uY2UgdGhlIG5hdmlnYXRpb24gaXMgdHJpZ2dlcmVkXG5cdCAqXG5cdCAqIEB1aTUtcmVzdHJpY3RlZFxuXHQgKiBAZmluYWxcblx0ICovXG5cdG5hdmlnYXRlVG9Db250ZXh0KFxuXHRcdG9Db250ZXh0OiBhbnksXG5cdFx0bVBhcmFtZXRlcnM6XG5cdFx0XHR8IHtcblx0XHRcdFx0XHRjaGVja05vSGFzaENoYW5nZT86IGJvb2xlYW47XG5cdFx0XHRcdFx0YXN5bmNDb250ZXh0PzogUHJvbWlzZTxhbnk+O1xuXHRcdFx0XHRcdGJEZWZlcnJlZENvbnRleHQ/OiBib29sZWFuO1xuXHRcdFx0XHRcdGVkaXRhYmxlPzogYm9vbGVhbjtcblx0XHRcdFx0XHR0cmFuc2llbnQ/OiBib29sZWFuO1xuXHRcdFx0XHRcdGJQZXJzaXN0T1BTY3JvbGw/OiBib29sZWFuO1xuXHRcdFx0XHRcdHVwZGF0ZUZDTExldmVsPzogbnVtYmVyO1xuXHRcdFx0XHRcdG5vUHJlc2VydmF0aW9uQ2FjaGU/OiBib29sZWFuO1xuXHRcdFx0XHRcdGJSZWNyZWF0ZUNvbnRleHQ/OiBib29sZWFuO1xuXHRcdFx0XHRcdGJGb3JjZUZvY3VzPzogYm9vbGVhbjtcblx0XHRcdFx0XHR0YXJnZXRQYXRoPzogc3RyaW5nO1xuXHRcdFx0XHRcdHNob3dQbGFjZWhvbGRlcj86IGJvb2xlYW47XG5cdFx0XHRcdFx0YkRyYWZ0TmF2aWdhdGlvbj86IGJvb2xlYW47XG5cdFx0XHQgIH1cblx0XHRcdHwgdW5kZWZpbmVkLFxuXHRcdG9WaWV3RGF0YTogYW55IHwgdW5kZWZpbmVkLFxuXHRcdG9DdXJyZW50VGFyZ2V0SW5mbzogYW55IHwgdW5kZWZpbmVkXG5cdCkge1xuXHRcdGxldCBzVGFyZ2V0Um91dGU6IHN0cmluZyA9IFwiXCIsXG5cdFx0XHRvUm91dGVQYXJhbWV0ZXJzUHJvbWlzZSxcblx0XHRcdGJJc1N0aWNreU1vZGU6IGJvb2xlYW4gPSBmYWxzZTtcblxuXHRcdGlmIChvQ29udGV4dC5nZXRNb2RlbCgpICYmIG9Db250ZXh0LmdldE1vZGVsKCkuZ2V0TWV0YU1vZGVsKSB7XG5cdFx0XHRiSXNTdGlja3lNb2RlID0gTW9kZWxIZWxwZXIuaXNTdGlja3lTZXNzaW9uU3VwcG9ydGVkKG9Db250ZXh0LmdldE1vZGVsKCkuZ2V0TWV0YU1vZGVsKCkpO1xuXHRcdH1cblx0XHQvLyBNYW5hZ2UgcGFyYW1ldGVyIG1hcHBpbmdcblx0XHRpZiAobVBhcmFtZXRlcnMgJiYgbVBhcmFtZXRlcnMudGFyZ2V0UGF0aCAmJiBvVmlld0RhdGEgJiYgb1ZpZXdEYXRhLm5hdmlnYXRpb24pIHtcblx0XHRcdGNvbnN0IG9Sb3V0ZURldGFpbCA9IG9WaWV3RGF0YS5uYXZpZ2F0aW9uW21QYXJhbWV0ZXJzLnRhcmdldFBhdGhdLmRldGFpbDtcblx0XHRcdHNUYXJnZXRSb3V0ZSA9IG9Sb3V0ZURldGFpbC5yb3V0ZTtcblxuXHRcdFx0aWYgKG9Sb3V0ZURldGFpbC5wYXJhbWV0ZXJzKSB7XG5cdFx0XHRcdG9Sb3V0ZVBhcmFtZXRlcnNQcm9taXNlID0gdGhpcy5wcmVwYXJlUGFyYW1ldGVycyhvUm91dGVEZXRhaWwucGFyYW1ldGVycywgc1RhcmdldFJvdXRlLCBvQ29udGV4dCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0bGV0IHNUYXJnZXRQYXRoID0gdGhpcy5fZ2V0UGF0aEZyb21Db250ZXh0KG9Db250ZXh0LCBtUGFyYW1ldGVycyk7XG5cdFx0Ly8gSWYgdGhlIHBhdGggaXMgZW1wdHksIHdlJ3JlIHN1cHBvc2VkIHRvIG5hdmlnYXRlIHRvIHRoZSBmaXJzdCBwYWdlIG9mIHRoZSBhcHBcblx0XHQvLyBDaGVjayBpZiB3ZSBuZWVkIHRvIGV4aXQgZnJvbSB0aGUgYXBwIGluc3RlYWRcblx0XHRpZiAoc1RhcmdldFBhdGgubGVuZ3RoID09PSAwICYmIHRoaXMuYkV4aXRPbk5hdmlnYXRlQmFja1RvUm9vdCkge1xuXHRcdFx0cmV0dXJuIHRoaXMub1JvdXRlclByb3h5LmV4aXRGcm9tQXBwKCk7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhlIGNvbnRleHQgaXMgZGVmZXJyZWQgb3IgYXN5bmMsIHdlIGFkZCAoLi4uKSB0byB0aGUgcGF0aFxuXHRcdGlmIChtUGFyYW1ldGVycz8uYXN5bmNDb250ZXh0IHx8IG1QYXJhbWV0ZXJzPy5iRGVmZXJyZWRDb250ZXh0KSB7XG5cdFx0XHRzVGFyZ2V0UGF0aCArPSBcIiguLi4pXCI7XG5cdFx0fVxuXG5cdFx0Ly8gQWRkIGxheW91dCBwYXJhbWV0ZXIgaWYgbmVlZGVkXG5cdFx0Y29uc3Qgc0xheW91dCA9IHRoaXMuX2NhbGN1bGF0ZUxheW91dChzVGFyZ2V0UGF0aCwgbVBhcmFtZXRlcnMpO1xuXHRcdGlmIChzTGF5b3V0KSB7XG5cdFx0XHRzVGFyZ2V0UGF0aCArPSBcIj9sYXlvdXQ9XCIgKyBzTGF5b3V0O1xuXHRcdH1cblxuXHRcdC8vIE5hdmlnYXRpb24gcGFyYW1ldGVycyBmb3IgbGF0ZXIgdXNhZ2Vcblx0XHRjb25zdCBvTmF2aWdhdGlvbkluZm8gPSB7XG5cdFx0XHRvQXN5bmNDb250ZXh0OiBtUGFyYW1ldGVycz8uYXN5bmNDb250ZXh0LFxuXHRcdFx0YkRlZmVycmVkQ29udGV4dDogbVBhcmFtZXRlcnM/LmJEZWZlcnJlZENvbnRleHQsXG5cdFx0XHRiVGFyZ2V0RWRpdGFibGU6IG1QYXJhbWV0ZXJzPy5lZGl0YWJsZSxcblx0XHRcdGJQZXJzaXN0T1BTY3JvbGw6IG1QYXJhbWV0ZXJzPy5iUGVyc2lzdE9QU2Nyb2xsLFxuXHRcdFx0dXNlQ29udGV4dDogbVBhcmFtZXRlcnM/LnVwZGF0ZUZDTExldmVsID09PSAtMSB8fCBtUGFyYW1ldGVycz8uYlJlY3JlYXRlQ29udGV4dCA/IHVuZGVmaW5lZCA6IG9Db250ZXh0LFxuXHRcdFx0YkRyYWZ0TmF2aWdhdGlvbjogbVBhcmFtZXRlcnM/LmJEcmFmdE5hdmlnYXRpb24sXG5cdFx0XHRiU2hvd1BsYWNlaG9sZGVyOiBtUGFyYW1ldGVycz8uc2hvd1BsYWNlaG9sZGVyICE9PSB1bmRlZmluZWQgPyBtUGFyYW1ldGVycz8uc2hvd1BsYWNlaG9sZGVyIDogdHJ1ZVxuXHRcdH07XG5cblx0XHRpZiAobVBhcmFtZXRlcnM/LmNoZWNrTm9IYXNoQ2hhbmdlKSB7XG5cdFx0XHQvLyBDaGVjayBpZiB0aGUgbmV3IGhhc2ggaXMgZGlmZmVyZW50IGZyb20gdGhlIGN1cnJlbnQgb25lXG5cdFx0XHRjb25zdCBzQ3VycmVudEhhc2hOb0FwcFN0YXRlID0gdGhpcy5vUm91dGVyUHJveHkuZ2V0SGFzaCgpLnJlcGxhY2UoL1smP117MX1zYXAtaWFwcC1zdGF0ZT1bQS1aMC05XSsvLCBcIlwiKTtcblx0XHRcdGlmIChzVGFyZ2V0UGF0aCA9PT0gc0N1cnJlbnRIYXNoTm9BcHBTdGF0ZSkge1xuXHRcdFx0XHQvLyBUaGUgaGFzaCBkb2Vzbid0IGNoYW5nZSwgYnV0IHdlIGZpcmUgdGhlIHJvdXRlTWF0Y2ggZXZlbnQgdG8gdHJpZ2dlciBwYWdlIHJlZnJlc2ggLyBiaW5kaW5nXG5cdFx0XHRcdGNvbnN0IG1FdmVudFBhcmFtZXRlcnM6IGFueSA9IHRoaXMub1JvdXRlci5nZXRSb3V0ZUluZm9CeUhhc2godGhpcy5vUm91dGVyUHJveHkuZ2V0SGFzaCgpKTtcblx0XHRcdFx0aWYgKG1FdmVudFBhcmFtZXRlcnMpIHtcblx0XHRcdFx0XHRtRXZlbnRQYXJhbWV0ZXJzLm5hdmlnYXRpb25JbmZvID0gb05hdmlnYXRpb25JbmZvO1xuXHRcdFx0XHRcdG1FdmVudFBhcmFtZXRlcnMucm91dGVJbmZvcm1hdGlvbiA9IHRoaXMuX2dldFJvdXRlSW5mb3JtYXRpb24odGhpcy5zQ3VycmVudFJvdXRlTmFtZSk7XG5cdFx0XHRcdFx0bUV2ZW50UGFyYW1ldGVycy5yb3V0ZVBhdHRlcm4gPSB0aGlzLnNDdXJyZW50Um91dGVQYXR0ZXJuO1xuXHRcdFx0XHRcdG1FdmVudFBhcmFtZXRlcnMudmlld3MgPSB0aGlzLmFDdXJyZW50Vmlld3M7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLm9Sb3V0ZXJQcm94eS5zZXRGb2N1c0ZvcmNlZCghIW1QYXJhbWV0ZXJzLmJGb3JjZUZvY3VzKTtcblxuXHRcdFx0XHR0aGlzLl9maXJlUm91dGVNYXRjaEV2ZW50cyhtRXZlbnRQYXJhbWV0ZXJzKTtcblxuXHRcdFx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKG1QYXJhbWV0ZXJzPy50cmFuc2llbnQgJiYgbVBhcmFtZXRlcnMuZWRpdGFibGUgPT0gdHJ1ZSAmJiBzVGFyZ2V0UGF0aC5pbmRleE9mKFwiKC4uLilcIikgPT09IC0xKSB7XG5cdFx0XHRpZiAoc1RhcmdldFBhdGguaW5kZXhPZihcIj9cIikgPiAtMSkge1xuXHRcdFx0XHRzVGFyZ2V0UGF0aCArPSBcIiZpLWFjdGlvbj1jcmVhdGVcIjtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNUYXJnZXRQYXRoICs9IFwiP2ktYWN0aW9uPWNyZWF0ZVwiO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENsZWFyIHVuYm91bmQgbWVzc2FnZXMgdXBvbiBuYXZpZ2F0aW5nIGZyb20gTFIgdG8gT1Bcblx0XHQvLyBUaGlzIGlzIHRvIGVuc3VyZSBzdGFsZSBlcnJvciBtZXNzYWdlcyBmcm9tIExSIGFyZSBub3Qgc2hvd24gdG8gdGhlIHVzZXIgYWZ0ZXIgbmF2aWdhdGlvbiB0byBPUC5cblx0XHRpZiAob0N1cnJlbnRUYXJnZXRJbmZvICYmIG9DdXJyZW50VGFyZ2V0SW5mby5uYW1lID09PSBcInNhcC5mZS50ZW1wbGF0ZXMuTGlzdFJlcG9ydFwiKSB7XG5cdFx0XHRjb25zdCBvUm91dGVJbmZvID0gdGhpcy5vUm91dGVyLmdldFJvdXRlSW5mb0J5SGFzaChzVGFyZ2V0UGF0aCk7XG5cdFx0XHRpZiAob1JvdXRlSW5mbykge1xuXHRcdFx0XHRjb25zdCBvUm91dGUgPSB0aGlzLl9nZXRSb3V0ZUluZm9ybWF0aW9uKG9Sb3V0ZUluZm8ubmFtZSk7XG5cdFx0XHRcdGlmIChvUm91dGUgJiYgb1JvdXRlLnRhcmdldHMgJiYgb1JvdXRlLnRhcmdldHMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdGNvbnN0IHNMYXN0VGFyZ2V0TmFtZSA9IG9Sb3V0ZS50YXJnZXRzW29Sb3V0ZS50YXJnZXRzLmxlbmd0aCAtIDFdO1xuXHRcdFx0XHRcdGNvbnN0IG9UYXJnZXQgPSB0aGlzLl9nZXRUYXJnZXRJbmZvcm1hdGlvbihzTGFzdFRhcmdldE5hbWUpO1xuXHRcdFx0XHRcdGlmIChvVGFyZ2V0ICYmIG9UYXJnZXQubmFtZSA9PT0gXCJzYXAuZmUudGVtcGxhdGVzLk9iamVjdFBhZ2VcIikge1xuXHRcdFx0XHRcdFx0bWVzc2FnZUhhbmRsaW5nLnJlbW92ZVVuYm91bmRUcmFuc2l0aW9uTWVzc2FnZXMoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBBZGQgdGhlIG5hdmlnYXRpb24gcGFyYW1ldGVycyBpbiB0aGUgcXVldWVcblx0XHR0aGlzLm5hdmlnYXRpb25JbmZvUXVldWUucHVzaChvTmF2aWdhdGlvbkluZm8pO1xuXG5cdFx0aWYgKHNUYXJnZXRSb3V0ZSAmJiBvUm91dGVQYXJhbWV0ZXJzUHJvbWlzZSkge1xuXHRcdFx0cmV0dXJuIG9Sb3V0ZVBhcmFtZXRlcnNQcm9taXNlLnRoZW4oKG9Sb3V0ZVBhcmFtZXRlcnM6IGFueSkgPT4ge1xuXHRcdFx0XHRvUm91dGVQYXJhbWV0ZXJzLmJJc1N0aWNreU1vZGUgPSBiSXNTdGlja3lNb2RlO1xuXHRcdFx0XHR0aGlzLm9Sb3V0ZXIubmF2VG8oc1RhcmdldFJvdXRlLCBvUm91dGVQYXJhbWV0ZXJzKTtcblx0XHRcdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMub1JvdXRlclByb3h5XG5cdFx0XHQubmF2VG9IYXNoKHNUYXJnZXRQYXRoLCBmYWxzZSwgbVBhcmFtZXRlcnM/Lm5vUHJlc2VydmF0aW9uQ2FjaGUsIG1QYXJhbWV0ZXJzPy5iRm9yY2VGb2N1cywgIWJJc1N0aWNreU1vZGUpXG5cdFx0XHQudGhlbigoYk5hdmlnYXRlZDogYW55KSA9PiB7XG5cdFx0XHRcdGlmICghYk5hdmlnYXRlZCkge1xuXHRcdFx0XHRcdC8vIFRoZSBuYXZpZ2F0aW9uIGRpZCBub3QgaGFwcGVuIC0tPiByZW1vdmUgdGhlIG5hdmlnYXRpb24gcGFyYW1ldGVycyBmcm9tIHRoZSBxdWV1ZSBhcyB0aGV5IHNob3VsZG4ndCBiZSB1c2VkXG5cdFx0XHRcdFx0dGhpcy5uYXZpZ2F0aW9uSW5mb1F1ZXVlLnBvcCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBOYXZpZ2F0ZXMgdG8gYSByb3V0ZS5cblx0ICpcblx0ICogQGZ1bmN0aW9uXG5cdCAqIEBuYW1lIHNhcC5mZS5jb3JlLmNvbnRyb2xsZXJleHRlbnNpb25zLlJvdXRpbmcjbmF2aWdhdGVUb1JvdXRlXG5cdCAqIEBtZW1iZXJvZiBzYXAuZmUuY29yZS5jb250cm9sbGVyZXh0ZW5zaW9ucy5Sb3V0aW5nXG5cdCAqIEBzdGF0aWNcblx0ICogQHBhcmFtIHtzdHJpbmd9IFtzVGFyZ2V0Um91dGVOYW1lXSBOYW1lIG9mIHRoZSB0YXJnZXQgcm91dGVcblx0ICogQHBhcmFtIHtvYmplY3R9IFtvUm91dGVQYXJhbWV0ZXJzXSBQYXJhbWV0ZXJzIHRvIGJlIHVzZWQgd2l0aCByb3V0ZSB0byBjcmVhdGUgdGhlIHRhcmdldCBoYXNoXG5cdCAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIHRoYXQgaXMgcmVzb2x2ZWQgd2hlbiB0aGUgbmF2aWdhdGlvbiBpcyBmaW5hbGl6ZWRcblx0ICpcblx0ICogQHVpNS1yZXN0cmljdGVkXG5cdCAqIEBmaW5hbFxuXHQgKi9cblx0bmF2aWdhdGVUb1JvdXRlKHNUYXJnZXRSb3V0ZU5hbWU6IHN0cmluZywgb1JvdXRlUGFyYW1ldGVyczogYW55IHwgdW5kZWZpbmVkKSB7XG5cdFx0Y29uc3Qgc1RhcmdldFVSTCA9IHRoaXMub1JvdXRlci5nZXRVUkwoc1RhcmdldFJvdXRlTmFtZSwgb1JvdXRlUGFyYW1ldGVycyk7XG5cdFx0cmV0dXJuIHRoaXMub1JvdXRlclByb3h5Lm5hdlRvSGFzaChzVGFyZ2V0VVJMLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCAhb1JvdXRlUGFyYW1ldGVycy5iSXNTdGlja3lNb2RlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgb25lIG9mIHRoZSBjdXJyZW50IHZpZXdzIG9uIHRoZSBzY3JlZW4gaXMgYm91bmQgdG8gYSBnaXZlbiBjb250ZXh0LlxuXHQgKlxuXHQgKiBAcGFyYW0ge3NhcC51aS5tb2RlbC5vZGF0YS52NC5Db250ZXh0fSBvQ29udGV4dCBUaGUgY29udGV4dFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIG9yIGBmYWxzZWAgaWYgdGhlIGN1cnJlbnQgc3RhdGUgaXMgaW1wYWN0ZWQgb3Igbm90XG5cdCAqL1xuXHRpc0N1cnJlbnRTdGF0ZUltcGFjdGVkQnkob0NvbnRleHQ6IGFueSkge1xuXHRcdGNvbnN0IHNQYXRoID0gb0NvbnRleHQuZ2V0UGF0aCgpO1xuXG5cdFx0Ly8gRmlyc3QsIGNoZWNrIHdpdGggdGhlIHRlY2huaWNhbCBwYXRoLiBXZSBoYXZlIHRvIHRyeSBpdCwgYmVjYXVzZSBmb3IgbGV2ZWwgPiAxLCB3ZVxuXHRcdC8vIHVzZXMgdGVjaG5pY2FsIGtleXMgZXZlbiBpZiBTZW1hbnRpYyBrZXlzIGFyZSBlbmFibGVkXG5cdFx0aWYgKHRoaXMub1JvdXRlclByb3h5LmlzQ3VycmVudFN0YXRlSW1wYWN0ZWRCeShzUGF0aCkpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH0gZWxzZSBpZiAoL15bXlxcKFxcKV0rXFwoW15cXChcXCldK1xcKSQvLnRlc3Qoc1BhdGgpKSB7XG5cdFx0XHQvLyBJZiB0aGUgY3VycmVudCBwYXRoIGNhbiBiZSBzZW1hbnRpYyAoaS5lLiBpcyBsaWtlIHh4eCh5eXkpKVxuXHRcdFx0Ly8gY2hlY2sgd2l0aCB0aGUgc2VtYW50aWMgcGF0aCBpZiB3ZSBjYW4gZmluZCBpdFxuXHRcdFx0bGV0IHNTZW1hbnRpY1BhdGg7XG5cdFx0XHRpZiAodGhpcy5vTGFzdFNlbWFudGljTWFwcGluZyAmJiB0aGlzLm9MYXN0U2VtYW50aWNNYXBwaW5nLnRlY2huaWNhbFBhdGggPT09IHNQYXRoKSB7XG5cdFx0XHRcdC8vIFdlIGhhdmUgYWxyZWFkeSByZXNvbHZlZCB0aGlzIHNlbWFudGljIHBhdGhcblx0XHRcdFx0c1NlbWFudGljUGF0aCA9IHRoaXMub0xhc3RTZW1hbnRpY01hcHBpbmcuc2VtYW50aWNQYXRoO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c1NlbWFudGljUGF0aCA9IFNlbWFudGljS2V5SGVscGVyLmdldFNlbWFudGljUGF0aChvQ29udGV4dCk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBzU2VtYW50aWNQYXRoICE9IHNQYXRoID8gdGhpcy5vUm91dGVyUHJveHkuaXNDdXJyZW50U3RhdGVJbXBhY3RlZEJ5KHNTZW1hbnRpY1BhdGgpIDogZmFsc2U7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHRfZmluZFBhdGhUb05hdmlnYXRlKHNQYXRoOiBhbnkpOiBzdHJpbmcge1xuXHRcdGNvbnN0IHJlZ2V4ID0gbmV3IFJlZ0V4cChcIi9bXi9dKiRcIik7XG5cdFx0c1BhdGggPSBzUGF0aC5yZXBsYWNlKHJlZ2V4LCBcIlwiKTtcblx0XHRpZiAodGhpcy5vUm91dGVyLm1hdGNoKHNQYXRoKSB8fCBzUGF0aCA9PT0gXCJcIikge1xuXHRcdFx0cmV0dXJuIHNQYXRoO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fZmluZFBhdGhUb05hdmlnYXRlKHNQYXRoKTtcblx0XHR9XG5cdH1cblxuXHRfY2hlY2tDb250ZXh0Rm9yU2VtYW50aWNQYXRoKG9Db250ZXh0OiBhbnkpIHtcblx0XHRjb25zdCBzUGF0aCA9IG9Db250ZXh0LmdldFBhdGgoKTtcblxuXHRcdC8vIEZpcnN0LCBjaGVjayBpZiB0aGlzIGlzIGEgbGV2ZWwtMSBvYmplY3QgKHBhdGggPSAvYWFhKGJiYikpXG5cdFx0aWYgKCEvXlxcL1teXFwoXStcXChbXlxcKV0rXFwpJC8udGVzdChzUGF0aCkpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHQvLyBUaGVuIGNoZWNrIGlmIHRoZSBlbnRpdHkgaGFzIHNlbWFudGljIGtleXNcblx0XHRjb25zdCBvTWV0YU1vZGVsID0gb0NvbnRleHQuZ2V0TW9kZWwoKS5nZXRNZXRhTW9kZWwoKSxcblx0XHRcdHNFbnRpdHlTZXROYW1lID0gb01ldGFNb2RlbC5nZXRNZXRhQ29udGV4dChvQ29udGV4dC5nZXRQYXRoKCkpLmdldE9iamVjdChcIkBzYXB1aS5uYW1lXCIpO1xuXHRcdGlmICghU2VtYW50aWNLZXlIZWxwZXIuZ2V0U2VtYW50aWNLZXlzKG9NZXRhTW9kZWwsIHNFbnRpdHlTZXROYW1lKSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdC8vIFRoZW4gY2hlY2sgdGhlIGVudGl0eSBpcyBkcmFmdC1lbmFibGVkXG5cdFx0cmV0dXJuIE1vZGVsSGVscGVyLmlzRHJhZnRTdXBwb3J0ZWQob01ldGFNb2RlbCwgc1BhdGgpO1xuXHR9XG5cblx0X2dldFBhdGhGcm9tQ29udGV4dChvQ29udGV4dDogYW55LCBtUGFyYW1ldGVyczogYW55KSB7XG5cdFx0bGV0IHNQYXRoO1xuXG5cdFx0aWYgKG9Db250ZXh0LmlzQShcInNhcC51aS5tb2RlbC5vZGF0YS52NC5PRGF0YUxpc3RCaW5kaW5nXCIpICYmIG9Db250ZXh0LmlzUmVsYXRpdmUoKSkge1xuXHRcdFx0c1BhdGggPSBvQ29udGV4dC5nZXRIZWFkZXJDb250ZXh0KCkuZ2V0UGF0aCgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzUGF0aCA9IG9Db250ZXh0LmdldFBhdGgoKTtcblx0XHR9XG5cblx0XHRpZiAobVBhcmFtZXRlcnMudXBkYXRlRkNMTGV2ZWwgPT09IC0xKSB7XG5cdFx0XHQvLyBXaGVuIG5hdmlnYXRpbmcgYmFjayBmcm9tIGEgY29udGV4dCwgd2UgbmVlZCB0byByZW1vdmUgdGhlIGxhc3QgY29tcG9uZW50IG9mIHRoZSBwYXRoXG5cdFx0XHRzUGF0aCA9IHRoaXMuX2ZpbmRQYXRoVG9OYXZpZ2F0ZShzUGF0aCk7XG5cblx0XHRcdC8vIENoZWNrIGlmIHdlJ3JlIG5hdmlnYXRpbmcgYmFjayB0byBhIHNlbWFudGljIHBhdGggdGhhdCB3YXMgcHJldmlvdXNseSByZXNvbHZlZFxuXHRcdFx0aWYgKHRoaXMub0xhc3RTZW1hbnRpY01hcHBpbmcgJiYgdGhpcy5vTGFzdFNlbWFudGljTWFwcGluZy50ZWNobmljYWxQYXRoID09PSBzUGF0aCkge1xuXHRcdFx0XHRzUGF0aCA9IHRoaXMub0xhc3RTZW1hbnRpY01hcHBpbmcuc2VtYW50aWNQYXRoO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAodGhpcy5fY2hlY2tDb250ZXh0Rm9yU2VtYW50aWNQYXRoKG9Db250ZXh0KSkge1xuXHRcdFx0Ly8gV2UgY2hlY2sgaWYgd2UgaGF2ZSB0byB1c2UgYSBzZW1hbnRpYyBwYXRoXG5cdFx0XHRjb25zdCBzU2VtYW50aWNQYXRoID0gU2VtYW50aWNLZXlIZWxwZXIuZ2V0U2VtYW50aWNQYXRoKG9Db250ZXh0LCB0cnVlKTtcblxuXHRcdFx0aWYgKCFzU2VtYW50aWNQYXRoKSB7XG5cdFx0XHRcdC8vIFdlIHdlcmUgbm90IGFibGUgdG8gYnVpbGQgdGhlIHNlbWFudGljIHBhdGggLS0+IFVzZSB0aGUgdGVjaG5pY2FsIHBhdGggYW5kXG5cdFx0XHRcdC8vIGNsZWFyIHRoZSBwcmV2aW91cyBtYXBwaW5nLCBvdGhlcndpc2UgdGhlIG9sZCBtYXBwaW5nIGlzIHVzZWQgaW4gRWRpdEZsb3cjdXBkYXRlRG9jdW1lbnRcblx0XHRcdFx0Ly8gYW5kIGl0IGxlYWRzIHRvIHVud2FudGVkIHBhZ2UgcmVsb2Fkc1xuXHRcdFx0XHR0aGlzLnNldExhc3RTZW1hbnRpY01hcHBpbmcodW5kZWZpbmVkKTtcblx0XHRcdH0gZWxzZSBpZiAoc1NlbWFudGljUGF0aCAhPT0gc1BhdGgpIHtcblx0XHRcdFx0Ly8gU3RvcmUgdGhlIG1hcHBpbmcgdGVjaG5pY2FsIDwtPiBzZW1hbnRpYyBwYXRoIHRvIGF2b2lkIHJlY2FsY3VsYXRpbmcgaXQgbGF0ZXJcblx0XHRcdFx0Ly8gYW5kIHVzZSB0aGUgc2VtYW50aWMgcGF0aCBpbnN0ZWFkIG9mIHRoZSB0ZWNobmljYWwgb25lXG5cdFx0XHRcdHRoaXMuc2V0TGFzdFNlbWFudGljTWFwcGluZyh7IHRlY2huaWNhbFBhdGg6IHNQYXRoLCBzZW1hbnRpY1BhdGg6IHNTZW1hbnRpY1BhdGggfSk7XG5cdFx0XHRcdHNQYXRoID0gc1NlbWFudGljUGF0aDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyByZW1vdmUgZXh0cmEgJy8nIGF0IHRoZSBiZWdpbm5pbmcgb2YgcGF0aFxuXHRcdGlmIChzUGF0aFswXSA9PT0gXCIvXCIpIHtcblx0XHRcdHNQYXRoID0gc1BhdGguc3Vic3RyaW5nKDEpO1xuXHRcdH1cblxuXHRcdHJldHVybiBzUGF0aDtcblx0fVxuXG5cdF9jYWxjdWxhdGVMYXlvdXQoc1BhdGg6IGFueSwgbVBhcmFtZXRlcnM6IGFueSkge1xuXHRcdGxldCBGQ0xMZXZlbCA9IG1QYXJhbWV0ZXJzLkZDTExldmVsO1xuXHRcdGlmIChtUGFyYW1ldGVycy51cGRhdGVGQ0xMZXZlbCkge1xuXHRcdFx0RkNMTGV2ZWwgKz0gbVBhcmFtZXRlcnMudXBkYXRlRkNMTGV2ZWw7XG5cdFx0XHRpZiAoRkNMTGV2ZWwgPCAwKSB7XG5cdFx0XHRcdEZDTExldmVsID0gMDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5vQXBwQ29tcG9uZW50LmdldFJvb3RWaWV3Q29udHJvbGxlcigpLmNhbGN1bGF0ZUxheW91dChGQ0xMZXZlbCwgc1BhdGgsIG1QYXJhbWV0ZXJzLnNMYXlvdXQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2ZW50IGhhbmRsZXIgYmVmb3JlIGEgcm91dGUgaXMgbWF0Y2hlZC5cblx0ICogRGlzcGxheXMgYSBidXN5IGluZGljYXRvci5cblx0ICpcblx0ICovXG5cdF9iZWZvcmVSb3V0ZU1hdGNoZWQoLypvRXZlbnQ6IEV2ZW50Ki8pIHtcblx0XHRjb25zdCBiUGxhY2Vob2xkZXJFbmFibGVkID0gbmV3IFBsYWNlaG9sZGVyKCkuaXNQbGFjZWhvbGRlckVuYWJsZWQoKTtcblx0XHRpZiAoIWJQbGFjZWhvbGRlckVuYWJsZWQpIHtcblx0XHRcdGNvbnN0IG9Sb290VmlldyA9IHRoaXMub0FwcENvbXBvbmVudC5nZXRSb290Q29udHJvbCgpO1xuXHRcdFx0QnVzeUxvY2tlci5sb2NrKG9Sb290Vmlldyk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEV2ZW50IGhhbmRsZXIgd2hlbiBhIHJvdXRlIGlzIG1hdGNoZWQuXG5cdCAqIEhpZGVzIHRoZSBidXN5IGluZGljYXRvciBhbmQgZmlyZXMgaXRzIG93biAncm91dGVtYXRjaGVkJyBldmVudC5cblx0ICpcblx0ICogQHBhcmFtIHtvYmplY3R9IG9FdmVudCBUaGUgZXZlbnRcblx0ICovXG5cdF9vblJvdXRlTWF0Y2hlZChvRXZlbnQ6IEV2ZW50KSB7XG5cdFx0Y29uc3Qgb0FwcFN0YXRlSGFuZGxlciA9IHRoaXMub0FwcENvbXBvbmVudC5nZXRBcHBTdGF0ZUhhbmRsZXIoKSxcblx0XHRcdG9Sb290VmlldyA9IHRoaXMub0FwcENvbXBvbmVudC5nZXRSb290Q29udHJvbCgpO1xuXHRcdGNvbnN0IGJQbGFjZWhvbGRlckVuYWJsZWQgPSBuZXcgUGxhY2Vob2xkZXIoKS5pc1BsYWNlaG9sZGVyRW5hYmxlZCgpO1xuXHRcdGlmIChCdXN5TG9ja2VyLmlzTG9ja2VkKG9Sb290VmlldykgJiYgIWJQbGFjZWhvbGRlckVuYWJsZWQpIHtcblx0XHRcdEJ1c3lMb2NrZXIudW5sb2NrKG9Sb290Vmlldyk7XG5cdFx0fVxuXHRcdGNvbnN0IG1QYXJhbWV0ZXJzOiBhbnkgPSBvRXZlbnQuZ2V0UGFyYW1ldGVycygpO1xuXHRcdGlmICh0aGlzLm5hdmlnYXRpb25JbmZvUXVldWUubGVuZ3RoKSB7XG5cdFx0XHRtUGFyYW1ldGVycy5uYXZpZ2F0aW9uSW5mbyA9IHRoaXMubmF2aWdhdGlvbkluZm9RdWV1ZVswXTtcblx0XHRcdHRoaXMubmF2aWdhdGlvbkluZm9RdWV1ZSA9IHRoaXMubmF2aWdhdGlvbkluZm9RdWV1ZS5zbGljZSgxKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bVBhcmFtZXRlcnMubmF2aWdhdGlvbkluZm8gPSB7fTtcblx0XHR9XG5cdFx0aWYgKG9BcHBTdGF0ZUhhbmRsZXIuY2hlY2tJZlJvdXRlQ2hhbmdlZEJ5SUFwcCgpKSB7XG5cdFx0XHRtUGFyYW1ldGVycy5uYXZpZ2F0aW9uSW5mby5iUmVhc29uSXNJYXBwU3RhdGUgPSB0cnVlO1xuXHRcdFx0b0FwcFN0YXRlSGFuZGxlci5yZXNldFJvdXRlQ2hhbmdlZEJ5SUFwcCgpO1xuXHRcdH1cblxuXHRcdHRoaXMuc0N1cnJlbnRSb3V0ZU5hbWUgPSBvRXZlbnQuZ2V0UGFyYW1ldGVyKFwibmFtZVwiKTtcblx0XHR0aGlzLnNDdXJyZW50Um91dGVQYXR0ZXJuID0gbVBhcmFtZXRlcnMuY29uZmlnLnBhdHRlcm47XG5cdFx0dGhpcy5hQ3VycmVudFZpZXdzID0gb0V2ZW50LmdldFBhcmFtZXRlcihcInZpZXdzXCIpO1xuXG5cdFx0bVBhcmFtZXRlcnMucm91dGVJbmZvcm1hdGlvbiA9IHRoaXMuX2dldFJvdXRlSW5mb3JtYXRpb24odGhpcy5zQ3VycmVudFJvdXRlTmFtZSk7XG5cdFx0bVBhcmFtZXRlcnMucm91dGVQYXR0ZXJuID0gdGhpcy5zQ3VycmVudFJvdXRlUGF0dGVybjtcblxuXHRcdHRoaXMuX2ZpcmVSb3V0ZU1hdGNoRXZlbnRzKG1QYXJhbWV0ZXJzKTtcblxuXHRcdC8vIENoZWNrIGlmIGN1cnJlbnQgaGFzaCBoYXMgYmVlbiBzZXQgYnkgdGhlIHJvdXRlclByb3h5Lm5hdlRvSGFzaCBmdW5jdGlvblxuXHRcdC8vIElmIG5vdCwgcmVidWlsZCBoaXN0b3J5IHByb3Blcmx5IChib3RoIGluIHRoZSBicm93c2VyIGFuZCB0aGUgUm91dGVyUHJveHkpXG5cdFx0aWYgKCFoaXN0b3J5LnN0YXRlIHx8IGhpc3Rvcnkuc3RhdGUuZmVMZXZlbCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHR0aGlzLm9Sb3V0ZXJQcm94eVxuXHRcdFx0XHQucmVzdG9yZUhpc3RvcnkoKVxuXHRcdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5vUm91dGVyUHJveHkucmVzb2x2ZVJvdXRlTWF0Y2goKTtcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKGZ1bmN0aW9uKG9FcnJvcjogYW55KSB7XG5cdFx0XHRcdFx0TG9nLmVycm9yKFwiRXJyb3Igd2hpbGUgcmVzdG9yaW5nIGhpc3RvcnlcIiwgb0Vycm9yKTtcblx0XHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMub1JvdXRlclByb3h5LnJlc29sdmVSb3V0ZU1hdGNoKCk7XG5cdFx0fVxuXHR9XG5cblx0YXR0YWNoUm91dGVNYXRjaGVkKG9EYXRhOiBhbnksIGZuRnVuY3Rpb246IGFueSwgb0xpc3RlbmVyOiBhbnkpIHtcblx0XHR0aGlzLmV2ZW50UHJvdmlkZXIuYXR0YWNoRXZlbnQoXCJyb3V0ZU1hdGNoZWRcIiwgb0RhdGEsIGZuRnVuY3Rpb24sIG9MaXN0ZW5lcik7XG5cdH1cblx0ZGV0YWNoUm91dGVNYXRjaGVkKGZuRnVuY3Rpb246IGFueSwgb0xpc3RlbmVyOiBhbnkpIHtcblx0XHR0aGlzLmV2ZW50UHJvdmlkZXIuZGV0YWNoRXZlbnQoXCJyb3V0ZU1hdGNoZWRcIiwgZm5GdW5jdGlvbiwgb0xpc3RlbmVyKTtcblx0fVxuXHRhdHRhY2hBZnRlclJvdXRlTWF0Y2hlZChvRGF0YTogYW55LCBmbkZ1bmN0aW9uOiBhbnksIG9MaXN0ZW5lcjogYW55KSB7XG5cdFx0dGhpcy5ldmVudFByb3ZpZGVyLmF0dGFjaEV2ZW50KFwiYWZ0ZXJSb3V0ZU1hdGNoZWRcIiwgb0RhdGEsIGZuRnVuY3Rpb24sIG9MaXN0ZW5lcik7XG5cdH1cblx0ZGV0YWNoQWZ0ZXJSb3V0ZU1hdGNoZWQoZm5GdW5jdGlvbjogYW55LCBvTGlzdGVuZXI6IGFueSkge1xuXHRcdHRoaXMuZXZlbnRQcm92aWRlci5kZXRhY2hFdmVudChcImFmdGVyUm91dGVNYXRjaGVkXCIsIGZuRnVuY3Rpb24sIG9MaXN0ZW5lcik7XG5cdH1cblxuXHRnZXRSb3V0ZUZyb21IYXNoKG9Sb3V0ZXI6IGFueSwgb0FwcENvbXBvbmVudDogYW55KSB7XG5cdFx0Y29uc3Qgc0hhc2ggPSBvUm91dGVyLmdldEhhc2hDaGFuZ2VyKCkuaGFzaDtcblx0XHRjb25zdCBvUm91dGVJbmZvID0gb1JvdXRlci5nZXRSb3V0ZUluZm9CeUhhc2goc0hhc2gpO1xuXHRcdHJldHVybiBvQXBwQ29tcG9uZW50XG5cdFx0XHQuZ2V0TWV0YWRhdGEoKVxuXHRcdFx0LmdldE1hbmlmZXN0RW50cnkoXCIvc2FwLnVpNS9yb3V0aW5nL3JvdXRlc1wiKVxuXHRcdFx0LmZpbHRlcihmdW5jdGlvbihvUm91dGU6IGFueSkge1xuXHRcdFx0XHRyZXR1cm4gb1JvdXRlLm5hbWUgPT09IG9Sb3V0ZUluZm8ubmFtZTtcblx0XHRcdH0pWzBdO1xuXHR9XG5cdGdldFRhcmdldHNGcm9tUm91dGUob1JvdXRlOiBhbnkpIHtcblx0XHRjb25zdCBvVGFyZ2V0ID0gb1JvdXRlLnRhcmdldDtcblx0XHRpZiAodHlwZW9mIG9UYXJnZXQgPT09IFwic3RyaW5nXCIpIHtcblx0XHRcdHJldHVybiBbdGhpcy5fbVRhcmdldHNbb1RhcmdldF1dO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zdCBhVGFyZ2V0OiBhbnlbXSA9IFtdO1xuXHRcdFx0b1RhcmdldC5mb3JFYWNoKChzVGFyZ2V0OiBhbnkpID0+IHtcblx0XHRcdFx0YVRhcmdldC5wdXNoKHRoaXMuX21UYXJnZXRzW3NUYXJnZXRdKTtcblx0XHRcdH0pO1xuXHRcdFx0cmV0dXJuIGFUYXJnZXQ7XG5cdFx0fVxuXHR9XG5cblx0aW5pdGlhbGl6ZVJvdXRpbmcoKSB7XG5cdFx0Ly8gQXR0YWNoIHJvdXRlciBoYW5kbGVyc1xuXHRcdHRoaXMuX2ZuT25Sb3V0ZU1hdGNoZWQgPSB0aGlzLl9vblJvdXRlTWF0Y2hlZC5iaW5kKHRoaXMpO1xuXHRcdHRoaXMub1JvdXRlci5hdHRhY2hSb3V0ZU1hdGNoZWQodGhpcy5fZm5PblJvdXRlTWF0Y2hlZCwgdGhpcyk7XG5cdFx0Y29uc3QgYlBsYWNlaG9sZGVyRW5hYmxlZCA9IG5ldyBQbGFjZWhvbGRlcigpLmlzUGxhY2Vob2xkZXJFbmFibGVkKCk7XG5cdFx0aWYgKCFiUGxhY2Vob2xkZXJFbmFibGVkKSB7XG5cdFx0XHR0aGlzLm9Sb3V0ZXIuYXR0YWNoQmVmb3JlUm91dGVNYXRjaGVkKHRoaXMuX2JlZm9yZVJvdXRlTWF0Y2hlZC5iaW5kKHRoaXMpKTtcblx0XHR9XG5cdFx0Ly8gUmVzZXQgaW50ZXJuYWwgc3RhdGVcblx0XHR0aGlzLm5hdmlnYXRpb25JbmZvUXVldWUgPSBbXTtcblx0XHRFZGl0U3RhdGUucmVzZXRFZGl0U3RhdGUoKTtcblx0XHR0aGlzLmJFeGl0T25OYXZpZ2F0ZUJhY2tUb1Jvb3QgPSAhdGhpcy5vUm91dGVyLm1hdGNoKFwiXCIpO1xuXG5cdFx0Y29uc3QgYklzSWFwcFN0YXRlID1cblx0XHRcdHRoaXMub1JvdXRlclxuXHRcdFx0XHQuZ2V0SGFzaENoYW5nZXIoKVxuXHRcdFx0XHQuZ2V0SGFzaCgpXG5cdFx0XHRcdC5pbmRleE9mKFwic2FwLWlhcHAtc3RhdGVcIikgIT09IC0xO1xuXHRcdGNvbnN0IGluaXRQcm9taXNlID0gdGhpcy5vQXBwQ29tcG9uZW50XG5cdFx0XHQuZ2V0U3RhcnR1cFBhcmFtZXRlcnMoKVxuXHRcdFx0LnRoZW4oKG9TdGFydHVwUGFyYW1ldGVyczogYW55KSA9PiB7XG5cdFx0XHRcdGNvbnN0IGJIYXNTdGFydFVwUGFyYW1ldGVycyA9IG9TdGFydHVwUGFyYW1ldGVycyAhPT0gdW5kZWZpbmVkICYmIE9iamVjdC5rZXlzKG9TdGFydHVwUGFyYW1ldGVycykubGVuZ3RoICE9PSAwO1xuXHRcdFx0XHRjb25zdCBzSGFzaCA9IHRoaXMub1JvdXRlci5nZXRIYXNoQ2hhbmdlcigpLmdldEhhc2goKTtcblx0XHRcdFx0Ly8gTWFuYWdlIHN0YXJ0dXAgcGFyYW1ldGVycyAoaW4gY2FzZSBvZiBubyBpYXBwLXN0YXRlKVxuXHRcdFx0XHRpZiAoIWJJc0lhcHBTdGF0ZSAmJiBiSGFzU3RhcnRVcFBhcmFtZXRlcnMgJiYgIXNIYXNoKSB7XG5cdFx0XHRcdFx0aWYgKG9TdGFydHVwUGFyYW1ldGVycy5wcmVmZXJyZWRNb2RlICYmIG9TdGFydHVwUGFyYW1ldGVycy5wcmVmZXJyZWRNb2RlWzBdLmluZGV4T2YoXCJjcmVhdGVcIikgIT09IC0xKSB7XG5cdFx0XHRcdFx0XHQvLyBDcmVhdGUgbW9kZVxuXHRcdFx0XHRcdFx0cmV0dXJuIHRoaXMuX21hbmFnZUNyZWF0ZVN0YXJ0dXAob1N0YXJ0dXBQYXJhbWV0ZXJzKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Ly8gRGVlcCBsaW5rXG5cdFx0XHRcdFx0XHRyZXR1cm4gdGhpcy5fbWFuYWdlRGVlcExpbmtTdGFydHVwKG9TdGFydHVwUGFyYW1ldGVycyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KVxuXHRcdFx0LmNhdGNoKGZ1bmN0aW9uKG9FcnJvcjogYW55KSB7XG5cdFx0XHRcdExvZy5lcnJvcihcIkVycm9yIGR1cmluZyByb3V0aW5nIGluaXRpYWxpemF0aW9uXCIsIG9FcnJvcik7XG5cdFx0XHR9KTtcblxuXHRcdHJldHVybiBpbml0UHJvbWlzZTtcblx0fVxuXG5cdGdldERlZmF1bHRDcmVhdGVIYXNoKG9TdGFydHVwUGFyYW1ldGVyczogYW55KSB7XG5cdFx0cmV0dXJuIEFwcFN0YXJ0dXBIZWxwZXIuZ2V0RGVmYXVsdENyZWF0ZUhhc2gob1N0YXJ0dXBQYXJhbWV0ZXJzLCB0aGlzLmdldENvbnRleHRQYXRoKCksIHRoaXMub1JvdXRlcik7XG5cdH1cblxuXHRfbWFuYWdlQ3JlYXRlU3RhcnR1cChvU3RhcnR1cFBhcmFtZXRlcnM6IGFueSkge1xuXHRcdHJldHVybiBBcHBTdGFydHVwSGVscGVyLmdldENyZWF0ZVN0YXJ0dXBIYXNoKG9TdGFydHVwUGFyYW1ldGVycywgdGhpcy5nZXRDb250ZXh0UGF0aCgpLCB0aGlzLm9Sb3V0ZXIsIHRoaXMub01ldGFNb2RlbCkudGhlbihcblx0XHRcdChzTmV3SGFzaDogYW55KSA9PiB7XG5cdFx0XHRcdGlmIChzTmV3SGFzaCkge1xuXHRcdFx0XHRcdCh0aGlzLm9Sb3V0ZXIuZ2V0SGFzaENoYW5nZXIoKS5yZXBsYWNlSGFzaCBhcyBhbnkpKHNOZXdIYXNoKTtcblx0XHRcdFx0XHR0aGlzLmJFeGl0T25OYXZpZ2F0ZUJhY2tUb1Jvb3QgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0KTtcblx0fVxuXG5cdF9tYW5hZ2VEZWVwTGlua1N0YXJ0dXAob1N0YXJ0dXBQYXJhbWV0ZXJzOiBhbnkpIHtcblx0XHRyZXR1cm4gQXBwU3RhcnR1cEhlbHBlci5nZXREZWVwTGlua1N0YXJ0dXBIYXNoKFxuXHRcdFx0dGhpcy5vQXBwQ29tcG9uZW50LmdldE1hbmlmZXN0KClbXCJzYXAudWk1XCJdLnJvdXRpbmcsXG5cdFx0XHRvU3RhcnR1cFBhcmFtZXRlcnMsXG5cdFx0XHR0aGlzLm9Nb2RlbFxuXHRcdCkudGhlbigob0RlZXBMaW5rOiBhbnkpID0+IHtcblx0XHRcdGxldCBzSGFzaDtcblx0XHRcdGlmIChvRGVlcExpbmsuY29udGV4dCkge1xuXHRcdFx0XHRjb25zdCBzVGVjaG5pY2FsUGF0aCA9IG9EZWVwTGluay5jb250ZXh0LmdldFBhdGgoKSxcblx0XHRcdFx0XHRzU2VtYW50aWNQYXRoID0gU2VtYW50aWNLZXlIZWxwZXIuZ2V0U2VtYW50aWNQYXRoKG9EZWVwTGluay5jb250ZXh0KTtcblxuXHRcdFx0XHRpZiAoc1NlbWFudGljUGF0aCAhPT0gc1RlY2huaWNhbFBhdGgpIHtcblx0XHRcdFx0XHQvLyBTdG9yZSB0aGUgbWFwcGluZyB0ZWNobmljYWwgPC0+IHNlbWFudGljIHBhdGggdG8gYXZvaWQgcmVjYWxjdWxhdGluZyBpdCBsYXRlclxuXHRcdFx0XHRcdC8vIGFuZCB1c2UgdGhlIHNlbWFudGljIHBhdGggaW5zdGVhZCBvZiB0aGUgdGVjaG5pY2FsIG9uZVxuXHRcdFx0XHRcdHRoaXMuc2V0TGFzdFNlbWFudGljTWFwcGluZyh7IHRlY2huaWNhbFBhdGg6IHNUZWNobmljYWxQYXRoLCBzZW1hbnRpY1BhdGg6IHNTZW1hbnRpY1BhdGggfSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRzSGFzaCA9IHNTZW1hbnRpY1BhdGguc3Vic3RyaW5nKDEpOyAvLyBUbyByZW1vdmUgdGhlIGxlYWRpbmcgJy8nXG5cdFx0XHR9IGVsc2UgaWYgKG9EZWVwTGluay5oYXNoKSB7XG5cdFx0XHRcdHNIYXNoID0gb0RlZXBMaW5rLmhhc2g7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzSGFzaCkge1xuXHRcdFx0XHQvL1JlcGxhY2UgdGhlIGhhc2ggd2l0aCBuZXdseSBjcmVhdGVkIGhhc2hcblx0XHRcdFx0KHRoaXMub1JvdXRlci5nZXRIYXNoQ2hhbmdlcigpLnJlcGxhY2VIYXNoIGFzIGFueSkoc0hhc2gpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0Z2V0T3V0Ym91bmRzKCkge1xuXHRcdHJldHVybiB0aGlzLm91dGJvdW5kcztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBuYW1lIG9mIHRoZSBEcmFmdCByb290IGVudGl0eSBzZXQgb3IgdGhlIHN0aWNreS1lbmFibGVkIGVudGl0eSBzZXQuXG5cdCAqXG5cdCAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBuYW1lIG9mIHRoZSByb290IEVudGl0eVNldFxuXHQgKlxuXHQgKiBAdWk1LXJlc3RyaWN0ZWRcblx0ICovXG5cdGdldENvbnRleHRQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLnNDb250ZXh0UGF0aDtcblx0fVxuXHRnZXRJbnRlcmZhY2UoKTogYW55IHtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxufVxuXG5jbGFzcyBSb3V0aW5nU2VydmljZUZhY3RvcnkgZXh0ZW5kcyBTZXJ2aWNlRmFjdG9yeTxSb3V0aW5nU2VydmljZVNldHRpbmdzPiB7XG5cdGNyZWF0ZUluc3RhbmNlKG9TZXJ2aWNlQ29udGV4dDogU2VydmljZUNvbnRleHQ8Um91dGluZ1NlcnZpY2VTZXR0aW5ncz4pIHtcblx0XHRjb25zdCBvUm91dGluZ1NlcnZpY2UgPSBuZXcgUm91dGluZ1NlcnZpY2Uob1NlcnZpY2VDb250ZXh0KTtcblx0XHRyZXR1cm4gb1JvdXRpbmdTZXJ2aWNlLmluaXRQcm9taXNlO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFJvdXRpbmdTZXJ2aWNlRmFjdG9yeTtcbiJdfQ==