@sapui5/sap.fe.core 1.97.0 → 1.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/package.json +7 -4
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +309 -405
  4. package/src/sap/fe/core/AnnotationHelper.ts +315 -0
  5. package/src/sap/fe/core/AppComponent.js +389 -397
  6. package/src/sap/fe/core/AppComponent.ts +403 -0
  7. package/src/sap/fe/core/AppStateHandler.js +198 -181
  8. package/src/sap/fe/core/AppStateHandler.ts +171 -0
  9. package/src/sap/fe/core/BaseController.js +83 -58
  10. package/src/sap/fe/core/BaseController.ts +68 -0
  11. package/src/sap/fe/core/BusyLocker.js +105 -121
  12. package/src/sap/fe/core/BusyLocker.ts +98 -0
  13. package/src/sap/fe/core/CommonUtils.js +2164 -2379
  14. package/src/sap/fe/core/CommonUtils.ts +2177 -0
  15. package/src/sap/fe/core/ExtensionAPI.js +279 -266
  16. package/src/sap/fe/core/ExtensionAPI.ts +250 -0
  17. package/src/sap/fe/core/PageController.js +218 -125
  18. package/src/sap/fe/core/PageController.ts +129 -0
  19. package/src/sap/fe/core/RouterProxy.js +924 -807
  20. package/src/sap/fe/core/RouterProxy.ts +840 -0
  21. package/src/sap/fe/core/Synchronization.js +41 -35
  22. package/src/sap/fe/core/Synchronization.ts +29 -0
  23. package/src/sap/fe/core/TemplateComponent.js +173 -155
  24. package/src/sap/fe/core/TemplateComponent.ts +173 -0
  25. package/src/sap/fe/core/TemplateModel.js +79 -54
  26. package/src/sap/fe/core/TemplateModel.ts +63 -0
  27. package/src/sap/fe/core/TransactionHelper.js +1560 -1579
  28. package/src/sap/fe/core/TransactionHelper.ts +1717 -0
  29. package/src/sap/fe/core/actions/collaboration/ActivitySync.js +392 -0
  30. package/src/sap/fe/core/actions/collaboration/ActivitySync.ts +355 -0
  31. package/src/sap/fe/core/actions/collaboration/CollaborationCommon.js +136 -0
  32. package/src/sap/fe/core/actions/collaboration/CollaborationCommon.ts +119 -0
  33. package/src/sap/fe/core/actions/collaboration/Manage.js +262 -0
  34. package/src/sap/fe/core/actions/collaboration/Manage.ts +244 -0
  35. package/src/sap/fe/core/actions/collaboration/ManageDialog.fragment.xml +103 -0
  36. package/src/sap/fe/core/actions/collaboration/UserDetails.fragment.xml +13 -0
  37. package/src/sap/fe/core/actions/draft.js +521 -581
  38. package/src/sap/fe/core/actions/draft.ts +566 -0
  39. package/src/sap/fe/core/actions/messageHandling.js +564 -511
  40. package/src/sap/fe/core/actions/messageHandling.ts +552 -0
  41. package/src/sap/fe/core/actions/nonDraft.js +17 -19
  42. package/src/sap/fe/core/actions/nonDraft.ts +12 -0
  43. package/src/sap/fe/core/actions/operations.js +1093 -1211
  44. package/src/sap/fe/core/actions/operations.ts +1192 -0
  45. package/src/sap/fe/core/actions/sticky.js +114 -104
  46. package/src/sap/fe/core/actions/sticky.ts +119 -0
  47. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +70 -66
  48. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.ts +65 -0
  49. package/src/sap/fe/core/controllerextensions/EditFlow.js +1594 -1701
  50. package/src/sap/fe/core/controllerextensions/EditFlow.ts +1672 -0
  51. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +80 -54
  52. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.ts +61 -0
  53. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +719 -505
  54. package/src/sap/fe/core/controllerextensions/InternalEditFlow.ts +783 -0
  55. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +797 -813
  56. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.ts +803 -0
  57. package/src/sap/fe/core/controllerextensions/InternalRouting.js +1005 -973
  58. package/src/sap/fe/core/controllerextensions/InternalRouting.ts +978 -0
  59. package/src/sap/fe/core/controllerextensions/KPIManagement.js +530 -476
  60. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +137 -46
  61. package/src/sap/fe/core/controllerextensions/MassEdit.js +144 -0
  62. package/src/sap/fe/core/controllerextensions/MassEdit.ts +156 -0
  63. package/src/sap/fe/core/controllerextensions/MessageHandler.js +234 -232
  64. package/src/sap/fe/core/controllerextensions/MessageHandler.ts +225 -0
  65. package/src/sap/fe/core/controllerextensions/PageReady.js +302 -337
  66. package/src/sap/fe/core/controllerextensions/PageReady.ts +23 -17
  67. package/src/sap/fe/core/controllerextensions/Paginator.js +189 -148
  68. package/src/sap/fe/core/controllerextensions/Paginator.ts +163 -0
  69. package/src/sap/fe/core/controllerextensions/Placeholder.js +158 -146
  70. package/src/sap/fe/core/controllerextensions/Placeholder.ts +151 -0
  71. package/src/sap/fe/core/controllerextensions/Routing.js +145 -106
  72. package/src/sap/fe/core/controllerextensions/Routing.ts +132 -0
  73. package/src/sap/fe/core/controllerextensions/RoutingListener.js +8 -6
  74. package/src/sap/fe/core/controllerextensions/RoutingListener.ts +3 -0
  75. package/src/sap/fe/core/controllerextensions/Share.js +220 -244
  76. package/src/sap/fe/core/controllerextensions/Share.ts +231 -0
  77. package/src/sap/fe/core/controllerextensions/SideEffects.js +593 -634
  78. package/src/sap/fe/core/controllerextensions/SideEffects.ts +29 -27
  79. package/src/sap/fe/core/controllerextensions/ViewState.js +789 -806
  80. package/src/sap/fe/core/controllerextensions/ViewState.ts +805 -0
  81. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +4 -3
  82. package/src/sap/fe/core/controls/ActionPartial.fragment.xml +2 -2
  83. package/src/sap/fe/core/controls/CommandExecution.js +68 -66
  84. package/src/sap/fe/core/controls/CommandExecution.ts +72 -0
  85. package/src/sap/fe/core/controls/ConditionalWrapper.js +91 -75
  86. package/src/sap/fe/core/controls/ConditionalWrapper.ts +83 -0
  87. package/src/sap/fe/core/controls/CustomQuickViewPage.js +131 -125
  88. package/src/sap/fe/core/controls/CustomQuickViewPage.ts +126 -0
  89. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +105 -110
  90. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.ts +101 -0
  91. package/src/sap/fe/core/controls/FieldWrapper.js +122 -140
  92. package/src/sap/fe/core/controls/FieldWrapper.ts +115 -0
  93. package/src/sap/fe/core/controls/FilterBar.js +163 -159
  94. package/src/sap/fe/core/controls/FilterBar.ts +143 -0
  95. package/src/sap/fe/core/controls/FormElementWrapper.js +46 -44
  96. package/src/sap/fe/core/controls/FormElementWrapper.ts +40 -0
  97. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +38 -42
  98. package/src/sap/fe/core/controls/MultiValueParameterDelegate.ts +31 -0
  99. package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +2 -1
  100. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +127 -116
  101. package/src/sap/fe/core/controls/filterbar/FilterContainer.ts +98 -0
  102. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +242 -255
  103. package/src/sap/fe/core/controls/filterbar/VisualFilter.ts +245 -0
  104. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +151 -141
  105. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.ts +125 -0
  106. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +336 -322
  107. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.ts +337 -0
  108. package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
  109. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +79 -0
  110. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.ts +70 -0
  111. package/src/sap/fe/core/converters/ConverterContext.js +348 -367
  112. package/src/sap/fe/core/converters/ConverterContext.ts +33 -19
  113. package/src/sap/fe/core/converters/ManifestSettings.js +12 -1
  114. package/src/sap/fe/core/converters/ManifestSettings.ts +16 -1
  115. package/src/sap/fe/core/converters/ManifestWrapper.js +354 -354
  116. package/src/sap/fe/core/converters/ManifestWrapper.ts +34 -6
  117. package/src/sap/fe/core/converters/MetaModelConverter.js +72 -9
  118. package/src/sap/fe/core/converters/MetaModelConverter.ts +75 -16
  119. package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
  120. package/src/sap/fe/core/converters/TemplateConverter.ts +4 -3
  121. package/src/sap/fe/core/converters/annotations/DataField.js +28 -14
  122. package/src/sap/fe/core/converters/annotations/DataField.ts +38 -14
  123. package/src/sap/fe/core/converters/common/AnnotationConverter.js +33 -21
  124. package/src/sap/fe/core/converters/controls/Common/Action.js +11 -2
  125. package/src/sap/fe/core/converters/controls/Common/Action.ts +8 -2
  126. package/src/sap/fe/core/converters/controls/Common/Chart.js +5 -3
  127. package/src/sap/fe/core/converters/controls/Common/Chart.ts +11 -3
  128. package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +3 -3
  129. package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +2 -2
  130. package/src/sap/fe/core/converters/controls/Common/Form.js +21 -11
  131. package/src/sap/fe/core/converters/controls/Common/Form.ts +28 -6
  132. package/src/sap/fe/core/converters/controls/Common/KPI.js +69 -4
  133. package/src/sap/fe/core/converters/controls/Common/KPI.ts +75 -2
  134. package/src/sap/fe/core/converters/controls/Common/Table.js +507 -408
  135. package/src/sap/fe/core/converters/controls/Common/Table.ts +618 -500
  136. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +592 -0
  137. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +718 -0
  138. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +465 -59
  139. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +462 -72
  140. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
  141. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
  142. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +17 -9
  143. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +24 -9
  144. package/src/sap/fe/core/converters/helpers/Aggregation.js +118 -121
  145. package/src/sap/fe/core/converters/helpers/Aggregation.ts +28 -5
  146. package/src/sap/fe/core/converters/helpers/BindingHelper.js +20 -6
  147. package/src/sap/fe/core/converters/helpers/BindingHelper.ts +16 -4
  148. package/src/sap/fe/core/converters/helpers/ConfigurableObject.js +12 -1
  149. package/src/sap/fe/core/converters/helpers/ConfigurableObject.ts +11 -0
  150. package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -1
  151. package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -0
  152. package/src/sap/fe/core/converters/helpers/Key.js +42 -57
  153. package/src/sap/fe/core/converters/helpers/Key.ts +1 -1
  154. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +28 -7
  155. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +23 -6
  156. package/src/sap/fe/core/converters/templates/ListReportConverter.js +20 -7
  157. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +36 -14
  158. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +7 -5
  159. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +5 -1
  160. package/src/sap/fe/core/designtime/AppComponent.designtime.js +93 -90
  161. package/src/sap/fe/core/designtime/AppComponent.designtime.ts +91 -0
  162. package/src/sap/fe/core/formatters/CollaborationFormatter.js +104 -0
  163. package/src/sap/fe/core/formatters/CollaborationFormatter.ts +60 -0
  164. package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
  165. package/src/sap/fe/core/formatters/CriticalityFormatter.ts +1 -1
  166. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  167. package/src/sap/fe/core/formatters/FPMFormatter.ts +4 -10
  168. package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
  169. package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -1
  170. package/src/sap/fe/core/formatters/TableFormatter.js +91 -29
  171. package/src/sap/fe/core/formatters/TableFormatter.ts +94 -28
  172. package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
  173. package/src/sap/fe/core/formatters/ValueFormatter.ts +30 -7
  174. package/src/sap/fe/core/fpm/Component.js +51 -54
  175. package/src/sap/fe/core/fpm/Component.ts +48 -0
  176. package/src/sap/fe/core/helpers/AppStartupHelper.js +373 -0
  177. package/src/sap/fe/core/helpers/AppStartupHelper.ts +417 -0
  178. package/src/sap/fe/core/helpers/BindingExpression.js +489 -442
  179. package/src/sap/fe/core/helpers/BindingExpression.ts +486 -469
  180. package/src/sap/fe/core/helpers/ClassSupport.js +212 -76
  181. package/src/sap/fe/core/helpers/ClassSupport.ts +198 -71
  182. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +64 -59
  183. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +52 -0
  184. package/src/sap/fe/core/helpers/EditState.js +81 -84
  185. package/src/sap/fe/core/helpers/EditState.ts +81 -0
  186. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +62 -48
  187. package/src/sap/fe/core/helpers/ExcelFormatHelper.ts +49 -0
  188. package/src/sap/fe/core/helpers/FPMHelper.js +52 -56
  189. package/src/sap/fe/core/helpers/FPMHelper.ts +62 -0
  190. package/src/sap/fe/core/helpers/KeepAliveHelper.js +4 -5
  191. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +10 -10
  192. package/src/sap/fe/core/helpers/MassEditHelper.js +604 -0
  193. package/src/sap/fe/core/helpers/MassEditHelper.ts +699 -0
  194. package/src/sap/fe/core/helpers/ModelHelper.js +253 -225
  195. package/src/sap/fe/core/helpers/ModelHelper.ts +250 -0
  196. package/src/sap/fe/core/helpers/PasteHelper.js +210 -132
  197. package/src/sap/fe/core/helpers/PasteHelper.ts +196 -0
  198. package/src/sap/fe/core/helpers/SemanticDateOperators.js +336 -313
  199. package/src/sap/fe/core/helpers/SemanticDateOperators.ts +334 -0
  200. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +66 -67
  201. package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +73 -0
  202. package/src/sap/fe/core/helpers/StableIdHelper.js +4 -7
  203. package/src/sap/fe/core/helpers/StableIdHelper.ts +2 -6
  204. package/src/sap/fe/core/jsx-runtime/jsx.js +1 -1
  205. package/src/sap/fe/core/jsx-runtime/jsx.ts +1 -1
  206. package/src/sap/fe/core/library.js +427 -425
  207. package/src/sap/fe/core/library.support.js +23 -27
  208. package/src/sap/fe/core/library.support.ts +23 -0
  209. package/src/sap/fe/core/library.ts +420 -0
  210. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +64 -0
  211. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +69 -0
  212. package/src/sap/fe/core/messagebundle.properties +78 -13
  213. package/src/sap/fe/core/messagebundle_ar.properties +58 -7
  214. package/src/sap/fe/core/messagebundle_bg.properties +58 -7
  215. package/src/sap/fe/core/messagebundle_ca.properties +58 -7
  216. package/src/sap/fe/core/messagebundle_cs.properties +59 -8
  217. package/src/sap/fe/core/messagebundle_cy.properties +58 -7
  218. package/src/sap/fe/core/messagebundle_da.properties +58 -7
  219. package/src/sap/fe/core/messagebundle_de.properties +58 -7
  220. package/src/sap/fe/core/messagebundle_el.properties +58 -7
  221. package/src/sap/fe/core/messagebundle_en.properties +57 -6
  222. package/src/sap/fe/core/messagebundle_en_GB.properties +57 -6
  223. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +61 -6
  224. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +58 -7
  225. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +58 -7
  226. package/src/sap/fe/core/messagebundle_es.properties +58 -7
  227. package/src/sap/fe/core/messagebundle_es_MX.properties +58 -7
  228. package/src/sap/fe/core/messagebundle_et.properties +58 -7
  229. package/src/sap/fe/core/messagebundle_fi.properties +60 -9
  230. package/src/sap/fe/core/messagebundle_fr.properties +64 -13
  231. package/src/sap/fe/core/messagebundle_fr_CA.properties +59 -8
  232. package/src/sap/fe/core/messagebundle_hi.properties +58 -7
  233. package/src/sap/fe/core/messagebundle_hr.properties +58 -7
  234. package/src/sap/fe/core/messagebundle_hu.properties +59 -8
  235. package/src/sap/fe/core/messagebundle_id.properties +61 -10
  236. package/src/sap/fe/core/messagebundle_it.properties +58 -7
  237. package/src/sap/fe/core/messagebundle_iw.properties +58 -7
  238. package/src/sap/fe/core/messagebundle_ja.properties +58 -7
  239. package/src/sap/fe/core/messagebundle_kk.properties +58 -7
  240. package/src/sap/fe/core/messagebundle_ko.properties +58 -7
  241. package/src/sap/fe/core/messagebundle_lt.properties +58 -7
  242. package/src/sap/fe/core/messagebundle_lv.properties +59 -8
  243. package/src/sap/fe/core/messagebundle_ms.properties +58 -7
  244. package/src/sap/fe/core/messagebundle_nl.properties +58 -7
  245. package/src/sap/fe/core/messagebundle_no.properties +58 -7
  246. package/src/sap/fe/core/messagebundle_pl.properties +58 -7
  247. package/src/sap/fe/core/messagebundle_pt.properties +59 -8
  248. package/src/sap/fe/core/messagebundle_pt_PT.properties +58 -7
  249. package/src/sap/fe/core/messagebundle_ro.properties +58 -7
  250. package/src/sap/fe/core/messagebundle_ru.properties +58 -7
  251. package/src/sap/fe/core/messagebundle_sh.properties +58 -7
  252. package/src/sap/fe/core/messagebundle_sk.properties +58 -7
  253. package/src/sap/fe/core/messagebundle_sl.properties +58 -7
  254. package/src/sap/fe/core/messagebundle_sv.properties +59 -8
  255. package/src/sap/fe/core/messagebundle_th.properties +58 -7
  256. package/src/sap/fe/core/messagebundle_tr.properties +60 -9
  257. package/src/sap/fe/core/messagebundle_uk.properties +58 -7
  258. package/src/sap/fe/core/messagebundle_vi.properties +58 -7
  259. package/src/sap/fe/core/messagebundle_zh_CN.properties +58 -7
  260. package/src/sap/fe/core/messagebundle_zh_TW.properties +58 -7
  261. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +45 -71
  262. package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -1
  263. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +231 -202
  264. package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +212 -0
  265. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +67 -92
  266. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +10 -6
  267. package/src/sap/fe/core/services/NavigationServiceFactory.js +351 -300
  268. package/src/sap/fe/core/services/NavigationServiceFactory.ts +313 -0
  269. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +114 -81
  270. package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +83 -0
  271. package/src/sap/fe/core/services/RoutingServiceFactory.js +927 -1152
  272. package/src/sap/fe/core/services/RoutingServiceFactory.ts +898 -0
  273. package/src/sap/fe/core/services/ShellServicesFactory.js +649 -707
  274. package/src/sap/fe/core/services/ShellServicesFactory.ts +52 -15
  275. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +569 -637
  276. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +78 -102
  277. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +429 -478
  278. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +460 -0
  279. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +10 -8
  280. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +8 -0
  281. package/src/sap/fe/core/support/AnnotationIssue.support.js +15 -3
  282. package/src/sap/fe/core/support/AnnotationIssue.support.ts +16 -2
  283. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -2
  284. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.ts +1 -1
  285. package/src/sap/fe/core/support/CommonHelper.js +1 -1
  286. package/src/sap/fe/core/support/CommonHelper.ts +1 -1
  287. package/src/sap/fe/core/support/Diagnostics.js +36 -48
  288. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
  289. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
  290. package/src/sap/fe/core/templating/DataModelPathHelper.js +97 -127
  291. package/src/sap/fe/core/templating/DataModelPathHelper.ts +112 -135
  292. package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
  293. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
  294. package/src/sap/fe/core/templating/FieldControlHelper.js +8 -8
  295. package/src/sap/fe/core/templating/FieldControlHelper.ts +25 -7
  296. package/src/sap/fe/core/templating/FilterHelper.js +140 -78
  297. package/src/sap/fe/core/templating/FilterHelper.ts +149 -78
  298. package/src/sap/fe/core/templating/PropertyHelper.js +3 -3
  299. package/src/sap/fe/core/templating/PropertyHelper.ts +2 -2
  300. package/src/sap/fe/core/templating/UIFormatters.js +76 -135
  301. package/src/sap/fe/core/templating/UIFormatters.ts +76 -99
  302. package/src/sap/fe/core/type/Email.js +1 -1
  303. package/src/sap/fe/core/type/Email.ts +4 -6
  304. package/ui5.yaml +0 -3
  305. package/src/sap/fe/core/controls/filterbar.d.js +0 -8
  306. package/src/sap/fe/core/controls/filterbar.d.ts +0 -0
@@ -1,809 +1,926 @@
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
- /* eslint-disable no-alert */
6
- sap.ui.define(
7
- ["sap/base/Log", "sap/ui/base/Object", "sap/ui/base/EventProvider", "sap/fe/core/Synchronization", "sap/ui/thirdparty/URI"],
8
- function(Log, BaseObject, EventProvider, Synchronization, URI) {
9
- "use strict";
10
-
11
- var enumState = {
12
- EQUAL: 0,
13
- COMPATIBLE: 1,
14
- ANCESTOR: 2,
15
- DIFFERENT: 3
16
- };
17
-
18
- var enumURLParams = {
19
- LAYOUTPARAM: "layout",
20
- IAPPSTATEPARAM: "sap-iapp-state"
21
- };
22
-
23
- /**
24
- * Creates a HashGuard object.
25
- *
26
- * @param {string} sGuardHash The hash used for the guard
27
- * @returns {object} The created hash guard
28
- */
29
- function createGuardFromHash(sGuardHash) {
30
- return {
31
- _guardHash: sGuardHash.replace(/\?[^\?]*$/, ""), // Remove query part
32
- check: function(sHash) {
33
- return sHash.indexOf(this._guardHash) === 0;
34
- }
35
- };
36
- }
37
-
38
- /**
39
- * Returns the iAppState part from a hash (or null if not found).
40
- *
41
- * @param {string} sHash The hash
42
- * @returns {string} The iAppState part of the hash
43
- */
44
- function findAppStateInHash(sHash) {
45
- var aAppState = sHash.match(new RegExp("\\?.*" + enumURLParams.IAPPSTATEPARAM + "=([^&]*)"));
46
- return aAppState && aAppState.length > 1 ? aAppState[1] : null;
47
- }
48
-
49
- /**
50
- * Returns a hash without its iAppState part.
51
- *
52
- * @param {string} sHash The hash
53
- * @returns {string} The hash without the iAppState
54
- */
55
- function removeAppStateInHash(sHash) {
56
- return sHash.replace(new RegExp("[&?]*" + enumURLParams.IAPPSTATEPARAM + "=[^&]*"), "");
57
- }
58
-
59
- /**
60
- * Adds an iAppState inside a hash (or replaces an existing one).
61
- *
62
- * @param {*} sHash The hash
63
- * @param {*} sAppStateKey The iAppState to add
64
- * @returns {string} The hash with the app state
65
- */
66
- function setAppStateInHash(sHash, sAppStateKey) {
67
- var sNewHash;
68
-
69
- if (sHash.indexOf(enumURLParams.IAPPSTATEPARAM) >= 0) {
70
- // If there's already an iAppState parameter in the hash, replace it
71
- sNewHash = sHash.replace(
72
- new RegExp(enumURLParams.IAPPSTATEPARAM + "=[^&]*"),
73
- enumURLParams.IAPPSTATEPARAM + "=" + sAppStateKey
74
- );
75
- } else {
76
- // Add the iAppState parameter in the hash
77
- if (sHash.indexOf("?") < 0) {
78
- sNewHash = sHash + "?";
79
- } else {
80
- sNewHash = sHash + "&";
81
- }
82
- sNewHash += enumURLParams.IAPPSTATEPARAM + "=" + sAppStateKey;
83
- }
84
-
85
- return sNewHash;
86
- }
87
-
88
- return BaseObject.extend("sap.fe.core.RouterProxy", {
89
- bIsRebuildHistoryRunning: false,
90
- bIsComputingTitleHierachy: false,
91
- bIsGuardCrossAllowed: false,
92
- sIAppStateKey: null,
93
-
94
- init: function(oAppComponent, isfclEnabled) {
95
- // Save the name of the app (including startup parameters) for rebuilding full hashes later
96
- oAppComponent
97
- .getService("shellServices")
98
- .then(
99
- function() {
100
- this._oShellServices = oAppComponent.getShellServices();
101
-
102
- this.initRaw(oAppComponent.getRouter());
103
- // We want to wait until the initial routeMatched is done before doing any navigation
104
- this.waitForRouteMatchBeforeNavigation();
105
-
106
- // Set feLevel=0 for the first Application page in the history
107
- history.replaceState(
108
- Object.assign(
109
- {
110
- feLevel: 0
111
- },
112
- history.state
113
- ),
114
- "",
115
- window.location
116
- );
117
- this.fclEnabled = isfclEnabled;
118
-
119
- this._fnBlockingNavFilter = this._blockingNavigationFilter.bind(this);
120
- this._oShellServices.registerNavigationFilter(this._fnBlockingNavFilter);
121
- }.bind(this)
122
- )
123
- .catch(function(oError) {
124
- Log.error("Cannot retrieve the shell services", oError);
125
- });
126
- this._fnHashGuard = this.hashGuard.bind(this);
127
- window.addEventListener("popstate", this._fnHashGuard);
128
- this._bDisableOnHashChange = false;
129
- this._bIgnoreRestore = false;
130
- this._bCleanedRestore = false;
131
- this._bForceFocus = true; // Trigger the focus mechanism for the first view displayed by the app
132
- },
133
-
134
- destroy: function() {
135
- if (this._oShellServices) {
136
- this._oShellServices.unregisterNavigationFilter(this._fnBlockingNavFilter);
137
- }
138
- window.removeEventListener("popstate", this._fnHashGuard);
139
- },
140
-
141
- /**
142
- * Raw initialization (for unit tests).
143
- *
144
- * @param {sap.ui.core.routing.Router} oRouter The router used by this proxy
145
- */
146
- initRaw: function(oRouter) {
147
- this._oRouter = oRouter;
148
- this._oManagedHistory = [];
149
- this._oNavigationGuard = null;
150
-
151
- var sCurrentAppHash = this.getHash();
152
- this._oManagedHistory.push(this._extractStateFromHash(sCurrentAppHash));
153
-
154
- // Set the iAppState if the initial hash contains one
155
- this.sIAppStateKey = findAppStateInHash(sCurrentAppHash);
156
- },
157
-
158
- getHash: function() {
159
- return this._oRouter.getHashChanger().getHash();
160
- },
161
-
162
- isFocusForced: function() {
163
- return this._bForceFocus;
164
- },
165
-
166
- setFocusForced: function(bForced) {
167
- this._bForceFocus = bForced;
168
- },
169
-
170
- /**
171
- * Resets the internal variable sIAppStateKey.
172
- *
173
- * @function
174
- * @name sap.fe.core.RouterProxy#removeIAppStateKey
175
- *
176
- * @ui5-restricted
177
- */
178
- removeIAppStateKey: function() {
179
- this.sIAppStateKey = null;
180
- },
181
-
182
- /**
183
- * Navigates to a specific hash.
184
- *
185
- * @function
186
- * @name sap.fe.core.RouterProxy#navToHash
187
- * @memberof sap.fe.core.RouterProxy
188
- * @static
189
- * @param {string} sHash Hash to be navigated to
190
- * @param {boolean} bPreserveHistory If set to true, non-ancestor entries in history will be retained
191
- * @param {boolean} bDisablePreservationCache If set to true, cache preservation mechanism is disabled for the current navigation
192
- * @param {boolean} bForceFocus If set to true, the logic to set the focus once the navigation is finalized will be triggered (onPageReady)
193
- * @returns {Promise} Promise that is resolved when the navigation is finalized
194
- * @ui5-restricted
195
- */
196
- navToHash: function(sHash, bPreserveHistory, bDisablePreservationCache, bForceFocus) {
197
- var that = this;
198
-
199
- if (this._oRouteMatchSynchronization) {
200
- return this._oRouteMatchSynchronization.waitFor().then(function() {
201
- that._oRouteMatchSynchronization = null;
202
- return that._internalNavToHash(sHash, bPreserveHistory, bDisablePreservationCache, bForceFocus);
203
- });
204
- } else {
205
- if (this._bActivateRouteMatchSynchro) {
206
- this.waitForRouteMatchBeforeNavigation();
207
- }
208
- return that._internalNavToHash(sHash, bPreserveHistory, bDisablePreservationCache, bForceFocus);
209
- }
210
- },
211
-
212
- _internalNavToHash: function(sHash, bPreserveHistory, bDisablePreservationCache, bForceFocus) {
213
- // Add the app state in the hash if needed
214
- if (this.fclEnabled && this.sIAppStateKey && !findAppStateInHash(sHash)) {
215
- sHash = setAppStateInHash(sHash, this.sIAppStateKey);
216
- }
217
-
218
- if (!this.checkHashWithGuard(sHash)) {
219
- if (!this.oResourceBundle) {
220
- this.oResourceBundle = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core");
221
- }
222
-
223
- // We have to use a confirm here for UI consistency reasons, as with some scenarios
224
- // in the EditFlow we rely on a UI5 mechanism that displays a confirm dialog.
225
- if (!confirm(this.oResourceBundle.getText("C_ROUTER_PROXY_SAPFE_EXIT_NOTSAVED_MESSAGE"))) {
226
- // The user clicked on Cancel --> cancel navigation
227
- return Promise.resolve();
228
- }
229
- this.bIsGuardCrossAllowed = true;
230
- }
231
-
232
- // In case the navigation will cause a new view to be displayed, we force the focus
233
- // I.e. if the keys for the hash we're navigating to is a superset of the current hash keys.
234
- var oNewState = this._extractStateFromHash(sHash);
235
- if (!this._bForceFocus) {
236
- // If the focus was already forced, keep it
237
- var aCurrentHashKeys = this._extractKeysFromHash(this.getHash());
238
- this._bForceFocus =
239
- bForceFocus ||
240
- (aCurrentHashKeys.length < oNewState.keys.length &&
241
- aCurrentHashKeys.every(function(key, index) {
242
- return key === oNewState.keys[index];
243
- }));
244
- }
245
-
246
- var oHistoryAction = this._pushNewState(oNewState, false, bPreserveHistory, bDisablePreservationCache);
247
-
248
- return this._rebuildBrowserHistory(oHistoryAction, false);
249
- },
250
-
251
- /**
252
- * Clears browser history if entries have been added without using the RouterProxy.
253
- * Updates the internal history accordingly.
254
- *
255
- * @returns {Promise} Promise that is resolved once the history is rebuilt
256
- */
257
- restoreHistory: function() {
258
- if (this._bApplyRestore) {
259
- this._bApplyRestore = false;
260
- var sTargetHash = this.getHash();
261
- sTargetHash = sTargetHash.replace(/(\?|&)restoreHistory=true/, "");
262
- var oNewState = this._extractStateFromHash(sTargetHash);
263
-
264
- var oHistoryAction = this._pushNewState(oNewState, true, false, true);
265
-
266
- return this._rebuildBrowserHistory(oHistoryAction, true);
267
- } else {
268
- return Promise.resolve();
269
- }
270
- },
271
-
272
- /**
273
- * Navigates back in the history.
274
- *
275
- * @returns {Promise} Promise that is resolved when the navigation is finalized
276
- */
277
- navBack: function() {
278
- var sCurrentHash = this.getHash(),
279
- sPreviousHash;
280
-
281
- // Look for the current hash in the managed history
282
- for (var i = this._oManagedHistory.length - 1; i > 0; i--) {
283
- if (this._oManagedHistory[i].hash === sCurrentHash) {
284
- sPreviousHash = this._oManagedHistory[i - 1].hash;
285
- break;
286
- }
287
- }
288
-
289
- if (sPreviousHash) {
290
- return this.navToHash(sPreviousHash);
291
- } else {
292
- // We couldn't find a previous hash in history
293
- // This can happen when navigating from a transient hash in a create app, and
294
- // in that case history.back would go back to the FLP
295
- window.history.back();
296
- return Promise.resolve();
297
- }
298
- },
299
-
300
- /**
301
- * Navigates to a route with parameters.
302
- *
303
- * @param {string} sRouteName The route name to be navigated to
304
- * @param {object} oParameters Parameters for the navigation
305
- * @returns {Promise} Promise that is resolved when the navigation is finalized
306
- * @ui5-restricted
307
- */
308
- navTo: function(sRouteName, oParameters) {
309
- var sHash = this._oRouter.getURL(sRouteName, oParameters);
310
- return this.navToHash(sHash, false, oParameters.noPreservationCache);
311
- },
312
-
313
- /**
314
- * Exits the current app by navigating back
315
- * to the previous app (if any) or the FLP.
316
- *
317
- * @returns {Promise} Promise that is resolved when we exit the app
318
- */
319
- exitFromApp: function() {
320
- return this._oShellServices.backToPreviousApp();
321
- },
322
-
323
- /**
324
- * Checks whether a given hash can have an impact on the current state
325
- * i.e. if the hash is equal, compatible or an ancestor of the current state.
326
- *
327
- * @param {*} sHash `true` if there is an impact
328
- * @returns {boolean} If there is an impact
329
- */
330
- isCurrentStateImpactedBy: function(sHash) {
331
- if (sHash[0] === "/") {
332
- sHash = sHash.substring(1);
333
- }
334
- var oLocalGuard = createGuardFromHash(sHash);
335
- return oLocalGuard.check(this.getHash());
336
- },
337
-
338
- /**
339
- * Checks if a navigation is currently being processed.
340
- *
341
- * @returns {boolean} `false` if a navigation has been triggered in the RouterProxy and is not yet finalized
342
- */
343
- isNavigationFinalized: function() {
344
- return !this.bIsRebuildHistoryRunning && !this._bDelayedRebuild;
345
- },
346
-
347
- /**
348
- * Sets the last state as a guard.
349
- * Each future navigation will be checked against this guard, and a confirmation dialog will
350
- * be displayed before the navigation crosses the guard (i.e. goes to an ancestor of the guard).
351
- */
352
- setNavigationGuard: function() {
353
- this._oNavigationGuard = createGuardFromHash(this.getHash());
354
- this.bIsGuardCrossAllowed = false;
355
- },
356
-
357
- /**
358
- * Disables the navigation guard.
359
- */
360
- discardNavigationGuard: function() {
361
- this._oNavigationGuard = null;
362
- },
363
-
364
- /**
365
- * Checks for the availability of the navigation guard.
366
- *
367
- * @returns {boolean} `true` if navigating guard is available
368
- */
369
- hasNavigationGuard: function() {
370
- return this._oNavigationGuard !== null;
371
- },
372
-
373
- /**
374
- * Tests a hash against the navigation guard.
375
- *
376
- * @param {string} sHash The hash to be tested
377
- * @returns {boolean} `true` if navigating to the hash doesn't cross the guard
378
- */
379
- checkHashWithGuard: function(sHash) {
380
- return this._oNavigationGuard === null || this._oNavigationGuard.check(sHash);
381
- },
382
-
383
- /**
384
- * Checks if the user allowed the navigation guard to be crossed.
385
- *
386
- * @returns {boolean} `true` if crossing the guard has been allowed by the user
387
- */
388
- isGuardCrossAllowedByUser: function() {
389
- return this.bIsGuardCrossAllowed;
390
- },
391
-
392
- /**
393
- * Activates the synchronization for routeMatchedEvent.
394
- * The next NavToHash call will create a Synchronization object that will be resolved
395
- * by the corresponding onRouteMatched event, preventing another NavToHash to happen in parallel.
396
- */
397
- activateRouteMatchSynchronization: function() {
398
- this._bActivateRouteMatchSynchro = true;
399
- },
400
-
401
- /**
402
- * Resolve the routeMatch synchronization object, unlocking potential pending NavToHash calls.
403
- */
404
- resolveRouteMatch: function() {
405
- if (this._oRouteMatchSynchronization) {
406
- this._oRouteMatchSynchronization.resolve();
407
- }
408
- },
409
-
410
- /**
411
- * Makes sure no navigation can happen before a routeMatch happened.
412
- */
413
- waitForRouteMatchBeforeNavigation: function() {
414
- this._oRouteMatchSynchronization = new Synchronization();
415
- this._bActivateRouteMatchSynchro = false;
416
- },
417
-
418
- _extractKeysFromHash: function(sHash) {
419
- if (sHash === undefined) {
420
- sHash = "";
421
- }
422
- var sHashNoParams = sHash.split("?")[0]; // remove params
423
- var aTokens = sHashNoParams.split("/");
424
- var aKeys = [];
425
-
426
- aTokens.forEach(function(sToken) {
427
- var regexKey = /[^\(\)]+\([^\(\)]+\)/; // abc(def)
428
- if (regexKey.test(sToken)) {
429
- aKeys.push(sToken.split("(")[0]);
430
- }
431
- });
432
-
433
- return aKeys;
434
- },
435
-
436
- /**
437
- * Builds a state from a hash.
438
- *
439
- * @param {string} sHash The hash to be used as entry
440
- * @returns {object} The state
441
- *
442
- * @ui5-restricted
443
- */
444
- _extractStateFromHash: function(sHash) {
445
- if (sHash === undefined) {
446
- sHash = "";
447
- }
448
-
449
- var oState = {
450
- keys: this._extractKeysFromHash(sHash)
451
- };
452
-
453
- // Retrieve layout (if any)
454
- var aLayout = sHash.match(new RegExp("\\?.*" + enumURLParams.LAYOUTPARAM + "=([^&]*)"));
455
- oState.sLayout = aLayout && aLayout.length > 1 ? aLayout[1] : null;
456
- if (oState.sLayout === "MidColumnFullScreen") {
457
- oState.screenMode = 1;
458
- } else if (oState.sLayout === "EndColumnFullScreen") {
459
- oState.screenMode = 2;
460
- } else {
461
- oState.screenMode = 0;
462
- }
463
-
464
- oState.hash = sHash;
465
- return oState;
466
- },
467
-
468
- /**
469
- * Adds a new state into the internal history structure.
470
- * Makes sure this new state is added after an ancestor.
471
- * Also sets the iAppState key in the whole history.
472
- *
473
- * @memberof sap.fe.core.RouterProxy
474
- * @param {object} oNewState The new state to be added
475
- * @param {boolean} bRebuildOnly `true` if we're rebuilding the history after a shell menu navigation
476
- * @param {boolean} bPreserveHistory If set to true, non-ancestor entries in history will be retained
477
- * @param {boolean} bDisableHistoryPreservation Disable the mechanism to retained marked entries in cache
478
- * @returns {object} The new state
479
- * @ui5-restricted
480
- * @final
481
- */
482
- _pushNewState: function(oNewState, bRebuildOnly, bPreserveHistory, bDisableHistoryPreservation) {
483
- var sCurrentHash = this.getHash(),
484
- lastIndex = this._oManagedHistory.length - 1,
485
- iPopCount = bRebuildOnly ? 1 : 0,
486
- that = this;
487
-
488
- // 1. Do some cleanup in the managed history : in case the user has navigated back in the browser history, we need to remove
489
- // the states ahead in history and make sure the top state corresponds to the current page
490
- // We don't do that when restoring the history, as the current state has been added on top of the browser history
491
- // and is not reflected in the managed history
492
- if (!bRebuildOnly) {
493
- while (lastIndex >= 0 && this._oManagedHistory[lastIndex].hash !== sCurrentHash) {
494
- this._oManagedHistory.pop();
495
- lastIndex--;
496
- }
497
-
498
- if (this._oManagedHistory.length === 0) {
499
- // We couldn't find the current location in the history. This can happen if a browser reload
500
- // happened, causing a reinitialization of the managed history.
501
- // In that case, we use the current location as the new starting point in the managed history
502
- this._oManagedHistory.push(this._extractStateFromHash(sCurrentHash));
503
- history.replaceState(Object.assign({ feLevel: 0 }, history.state), "");
504
- }
505
- }
506
-
507
- // 2. Mark the top state as preserved if required
508
- if (bPreserveHistory && !bDisableHistoryPreservation) {
509
- this._oManagedHistory[this._oManagedHistory.length - 1].preserved = true;
510
- }
511
-
512
- // 3. Then pop all states until we find an ancestor of the new state, or we find a state that need to be preserved
513
- var oLastRemovedItem;
514
- while (this._oManagedHistory.length > 0) {
515
- var oTopState = this._oManagedHistory[this._oManagedHistory.length - 1];
516
- if (
517
- (bDisableHistoryPreservation || !oTopState.preserved) &&
518
- this._compareCacheStates(oTopState, oNewState) !== enumState.ANCESTOR
519
- ) {
520
- // The top state is not an ancestor of oNewState and is not preserved --> we can pop it
521
- oLastRemovedItem = this._oManagedHistory.pop();
522
- iPopCount++;
523
- } else if (oTopState.preserved && removeAppStateInHash(oTopState.hash) === removeAppStateInHash(oNewState.hash)) {
524
- // We try to add a state that is already in cache (due to preserved flag) but with a different iapp-state
525
- // --> we should delete the previous entry (it will be later replaced by the new one) and stop popping
526
- oLastRemovedItem = this._oManagedHistory.pop();
527
- iPopCount++;
528
- oNewState.preserved = true;
529
- break;
530
- } else {
531
- break; // Ancestor or preserved state found --> we stop popping out states
532
- }
533
- }
534
-
535
- // 4. iAppState management
536
- this.sIAppStateKey = findAppStateInHash(oNewState.hash);
537
- if (this.fclEnabled && this.sIAppStateKey) {
538
- // In case of FCL, the new app state needs to be applied to the whole history
539
- this._oManagedHistory.forEach(function(oManagedState) {
540
- oManagedState.hash = setAppStateInHash(oManagedState.hash, that.sIAppStateKey);
541
- });
542
- } else if (!this.fclEnabled && oLastRemovedItem) {
543
- var sPreviousIAppStateKey = findAppStateInHash(oLastRemovedItem.hash);
544
- var oComparisonStateResult = this._compareCacheStates(oLastRemovedItem, oNewState);
545
- // if current state doesn't contain a i-appstate and this state should replace a state containing a iAppState
546
- // then the previous iAppState is preserved
547
- if (
548
- !this.sIAppStateKey &&
549
- sPreviousIAppStateKey &&
550
- (oComparisonStateResult === enumState.EQUAL || oComparisonStateResult === enumState.COMPATIBLE)
551
- ) {
552
- oNewState.hash = setAppStateInHash(oNewState.hash, sPreviousIAppStateKey);
553
- }
554
- }
555
-
556
- // 5. Now we can push the state at the top of the internal history
557
- var bHasSameHash = oLastRemovedItem && oNewState.hash === oLastRemovedItem.hash;
558
- if (this._oManagedHistory.length === 0 || this._oManagedHistory[this._oManagedHistory.length - 1].hash !== oNewState.hash) {
559
- this._oManagedHistory.push(oNewState);
560
- }
561
-
562
- // 6. Determine which actions to do on the history
563
- if (iPopCount === 0) {
564
- // No state was popped --> append
565
- return { type: "append" };
566
- } else if (iPopCount === 1) {
567
- // Only 1 state was popped --> replace current hash unless hash is the same (then nothing to do)
568
- return bHasSameHash ? { type: "none" } : { type: "replace" };
569
- } else {
570
- // More than 1 state was popped --> go bakc in history and replace hash if necessary
571
- return bHasSameHash ? { type: "back", steps: iPopCount - 1 } : { type: "back-replace", steps: iPopCount - 1 };
572
- }
573
- },
574
-
575
- _blockingNavigationFilter: function() {
576
- return this._bDisableOnHashChange ? "Custom" : "Continue";
577
- },
578
-
579
- /**
580
- * Disable the routing by calling the router stop method.
581
- *
582
- * @function
583
- * @memberof sap.fe.core.RouterProxy
584
- *
585
- * @ui5-restricted
586
- * @final
587
- */
588
- _disableEventOnHashChange: function() {
589
- this._bDisableOnHashChange = true;
590
- this._oRouter.stop();
591
- },
592
-
593
- /**
594
- * Enable the routing by calling the router initialize method.
595
- *
596
- * @function
597
- * @name sap.fe.core.RouterProxy#_enableEventOnHashChange
598
- * @memberof sap.fe.core.RouterProxy
599
- * @param {Array} [bIgnoreCurrentHash] Ignore the last hash event triggered before the router has initialized
600
- *
601
- * @ui5-restricted
602
- * @final
603
- */
604
- _enableEventOnHashChange: function(bIgnoreCurrentHash) {
605
- this._bDisableOnHashChange = false;
606
- this._oRouter.initialize(bIgnoreCurrentHash);
607
- },
608
-
609
- /**
610
- * Rebuilds the browser history from the app root page.
611
- *
612
- * @memberof sap.fe.core.RouterProxy
613
- * @param {object} oHistoryAction Specifies the navigation action to be performed
614
- * @param {boolean} bRebuildOnly `true` if rebuilding history
615
- * @returns {Promise} A promise that is resolved when the navigation is finalized
616
- * @ui5-restricted
617
- * @final
618
- */
619
- _rebuildBrowserHistory: function(oHistoryAction, bRebuildOnly) {
620
- var that = this;
621
- return new Promise(function(resolve, reject) {
622
- that.bIsRebuildHistoryRunning = true;
623
- var oTargetState = that._oManagedHistory[that._oManagedHistory.length - 1],
624
- newLevel = that._oManagedHistory.length - 1;
625
-
626
- function replaceAsync() {
627
- if (!bRebuildOnly) {
628
- that._enableEventOnHashChange(true);
629
- }
630
-
631
- that._oRouter.getHashChanger().replaceHash(oTargetState.hash);
632
- history.replaceState(Object.assign({ feLevel: newLevel }, history.state), "");
633
-
634
- if (bRebuildOnly) {
635
- setTimeout(function() {
636
- // Timeout to let 'hashchange' event be processed before by the HashChanger, so that
637
- // onRouteMatched notification isn't raised
638
- that._enableEventOnHashChange(true);
639
- }, 0);
640
- }
641
-
642
- that.bIsRebuildHistoryRunning = false;
643
- resolve();
644
- }
645
-
646
- // Async callbacks when navigating back, in order to let all notifications and events get processed
647
- function backReplaceAsync() {
648
- window.removeEventListener("popstate", backReplaceAsync);
649
- setTimeout(function() {
650
- // Timeout to let 'hashchange' event be processed before by the HashChanger
651
- replaceAsync();
652
- }, 0);
653
- }
654
-
655
- function backAsync() {
656
- window.removeEventListener("popstate", backAsync);
657
- that.bIsRebuildHistoryRunning = false;
658
- resolve();
659
- }
660
-
661
- that._bIgnoreRestore = true;
662
-
663
- switch (oHistoryAction.type) {
664
- case "replace":
665
- that._oRouter.getHashChanger().replaceHash(oTargetState.hash);
666
- history.replaceState(Object.assign({ feLevel: newLevel }, history.state), "");
667
- that.bIsRebuildHistoryRunning = false;
668
- resolve();
669
- break;
670
-
671
- case "append":
672
- that._oRouter.getHashChanger().setHash(oTargetState.hash);
673
- history.replaceState(Object.assign({ feLevel: newLevel }, history.state), "");
674
- that.bIsRebuildHistoryRunning = false;
675
- resolve();
676
- break;
677
-
678
- case "back":
679
- window.addEventListener("popstate", backAsync);
680
- history.go(-oHistoryAction.steps);
681
- break;
682
-
683
- case "back-replace":
684
- that._disableEventOnHashChange();
685
- window.addEventListener("popstate", backReplaceAsync);
686
- history.go(-oHistoryAction.steps);
687
- break;
688
-
689
- default:
690
- // No navigation
691
- that.bIsRebuildHistoryRunning = false;
692
- resolve();
693
- }
694
- });
695
- },
696
-
697
- getLastHistoryEntry: function() {
698
- return this._oManagedHistory[this._oManagedHistory.length - 1];
699
- },
700
-
701
- hashGuard: function(oEvent) {
702
- if (this._bCleanedRestore) {
703
- this._bCleanedRestore = false;
704
- return;
705
- }
706
- var sHash = window.location.hash;
707
- if (sHash.indexOf("restoreHistory=true") !== -1) {
708
- this._bApplyRestore = true;
709
- } else if (!this.bIsRebuildHistoryRunning) {
710
- var aHashSplit = sHash.split("&/");
711
- var sAppHash = aHashSplit[1] ? aHashSplit[1] : "";
712
- if (this.checkHashWithGuard(sAppHash)) {
713
- this._bDelayedRebuild = true;
714
- var oNewState = this._extractStateFromHash(sAppHash);
715
- this._pushNewState(oNewState, false, false, true);
716
-
717
- var that = this;
718
- setTimeout(function() {
719
- that._bDelayedRebuild = false;
720
- }, 0);
721
- }
722
- }
723
- },
724
-
725
- /**
726
- * Compares 2 states.
727
- *
728
- * @param {object} oState1
729
- * @param {object} oState2
730
- * @returns {number} The result of the comparison:
731
- * - enumState.EQUAL if oState1 and oState2 are equal
732
- * - enumState.COMPATIBLE if oState1 and oState2 are compatible
733
- * - enumState.ANCESTOR if oState1 is an ancestor of oState2
734
- * - enumState.DIFFERENT if the 2 states are different
735
- */
736
-
737
- _compareCacheStates: function(oState1, oState2) {
738
- // First compare object keys
739
- if (oState1.keys.length > oState2.keys.length) {
740
- return enumState.DIFFERENT;
741
- }
742
- var equal = true;
743
- var index;
744
- for (index = 0; equal && index < oState1.keys.length; index++) {
745
- if (oState1.keys[index] !== oState2.keys[index]) {
746
- equal = false;
747
- }
748
- }
749
- if (!equal) {
750
- // Some objects keys are different
751
- return enumState.DIFFERENT;
752
- }
753
-
754
- // All keys from oState1 are in oState2 --> check if ancestor
755
- if (oState1.keys.length < oState2.keys.length || oState1.screenMode < oState2.screenMode) {
756
- return enumState.ANCESTOR;
757
- }
758
- if (oState1.screenMode > oState2.screenMode) {
759
- return enumState.DIFFERENT; // Not sure this case can happen...
760
- }
761
-
762
- // At this stage, the 2 states have the same object keys (in the same order) and same screenmode
763
- // They can be either compatible or equal
764
- return oState1.sLayout === oState2.sLayout ? enumState.EQUAL : enumState.COMPATIBLE;
765
- },
766
-
767
- /**
768
- * Checks if back exits the present guard set.
769
- *
770
- * @param {string} sPresentHash The current hash. Only used for unit tests.
771
- * @returns {boolean} `true` if back exits there is a guard exit on back
772
- */
773
- checkIfBackIsOutOfGuard: function(sPresentHash) {
774
- var that = this,
775
- sPrevHash;
776
-
777
- if (sPresentHash === undefined) {
778
- // We use window.location.hash instead of HashChanger.getInstance().getHash() because the latter
779
- // replaces characters in the URL (e.g. %24 replaced by $) and it causes issues when comparing
780
- // with the URLs in the managed history
781
- var oSplitHash = this._oShellServices.splitHash(window.location.hash);
782
- if (oSplitHash && oSplitHash.appSpecificRoute) {
783
- sPresentHash = oSplitHash.appSpecificRoute;
784
- if (sPresentHash.indexOf("&/") === 0) {
785
- sPresentHash = sPresentHash.substring(2);
786
- }
787
- } else {
788
- sPresentHash = window.location.hash.substring(1); // To remove the '#'
789
- if (sPresentHash[0] === "/") {
790
- sPresentHash = sPresentHash.substring(1);
791
- }
792
- }
793
- }
794
- sPresentHash = URI.decode(sPresentHash);
795
- if (that._oNavigationGuard) {
796
- for (var i = that._oManagedHistory.length - 1; i > 0; i--) {
797
- if (that._oManagedHistory[i].hash === sPresentHash) {
798
- sPrevHash = that._oManagedHistory[i - 1].hash;
799
- break;
800
- }
801
- }
802
-
803
- return !sPrevHash || !that.checkHashWithGuard(sPrevHash);
804
- }
805
- return false;
806
- }
807
- });
808
- }
809
- );
5
+ sap.ui.define(["sap/base/Log", "sap/ui/base/Object", "sap/fe/core/Synchronization", "sap/ui/thirdparty/URI", "sap/fe/core/helpers/ClassSupport"], function (Log, BaseObject, Synchronization, URI, ClassSupport) {
6
+ "use strict";
7
+
8
+ var _dec, _class;
9
+
10
+ var UI5Class = ClassSupport.UI5Class;
11
+
12
+ 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); }
13
+
14
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
15
+
16
+ var enumState = {
17
+ EQUAL: 0,
18
+ COMPATIBLE: 1,
19
+ ANCESTOR: 2,
20
+ DIFFERENT: 3
21
+ };
22
+ var enumURLParams = {
23
+ LAYOUTPARAM: "layout",
24
+ IAPPSTATEPARAM: "sap-iapp-state"
25
+ };
26
+ /**
27
+ * Creates a HashGuard object.
28
+ *
29
+ * @param {string} sGuardHash The hash used for the guard
30
+ * @returns {object} The created hash guard
31
+ */
32
+
33
+ function createGuardFromHash(sGuardHash) {
34
+ return {
35
+ _guardHash: sGuardHash.replace(/\?[^\?]*$/, ""),
36
+ // Remove query part
37
+ check: function (sHash) {
38
+ return sHash.indexOf(this._guardHash) === 0;
39
+ }
40
+ };
41
+ }
42
+ /**
43
+ * Returns the iAppState part from a hash (or null if not found).
44
+ *
45
+ * @param {string} sHash The hash
46
+ * @returns {string} The iAppState part of the hash
47
+ */
48
+
49
+
50
+ function findAppStateInHash(sHash) {
51
+ var aAppState = sHash.match(new RegExp("\\?.*" + enumURLParams.IAPPSTATEPARAM + "=([^&]*)"));
52
+ return aAppState && aAppState.length > 1 ? aAppState[1] : null;
53
+ }
54
+ /**
55
+ * Returns a hash without its iAppState part.
56
+ *
57
+ * @param {string} sHash The hash
58
+ * @returns {string} The hash without the iAppState
59
+ */
60
+
61
+
62
+ function removeAppStateInHash(sHash) {
63
+ return sHash.replace(new RegExp("[&?]*" + enumURLParams.IAPPSTATEPARAM + "=[^&]*"), "");
64
+ }
65
+ /**
66
+ * Adds an iAppState inside a hash (or replaces an existing one).
67
+ *
68
+ * @param {*} sHash The hash
69
+ * @param {*} sAppStateKey The iAppState to add
70
+ * @returns {string} The hash with the app state
71
+ */
72
+
73
+
74
+ function setAppStateInHash(sHash, sAppStateKey) {
75
+ var sNewHash;
76
+
77
+ if (sHash.indexOf(enumURLParams.IAPPSTATEPARAM) >= 0) {
78
+ // If there's already an iAppState parameter in the hash, replace it
79
+ sNewHash = sHash.replace(new RegExp(enumURLParams.IAPPSTATEPARAM + "=[^&]*"), enumURLParams.IAPPSTATEPARAM + "=" + sAppStateKey);
80
+ } else {
81
+ // Add the iAppState parameter in the hash
82
+ if (sHash.indexOf("?") < 0) {
83
+ sNewHash = sHash + "?";
84
+ } else {
85
+ sNewHash = sHash + "&";
86
+ }
87
+
88
+ sNewHash += enumURLParams.IAPPSTATEPARAM + "=" + sAppStateKey;
89
+ }
90
+
91
+ return sNewHash;
92
+ }
93
+
94
+ var RouterProxy = (_dec = UI5Class("sap.fe.core.RouterProxy"), _dec(_class = /*#__PURE__*/function (_BaseObject) {
95
+ _inherits(RouterProxy, _BaseObject);
96
+
97
+ function RouterProxy() {
98
+ var _this;
99
+
100
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
101
+ args[_key] = arguments[_key];
102
+ }
103
+
104
+ _this = _BaseObject.call.apply(_BaseObject, [this].concat(args)) || this;
105
+ _this.bIsRebuildHistoryRunning = false;
106
+ _this.bIsComputingTitleHierachy = false;
107
+ _this.bIsGuardCrossAllowed = false;
108
+ _this.sIAppStateKey = null;
109
+ _this._bActivateRouteMatchSynchro = false;
110
+ _this._bApplyRestore = false;
111
+ _this._bDelayedRebuild = false;
112
+ return _this;
113
+ }
114
+
115
+ var _proto = RouterProxy.prototype;
116
+
117
+ _proto.init = function init(oAppComponent, isfclEnabled) {
118
+ var _this2 = this;
119
+
120
+ // Save the name of the app (including startup parameters) for rebuilding full hashes later
121
+ oAppComponent.getService("shellServices").then(function () {
122
+ _this2._oShellServices = oAppComponent.getShellServices();
123
+
124
+ _this2.initRaw(oAppComponent.getRouter()); // We want to wait until the initial routeMatched is done before doing any navigation
125
+
126
+
127
+ _this2.waitForRouteMatchBeforeNavigation(); // Set feLevel=0 for the first Application page in the history
128
+
129
+
130
+ history.replaceState(Object.assign({
131
+ feLevel: 0
132
+ }, history.state), "", window.location);
133
+ _this2.fclEnabled = isfclEnabled;
134
+ _this2._fnBlockingNavFilter = _this2._blockingNavigationFilter.bind(_this2);
135
+
136
+ _this2._oShellServices.registerNavigationFilter(_this2._fnBlockingNavFilter);
137
+ }).catch(function (oError) {
138
+ Log.error("Cannot retrieve the shell services", oError);
139
+ });
140
+ this._fnHashGuard = this.hashGuard.bind(this);
141
+ window.addEventListener("popstate", this._fnHashGuard);
142
+ this._bDisableOnHashChange = false;
143
+ this._bIgnoreRestore = false;
144
+ this._bCleanedRestore = false;
145
+ this._bForceFocus = true; // Trigger the focus mechanism for the first view displayed by the app
146
+ };
147
+
148
+ _proto.destroy = function destroy() {
149
+ if (this._oShellServices) {
150
+ this._oShellServices.unregisterNavigationFilter(this._fnBlockingNavFilter);
151
+ }
152
+
153
+ window.removeEventListener("popstate", this._fnHashGuard);
154
+ }
155
+ /**
156
+ * Raw initialization (for unit tests).
157
+ *
158
+ * @param {sap.ui.core.routing.Router} oRouter The router used by this proxy
159
+ */
160
+ ;
161
+
162
+ _proto.initRaw = function initRaw(oRouter) {
163
+ this._oRouter = oRouter;
164
+ this._oManagedHistory = [];
165
+ this._oNavigationGuard = null;
166
+ var sCurrentAppHash = this.getHash();
167
+
168
+ this._oManagedHistory.push(this._extractStateFromHash(sCurrentAppHash)); // Set the iAppState if the initial hash contains one
169
+
170
+
171
+ this.sIAppStateKey = findAppStateInHash(sCurrentAppHash);
172
+ };
173
+
174
+ _proto.getHash = function getHash() {
175
+ return this._oRouter.getHashChanger().getHash();
176
+ };
177
+
178
+ _proto.isFocusForced = function isFocusForced() {
179
+ return this._bForceFocus;
180
+ };
181
+
182
+ _proto.setFocusForced = function setFocusForced(bForced) {
183
+ this._bForceFocus = bForced;
184
+ }
185
+ /**
186
+ * Resets the internal variable sIAppStateKey.
187
+ *
188
+ * @function
189
+ * @name sap.fe.core.RouterProxy#removeIAppStateKey
190
+ *
191
+ * @ui5-restricted
192
+ */
193
+ ;
194
+
195
+ _proto.removeIAppStateKey = function removeIAppStateKey() {
196
+ this.sIAppStateKey = null;
197
+ }
198
+ /**
199
+ * Navigates to a specific hash.
200
+ *
201
+ * @function
202
+ * @name sap.fe.core.RouterProxy#navToHash
203
+ * @memberof sap.fe.core.RouterProxy
204
+ * @static
205
+ * @param {string} sHash Hash to be navigated to
206
+ * @param {boolean} bPreserveHistory If set to true, non-ancestor entries in history will be retained
207
+ * @param {boolean} bDisablePreservationCache If set to true, cache preservation mechanism is disabled for the current navigation
208
+ * @param {boolean} bForceFocus If set to true, the logic to set the focus once the navigation is finalized will be triggered (onPageReady)
209
+ * @param {boolean} bPreserveShellBackNavigationHandler If not set to false, the back navigation is set to undefined
210
+ * @returns {Promise} Promise (resolved when the navigation is finalized) that returns 'true' if a navigation took place, 'false' if the navigation didn't happen
211
+ * @ui5-restricted
212
+ */
213
+ ;
214
+
215
+ _proto.navToHash = function navToHash(sHash, bPreserveHistory, bDisablePreservationCache, bForceFocus, bPreserveShellBackNavigationHandler) {
216
+ var _this3 = this;
217
+
218
+ if (bPreserveShellBackNavigationHandler !== false) {
219
+ this._oShellServices.setBackNavigation();
220
+ }
221
+
222
+ if (this._oRouteMatchSynchronization) {
223
+ return this._oRouteMatchSynchronization.waitFor().then(function () {
224
+ _this3._oRouteMatchSynchronization = undefined;
225
+ return _this3._internalNavToHash(sHash, bPreserveHistory, bDisablePreservationCache, bForceFocus);
226
+ });
227
+ } else {
228
+ if (this._bActivateRouteMatchSynchro) {
229
+ this.waitForRouteMatchBeforeNavigation();
230
+ }
231
+
232
+ return this._internalNavToHash(sHash, bPreserveHistory, bDisablePreservationCache, bForceFocus);
233
+ }
234
+ };
235
+
236
+ _proto._internalNavToHash = function _internalNavToHash(sHash, bPreserveHistory, bDisablePreservationCache, bForceFocus) {
237
+ // Add the app state in the hash if needed
238
+ if (this.fclEnabled && this.sIAppStateKey && !findAppStateInHash(sHash)) {
239
+ sHash = setAppStateInHash(sHash, this.sIAppStateKey);
240
+ }
241
+
242
+ if (!this.checkHashWithGuard(sHash)) {
243
+ if (!this.oResourceBundle) {
244
+ this.oResourceBundle = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core");
245
+ } // We have to use a confirm here for UI consistency reasons, as with some scenarios
246
+ // in the EditFlow we rely on a UI5 mechanism that displays a confirm dialog.
247
+ // eslint-disable-next-line no-alert
248
+
249
+
250
+ if (!confirm(this.oResourceBundle.getText("C_ROUTER_PROXY_SAPFE_EXIT_NOTSAVED_MESSAGE"))) {
251
+ // The user clicked on Cancel --> cancel navigation
252
+ return Promise.resolve(false);
253
+ }
254
+
255
+ this.bIsGuardCrossAllowed = true;
256
+ } // In case the navigation will cause a new view to be displayed, we force the focus
257
+ // I.e. if the keys for the hash we're navigating to is a superset of the current hash keys.
258
+
259
+
260
+ var oNewState = this._extractStateFromHash(sHash);
261
+
262
+ if (!this._bForceFocus) {
263
+ // If the focus was already forced, keep it
264
+ var aCurrentHashKeys = this._extractKeysFromHash(this.getHash());
265
+
266
+ this._bForceFocus = bForceFocus || aCurrentHashKeys.length < oNewState.keys.length && aCurrentHashKeys.every(function (key, index) {
267
+ return key === oNewState.keys[index];
268
+ });
269
+ }
270
+
271
+ var oHistoryAction = this._pushNewState(oNewState, false, bPreserveHistory, bDisablePreservationCache);
272
+
273
+ return this._rebuildBrowserHistory(oHistoryAction, false);
274
+ }
275
+ /**
276
+ * Clears browser history if entries have been added without using the RouterProxy.
277
+ * Updates the internal history accordingly.
278
+ *
279
+ * @returns {Promise} Promise that is resolved once the history is rebuilt
280
+ */
281
+ ;
282
+
283
+ _proto.restoreHistory = function restoreHistory() {
284
+ if (this._bApplyRestore) {
285
+ this._bApplyRestore = false;
286
+ var sTargetHash = this.getHash();
287
+ sTargetHash = sTargetHash.replace(/(\?|&)restoreHistory=true/, "");
288
+
289
+ var oNewState = this._extractStateFromHash(sTargetHash);
290
+
291
+ var oHistoryAction = this._pushNewState(oNewState, true, false, true);
292
+
293
+ return this._rebuildBrowserHistory(oHistoryAction, true);
294
+ } else {
295
+ return Promise.resolve();
296
+ }
297
+ }
298
+ /**
299
+ * Navigates back in the history.
300
+ *
301
+ * @returns {Promise} Promise that is resolved when the navigation is finalized
302
+ */
303
+ ;
304
+
305
+ _proto.navBack = function navBack() {
306
+ var sCurrentHash = this.getHash();
307
+ var sPreviousHash; // Look for the current hash in the managed history
308
+
309
+ for (var i = this._oManagedHistory.length - 1; i > 0; i--) {
310
+ if (this._oManagedHistory[i].hash === sCurrentHash) {
311
+ sPreviousHash = this._oManagedHistory[i - 1].hash;
312
+ break;
313
+ }
314
+ }
315
+
316
+ if (sPreviousHash) {
317
+ return this.navToHash(sPreviousHash);
318
+ } else {
319
+ // We couldn't find a previous hash in history
320
+ // This can happen when navigating from a transient hash in a create app, and
321
+ // in that case history.back would go back to the FLP
322
+ window.history.back();
323
+ return Promise.resolve();
324
+ }
325
+ }
326
+ /**
327
+ * Navigates to a route with parameters.
328
+ * @param {string} sRouteName The route name to be navigated to
329
+ * @param {object} oParameters Parameters for the navigation
330
+ * @returns {Promise} Promise that is resolved when the navigation is finalized
331
+ * @ui5-restricted
332
+ */
333
+ ;
334
+
335
+ _proto.navTo = function navTo(sRouteName, oParameters) {
336
+ var sHash = this._oRouter.getURL(sRouteName, oParameters);
337
+
338
+ return this.navToHash(sHash, false, oParameters.noPreservationCache, false, !oParameters.bIsStickyMode);
339
+ }
340
+ /**
341
+ * Exits the current app by navigating back
342
+ * to the previous app (if any) or the FLP.
343
+ *
344
+ * @returns {Promise} Promise that is resolved when we exit the app
345
+ */
346
+ ;
347
+
348
+ _proto.exitFromApp = function exitFromApp() {
349
+ return this._oShellServices.backToPreviousApp();
350
+ }
351
+ /**
352
+ * Checks whether a given hash can have an impact on the current state
353
+ * i.e. if the hash is equal, compatible or an ancestor of the current state.
354
+ *
355
+ * @param {*} sHash `true` if there is an impact
356
+ * @returns {boolean} If there is an impact
357
+ */
358
+ ;
359
+
360
+ _proto.isCurrentStateImpactedBy = function isCurrentStateImpactedBy(sHash) {
361
+ if (sHash[0] === "/") {
362
+ sHash = sHash.substring(1);
363
+ }
364
+
365
+ var oLocalGuard = createGuardFromHash(sHash);
366
+ return oLocalGuard.check(this.getHash());
367
+ }
368
+ /**
369
+ * Checks if a navigation is currently being processed.
370
+ *
371
+ * @returns {boolean} `false` if a navigation has been triggered in the RouterProxy and is not yet finalized
372
+ */
373
+ ;
374
+
375
+ _proto.isNavigationFinalized = function isNavigationFinalized() {
376
+ return !this.bIsRebuildHistoryRunning && !this._bDelayedRebuild;
377
+ }
378
+ /**
379
+ * Sets the last state as a guard.
380
+ * Each future navigation will be checked against this guard, and a confirmation dialog will
381
+ * be displayed before the navigation crosses the guard (i.e. goes to an ancestor of the guard).
382
+ */
383
+ ;
384
+
385
+ _proto.setNavigationGuard = function setNavigationGuard() {
386
+ this._oNavigationGuard = createGuardFromHash(this.getHash());
387
+ this.bIsGuardCrossAllowed = false;
388
+ }
389
+ /**
390
+ * Disables the navigation guard.
391
+ */
392
+ ;
393
+
394
+ _proto.discardNavigationGuard = function discardNavigationGuard() {
395
+ this._oNavigationGuard = null;
396
+ }
397
+ /**
398
+ * Checks for the availability of the navigation guard.
399
+ *
400
+ * @returns {boolean} `true` if navigating guard is available
401
+ */
402
+ ;
403
+
404
+ _proto.hasNavigationGuard = function hasNavigationGuard() {
405
+ return this._oNavigationGuard !== null;
406
+ }
407
+ /**
408
+ * Tests a hash against the navigation guard.
409
+ *
410
+ * @param {string} sHash The hash to be tested
411
+ * @returns {boolean} `true` if navigating to the hash doesn't cross the guard
412
+ */
413
+ ;
414
+
415
+ _proto.checkHashWithGuard = function checkHashWithGuard(sHash) {
416
+ return this._oNavigationGuard === null || this._oNavigationGuard.check(sHash);
417
+ }
418
+ /**
419
+ * Checks if the user allowed the navigation guard to be crossed.
420
+ *
421
+ * @returns {boolean} `true` if crossing the guard has been allowed by the user
422
+ */
423
+ ;
424
+
425
+ _proto.isGuardCrossAllowedByUser = function isGuardCrossAllowedByUser() {
426
+ return this.bIsGuardCrossAllowed;
427
+ }
428
+ /**
429
+ * Activates the synchronization for routeMatchedEvent.
430
+ * The next NavToHash call will create a Synchronization object that will be resolved
431
+ * by the corresponding onRouteMatched event, preventing another NavToHash to happen in parallel.
432
+ */
433
+ ;
434
+
435
+ _proto.activateRouteMatchSynchronization = function activateRouteMatchSynchronization() {
436
+ this._bActivateRouteMatchSynchro = true;
437
+ }
438
+ /**
439
+ * Resolve the routeMatch synchronization object, unlocking potential pending NavToHash calls.
440
+ */
441
+ ;
442
+
443
+ _proto.resolveRouteMatch = function resolveRouteMatch() {
444
+ if (this._oRouteMatchSynchronization) {
445
+ this._oRouteMatchSynchronization.resolve();
446
+ }
447
+ }
448
+ /**
449
+ * Makes sure no navigation can happen before a routeMatch happened.
450
+ */
451
+ ;
452
+
453
+ _proto.waitForRouteMatchBeforeNavigation = function waitForRouteMatchBeforeNavigation() {
454
+ this._oRouteMatchSynchronization = new Synchronization();
455
+ this._bActivateRouteMatchSynchro = false;
456
+ };
457
+
458
+ _proto._extractKeysFromHash = function _extractKeysFromHash(sHash) {
459
+ if (sHash === undefined) {
460
+ sHash = "";
461
+ }
462
+
463
+ var sHashNoParams = sHash.split("?")[0]; // remove params
464
+
465
+ var aTokens = sHashNoParams.split("/");
466
+ var aKeys = [];
467
+ aTokens.forEach(function (sToken) {
468
+ var regexKey = /[^\(\)]+\([^\(\)]+\)/; // abc(def)
469
+
470
+ if (regexKey.test(sToken)) {
471
+ aKeys.push(sToken.split("(")[0]);
472
+ }
473
+ });
474
+ return aKeys;
475
+ }
476
+ /**
477
+ * Builds a state from a hash.
478
+ *
479
+ * @param {string} sHash The hash to be used as entry
480
+ * @returns {object} The state
481
+ *
482
+ * @ui5-restricted
483
+ */
484
+ ;
485
+
486
+ _proto._extractStateFromHash = function _extractStateFromHash(sHash) {
487
+ if (sHash === undefined) {
488
+ sHash = "";
489
+ }
490
+
491
+ var oState = {
492
+ keys: this._extractKeysFromHash(sHash)
493
+ }; // Retrieve layout (if any)
494
+
495
+ var aLayout = sHash.match(new RegExp("\\?.*" + enumURLParams.LAYOUTPARAM + "=([^&]*)"));
496
+ oState.sLayout = aLayout && aLayout.length > 1 ? aLayout[1] : null;
497
+
498
+ if (oState.sLayout === "MidColumnFullScreen") {
499
+ oState.screenMode = 1;
500
+ } else if (oState.sLayout === "EndColumnFullScreen") {
501
+ oState.screenMode = 2;
502
+ } else {
503
+ oState.screenMode = 0;
504
+ }
505
+
506
+ oState.hash = sHash;
507
+ return oState;
508
+ }
509
+ /**
510
+ * Adds a new state into the internal history structure.
511
+ * Makes sure this new state is added after an ancestor.
512
+ * Also sets the iAppState key in the whole history.
513
+ *
514
+ * @memberof sap.fe.core.RouterProxy
515
+ * @param {object} oNewState The new state to be added
516
+ * @param {boolean} bRebuildOnly `true` if we're rebuilding the history after a shell menu navigation
517
+ * @param {boolean} bPreserveHistory If set to true, non-ancestor entries in history will be retained
518
+ * @param {boolean} bDisableHistoryPreservation Disable the mechanism to retained marked entries in cache
519
+ * @returns {object} The new state
520
+ * @ui5-restricted
521
+ * @final
522
+ */
523
+ ;
524
+
525
+ _proto._pushNewState = function _pushNewState(oNewState, bRebuildOnly, bPreserveHistory, bDisableHistoryPreservation) {
526
+ var _this4 = this;
527
+
528
+ var sCurrentHash = this.getHash();
529
+ var lastIndex = this._oManagedHistory.length - 1;
530
+ var iPopCount = bRebuildOnly ? 1 : 0; // 1. Do some cleanup in the managed history : in case the user has navigated back in the browser history, we need to remove
531
+ // the states ahead in history and make sure the top state corresponds to the current page
532
+ // We don't do that when restoring the history, as the current state has been added on top of the browser history
533
+ // and is not reflected in the managed history
534
+
535
+ if (!bRebuildOnly) {
536
+ while (lastIndex >= 0 && this._oManagedHistory[lastIndex].hash !== sCurrentHash) {
537
+ this._oManagedHistory.pop();
538
+
539
+ lastIndex--;
540
+ }
541
+
542
+ if (this._oManagedHistory.length === 0) {
543
+ // We couldn't find the current location in the history. This can happen if a browser reload
544
+ // happened, causing a reinitialization of the managed history.
545
+ // In that case, we use the current location as the new starting point in the managed history
546
+ this._oManagedHistory.push(this._extractStateFromHash(sCurrentHash));
547
+
548
+ history.replaceState(Object.assign({
549
+ feLevel: 0
550
+ }, history.state), "");
551
+ }
552
+ } // 2. Mark the top state as preserved if required
553
+
554
+
555
+ if (bPreserveHistory && !bDisableHistoryPreservation) {
556
+ this._oManagedHistory[this._oManagedHistory.length - 1].preserved = true;
557
+ } // 3. Then pop all states until we find an ancestor of the new state, or we find a state that need to be preserved
558
+
559
+
560
+ var oLastRemovedItem;
561
+
562
+ while (this._oManagedHistory.length > 0) {
563
+ var oTopState = this._oManagedHistory[this._oManagedHistory.length - 1];
564
+
565
+ if ((bDisableHistoryPreservation || !oTopState.preserved) && this._compareCacheStates(oTopState, oNewState) !== enumState.ANCESTOR) {
566
+ // The top state is not an ancestor of oNewState and is not preserved --> we can pop it
567
+ oLastRemovedItem = this._oManagedHistory.pop();
568
+ iPopCount++;
569
+ } else if (oTopState.preserved && removeAppStateInHash(oTopState.hash) === removeAppStateInHash(oNewState.hash)) {
570
+ // We try to add a state that is already in cache (due to preserved flag) but with a different iapp-state
571
+ // --> we should delete the previous entry (it will be later replaced by the new one) and stop popping
572
+ oLastRemovedItem = this._oManagedHistory.pop();
573
+ iPopCount++;
574
+ oNewState.preserved = true;
575
+ break;
576
+ } else {
577
+ break; // Ancestor or preserved state found --> we stop popping out states
578
+ }
579
+ } // 4. iAppState management
580
+
581
+
582
+ this.sIAppStateKey = findAppStateInHash(oNewState.hash);
583
+
584
+ if (this.fclEnabled && this.sIAppStateKey) {
585
+ // In case of FCL, the new app state needs to be applied to the whole history
586
+ this._oManagedHistory.forEach(function (oManagedState) {
587
+ oManagedState.hash = setAppStateInHash(oManagedState.hash, _this4.sIAppStateKey);
588
+ });
589
+ } else if (!this.fclEnabled && oLastRemovedItem) {
590
+ var sPreviousIAppStateKey = findAppStateInHash(oLastRemovedItem.hash);
591
+
592
+ var oComparisonStateResult = this._compareCacheStates(oLastRemovedItem, oNewState); // if current state doesn't contain a i-appstate and this state should replace a state containing a iAppState
593
+ // then the previous iAppState is preserved
594
+
595
+
596
+ if (!this.sIAppStateKey && sPreviousIAppStateKey && (oComparisonStateResult === enumState.EQUAL || oComparisonStateResult === enumState.COMPATIBLE)) {
597
+ oNewState.hash = setAppStateInHash(oNewState.hash, sPreviousIAppStateKey);
598
+ }
599
+ } // 5. Now we can push the state at the top of the internal history
600
+
601
+
602
+ var bHasSameHash = oLastRemovedItem && oNewState.hash === oLastRemovedItem.hash;
603
+
604
+ if (this._oManagedHistory.length === 0 || this._oManagedHistory[this._oManagedHistory.length - 1].hash !== oNewState.hash) {
605
+ this._oManagedHistory.push(oNewState);
606
+ } // 6. Determine which actions to do on the history
607
+
608
+
609
+ if (iPopCount === 0) {
610
+ // No state was popped --> append
611
+ return {
612
+ type: "append"
613
+ };
614
+ } else if (iPopCount === 1) {
615
+ // Only 1 state was popped --> replace current hash unless hash is the same (then nothing to do)
616
+ return bHasSameHash ? {
617
+ type: "none"
618
+ } : {
619
+ type: "replace"
620
+ };
621
+ } else {
622
+ // More than 1 state was popped --> go bakc in history and replace hash if necessary
623
+ return bHasSameHash ? {
624
+ type: "back",
625
+ steps: iPopCount - 1
626
+ } : {
627
+ type: "back-replace",
628
+ steps: iPopCount - 1
629
+ };
630
+ }
631
+ };
632
+
633
+ _proto._blockingNavigationFilter = function _blockingNavigationFilter() {
634
+ return this._bDisableOnHashChange ? "Custom" : "Continue";
635
+ }
636
+ /**
637
+ * Disable the routing by calling the router stop method.
638
+ *
639
+ * @function
640
+ * @memberof sap.fe.core.RouterProxy
641
+ *
642
+ * @ui5-restricted
643
+ * @final
644
+ */
645
+ ;
646
+
647
+ _proto._disableEventOnHashChange = function _disableEventOnHashChange() {
648
+ this._bDisableOnHashChange = true;
649
+
650
+ this._oRouter.stop();
651
+ }
652
+ /**
653
+ * Enable the routing by calling the router initialize method.
654
+ *
655
+ * @function
656
+ * @name sap.fe.core.RouterProxy#_enableEventOnHashChange
657
+ * @memberof sap.fe.core.RouterProxy
658
+ * @param {boolean} [bIgnoreCurrentHash] Ignore the last hash event triggered before the router has initialized
659
+ *
660
+ * @ui5-restricted
661
+ * @final
662
+ */
663
+ ;
664
+
665
+ _proto._enableEventOnHashChange = function _enableEventOnHashChange(bIgnoreCurrentHash) {
666
+ this._bDisableOnHashChange = false;
667
+
668
+ this._oRouter.initialize(bIgnoreCurrentHash);
669
+ }
670
+ /**
671
+ * Synchronizes the browser history with the internal history of the routerProxy, and triggers a navigation if needed.
672
+ *
673
+ * @memberof sap.fe.core.RouterProxy
674
+ * @param {object} oHistoryAction Specifies the navigation action to be performed
675
+ * @param {boolean} bRebuildOnly `true` if internal history is currently being rebuilt
676
+ * @returns {Promise} Promise (resolved when the navigation is finalized) that returns 'true' if a navigation took place, 'false' if the navigation didn't happen
677
+ * @ui5-restricted
678
+ * @final
679
+ */
680
+ ;
681
+
682
+ _proto._rebuildBrowserHistory = function _rebuildBrowserHistory(oHistoryAction, bRebuildOnly) {
683
+ var _this5 = this;
684
+
685
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
686
+ var that = this;
687
+ return new Promise(function (resolve) {
688
+ _this5.bIsRebuildHistoryRunning = true;
689
+ var oTargetState = _this5._oManagedHistory[_this5._oManagedHistory.length - 1],
690
+ newLevel = _this5._oManagedHistory.length - 1;
691
+
692
+ function replaceAsync() {
693
+ if (!bRebuildOnly) {
694
+ that._enableEventOnHashChange(true);
695
+ }
696
+
697
+ that._oRouter.getHashChanger().replaceHash(oTargetState.hash);
698
+
699
+ history.replaceState(Object.assign({
700
+ feLevel: newLevel
701
+ }, history.state), "");
702
+
703
+ if (bRebuildOnly) {
704
+ setTimeout(function () {
705
+ // Timeout to let 'hashchange' event be processed before by the HashChanger, so that
706
+ // onRouteMatched notification isn't raised
707
+ that._enableEventOnHashChange(true);
708
+ }, 0);
709
+ }
710
+
711
+ that.bIsRebuildHistoryRunning = false;
712
+ resolve(true); // a navigation occurred
713
+ } // Async callbacks when navigating back, in order to let all notifications and events get processed
714
+
715
+
716
+ function backReplaceAsync() {
717
+ window.removeEventListener("popstate", backReplaceAsync);
718
+ setTimeout(function () {
719
+ // Timeout to let 'hashchange' event be processed before by the HashChanger
720
+ replaceAsync();
721
+ }, 0);
722
+ }
723
+
724
+ function backAsync() {
725
+ window.removeEventListener("popstate", backAsync);
726
+ that.bIsRebuildHistoryRunning = false;
727
+ resolve(true); // a navigation occurred
728
+ }
729
+
730
+ that._bIgnoreRestore = true;
731
+
732
+ switch (oHistoryAction.type) {
733
+ case "replace":
734
+ that._oRouter.getHashChanger().replaceHash(oTargetState.hash);
735
+
736
+ history.replaceState(Object.assign({
737
+ feLevel: newLevel
738
+ }, history.state), "");
739
+ that.bIsRebuildHistoryRunning = false;
740
+ resolve(true); // a navigation occurred
741
+
742
+ break;
743
+
744
+ case "append":
745
+ that._oRouter.getHashChanger().setHash(oTargetState.hash);
746
+
747
+ history.replaceState(Object.assign({
748
+ feLevel: newLevel
749
+ }, history.state), "");
750
+ that.bIsRebuildHistoryRunning = false;
751
+ resolve(true); // a navigation occurred
752
+
753
+ break;
754
+
755
+ case "back":
756
+ window.addEventListener("popstate", backAsync);
757
+ history.go(-oHistoryAction.steps);
758
+ break;
759
+
760
+ case "back-replace":
761
+ _this5._disableEventOnHashChange();
762
+
763
+ window.addEventListener("popstate", backReplaceAsync);
764
+ history.go(-oHistoryAction.steps);
765
+ break;
766
+
767
+ default:
768
+ // No navigation
769
+ _this5.bIsRebuildHistoryRunning = false;
770
+ resolve(false);
771
+ // no navigation --> resolve to false
772
+ }
773
+ });
774
+ };
775
+
776
+ _proto.getLastHistoryEntry = function getLastHistoryEntry() {
777
+ return this._oManagedHistory[this._oManagedHistory.length - 1];
778
+ };
779
+
780
+ _proto.hashGuard = function hashGuard() {
781
+ var _this6 = this;
782
+
783
+ if (this._bCleanedRestore) {
784
+ this._bCleanedRestore = false;
785
+ return;
786
+ }
787
+
788
+ var sHash = window.location.hash;
789
+
790
+ if (sHash.indexOf("restoreHistory=true") !== -1) {
791
+ this._bApplyRestore = true;
792
+ } else if (!this.bIsRebuildHistoryRunning) {
793
+ var aHashSplit = sHash.split("&/");
794
+ var sAppHash = aHashSplit[1] ? aHashSplit[1] : "";
795
+
796
+ if (this.checkHashWithGuard(sAppHash)) {
797
+ this._bDelayedRebuild = true;
798
+
799
+ var oNewState = this._extractStateFromHash(sAppHash);
800
+
801
+ this._pushNewState(oNewState, false, false, true);
802
+
803
+ setTimeout(function () {
804
+ _this6._bDelayedRebuild = false;
805
+ }, 0);
806
+ }
807
+ }
808
+ }
809
+ /**
810
+ * Compares 2 states.
811
+ *
812
+ * @param {object} oState1
813
+ * @param {object} oState2
814
+ * @returns {number} The result of the comparison:
815
+ * - enumState.EQUAL if oState1 and oState2 are equal
816
+ * - enumState.COMPATIBLE if oState1 and oState2 are compatible
817
+ * - enumState.ANCESTOR if oState1 is an ancestor of oState2
818
+ * - enumState.DIFFERENT if the 2 states are different
819
+ */
820
+ ;
821
+
822
+ _proto._compareCacheStates = function _compareCacheStates(oState1, oState2) {
823
+ // First compare object keys
824
+ if (oState1.keys.length > oState2.keys.length) {
825
+ return enumState.DIFFERENT;
826
+ }
827
+
828
+ var equal = true;
829
+ var index;
830
+
831
+ for (index = 0; equal && index < oState1.keys.length; index++) {
832
+ if (oState1.keys[index] !== oState2.keys[index]) {
833
+ equal = false;
834
+ }
835
+ }
836
+
837
+ if (!equal) {
838
+ // Some objects keys are different
839
+ return enumState.DIFFERENT;
840
+ } // All keys from oState1 are in oState2 --> check if ancestor
841
+
842
+
843
+ if (oState1.keys.length < oState2.keys.length || oState1.screenMode < oState2.screenMode) {
844
+ return enumState.ANCESTOR;
845
+ }
846
+
847
+ if (oState1.screenMode > oState2.screenMode) {
848
+ return enumState.DIFFERENT; // Not sure this case can happen...
849
+ } // At this stage, the 2 states have the same object keys (in the same order) and same screenmode
850
+ // They can be either compatible or equal
851
+
852
+
853
+ return oState1.sLayout === oState2.sLayout ? enumState.EQUAL : enumState.COMPATIBLE;
854
+ }
855
+ /**
856
+ * Checks if back exits the present guard set.
857
+ *
858
+ * @param {string} sPresentHash The current hash. Only used for unit tests.
859
+ * @returns {boolean} `true` if back exits there is a guard exit on back
860
+ */
861
+ ;
862
+
863
+ _proto.checkIfBackIsOutOfGuard = function checkIfBackIsOutOfGuard(sPresentHash) {
864
+ var sPrevHash;
865
+ var sCurrentHash;
866
+
867
+ if (sPresentHash === undefined) {
868
+ // We use window.location.hash instead of HashChanger.getInstance().getHash() because the latter
869
+ // replaces characters in the URL (e.g. %24 replaced by $) and it causes issues when comparing
870
+ // with the URLs in the managed history
871
+ var oSplitHash = this._oShellServices.splitHash(window.location.hash);
872
+
873
+ if (oSplitHash && oSplitHash.appSpecificRoute) {
874
+ sCurrentHash = oSplitHash.appSpecificRoute;
875
+
876
+ if (sCurrentHash.indexOf("&/") === 0) {
877
+ sCurrentHash = sCurrentHash.substring(2);
878
+ }
879
+ } else {
880
+ sCurrentHash = window.location.hash.substring(1); // To remove the '#'
881
+
882
+ if (sCurrentHash[0] === "/") {
883
+ sCurrentHash = sCurrentHash.substring(1);
884
+ }
885
+ }
886
+ } else {
887
+ sCurrentHash = sPresentHash;
888
+ }
889
+
890
+ sPresentHash = URI.decode(sCurrentHash);
891
+
892
+ if (this._oNavigationGuard) {
893
+ for (var i = this._oManagedHistory.length - 1; i > 0; i--) {
894
+ if (this._oManagedHistory[i].hash === sPresentHash) {
895
+ sPrevHash = this._oManagedHistory[i - 1].hash;
896
+ break;
897
+ }
898
+ }
899
+
900
+ return !sPrevHash || !this.checkHashWithGuard(sPrevHash);
901
+ }
902
+
903
+ return false;
904
+ }
905
+ /**
906
+ * Checks if the last 2 entries in the history share the same context.
907
+ *
908
+ * @returns {boolean} `true` if they share the same context.
909
+ */
910
+ ;
911
+
912
+ _proto.checkIfBackHasSameContext = function checkIfBackHasSameContext() {
913
+ if (this._oManagedHistory.length < 2) {
914
+ return false;
915
+ }
916
+
917
+ var oCurrentState = this._oManagedHistory[this._oManagedHistory.length - 1];
918
+ var oPreviousState = this._oManagedHistory[this._oManagedHistory.length - 2];
919
+ return oCurrentState.hash.split("?")[0] === oPreviousState.hash.split("?")[0];
920
+ };
921
+
922
+ return RouterProxy;
923
+ }(BaseObject)) || _class);
924
+ return RouterProxy;
925
+ }, false);
926
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlJvdXRlclByb3h5LnRzIl0sIm5hbWVzIjpbImVudW1TdGF0ZSIsIkVRVUFMIiwiQ09NUEFUSUJMRSIsIkFOQ0VTVE9SIiwiRElGRkVSRU5UIiwiZW51bVVSTFBhcmFtcyIsIkxBWU9VVFBBUkFNIiwiSUFQUFNUQVRFUEFSQU0iLCJjcmVhdGVHdWFyZEZyb21IYXNoIiwic0d1YXJkSGFzaCIsIl9ndWFyZEhhc2giLCJyZXBsYWNlIiwiY2hlY2siLCJzSGFzaCIsImluZGV4T2YiLCJmaW5kQXBwU3RhdGVJbkhhc2giLCJhQXBwU3RhdGUiLCJtYXRjaCIsIlJlZ0V4cCIsImxlbmd0aCIsInJlbW92ZUFwcFN0YXRlSW5IYXNoIiwic2V0QXBwU3RhdGVJbkhhc2giLCJzQXBwU3RhdGVLZXkiLCJzTmV3SGFzaCIsIlJvdXRlclByb3h5IiwiVUk1Q2xhc3MiLCJiSXNSZWJ1aWxkSGlzdG9yeVJ1bm5pbmciLCJiSXNDb21wdXRpbmdUaXRsZUhpZXJhY2h5IiwiYklzR3VhcmRDcm9zc0FsbG93ZWQiLCJzSUFwcFN0YXRlS2V5IiwiX2JBY3RpdmF0ZVJvdXRlTWF0Y2hTeW5jaHJvIiwiX2JBcHBseVJlc3RvcmUiLCJfYkRlbGF5ZWRSZWJ1aWxkIiwiaW5pdCIsIm9BcHBDb21wb25lbnQiLCJpc2ZjbEVuYWJsZWQiLCJnZXRTZXJ2aWNlIiwidGhlbiIsIl9vU2hlbGxTZXJ2aWNlcyIsImdldFNoZWxsU2VydmljZXMiLCJpbml0UmF3IiwiZ2V0Um91dGVyIiwid2FpdEZvclJvdXRlTWF0Y2hCZWZvcmVOYXZpZ2F0aW9uIiwiaGlzdG9yeSIsInJlcGxhY2VTdGF0ZSIsIk9iamVjdCIsImFzc2lnbiIsImZlTGV2ZWwiLCJzdGF0ZSIsIndpbmRvdyIsImxvY2F0aW9uIiwiZmNsRW5hYmxlZCIsIl9mbkJsb2NraW5nTmF2RmlsdGVyIiwiX2Jsb2NraW5nTmF2aWdhdGlvbkZpbHRlciIsImJpbmQiLCJyZWdpc3Rlck5hdmlnYXRpb25GaWx0ZXIiLCJjYXRjaCIsIm9FcnJvciIsIkxvZyIsImVycm9yIiwiX2ZuSGFzaEd1YXJkIiwiaGFzaEd1YXJkIiwiYWRkRXZlbnRMaXN0ZW5lciIsIl9iRGlzYWJsZU9uSGFzaENoYW5nZSIsIl9iSWdub3JlUmVzdG9yZSIsIl9iQ2xlYW5lZFJlc3RvcmUiLCJfYkZvcmNlRm9jdXMiLCJkZXN0cm95IiwidW5yZWdpc3Rlck5hdmlnYXRpb25GaWx0ZXIiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwib1JvdXRlciIsIl9vUm91dGVyIiwiX29NYW5hZ2VkSGlzdG9yeSIsIl9vTmF2aWdhdGlvbkd1YXJkIiwic0N1cnJlbnRBcHBIYXNoIiwiZ2V0SGFzaCIsInB1c2giLCJfZXh0cmFjdFN0YXRlRnJvbUhhc2giLCJnZXRIYXNoQ2hhbmdlciIsImlzRm9jdXNGb3JjZWQiLCJzZXRGb2N1c0ZvcmNlZCIsImJGb3JjZWQiLCJyZW1vdmVJQXBwU3RhdGVLZXkiLCJuYXZUb0hhc2giLCJiUHJlc2VydmVIaXN0b3J5IiwiYkRpc2FibGVQcmVzZXJ2YXRpb25DYWNoZSIsImJGb3JjZUZvY3VzIiwiYlByZXNlcnZlU2hlbGxCYWNrTmF2aWdhdGlvbkhhbmRsZXIiLCJzZXRCYWNrTmF2aWdhdGlvbiIsIl9vUm91dGVNYXRjaFN5bmNocm9uaXphdGlvbiIsIndhaXRGb3IiLCJ1bmRlZmluZWQiLCJfaW50ZXJuYWxOYXZUb0hhc2giLCJjaGVja0hhc2hXaXRoR3VhcmQiLCJvUmVzb3VyY2VCdW5kbGUiLCJzYXAiLCJ1aSIsImdldENvcmUiLCJnZXRMaWJyYXJ5UmVzb3VyY2VCdW5kbGUiLCJjb25maXJtIiwiZ2V0VGV4dCIsIlByb21pc2UiLCJyZXNvbHZlIiwib05ld1N0YXRlIiwiYUN1cnJlbnRIYXNoS2V5cyIsIl9leHRyYWN0S2V5c0Zyb21IYXNoIiwia2V5cyIsImV2ZXJ5Iiwia2V5IiwiaW5kZXgiLCJvSGlzdG9yeUFjdGlvbiIsIl9wdXNoTmV3U3RhdGUiLCJfcmVidWlsZEJyb3dzZXJIaXN0b3J5IiwicmVzdG9yZUhpc3RvcnkiLCJzVGFyZ2V0SGFzaCIsIm5hdkJhY2siLCJzQ3VycmVudEhhc2giLCJzUHJldmlvdXNIYXNoIiwiaSIsImhhc2giLCJiYWNrIiwibmF2VG8iLCJzUm91dGVOYW1lIiwib1BhcmFtZXRlcnMiLCJnZXRVUkwiLCJub1ByZXNlcnZhdGlvbkNhY2hlIiwiYklzU3RpY2t5TW9kZSIsImV4aXRGcm9tQXBwIiwiYmFja1RvUHJldmlvdXNBcHAiLCJpc0N1cnJlbnRTdGF0ZUltcGFjdGVkQnkiLCJzdWJzdHJpbmciLCJvTG9jYWxHdWFyZCIsImlzTmF2aWdhdGlvbkZpbmFsaXplZCIsInNldE5hdmlnYXRpb25HdWFyZCIsImRpc2NhcmROYXZpZ2F0aW9uR3VhcmQiLCJoYXNOYXZpZ2F0aW9uR3VhcmQiLCJpc0d1YXJkQ3Jvc3NBbGxvd2VkQnlVc2VyIiwiYWN0aXZhdGVSb3V0ZU1hdGNoU3luY2hyb25pemF0aW9uIiwicmVzb2x2ZVJvdXRlTWF0Y2giLCJTeW5jaHJvbml6YXRpb24iLCJzSGFzaE5vUGFyYW1zIiwic3BsaXQiLCJhVG9rZW5zIiwiYUtleXMiLCJmb3JFYWNoIiwic1Rva2VuIiwicmVnZXhLZXkiLCJ0ZXN0Iiwib1N0YXRlIiwiYUxheW91dCIsInNMYXlvdXQiLCJzY3JlZW5Nb2RlIiwiYlJlYnVpbGRPbmx5IiwiYkRpc2FibGVIaXN0b3J5UHJlc2VydmF0aW9uIiwibGFzdEluZGV4IiwiaVBvcENvdW50IiwicG9wIiwicHJlc2VydmVkIiwib0xhc3RSZW1vdmVkSXRlbSIsIm9Ub3BTdGF0ZSIsIl9jb21wYXJlQ2FjaGVTdGF0ZXMiLCJvTWFuYWdlZFN0YXRlIiwic1ByZXZpb3VzSUFwcFN0YXRlS2V5Iiwib0NvbXBhcmlzb25TdGF0ZVJlc3VsdCIsImJIYXNTYW1lSGFzaCIsInR5cGUiLCJzdGVwcyIsIl9kaXNhYmxlRXZlbnRPbkhhc2hDaGFuZ2UiLCJzdG9wIiwiX2VuYWJsZUV2ZW50T25IYXNoQ2hhbmdlIiwiYklnbm9yZUN1cnJlbnRIYXNoIiwiaW5pdGlhbGl6ZSIsInRoYXQiLCJvVGFyZ2V0U3RhdGUiLCJuZXdMZXZlbCIsInJlcGxhY2VBc3luYyIsInJlcGxhY2VIYXNoIiwic2V0VGltZW91dCIsImJhY2tSZXBsYWNlQXN5bmMiLCJiYWNrQXN5bmMiLCJzZXRIYXNoIiwiZ28iLCJnZXRMYXN0SGlzdG9yeUVudHJ5IiwiYUhhc2hTcGxpdCIsInNBcHBIYXNoIiwib1N0YXRlMSIsIm9TdGF0ZTIiLCJlcXVhbCIsImNoZWNrSWZCYWNrSXNPdXRPZkd1YXJkIiwic1ByZXNlbnRIYXNoIiwic1ByZXZIYXNoIiwib1NwbGl0SGFzaCIsInNwbGl0SGFzaCIsImFwcFNwZWNpZmljUm91dGUiLCJVUkkiLCJkZWNvZGUiLCJjaGVja0lmQmFja0hhc1NhbWVDb250ZXh0Iiwib0N1cnJlbnRTdGF0ZSIsIm9QcmV2aW91c1N0YXRlIiwiQmFzZU9iamVjdCJdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBT0EsTUFBTUEsU0FBUyxHQUFHO0FBQ2pCQyxJQUFBQSxLQUFLLEVBQUUsQ0FEVTtBQUVqQkMsSUFBQUEsVUFBVSxFQUFFLENBRks7QUFHakJDLElBQUFBLFFBQVEsRUFBRSxDQUhPO0FBSWpCQyxJQUFBQSxTQUFTLEVBQUU7QUFKTSxHQUFsQjtBQU1BLE1BQU1DLGFBQWEsR0FBRztBQUNyQkMsSUFBQUEsV0FBVyxFQUFFLFFBRFE7QUFFckJDLElBQUFBLGNBQWMsRUFBRTtBQUZLLEdBQXRCO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUNBLFdBQVNDLG1CQUFULENBQTZCQyxVQUE3QixFQUFpRDtBQUNoRCxXQUFPO0FBQ05DLE1BQUFBLFVBQVUsRUFBRUQsVUFBVSxDQUFDRSxPQUFYLENBQW1CLFdBQW5CLEVBQWdDLEVBQWhDLENBRE47QUFDMkM7QUFDakRDLE1BQUFBLEtBQUssRUFBRSxVQUFTQyxLQUFULEVBQXFCO0FBQzNCLGVBQU9BLEtBQUssQ0FBQ0MsT0FBTixDQUFjLEtBQUtKLFVBQW5CLE1BQW1DLENBQTFDO0FBQ0E7QUFKSyxLQUFQO0FBTUE7QUFDRDtBQUNBO0FBQ0E7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TCxDQUFzQnJELE1BQXRCLEdBQStCLENBQXJELENBQXZCO0FBRUEsYUFBT2tMLGFBQWEsQ0FBQzlFLElBQWQsQ0FBbUJzQixLQUFuQixDQUF5QixHQUF6QixFQUE4QixDQUE5QixNQUFxQ3lELGNBQWMsQ0FBQy9FLElBQWYsQ0FBb0JzQixLQUFwQixDQUEwQixHQUExQixFQUErQixDQUEvQixDQUE1QztBQUNBLEs7OztJQXB2QndCMEQsVTtTQXV2QlgvSyxXIiwic291cmNlUm9vdCI6Ii4iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgTG9nIGZyb20gXCJzYXAvYmFzZS9Mb2dcIjtcbmltcG9ydCBCYXNlT2JqZWN0IGZyb20gXCJzYXAvdWkvYmFzZS9PYmplY3RcIjtcbmltcG9ydCBTeW5jaHJvbml6YXRpb24gZnJvbSBcInNhcC9mZS9jb3JlL1N5bmNocm9uaXphdGlvblwiO1xuaW1wb3J0IFVSSSBmcm9tIFwic2FwL3VpL3RoaXJkcGFydHkvVVJJXCI7XG5pbXBvcnQgeyBJU2hlbGxTZXJ2aWNlcyB9IGZyb20gXCJzYXAvZmUvY29yZS9zZXJ2aWNlcy9TaGVsbFNlcnZpY2VzRmFjdG9yeVwiO1xuaW1wb3J0IFJvdXRlciBmcm9tIFwic2FwL3VpL2NvcmUvcm91dGluZy9Sb3V0ZXJcIjtcbmltcG9ydCB7IFVJNUNsYXNzIH0gZnJvbSBcInNhcC9mZS9jb3JlL2hlbHBlcnMvQ2xhc3NTdXBwb3J0XCI7XG5pbXBvcnQgUmVzb3VyY2VCdW5kbGUgZnJvbSBcInNhcC9iYXNlL2kxOG4vUmVzb3VyY2VCdW5kbGVcIjtcblxuY29uc3QgZW51bVN0YXRlID0ge1xuXHRFUVVBTDogMCxcblx0Q09NUEFUSUJMRTogMSxcblx0QU5DRVNUT1I6IDIsXG5cdERJRkZFUkVOVDogM1xufTtcbmNvbnN0IGVudW1VUkxQYXJhbXMgPSB7XG5cdExBWU9VVFBBUkFNOiBcImxheW91dFwiLFxuXHRJQVBQU1RBVEVQQVJBTTogXCJzYXAtaWFwcC1zdGF0ZVwiXG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBIYXNoR3VhcmQgb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzR3VhcmRIYXNoIFRoZSBoYXNoIHVzZWQgZm9yIHRoZSBndWFyZFxuICogQHJldHVybnMge29iamVjdH0gVGhlIGNyZWF0ZWQgaGFzaCBndWFyZFxuICovXG5mdW5jdGlvbiBjcmVhdGVHdWFyZEZyb21IYXNoKHNHdWFyZEhhc2g6IHN0cmluZykge1xuXHRyZXR1cm4ge1xuXHRcdF9ndWFyZEhhc2g6IHNHdWFyZEhhc2gucmVwbGFjZSgvXFw/W15cXD9dKiQvLCBcIlwiKSwgLy8gUmVtb3ZlIHF1ZXJ5IHBhcnRcblx0XHRjaGVjazogZnVuY3Rpb24oc0hhc2g6IGFueSkge1xuXHRcdFx0cmV0dXJuIHNIYXNoLmluZGV4T2YodGhpcy5fZ3VhcmRIYXNoKSA9PT0gMDtcblx0XHR9XG5cdH07XG59XG4vKipcbiAqIFJldHVybnMgdGhlIGlBcHBTdGF0ZSBwYXJ0IGZyb20gYSBoYXNoIChvciBudWxsIGlmIG5vdCBmb3VuZCkuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHNIYXNoIFRoZSBoYXNoXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgaUFwcFN0YXRlIHBhcnQgb2YgdGhlIGhhc2hcbiAqL1xuZnVuY3Rpb24gZmluZEFwcFN0YXRlSW5IYXNoKHNIYXNoOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcblx0Y29uc3QgYUFwcFN0YXRlID0gc0hhc2gubWF0Y2gobmV3IFJlZ0V4cChcIlxcXFw/LipcIiArIGVudW1VUkxQYXJhbXMuSUFQUFNUQVRFUEFSQU0gKyBcIj0oW14mXSopXCIpKTtcblx0cmV0dXJuIGFBcHBTdGF0ZSAmJiBhQXBwU3RhdGUubGVuZ3RoID4gMSA/IGFBcHBTdGF0ZVsxXSA6IG51bGw7XG59XG4vKipcbiAqIFJldHVybnMgYSBoYXNoIHdpdGhvdXQgaXRzIGlBcHBTdGF0ZSBwYXJ0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzSGFzaCBUaGUgaGFzaFxuICogQHJldHVybnMge3N0cmluZ30gVGhlIGhhc2ggd2l0aG91dCB0aGUgaUFwcFN0YXRlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUFwcFN0YXRlSW5IYXNoKHNIYXNoOiBzdHJpbmcpIHtcblx0cmV0dXJuIHNIYXNoLnJlcGxhY2UobmV3IFJlZ0V4cChcIlsmP10qXCIgKyBlbnVtVVJMUGFyYW1zLklBUFBTVEFURVBBUkFNICsgXCI9W14mXSpcIiksIFwiXCIpO1xufVxuLyoqXG4gKiBBZGRzIGFuIGlBcHBTdGF0ZSBpbnNpZGUgYSBoYXNoIChvciByZXBsYWNlcyBhbiBleGlzdGluZyBvbmUpLlxuICpcbiAqIEBwYXJhbSB7Kn0gc0hhc2ggVGhlIGhhc2hcbiAqIEBwYXJhbSB7Kn0gc0FwcFN0YXRlS2V5IFRoZSBpQXBwU3RhdGUgdG8gYWRkXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgaGFzaCB3aXRoIHRoZSBhcHAgc3RhdGVcbiAqL1xuZnVuY3Rpb24gc2V0QXBwU3RhdGVJbkhhc2goc0hhc2g6IGFueSwgc0FwcFN0YXRlS2V5OiBhbnkpIHtcblx0bGV0IHNOZXdIYXNoO1xuXG5cdGlmIChzSGFzaC5pbmRleE9mKGVudW1VUkxQYXJhbXMuSUFQUFNUQVRFUEFSQU0pID49IDApIHtcblx0XHQvLyBJZiB0aGVyZSdzIGFscmVhZHkgYW4gaUFwcFN0YXRlIHBhcmFtZXRlciBpbiB0aGUgaGFzaCwgcmVwbGFjZSBpdFxuXHRcdHNOZXdIYXNoID0gc0hhc2gucmVwbGFjZShuZXcgUmVnRXhwKGVudW1VUkxQYXJhbXMuSUFQUFNUQVRFUEFSQU0gKyBcIj1bXiZdKlwiKSwgZW51bVVSTFBhcmFtcy5JQVBQU1RBVEVQQVJBTSArIFwiPVwiICsgc0FwcFN0YXRlS2V5KTtcblx0fSBlbHNlIHtcblx0XHQvLyBBZGQgdGhlIGlBcHBTdGF0ZSBwYXJhbWV0ZXIgaW4gdGhlIGhhc2hcblx0XHRpZiAoc0hhc2guaW5kZXhPZihcIj9cIikgPCAwKSB7XG5cdFx0XHRzTmV3SGFzaCA9IHNIYXNoICsgXCI/XCI7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHNOZXdIYXNoID0gc0hhc2ggKyBcIiZcIjtcblx0XHR9XG5cdFx0c05ld0hhc2ggKz0gZW51bVVSTFBhcmFtcy5JQVBQU1RBVEVQQVJBTSArIFwiPVwiICsgc0FwcFN0YXRlS2V5O1xuXHR9XG5cblx0cmV0dXJuIHNOZXdIYXNoO1xufVxuXG5AVUk1Q2xhc3MoXCJzYXAuZmUuY29yZS5Sb3V0ZXJQcm94eVwiKVxuY2xhc3MgUm91dGVyUHJveHkgZXh0ZW5kcyBCYXNlT2JqZWN0IHtcblx0YklzUmVidWlsZEhpc3RvcnlSdW5uaW5nID0gZmFsc2U7XG5cdGJJc0NvbXB1dGluZ1RpdGxlSGllcmFjaHkgPSBmYWxzZTtcblx0YklzR3VhcmRDcm9zc0FsbG93ZWQgPSBmYWxzZTtcblx0c0lBcHBTdGF0ZUtleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cdF9vU2hlbGxTZXJ2aWNlcyE6IElTaGVsbFNlcnZpY2VzO1xuXHRmY2xFbmFibGVkITogYm9vbGVhbjtcblx0X2ZuQmxvY2tpbmdOYXZGaWx0ZXIhOiBGdW5jdGlvbjtcblx0X2ZuSGFzaEd1YXJkITogRnVuY3Rpb247XG5cdF9iRGlzYWJsZU9uSGFzaENoYW5nZSE6IGJvb2xlYW47XG5cdF9iSWdub3JlUmVzdG9yZSE6IGJvb2xlYW47XG5cdF9iQ2xlYW5lZFJlc3RvcmUhOiBib29sZWFuO1xuXHRfYkZvcmNlRm9jdXMhOiBib29sZWFuO1xuXHRfb1JvdXRlciE6IFJvdXRlcjtcblx0X29NYW5hZ2VkSGlzdG9yeSE6IGFueVtdO1xuXHRfb05hdmlnYXRpb25HdWFyZDogYW55O1xuXHRvUmVzb3VyY2VCdW5kbGU/OiBSZXNvdXJjZUJ1bmRsZTtcblx0X29Sb3V0ZU1hdGNoU3luY2hyb25pemF0aW9uPzogU3luY2hyb25pemF0aW9uO1xuXHRfYkFjdGl2YXRlUm91dGVNYXRjaFN5bmNocm86IGJvb2xlYW4gPSBmYWxzZTtcblx0X2JBcHBseVJlc3RvcmU6IGJvb2xlYW4gPSBmYWxzZTtcblx0X2JEZWxheWVkUmVidWlsZDogYm9vbGVhbiA9IGZhbHNlO1xuXG5cdGluaXQob0FwcENvbXBvbmVudDogYW55LCBpc2ZjbEVuYWJsZWQ6IGJvb2xlYW4pIHtcblx0XHQvLyBTYXZlIHRoZSBuYW1lIG9mIHRoZSBhcHAgKGluY2x1ZGluZyBzdGFydHVwIHBhcmFtZXRlcnMpIGZvciByZWJ1aWxkaW5nIGZ1bGwgaGFzaGVzIGxhdGVyXG5cdFx0b0FwcENvbXBvbmVudFxuXHRcdFx0LmdldFNlcnZpY2UoXCJzaGVsbFNlcnZpY2VzXCIpXG5cdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdHRoaXMuX29TaGVsbFNlcnZpY2VzID0gb0FwcENvbXBvbmVudC5nZXRTaGVsbFNlcnZpY2VzKCk7XG5cblx0XHRcdFx0dGhpcy5pbml0UmF3KG9BcHBDb21wb25lbnQuZ2V0Um91dGVyKCkpO1xuXHRcdFx0XHQvLyBXZSB3YW50IHRvIHdhaXQgdW50aWwgdGhlIGluaXRpYWwgcm91dGVNYXRjaGVkIGlzIGRvbmUgYmVmb3JlIGRvaW5nIGFueSBuYXZpZ2F0aW9uXG5cdFx0XHRcdHRoaXMud2FpdEZvclJvdXRlTWF0Y2hCZWZvcmVOYXZpZ2F0aW9uKCk7XG5cblx0XHRcdFx0Ly8gU2V0IGZlTGV2ZWw9MCBmb3IgdGhlIGZpcnN0IEFwcGxpY2F0aW9uIHBhZ2UgaW4gdGhlIGhpc3Rvcnlcblx0XHRcdFx0aGlzdG9yeS5yZXBsYWNlU3RhdGUoXG5cdFx0XHRcdFx0T2JqZWN0LmFzc2lnbihcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0ZmVMZXZlbDogMFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdGhpc3Rvcnkuc3RhdGVcblx0XHRcdFx0XHQpLFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uIGFzIGFueVxuXHRcdFx0XHQpO1xuXHRcdFx0XHR0aGlzLmZjbEVuYWJsZWQgPSBpc2ZjbEVuYWJsZWQ7XG5cblx0XHRcdFx0dGhpcy5fZm5CbG9ja2luZ05hdkZpbHRlciA9IHRoaXMuX2Jsb2NraW5nTmF2aWdhdGlvbkZpbHRlci5iaW5kKHRoaXMpO1xuXHRcdFx0XHR0aGlzLl9vU2hlbGxTZXJ2aWNlcy5yZWdpc3Rlck5hdmlnYXRpb25GaWx0ZXIodGhpcy5fZm5CbG9ja2luZ05hdkZpbHRlcik7XG5cdFx0XHR9KVxuXHRcdFx0LmNhdGNoKGZ1bmN0aW9uKG9FcnJvcjogYW55KSB7XG5cdFx0XHRcdExvZy5lcnJvcihcIkNhbm5vdCByZXRyaWV2ZSB0aGUgc2hlbGwgc2VydmljZXNcIiwgb0Vycm9yKTtcblx0XHRcdH0pO1xuXHRcdHRoaXMuX2ZuSGFzaEd1YXJkID0gdGhpcy5oYXNoR3VhcmQuYmluZCh0aGlzKTtcblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcInBvcHN0YXRlXCIsIHRoaXMuX2ZuSGFzaEd1YXJkIGFzIGFueSk7XG5cdFx0dGhpcy5fYkRpc2FibGVPbkhhc2hDaGFuZ2UgPSBmYWxzZTtcblx0XHR0aGlzLl9iSWdub3JlUmVzdG9yZSA9IGZhbHNlO1xuXHRcdHRoaXMuX2JDbGVhbmVkUmVzdG9yZSA9IGZhbHNlO1xuXHRcdHRoaXMuX2JGb3JjZUZvY3VzID0gdHJ1ZTsgLy8gVHJpZ2dlciB0aGUgZm9jdXMgbWVjaGFuaXNtIGZvciB0aGUgZmlyc3QgdmlldyBkaXNwbGF5ZWQgYnkgdGhlIGFwcFxuXHR9XG5cblx0ZGVzdHJveSgpIHtcblx0XHRpZiAodGhpcy5fb1NoZWxsU2VydmljZXMpIHtcblx0XHRcdHRoaXMuX29TaGVsbFNlcnZpY2VzLnVucmVnaXN0ZXJOYXZpZ2F0aW9uRmlsdGVyKHRoaXMuX2ZuQmxvY2tpbmdOYXZGaWx0ZXIpO1xuXHRcdH1cblx0XHR3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInBvcHN0YXRlXCIsIHRoaXMuX2ZuSGFzaEd1YXJkIGFzIGFueSk7XG5cdH1cblxuXHQvKipcblx0ICogUmF3IGluaXRpYWxpemF0aW9uIChmb3IgdW5pdCB0ZXN0cykuXG5cdCAqXG5cdCAqIEBwYXJhbSB7c2FwLnVpLmNvcmUucm91dGluZy5Sb3V0ZXJ9IG9Sb3V0ZXIgVGhlIHJvdXRlciB1c2VkIGJ5IHRoaXMgcHJveHlcblx0ICovXG5cdGluaXRSYXcob1JvdXRlcjogUm91dGVyKSB7XG5cdFx0dGhpcy5fb1JvdXRlciA9IG9Sb3V0ZXI7XG5cdFx0dGhpcy5fb01hbmFnZWRIaXN0b3J5ID0gW107XG5cdFx0dGhpcy5fb05hdmlnYXRpb25HdWFyZCA9IG51bGw7XG5cblx0XHRjb25zdCBzQ3VycmVudEFwcEhhc2ggPSB0aGlzLmdldEhhc2goKTtcblx0XHR0aGlzLl9vTWFuYWdlZEhpc3RvcnkucHVzaCh0aGlzLl9leHRyYWN0U3RhdGVGcm9tSGFzaChzQ3VycmVudEFwcEhhc2gpKTtcblxuXHRcdC8vIFNldCB0aGUgaUFwcFN0YXRlIGlmIHRoZSBpbml0aWFsIGhhc2ggY29udGFpbnMgb25lXG5cdFx0dGhpcy5zSUFwcFN0YXRlS2V5ID0gZmluZEFwcFN0YXRlSW5IYXNoKHNDdXJyZW50QXBwSGFzaCk7XG5cdH1cblxuXHRnZXRIYXNoKCkge1xuXHRcdHJldHVybiB0aGlzLl9vUm91dGVyLmdldEhhc2hDaGFuZ2VyKCkuZ2V0SGFzaCgpO1xuXHR9XG5cblx0aXNGb2N1c0ZvcmNlZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5fYkZvcmNlRm9jdXM7XG5cdH1cblxuXHRzZXRGb2N1c0ZvcmNlZChiRm9yY2VkOiBib29sZWFuKSB7XG5cdFx0dGhpcy5fYkZvcmNlRm9jdXMgPSBiRm9yY2VkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlc2V0cyB0aGUgaW50ZXJuYWwgdmFyaWFibGUgc0lBcHBTdGF0ZUtleS5cblx0ICpcblx0ICogQGZ1bmN0aW9uXG5cdCAqIEBuYW1lIHNhcC5mZS5jb3JlLlJvdXRlclByb3h5I3JlbW92ZUlBcHBTdGF0ZUtleVxuXHQgKlxuXHQgKiBAdWk1LXJlc3RyaWN0ZWRcblx0ICovXG5cdHJlbW92ZUlBcHBTdGF0ZUtleSgpIHtcblx0XHR0aGlzLnNJQXBwU3RhdGVLZXkgPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIE5hdmlnYXRlcyB0byBhIHNwZWNpZmljIGhhc2guXG5cdCAqXG5cdCAqIEBmdW5jdGlvblxuXHQgKiBAbmFtZSBzYXAuZmUuY29yZS5Sb3V0ZXJQcm94eSNuYXZUb0hhc2hcblx0ICogQG1lbWJlcm9mIHNhcC5mZS5jb3JlLlJvdXRlclByb3h5XG5cdCAqIEBzdGF0aWNcblx0ICogQHBhcmFtIHtzdHJpbmd9IHNIYXNoIEhhc2ggdG8gYmUgbmF2aWdhdGVkIHRvXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gYlByZXNlcnZlSGlzdG9yeSBJZiBzZXQgdG8gdHJ1ZSwgbm9uLWFuY2VzdG9yIGVudHJpZXMgaW4gaGlzdG9yeSB3aWxsIGJlIHJldGFpbmVkXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gYkRpc2FibGVQcmVzZXJ2YXRpb25DYWNoZSBJZiBzZXQgdG8gdHJ1ZSwgY2FjaGUgcHJlc2VydmF0aW9uIG1lY2hhbmlzbSBpcyBkaXNhYmxlZCBmb3IgdGhlIGN1cnJlbnQgbmF2aWdhdGlvblxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGJGb3JjZUZvY3VzIElmIHNldCB0byB0cnVlLCB0aGUgbG9naWMgdG8gc2V0IHRoZSBmb2N1cyBvbmNlIHRoZSBuYXZpZ2F0aW9uIGlzIGZpbmFsaXplZCB3aWxsIGJlIHRyaWdnZXJlZCAob25QYWdlUmVhZHkpXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gYlByZXNlcnZlU2hlbGxCYWNrTmF2aWdhdGlvbkhhbmRsZXIgSWYgbm90IHNldCB0byBmYWxzZSwgdGhlIGJhY2sgbmF2aWdhdGlvbiBpcyBzZXQgdG8gdW5kZWZpbmVkXG5cdCAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIChyZXNvbHZlZCB3aGVuIHRoZSBuYXZpZ2F0aW9uIGlzIGZpbmFsaXplZCkgdGhhdCByZXR1cm5zICd0cnVlJyBpZiBhIG5hdmlnYXRpb24gdG9vayBwbGFjZSwgJ2ZhbHNlJyBpZiB0aGUgbmF2aWdhdGlvbiBkaWRuJ3QgaGFwcGVuXG5cdCAqIEB1aTUtcmVzdHJpY3RlZFxuXHQgKi9cblx0bmF2VG9IYXNoKFxuXHRcdHNIYXNoOiBzdHJpbmcgfCB1bmRlZmluZWQsXG5cdFx0YlByZXNlcnZlSGlzdG9yeT86IGJvb2xlYW4sXG5cdFx0YkRpc2FibGVQcmVzZXJ2YXRpb25DYWNoZT86IGJvb2xlYW4sXG5cdFx0YkZvcmNlRm9jdXM/OiBib29sZWFuLFxuXHRcdGJQcmVzZXJ2ZVNoZWxsQmFja05hdmlnYXRpb25IYW5kbGVyPzogYm9vbGVhblxuXHQpIHtcblx0XHRpZiAoYlByZXNlcnZlU2hlbGxCYWNrTmF2aWdhdGlvbkhhbmRsZXIgIT09IGZhbHNlKSB7XG5cdFx0XHR0aGlzLl9vU2hlbGxTZXJ2aWNlcy5zZXRCYWNrTmF2aWdhdGlvbigpO1xuXHRcdH1cblx0XHRpZiAodGhpcy5fb1JvdXRlTWF0Y2hTeW5jaHJvbml6YXRpb24pIHtcblx0XHRcdHJldHVybiB0aGlzLl9vUm91dGVNYXRjaFN5bmNocm9uaXphdGlvbi53YWl0Rm9yKCkudGhlbigoKSA9PiB7XG5cdFx0XHRcdHRoaXMuX29Sb3V0ZU1hdGNoU3luY2hyb25pemF0aW9uID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5faW50ZXJuYWxOYXZUb0hhc2goc0hhc2gsIGJQcmVzZXJ2ZUhpc3RvcnksIGJEaXNhYmxlUHJlc2VydmF0aW9uQ2FjaGUsIGJGb3JjZUZvY3VzKTtcblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAodGhpcy5fYkFjdGl2YXRlUm91dGVNYXRjaFN5bmNocm8pIHtcblx0XHRcdFx0dGhpcy53YWl0Rm9yUm91dGVNYXRjaEJlZm9yZU5hdmlnYXRpb24oKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB0aGlzLl9pbnRlcm5hbE5hdlRvSGFzaChzSGFzaCwgYlByZXNlcnZlSGlzdG9yeSwgYkRpc2FibGVQcmVzZXJ2YXRpb25DYWNoZSwgYkZvcmNlRm9jdXMpO1xuXHRcdH1cblx0fVxuXG5cdF9pbnRlcm5hbE5hdlRvSGFzaChzSGFzaDogYW55LCBiUHJlc2VydmVIaXN0b3J5OiBhbnksIGJEaXNhYmxlUHJlc2VydmF0aW9uQ2FjaGU6IGFueSwgYkZvcmNlRm9jdXM/OiBib29sZWFuKSB7XG5cdFx0Ly8gQWRkIHRoZSBhcHAgc3RhdGUgaW4gdGhlIGhhc2ggaWYgbmVlZGVkXG5cdFx0aWYgKHRoaXMuZmNsRW5hYmxlZCAmJiB0aGlzLnNJQXBwU3RhdGVLZXkgJiYgIWZpbmRBcHBTdGF0ZUluSGFzaChzSGFzaCkpIHtcblx0XHRcdHNIYXNoID0gc2V0QXBwU3RhdGVJbkhhc2goc0hhc2gsIHRoaXMuc0lBcHBTdGF0ZUtleSk7XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLmNoZWNrSGFzaFdpdGhHdWFyZChzSGFzaCkpIHtcblx0XHRcdGlmICghdGhpcy5vUmVzb3VyY2VCdW5kbGUpIHtcblx0XHRcdFx0dGhpcy5vUmVzb3VyY2VCdW5kbGUgPSBzYXAudWkuZ2V0Q29yZSgpLmdldExpYnJhcnlSZXNvdXJjZUJ1bmRsZShcInNhcC5mZS5jb3JlXCIpIGFzIFJlc291cmNlQnVuZGxlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBXZSBoYXZlIHRvIHVzZSBhIGNvbmZpcm0gaGVyZSBmb3IgVUkgY29uc2lzdGVuY3kgcmVhc29ucywgYXMgd2l0aCBzb21lIHNjZW5hcmlvc1xuXHRcdFx0Ly8gaW4gdGhlIEVkaXRGbG93IHdlIHJlbHkgb24gYSBVSTUgbWVjaGFuaXNtIHRoYXQgZGlzcGxheXMgYSBjb25maXJtIGRpYWxvZy5cblx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hbGVydFxuXHRcdFx0aWYgKCFjb25maXJtKHRoaXMub1Jlc291cmNlQnVuZGxlLmdldFRleHQoXCJDX1JPVVRFUl9QUk9YWV9TQVBGRV9FWElUX05PVFNBVkVEX01FU1NBR0VcIikpKSB7XG5cdFx0XHRcdC8vIFRoZSB1c2VyIGNsaWNrZWQgb24gQ2FuY2VsIC0tPiBjYW5jZWwgbmF2aWdhdGlvblxuXHRcdFx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcblx0XHRcdH1cblx0XHRcdHRoaXMuYklzR3VhcmRDcm9zc0FsbG93ZWQgPSB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIEluIGNhc2UgdGhlIG5hdmlnYXRpb24gd2lsbCBjYXVzZSBhIG5ldyB2aWV3IHRvIGJlIGRpc3BsYXllZCwgd2UgZm9yY2UgdGhlIGZvY3VzXG5cdFx0Ly8gSS5lLiBpZiB0aGUga2V5cyBmb3IgdGhlIGhhc2ggd2UncmUgbmF2aWdhdGluZyB0byBpcyBhIHN1cGVyc2V0IG9mIHRoZSBjdXJyZW50IGhhc2gga2V5cy5cblx0XHRjb25zdCBvTmV3U3RhdGUgPSB0aGlzLl9leHRyYWN0U3RhdGVGcm9tSGFzaChzSGFzaCk7XG5cdFx0aWYgKCF0aGlzLl9iRm9yY2VGb2N1cykge1xuXHRcdFx0Ly8gSWYgdGhlIGZvY3VzIHdhcyBhbHJlYWR5IGZvcmNlZCwga2VlcCBpdFxuXHRcdFx0Y29uc3QgYUN1cnJlbnRIYXNoS2V5cyA9IHRoaXMuX2V4dHJhY3RLZXlzRnJvbUhhc2godGhpcy5nZXRIYXNoKCkpO1xuXHRcdFx0dGhpcy5fYkZvcmNlRm9jdXMgPVxuXHRcdFx0XHRiRm9yY2VGb2N1cyB8fFxuXHRcdFx0XHQoYUN1cnJlbnRIYXNoS2V5cy5sZW5ndGggPCBvTmV3U3RhdGUua2V5cy5sZW5ndGggJiZcblx0XHRcdFx0XHRhQ3VycmVudEhhc2hLZXlzLmV2ZXJ5KGZ1bmN0aW9uKGtleTogYW55LCBpbmRleDogYW55KSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4ga2V5ID09PSBvTmV3U3RhdGUua2V5c1tpbmRleF07XG5cdFx0XHRcdFx0fSkpO1xuXHRcdH1cblxuXHRcdGNvbnN0IG9IaXN0b3J5QWN0aW9uID0gdGhpcy5fcHVzaE5ld1N0YXRlKG9OZXdTdGF0ZSwgZmFsc2UsIGJQcmVzZXJ2ZUhpc3RvcnksIGJEaXNhYmxlUHJlc2VydmF0aW9uQ2FjaGUpO1xuXG5cdFx0cmV0dXJuIHRoaXMuX3JlYnVpbGRCcm93c2VySGlzdG9yeShvSGlzdG9yeUFjdGlvbiwgZmFsc2UpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsZWFycyBicm93c2VyIGhpc3RvcnkgaWYgZW50cmllcyBoYXZlIGJlZW4gYWRkZWQgd2l0aG91dCB1c2luZyB0aGUgUm91dGVyUHJveHkuXG5cdCAqIFVwZGF0ZXMgdGhlIGludGVybmFsIGhpc3RvcnkgYWNjb3JkaW5nbHkuXG5cdCAqXG5cdCAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIHRoYXQgaXMgcmVzb2x2ZWQgb25jZSB0aGUgaGlzdG9yeSBpcyByZWJ1aWx0XG5cdCAqL1xuXHRyZXN0b3JlSGlzdG9yeSgpIHtcblx0XHRpZiAodGhpcy5fYkFwcGx5UmVzdG9yZSkge1xuXHRcdFx0dGhpcy5fYkFwcGx5UmVzdG9yZSA9IGZhbHNlO1xuXHRcdFx0bGV0IHNUYXJnZXRIYXNoID0gdGhpcy5nZXRIYXNoKCk7XG5cdFx0XHRzVGFyZ2V0SGFzaCA9IHNUYXJnZXRIYXNoLnJlcGxhY2UoLyhcXD98JilyZXN0b3JlSGlzdG9yeT10cnVlLywgXCJcIik7XG5cdFx0XHRjb25zdCBvTmV3U3RhdGUgPSB0aGlzLl9leHRyYWN0U3RhdGVGcm9tSGFzaChzVGFyZ2V0SGFzaCk7XG5cblx0XHRcdGNvbnN0IG9IaXN0b3J5QWN0aW9uID0gdGhpcy5fcHVzaE5ld1N0YXRlKG9OZXdTdGF0ZSwgdHJ1ZSwgZmFsc2UsIHRydWUpO1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5fcmVidWlsZEJyb3dzZXJIaXN0b3J5KG9IaXN0b3J5QWN0aW9uLCB0cnVlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBOYXZpZ2F0ZXMgYmFjayBpbiB0aGUgaGlzdG9yeS5cblx0ICpcblx0ICogQHJldHVybnMge1Byb21pc2V9IFByb21pc2UgdGhhdCBpcyByZXNvbHZlZCB3aGVuIHRoZSBuYXZpZ2F0aW9uIGlzIGZpbmFsaXplZFxuXHQgKi9cblx0bmF2QmFjaygpIHtcblx0XHRjb25zdCBzQ3VycmVudEhhc2ggPSB0aGlzLmdldEhhc2goKTtcblx0XHRsZXQgc1ByZXZpb3VzSGFzaDtcblxuXHRcdC8vIExvb2sgZm9yIHRoZSBjdXJyZW50IGhhc2ggaW4gdGhlIG1hbmFnZWQgaGlzdG9yeVxuXHRcdGZvciAobGV0IGkgPSB0aGlzLl9vTWFuYWdlZEhpc3RvcnkubGVuZ3RoIC0gMTsgaSA+IDA7IGktLSkge1xuXHRcdFx0aWYgKHRoaXMuX29NYW5hZ2VkSGlzdG9yeVtpXS5oYXNoID09PSBzQ3VycmVudEhhc2gpIHtcblx0XHRcdFx0c1ByZXZpb3VzSGFzaCA9IHRoaXMuX29NYW5hZ2VkSGlzdG9yeVtpIC0gMV0uaGFzaDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKHNQcmV2aW91c0hhc2gpIHtcblx0XHRcdHJldHVybiB0aGlzLm5hdlRvSGFzaChzUHJldmlvdXNIYXNoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gV2UgY291bGRuJ3QgZmluZCBhIHByZXZpb3VzIGhhc2ggaW4gaGlzdG9yeVxuXHRcdFx0Ly8gVGhpcyBjYW4gaGFwcGVuIHdoZW4gbmF2aWdhdGluZyBmcm9tIGEgdHJhbnNpZW50IGhhc2ggaW4gYSBjcmVhdGUgYXBwLCBhbmRcblx0XHRcdC8vIGluIHRoYXQgY2FzZSBoaXN0b3J5LmJhY2sgd291bGQgZ28gYmFjayB0byB0aGUgRkxQXG5cdFx0XHR3aW5kb3cuaGlzdG9yeS5iYWNrKCk7XG5cdFx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE5hdmlnYXRlcyB0byBhIHJvdXRlIHdpdGggcGFyYW1ldGVycy5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHNSb3V0ZU5hbWUgVGhlIHJvdXRlIG5hbWUgdG8gYmUgbmF2aWdhdGVkIHRvXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBvUGFyYW1ldGVycyBQYXJhbWV0ZXJzIGZvciB0aGUgbmF2aWdhdGlvblxuXHQgKiBAcmV0dXJucyB7UHJvbWlzZX0gUHJvbWlzZSB0aGF0IGlzIHJlc29sdmVkIHdoZW4gdGhlIG5hdmlnYXRpb24gaXMgZmluYWxpemVkXG5cdCAqIEB1aTUtcmVzdHJpY3RlZFxuXHQgKi9cblx0bmF2VG8oc1JvdXRlTmFtZTogc3RyaW5nLCBvUGFyYW1ldGVyczogYW55KSB7XG5cdFx0Y29uc3Qgc0hhc2ggPSB0aGlzLl9vUm91dGVyLmdldFVSTChzUm91dGVOYW1lLCBvUGFyYW1ldGVycyk7XG5cdFx0cmV0dXJuIHRoaXMubmF2VG9IYXNoKHNIYXNoLCBmYWxzZSwgb1BhcmFtZXRlcnMubm9QcmVzZXJ2YXRpb25DYWNoZSwgZmFsc2UsICFvUGFyYW1ldGVycy5iSXNTdGlja3lNb2RlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeGl0cyB0aGUgY3VycmVudCBhcHAgYnkgbmF2aWdhdGluZyBiYWNrXG5cdCAqIHRvIHRoZSBwcmV2aW91cyBhcHAgKGlmIGFueSkgb3IgdGhlIEZMUC5cblx0ICpcblx0ICogQHJldHVybnMge1Byb21pc2V9IFByb21pc2UgdGhhdCBpcyByZXNvbHZlZCB3aGVuIHdlIGV4aXQgdGhlIGFwcFxuXHQgKi9cblx0ZXhpdEZyb21BcHAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX29TaGVsbFNlcnZpY2VzLmJhY2tUb1ByZXZpb3VzQXBwKCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIHdoZXRoZXIgYSBnaXZlbiBoYXNoIGNhbiBoYXZlIGFuIGltcGFjdCBvbiB0aGUgY3VycmVudCBzdGF0ZVxuXHQgKiBpLmUuIGlmIHRoZSBoYXNoIGlzIGVxdWFsLCBjb21wYXRpYmxlIG9yIGFuIGFuY2VzdG9yIG9mIHRoZSBjdXJyZW50IHN0YXRlLlxuXHQgKlxuXHQgKiBAcGFyYW0geyp9IHNIYXNoIGB0cnVlYCBpZiB0aGVyZSBpcyBhbiBpbXBhY3Rcblx0ICogQHJldHVybnMge2Jvb2xlYW59IElmIHRoZXJlIGlzIGFuIGltcGFjdFxuXHQgKi9cblx0aXNDdXJyZW50U3RhdGVJbXBhY3RlZEJ5KHNIYXNoOiBhbnkpIHtcblx0XHRpZiAoc0hhc2hbMF0gPT09IFwiL1wiKSB7XG5cdFx0XHRzSGFzaCA9IHNIYXNoLnN1YnN0cmluZygxKTtcblx0XHR9XG5cdFx0Y29uc3Qgb0xvY2FsR3VhcmQgPSBjcmVhdGVHdWFyZEZyb21IYXNoKHNIYXNoKTtcblx0XHRyZXR1cm4gb0xvY2FsR3VhcmQuY2hlY2sodGhpcy5nZXRIYXNoKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBhIG5hdmlnYXRpb24gaXMgY3VycmVudGx5IGJlaW5nIHByb2Nlc3NlZC5cblx0ICpcblx0ICogQHJldHVybnMge2Jvb2xlYW59IGBmYWxzZWAgaWYgYSBuYXZpZ2F0aW9uIGhhcyBiZWVuIHRyaWdnZXJlZCBpbiB0aGUgUm91dGVyUHJveHkgYW5kIGlzIG5vdCB5ZXQgZmluYWxpemVkXG5cdCAqL1xuXHRpc05hdmlnYXRpb25GaW5hbGl6ZWQoKSB7XG5cdFx0cmV0dXJuICF0aGlzLmJJc1JlYnVpbGRIaXN0b3J5UnVubmluZyAmJiAhdGhpcy5fYkRlbGF5ZWRSZWJ1aWxkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGxhc3Qgc3RhdGUgYXMgYSBndWFyZC5cblx0ICogRWFjaCBmdXR1cmUgbmF2aWdhdGlvbiB3aWxsIGJlIGNoZWNrZWQgYWdhaW5zdCB0aGlzIGd1YXJkLCBhbmQgYSBjb25maXJtYXRpb24gZGlhbG9nIHdpbGxcblx0ICogYmUgZGlzcGxheWVkIGJlZm9yZSB0aGUgbmF2aWdhdGlvbiBjcm9zc2VzIHRoZSBndWFyZCAoaS5lLiBnb2VzIHRvIGFuIGFuY2VzdG9yIG9mIHRoZSBndWFyZCkuXG5cdCAqL1xuXHRzZXROYXZpZ2F0aW9uR3VhcmQoKSB7XG5cdFx0dGhpcy5fb05hdmlnYXRpb25HdWFyZCA9IGNyZWF0ZUd1YXJkRnJvbUhhc2godGhpcy5nZXRIYXNoKCkpO1xuXHRcdHRoaXMuYklzR3VhcmRDcm9zc0FsbG93ZWQgPSBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNhYmxlcyB0aGUgbmF2aWdhdGlvbiBndWFyZC5cblx0ICovXG5cdGRpc2NhcmROYXZpZ2F0aW9uR3VhcmQoKSB7XG5cdFx0dGhpcy5fb05hdmlnYXRpb25HdWFyZCA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGZvciB0aGUgYXZhaWxhYmlsaXR5IG9mIHRoZSBuYXZpZ2F0aW9uIGd1YXJkLlxuXHQgKlxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIG5hdmlnYXRpbmcgZ3VhcmQgaXMgYXZhaWxhYmxlXG5cdCAqL1xuXHRoYXNOYXZpZ2F0aW9uR3VhcmQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX29OYXZpZ2F0aW9uR3VhcmQgIT09IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogVGVzdHMgYSBoYXNoIGFnYWluc3QgdGhlIG5hdmlnYXRpb24gZ3VhcmQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzSGFzaCBUaGUgaGFzaCB0byBiZSB0ZXN0ZWRcblx0ICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiBuYXZpZ2F0aW5nIHRvIHRoZSBoYXNoIGRvZXNuJ3QgY3Jvc3MgdGhlIGd1YXJkXG5cdCAqL1xuXHRjaGVja0hhc2hXaXRoR3VhcmQoc0hhc2g6IHN0cmluZykge1xuXHRcdHJldHVybiB0aGlzLl9vTmF2aWdhdGlvbkd1YXJkID09PSBudWxsIHx8IHRoaXMuX29OYXZpZ2F0aW9uR3VhcmQuY2hlY2soc0hhc2gpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgdXNlciBhbGxvd2VkIHRoZSBuYXZpZ2F0aW9uIGd1YXJkIHRvIGJlIGNyb3NzZWQuXG5cdCAqXG5cdCAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgY3Jvc3NpbmcgdGhlIGd1YXJkIGhhcyBiZWVuIGFsbG93ZWQgYnkgdGhlIHVzZXJcblx0ICovXG5cdGlzR3VhcmRDcm9zc0FsbG93ZWRCeVVzZXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMuYklzR3VhcmRDcm9zc0FsbG93ZWQ7XG5cdH1cblxuXHQvKipcblx0ICogQWN0aXZhdGVzIHRoZSBzeW5jaHJvbml6YXRpb24gZm9yIHJvdXRlTWF0Y2hlZEV2ZW50LlxuXHQgKiBUaGUgbmV4dCBOYXZUb0hhc2ggY2FsbCB3aWxsIGNyZWF0ZSBhIFN5bmNocm9uaXphdGlvbiBvYmplY3QgdGhhdCB3aWxsIGJlIHJlc29sdmVkXG5cdCAqIGJ5IHRoZSBjb3JyZXNwb25kaW5nIG9uUm91dGVNYXRjaGVkIGV2ZW50LCBwcmV2ZW50aW5nIGFub3RoZXIgTmF2VG9IYXNoIHRvIGhhcHBlbiBpbiBwYXJhbGxlbC5cblx0ICovXG5cdGFjdGl2YXRlUm91dGVNYXRjaFN5bmNocm9uaXphdGlvbigpIHtcblx0XHR0aGlzLl9iQWN0aXZhdGVSb3V0ZU1hdGNoU3luY2hybyA9IHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogUmVzb2x2ZSB0aGUgcm91dGVNYXRjaCBzeW5jaHJvbml6YXRpb24gb2JqZWN0LCB1bmxvY2tpbmcgcG90ZW50aWFsIHBlbmRpbmcgTmF2VG9IYXNoIGNhbGxzLlxuXHQgKi9cblx0cmVzb2x2ZVJvdXRlTWF0Y2goKSB7XG5cdFx0aWYgKHRoaXMuX29Sb3V0ZU1hdGNoU3luY2hyb25pemF0aW9uKSB7XG5cdFx0XHR0aGlzLl9vUm91dGVNYXRjaFN5bmNocm9uaXphdGlvbi5yZXNvbHZlKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHN1cmUgbm8gbmF2aWdhdGlvbiBjYW4gaGFwcGVuIGJlZm9yZSBhIHJvdXRlTWF0Y2ggaGFwcGVuZWQuXG5cdCAqL1xuXHR3YWl0Rm9yUm91dGVNYXRjaEJlZm9yZU5hdmlnYXRpb24oKSB7XG5cdFx0dGhpcy5fb1JvdXRlTWF0Y2hTeW5jaHJvbml6YXRpb24gPSBuZXcgU3luY2hyb25pemF0aW9uKCk7XG5cdFx0dGhpcy5fYkFjdGl2YXRlUm91dGVNYXRjaFN5bmNocm8gPSBmYWxzZTtcblx0fVxuXG5cdF9leHRyYWN0S2V5c0Zyb21IYXNoKHNIYXNoOiBhbnkpIHtcblx0XHRpZiAoc0hhc2ggPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0c0hhc2ggPSBcIlwiO1xuXHRcdH1cblx0XHRjb25zdCBzSGFzaE5vUGFyYW1zID0gc0hhc2guc3BsaXQoXCI/XCIpWzBdOyAvLyByZW1vdmUgcGFyYW1zXG5cdFx0Y29uc3QgYVRva2VucyA9IHNIYXNoTm9QYXJhbXMuc3BsaXQoXCIvXCIpO1xuXHRcdGNvbnN0IGFLZXlzOiBhbnlbXSA9IFtdO1xuXG5cdFx0YVRva2Vucy5mb3JFYWNoKGZ1bmN0aW9uKHNUb2tlbjogYW55KSB7XG5cdFx0XHRjb25zdCByZWdleEtleSA9IC9bXlxcKFxcKV0rXFwoW15cXChcXCldK1xcKS87IC8vIGFiYyhkZWYpXG5cdFx0XHRpZiAocmVnZXhLZXkudGVzdChzVG9rZW4pKSB7XG5cdFx0XHRcdGFLZXlzLnB1c2goc1Rva2VuLnNwbGl0KFwiKFwiKVswXSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gYUtleXM7XG5cdH1cblxuXHQvKipcblx0ICogQnVpbGRzIGEgc3RhdGUgZnJvbSBhIGhhc2guXG5cdCAqXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzSGFzaCBUaGUgaGFzaCB0byBiZSB1c2VkIGFzIGVudHJ5XG5cdCAqIEByZXR1cm5zIHtvYmplY3R9IFRoZSBzdGF0ZVxuXHQgKlxuXHQgKiBAdWk1LXJlc3RyaWN0ZWRcblx0ICovXG5cdF9leHRyYWN0U3RhdGVGcm9tSGFzaChzSGFzaDogc3RyaW5nKSB7XG5cdFx0aWYgKHNIYXNoID09PSB1bmRlZmluZWQpIHtcblx0XHRcdHNIYXNoID0gXCJcIjtcblx0XHR9XG5cblx0XHRjb25zdCBvU3RhdGU6IGFueSA9IHtcblx0XHRcdGtleXM6IHRoaXMuX2V4dHJhY3RLZXlzRnJvbUhhc2goc0hhc2gpXG5cdFx0fTtcblxuXHRcdC8vIFJldHJpZXZlIGxheW91dCAoaWYgYW55KVxuXHRcdGNvbnN0IGFMYXlvdXQgPSBzSGFzaC5tYXRjaChuZXcgUmVnRXhwKFwiXFxcXD8uKlwiICsgZW51bVVSTFBhcmFtcy5MQVlPVVRQQVJBTSArIFwiPShbXiZdKilcIikpO1xuXHRcdG9TdGF0ZS5zTGF5b3V0ID0gYUxheW91dCAmJiBhTGF5b3V0Lmxlbmd0aCA+IDEgPyBhTGF5b3V0WzFdIDogbnVsbDtcblx0XHRpZiAob1N0YXRlLnNMYXlvdXQgPT09IFwiTWlkQ29sdW1uRnVsbFNjcmVlblwiKSB7XG5cdFx0XHRvU3RhdGUuc2NyZWVuTW9kZSA9IDE7XG5cdFx0fSBlbHNlIGlmIChvU3RhdGUuc0xheW91dCA9PT0gXCJFbmRDb2x1bW5GdWxsU2NyZWVuXCIpIHtcblx0XHRcdG9TdGF0ZS5zY3JlZW5Nb2RlID0gMjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0b1N0YXRlLnNjcmVlbk1vZGUgPSAwO1xuXHRcdH1cblxuXHRcdG9TdGF0ZS5oYXNoID0gc0hhc2g7XG5cdFx0cmV0dXJuIG9TdGF0ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbmV3IHN0YXRlIGludG8gdGhlIGludGVybmFsIGhpc3Rvcnkgc3RydWN0dXJlLlxuXHQgKiBNYWtlcyBzdXJlIHRoaXMgbmV3IHN0YXRlIGlzIGFkZGVkIGFmdGVyIGFuIGFuY2VzdG9yLlxuXHQgKiBBbHNvIHNldHMgdGhlIGlBcHBTdGF0ZSBrZXkgaW4gdGhlIHdob2xlIGhpc3RvcnkuXG5cdCAqXG5cdCAqIEBtZW1iZXJvZiBzYXAuZmUuY29yZS5Sb3V0ZXJQcm94eVxuXHQgKiBAcGFyYW0ge29iamVjdH0gb05ld1N0YXRlIFRoZSBuZXcgc3RhdGUgdG8gYmUgYWRkZWRcblx0ICogQHBhcmFtIHtib29sZWFufSBiUmVidWlsZE9ubHkgYHRydWVgIGlmIHdlJ3JlIHJlYnVpbGRpbmcgdGhlIGhpc3RvcnkgYWZ0ZXIgYSBzaGVsbCBtZW51IG5hdmlnYXRpb25cblx0ICogQHBhcmFtIHtib29sZWFufSBiUHJlc2VydmVIaXN0b3J5IElmIHNldCB0byB0cnVlLCBub24tYW5jZXN0b3IgZW50cmllcyBpbiBoaXN0b3J5IHdpbGwgYmUgcmV0YWluZWRcblx0ICogQHBhcmFtIHtib29sZWFufSBiRGlzYWJsZUhpc3RvcnlQcmVzZXJ2YXRpb24gRGlzYWJsZSB0aGUgbWVjaGFuaXNtIHRvIHJldGFpbmVkIG1hcmtlZCBlbnRyaWVzIGluIGNhY2hlXG5cdCAqIEByZXR1cm5zIHtvYmplY3R9IFRoZSBuZXcgc3RhdGVcblx0ICogQHVpNS1yZXN0cmljdGVkXG5cdCAqIEBmaW5hbFxuXHQgKi9cblx0X3B1c2hOZXdTdGF0ZShvTmV3U3RhdGU6IGFueSwgYlJlYnVpbGRPbmx5OiBib29sZWFuLCBiUHJlc2VydmVIaXN0b3J5OiBib29sZWFuLCBiRGlzYWJsZUhpc3RvcnlQcmVzZXJ2YXRpb246IGJvb2xlYW4pIHtcblx0XHRjb25zdCBzQ3VycmVudEhhc2ggPSB0aGlzLmdldEhhc2goKTtcblx0XHRsZXQgbGFzdEluZGV4ID0gdGhpcy5fb01hbmFnZWRIaXN0b3J5Lmxlbmd0aCAtIDE7XG5cdFx0bGV0IGlQb3BDb3VudCA9IGJSZWJ1aWxkT25seSA/IDEgOiAwO1xuXG5cdFx0Ly8gMS4gRG8gc29tZSBjbGVhbnVwIGluIHRoZSBtYW5hZ2VkIGhpc3RvcnkgOiBpbiBjYXNlIHRoZSB1c2VyIGhhcyBuYXZpZ2F0ZWQgYmFjayBpbiB0aGUgYnJvd3NlciBoaXN0b3J5LCB3ZSBuZWVkIHRvIHJlbW92ZVxuXHRcdC8vIHRoZSBzdGF0ZXMgYWhlYWQgaW4gaGlzdG9yeSBhbmQgbWFrZSBzdXJlIHRoZSB0b3Agc3RhdGUgY29ycmVzcG9uZHMgdG8gdGhlIGN1cnJlbnQgcGFnZVxuXHRcdC8vIFdlIGRvbid0IGRvIHRoYXQgd2hlbiByZXN0b3JpbmcgdGhlIGhpc3RvcnksIGFzIHRoZSBjdXJyZW50IHN0YXRlIGhhcyBiZWVuIGFkZGVkIG9uIHRvcCBvZiB0aGUgYnJvd3NlciBoaXN0b3J5XG5cdFx0Ly8gYW5kIGlzIG5vdCByZWZsZWN0ZWQgaW4gdGhlIG1hbmFnZWQgaGlzdG9yeVxuXHRcdGlmICghYlJlYnVpbGRPbmx5KSB7XG5cdFx0XHR3aGlsZSAobGFzdEluZGV4ID49IDAgJiYgdGhpcy5fb01hbmFnZWRIaXN0b3J5W2xhc3RJbmRleF0uaGFzaCAhPT0gc0N1cnJlbnRIYXNoKSB7XG5cdFx0XHRcdHRoaXMuX29NYW5hZ2VkSGlzdG9yeS5wb3AoKTtcblx0XHRcdFx0bGFzdEluZGV4LS07XG5cdFx0XHR9XG5cblx0XHRcdGlmICh0aGlzLl9vTWFuYWdlZEhpc3RvcnkubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRcdC8vIFdlIGNvdWxkbid0IGZpbmQgdGhlIGN1cnJlbnQgbG9jYXRpb24gaW4gdGhlIGhpc3RvcnkuIFRoaXMgY2FuIGhhcHBlbiBpZiBhIGJyb3dzZXIgcmVsb2FkXG5cdFx0XHRcdC8vIGhhcHBlbmVkLCBjYXVzaW5nIGEgcmVpbml0aWFsaXphdGlvbiBvZiB0aGUgbWFuYWdlZCBoaXN0b3J5LlxuXHRcdFx0XHQvLyBJbiB0aGF0IGNhc2UsIHdlIHVzZSB0aGUgY3VycmVudCBsb2NhdGlvbiBhcyB0aGUgbmV3IHN0YXJ0aW5nIHBvaW50IGluIHRoZSBtYW5hZ2VkIGhpc3Rvcnlcblx0XHRcdFx0dGhpcy5fb01hbmFnZWRIaXN0b3J5LnB1c2godGhpcy5fZXh0cmFjdFN0YXRlRnJvbUhhc2goc0N1cnJlbnRIYXNoKSk7XG5cdFx0XHRcdGhpc3RvcnkucmVwbGFjZVN0YXRlKE9iamVjdC5hc3NpZ24oeyBmZUxldmVsOiAwIH0sIGhpc3Rvcnkuc3RhdGUpLCBcIlwiKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyAyLiBNYXJrIHRoZSB0b3Agc3RhdGUgYXMgcHJlc2VydmVkIGlmIHJlcXVpcmVkXG5cdFx0aWYgKGJQcmVzZXJ2ZUhpc3RvcnkgJiYgIWJEaXNhYmxlSGlzdG9yeVByZXNlcnZhdGlvbikge1xuXHRcdFx0dGhpcy5fb01hbmFnZWRIaXN0b3J5W3RoaXMuX29NYW5hZ2VkSGlzdG9yeS5sZW5ndGggLSAxXS5wcmVzZXJ2ZWQgPSB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIDMuIFRoZW4gcG9wIGFsbCBzdGF0ZXMgdW50aWwgd2UgZmluZCBhbiBhbmNlc3RvciBvZiB0aGUgbmV3IHN0YXRlLCBvciB3ZSBmaW5kIGEgc3RhdGUgdGhhdCBuZWVkIHRvIGJlIHByZXNlcnZlZFxuXHRcdGxldCBvTGFzdFJlbW92ZWRJdGVtO1xuXHRcdHdoaWxlICh0aGlzLl9vTWFuYWdlZEhpc3RvcnkubGVuZ3RoID4gMCkge1xuXHRcdFx0Y29uc3Qgb1RvcFN0YXRlID0gdGhpcy5fb01hbmFnZWRIaXN0b3J5W3RoaXMuX29NYW5hZ2VkSGlzdG9yeS5sZW5ndGggLSAxXTtcblx0XHRcdGlmIChcblx0XHRcdFx0KGJEaXNhYmxlSGlzdG9yeVByZXNlcnZhdGlvbiB8fCAhb1RvcFN0YXRlLnByZXNlcnZlZCkgJiZcblx0XHRcdFx0dGhpcy5fY29tcGFyZUNhY2hlU3RhdGVzKG9Ub3BTdGF0ZSwgb05ld1N0YXRlKSAhPT0gZW51bVN0YXRlLkFOQ0VTVE9SXG5cdFx0XHQpIHtcblx0XHRcdFx0Ly8gVGhlIHRvcCBzdGF0ZSBpcyBub3QgYW4gYW5jZXN0b3Igb2Ygb05ld1N0YXRlIGFuZCBpcyBub3QgcHJlc2VydmVkIC0tPiB3ZSBjYW4gcG9wIGl0XG5cdFx0XHRcdG9MYXN0UmVtb3ZlZEl0ZW0gPSB0aGlzLl9vTWFuYWdlZEhpc3RvcnkucG9wKCk7XG5cdFx0XHRcdGlQb3BDb3VudCsrO1xuXHRcdFx0fSBlbHNlIGlmIChvVG9wU3RhdGUucHJlc2VydmVkICYmIHJlbW92ZUFwcFN0YXRlSW5IYXNoKG9Ub3BTdGF0ZS5oYXNoKSA9PT0gcmVtb3ZlQXBwU3RhdGVJbkhhc2gob05ld1N0YXRlLmhhc2gpKSB7XG5cdFx0XHRcdC8vIFdlIHRyeSB0byBhZGQgYSBzdGF0ZSB0aGF0IGlzIGFscmVhZHkgaW4gY2FjaGUgKGR1ZSB0byBwcmVzZXJ2ZWQgZmxhZykgYnV0IHdpdGggYSBkaWZmZXJlbnQgaWFwcC1zdGF0ZVxuXHRcdFx0XHQvLyAtLT4gd2Ugc2hvdWxkIGRlbGV0ZSB0aGUgcHJldmlvdXMgZW50cnkgKGl0IHdpbGwgYmUgbGF0ZXIgcmVwbGFjZWQgYnkgdGhlIG5ldyBvbmUpIGFuZCBzdG9wIHBvcHBpbmdcblx0XHRcdFx0b0xhc3RSZW1vdmVkSXRlbSA9IHRoaXMuX29NYW5hZ2VkSGlzdG9yeS5wb3AoKTtcblx0XHRcdFx0aVBvcENvdW50Kys7XG5cdFx0XHRcdG9OZXdTdGF0ZS5wcmVzZXJ2ZWQgPSB0cnVlO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGJyZWFrOyAvLyBBbmNlc3RvciBvciBwcmVzZXJ2ZWQgc3RhdGUgZm91bmQgLS0+IHdlIHN0b3AgcG9wcGluZyBvdXQgc3RhdGVzXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gNC4gaUFwcFN0YXRlIG1hbmFnZW1lbnRcblx0XHR0aGlzLnNJQXBwU3RhdGVLZXkgPSBmaW5kQXBwU3RhdGVJbkhhc2gob05ld1N0YXRlLmhhc2gpO1xuXHRcdGlmICh0aGlzLmZjbEVuYWJsZWQgJiYgdGhpcy5zSUFwcFN0YXRlS2V5KSB7XG5cdFx0XHQvLyBJbiBjYXNlIG9mIEZDTCwgdGhlIG5ldyBhcHAgc3RhdGUgbmVlZHMgdG8gYmUgYXBwbGllZCB0byB0aGUgd2hvbGUgaGlzdG9yeVxuXHRcdFx0dGhpcy5fb01hbmFnZWRIaXN0b3J5LmZvckVhY2goKG9NYW5hZ2VkU3RhdGU6IGFueSkgPT4ge1xuXHRcdFx0XHRvTWFuYWdlZFN0YXRlLmhhc2ggPSBzZXRBcHBTdGF0ZUluSGFzaChvTWFuYWdlZFN0YXRlLmhhc2gsIHRoaXMuc0lBcHBTdGF0ZUtleSk7XG5cdFx0XHR9KTtcblx0XHR9IGVsc2UgaWYgKCF0aGlzLmZjbEVuYWJsZWQgJiYgb0xhc3RSZW1vdmVkSXRlbSkge1xuXHRcdFx0Y29uc3Qgc1ByZXZpb3VzSUFwcFN0YXRlS2V5ID0gZmluZEFwcFN0YXRlSW5IYXNoKG9MYXN0UmVtb3ZlZEl0ZW0uaGFzaCk7XG5cdFx0XHRjb25zdCBvQ29tcGFyaXNvblN0YXRlUmVzdWx0ID0gdGhpcy5fY29tcGFyZUNhY2hlU3RhdGVzKG9MYXN0UmVtb3ZlZEl0ZW0sIG9OZXdTdGF0ZSk7XG5cdFx0XHQvLyBpZiBjdXJyZW50IHN0YXRlIGRvZXNuJ3QgY29udGFpbiBhIGktYXBwc3RhdGUgYW5kIHRoaXMgc3RhdGUgc2hvdWxkIHJlcGxhY2UgYSBzdGF0ZSBjb250YWluaW5nIGEgaUFwcFN0YXRlXG5cdFx0XHQvLyB0aGVuIHRoZSBwcmV2aW91cyBpQXBwU3RhdGUgaXMgcHJlc2VydmVkXG5cdFx0XHRpZiAoXG5cdFx0XHRcdCF0aGlzLnNJQXBwU3RhdGVLZXkgJiZcblx0XHRcdFx0c1ByZXZpb3VzSUFwcFN0YXRlS2V5ICYmXG5cdFx0XHRcdChvQ29tcGFyaXNvblN0YXRlUmVzdWx0ID09PSBlbnVtU3RhdGUuRVFVQUwgfHwgb0NvbXBhcmlzb25TdGF0ZVJlc3VsdCA9PT0gZW51bVN0YXRlLkNPTVBBVElCTEUpXG5cdFx0XHQpIHtcblx0XHRcdFx0b05ld1N0YXRlLmhhc2ggPSBzZXRBcHBTdGF0ZUluSGFzaChvTmV3U3RhdGUuaGFzaCwgc1ByZXZpb3VzSUFwcFN0YXRlS2V5KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyA1LiBOb3cgd2UgY2FuIHB1c2ggdGhlIHN0YXRlIGF0IHRoZSB0b3Agb2YgdGhlIGludGVybmFsIGhpc3Rvcnlcblx0XHRjb25zdCBiSGFzU2FtZUhhc2ggPSBvTGFzdFJlbW92ZWRJdGVtICYmIG9OZXdTdGF0ZS5oYXNoID09PSBvTGFzdFJlbW92ZWRJdGVtLmhhc2g7XG5cdFx0aWYgKHRoaXMuX29NYW5hZ2VkSGlzdG9yeS5sZW5ndGggPT09IDAgfHwgdGhpcy5fb01hbmFnZWRIaXN0b3J5W3RoaXMuX29NYW5hZ2VkSGlzdG9yeS5sZW5ndGggLSAxXS5oYXNoICE9PSBvTmV3U3RhdGUuaGFzaCkge1xuXHRcdFx0dGhpcy5fb01hbmFnZWRIaXN0b3J5LnB1c2gob05ld1N0YXRlKTtcblx0XHR9XG5cblx0XHQvLyA2LiBEZXRlcm1pbmUgd2hpY2ggYWN0aW9ucyB0byBkbyBvbiB0aGUgaGlzdG9yeVxuXHRcdGlmIChpUG9wQ291bnQgPT09IDApIHtcblx0XHRcdC8vIE5vIHN0YXRlIHdhcyBwb3BwZWQgLS0+IGFwcGVuZFxuXHRcdFx0cmV0dXJuIHsgdHlwZTogXCJhcHBlbmRcIiB9O1xuXHRcdH0gZWxzZSBpZiAoaVBvcENvdW50ID09PSAxKSB7XG5cdFx0XHQvLyBPbmx5IDEgc3RhdGUgd2FzIHBvcHBlZCAtLT4gcmVwbGFjZSBjdXJyZW50IGhhc2ggdW5sZXNzIGhhc2ggaXMgdGhlIHNhbWUgKHRoZW4gbm90aGluZyB0byBkbylcblx0XHRcdHJldHVybiBiSGFzU2FtZUhhc2ggPyB7IHR5cGU6IFwibm9uZVwiIH0gOiB7IHR5cGU6IFwicmVwbGFjZVwiIH07XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIE1vcmUgdGhhbiAxIHN0YXRlIHdhcyBwb3BwZWQgLS0+IGdvIGJha2MgaW4gaGlzdG9yeSBhbmQgcmVwbGFjZSBoYXNoIGlmIG5lY2Vzc2FyeVxuXHRcdFx0cmV0dXJuIGJIYXNTYW1lSGFzaCA/IHsgdHlwZTogXCJiYWNrXCIsIHN0ZXBzOiBpUG9wQ291bnQgLSAxIH0gOiB7IHR5cGU6IFwiYmFjay1yZXBsYWNlXCIsIHN0ZXBzOiBpUG9wQ291bnQgLSAxIH07XG5cdFx0fVxuXHR9XG5cblx0X2Jsb2NraW5nTmF2aWdhdGlvbkZpbHRlcigpIHtcblx0XHRyZXR1cm4gdGhpcy5fYkRpc2FibGVPbkhhc2hDaGFuZ2UgPyBcIkN1c3RvbVwiIDogXCJDb250aW51ZVwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc2FibGUgdGhlIHJvdXRpbmcgYnkgY2FsbGluZyB0aGUgcm91dGVyIHN0b3AgbWV0aG9kLlxuXHQgKlxuXHQgKiBAZnVuY3Rpb25cblx0ICogQG1lbWJlcm9mIHNhcC5mZS5jb3JlLlJvdXRlclByb3h5XG5cdCAqXG5cdCAqIEB1aTUtcmVzdHJpY3RlZFxuXHQgKiBAZmluYWxcblx0ICovXG5cdF9kaXNhYmxlRXZlbnRPbkhhc2hDaGFuZ2UoKSB7XG5cdFx0dGhpcy5fYkRpc2FibGVPbkhhc2hDaGFuZ2UgPSB0cnVlO1xuXHRcdHRoaXMuX29Sb3V0ZXIuc3RvcCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEVuYWJsZSB0aGUgcm91dGluZyBieSBjYWxsaW5nIHRoZSByb3V0ZXIgaW5pdGlhbGl6ZSBtZXRob2QuXG5cdCAqXG5cdCAqIEBmdW5jdGlvblxuXHQgKiBAbmFtZSBzYXAuZmUuY29yZS5Sb3V0ZXJQcm94eSNfZW5hYmxlRXZlbnRPbkhhc2hDaGFuZ2Vcblx0ICogQG1lbWJlcm9mIHNhcC5mZS5jb3JlLlJvdXRlclByb3h5XG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gW2JJZ25vcmVDdXJyZW50SGFzaF0gSWdub3JlIHRoZSBsYXN0IGhhc2ggZXZlbnQgdHJpZ2dlcmVkIGJlZm9yZSB0aGUgcm91dGVyIGhhcyBpbml0aWFsaXplZFxuXHQgKlxuXHQgKiBAdWk1LXJlc3RyaWN0ZWRcblx0ICogQGZpbmFsXG5cdCAqL1xuXHRfZW5hYmxlRXZlbnRPbkhhc2hDaGFuZ2UoYklnbm9yZUN1cnJlbnRIYXNoOiBib29sZWFuIHwgdW5kZWZpbmVkKSB7XG5cdFx0dGhpcy5fYkRpc2FibGVPbkhhc2hDaGFuZ2UgPSBmYWxzZTtcblx0XHR0aGlzLl9vUm91dGVyLmluaXRpYWxpemUoYklnbm9yZUN1cnJlbnRIYXNoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTeW5jaHJvbml6ZXMgdGhlIGJyb3dzZXIgaGlzdG9yeSB3aXRoIHRoZSBpbnRlcm5hbCBoaXN0b3J5IG9mIHRoZSByb3V0ZXJQcm94eSwgYW5kIHRyaWdnZXJzIGEgbmF2aWdhdGlvbiBpZiBuZWVkZWQuXG5cdCAqXG5cdCAqIEBtZW1iZXJvZiBzYXAuZmUuY29yZS5Sb3V0ZXJQcm94eVxuXHQgKiBAcGFyYW0ge29iamVjdH0gb0hpc3RvcnlBY3Rpb24gU3BlY2lmaWVzIHRoZSBuYXZpZ2F0aW9uIGFjdGlvbiB0byBiZSBwZXJmb3JtZWRcblx0ICogQHBhcmFtIHtib29sZWFufSBiUmVidWlsZE9ubHkgYHRydWVgIGlmIGludGVybmFsIGhpc3RvcnkgaXMgY3VycmVudGx5IGJlaW5nIHJlYnVpbHRcblx0ICogQHJldHVybnMge1Byb21pc2V9IFByb21pc2UgKHJlc29sdmVkIHdoZW4gdGhlIG5hdmlnYXRpb24gaXMgZmluYWxpemVkKSB0aGF0IHJldHVybnMgJ3RydWUnIGlmIGEgbmF2aWdhdGlvbiB0b29rIHBsYWNlLCAnZmFsc2UnIGlmIHRoZSBuYXZpZ2F0aW9uIGRpZG4ndCBoYXBwZW5cblx0ICogQHVpNS1yZXN0cmljdGVkXG5cdCAqIEBmaW5hbFxuXHQgKi9cblx0X3JlYnVpbGRCcm93c2VySGlzdG9yeShvSGlzdG9yeUFjdGlvbjogYW55LCBiUmVidWlsZE9ubHk6IGJvb2xlYW4pIHtcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcblx0XHRjb25zdCB0aGF0ID0gdGhpcztcblx0XHRyZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG5cdFx0XHR0aGlzLmJJc1JlYnVpbGRIaXN0b3J5UnVubmluZyA9IHRydWU7XG5cdFx0XHRjb25zdCBvVGFyZ2V0U3RhdGUgPSB0aGlzLl9vTWFuYWdlZEhpc3RvcnlbdGhpcy5fb01hbmFnZWRIaXN0b3J5Lmxlbmd0aCAtIDFdLFxuXHRcdFx0XHRuZXdMZXZlbCA9IHRoaXMuX29NYW5hZ2VkSGlzdG9yeS5sZW5ndGggLSAxO1xuXG5cdFx0XHRmdW5jdGlvbiByZXBsYWNlQXN5bmMoKSB7XG5cdFx0XHRcdGlmICghYlJlYnVpbGRPbmx5KSB7XG5cdFx0XHRcdFx0dGhhdC5fZW5hYmxlRXZlbnRPbkhhc2hDaGFuZ2UodHJ1ZSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQodGhhdC5fb1JvdXRlci5nZXRIYXNoQ2hhbmdlcigpLnJlcGxhY2VIYXNoIGFzIGFueSkob1RhcmdldFN0YXRlLmhhc2gpO1xuXHRcdFx0XHRoaXN0b3J5LnJlcGxhY2VTdGF0ZShPYmplY3QuYXNzaWduKHsgZmVMZXZlbDogbmV3TGV2ZWwgfSwgaGlzdG9yeS5zdGF0ZSksIFwiXCIpO1xuXG5cdFx0XHRcdGlmIChiUmVidWlsZE9ubHkpIHtcblx0XHRcdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0Ly8gVGltZW91dCB0byBsZXQgJ2hhc2hjaGFuZ2UnIGV2ZW50IGJlIHByb2Nlc3NlZCBiZWZvcmUgYnkgdGhlIEhhc2hDaGFuZ2VyLCBzbyB0aGF0XG5cdFx0XHRcdFx0XHQvLyBvblJvdXRlTWF0Y2hlZCBub3RpZmljYXRpb24gaXNuJ3QgcmFpc2VkXG5cdFx0XHRcdFx0XHR0aGF0Ll9lbmFibGVFdmVudE9uSGFzaENoYW5nZSh0cnVlKTtcblx0XHRcdFx0XHR9LCAwKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoYXQuYklzUmVidWlsZEhpc3RvcnlSdW5uaW5nID0gZmFsc2U7XG5cdFx0XHRcdHJlc29sdmUodHJ1ZSk7IC8vIGEgbmF2aWdhdGlvbiBvY2N1cnJlZFxuXHRcdFx0fVxuXG5cdFx0XHQvLyBBc3luYyBjYWxsYmFja3Mgd2hlbiBuYXZpZ2F0aW5nIGJhY2ssIGluIG9yZGVyIHRvIGxldCBhbGwgbm90aWZpY2F0aW9ucyBhbmQgZXZlbnRzIGdldCBwcm9jZXNzZWRcblx0XHRcdGZ1bmN0aW9uIGJhY2tSZXBsYWNlQXN5bmMoKSB7XG5cdFx0XHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwicG9wc3RhdGVcIiwgYmFja1JlcGxhY2VBc3luYyk7XG5cdFx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0Ly8gVGltZW91dCB0byBsZXQgJ2hhc2hjaGFuZ2UnIGV2ZW50IGJlIHByb2Nlc3NlZCBiZWZvcmUgYnkgdGhlIEhhc2hDaGFuZ2VyXG5cdFx0XHRcdFx0cmVwbGFjZUFzeW5jKCk7XG5cdFx0XHRcdH0sIDApO1xuXHRcdFx0fVxuXG5cdFx0XHRmdW5jdGlvbiBiYWNrQXN5bmMoKSB7XG5cdFx0XHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwicG9wc3RhdGVcIiwgYmFja0FzeW5jKTtcblx0XHRcdFx0dGhhdC5iSXNSZWJ1aWxkSGlzdG9yeVJ1bm5pbmcgPSBmYWxzZTtcblx0XHRcdFx0cmVzb2x2ZSh0cnVlKTsgLy8gYSBuYXZpZ2F0aW9uIG9jY3VycmVkXG5cdFx0XHR9XG5cblx0XHRcdHRoYXQuX2JJZ25vcmVSZXN0b3JlID0gdHJ1ZTtcblxuXHRcdFx0c3dpdGNoIChvSGlzdG9yeUFjdGlvbi50eXBlKSB7XG5cdFx0XHRcdGNhc2UgXCJyZXBsYWNlXCI6XG5cdFx0XHRcdFx0KHRoYXQuX29Sb3V0ZXIuZ2V0SGFzaENoYW5nZXIoKS5yZXBsYWNlSGFzaCBhcyBhbnkpKG9UYXJnZXRTdGF0ZS5oYXNoKTtcblx0XHRcdFx0XHRoaXN0b3J5LnJlcGxhY2VTdGF0ZShPYmplY3QuYXNzaWduKHsgZmVMZXZlbDogbmV3TGV2ZWwgfSwgaGlzdG9yeS5zdGF0ZSksIFwiXCIpO1xuXHRcdFx0XHRcdHRoYXQuYklzUmVidWlsZEhpc3RvcnlSdW5uaW5nID0gZmFsc2U7XG5cdFx0XHRcdFx0cmVzb2x2ZSh0cnVlKTsgLy8gYSBuYXZpZ2F0aW9uIG9jY3VycmVkXG5cdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0Y2FzZSBcImFwcGVuZFwiOlxuXHRcdFx0XHRcdHRoYXQuX29Sb3V0ZXIuZ2V0SGFzaENoYW5nZXIoKS5zZXRIYXNoKG9UYXJnZXRTdGF0ZS5oYXNoKTtcblx0XHRcdFx0XHRoaXN0b3J5LnJlcGxhY2VTdGF0ZShPYmplY3QuYXNzaWduKHsgZmVMZXZlbDogbmV3TGV2ZWwgfSwgaGlzdG9yeS5zdGF0ZSksIFwiXCIpO1xuXHRcdFx0XHRcdHRoYXQuYklzUmVidWlsZEhpc3RvcnlSdW5uaW5nID0gZmFsc2U7XG5cdFx0XHRcdFx0cmVzb2x2ZSh0cnVlKTsgLy8gYSBuYXZpZ2F0aW9uIG9jY3VycmVkXG5cdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0Y2FzZSBcImJhY2tcIjpcblx0XHRcdFx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcInBvcHN0YXRlXCIsIGJhY2tBc3luYyk7XG5cdFx0XHRcdFx0aGlzdG9yeS5nbygtb0hpc3RvcnlBY3Rpb24uc3RlcHMpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdGNhc2UgXCJiYWNrLXJlcGxhY2VcIjpcblx0XHRcdFx0XHR0aGlzLl9kaXNhYmxlRXZlbnRPbkhhc2hDaGFuZ2UoKTtcblx0XHRcdFx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcInBvcHN0YXRlXCIsIGJhY2tSZXBsYWNlQXN5bmMpO1xuXHRcdFx0XHRcdGhpc3RvcnkuZ28oLW9IaXN0b3J5QWN0aW9uLnN0ZXBzKTtcblx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdC8vIE5vIG5hdmlnYXRpb25cblx0XHRcdFx0XHR0aGlzLmJJc1JlYnVpbGRIaXN0b3J5UnVubmluZyA9IGZhbHNlO1xuXHRcdFx0XHRcdHJlc29sdmUoZmFsc2UpOyAvLyBubyBuYXZpZ2F0aW9uIC0tPiByZXNvbHZlIHRvIGZhbHNlXG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRnZXRMYXN0SGlzdG9yeUVudHJ5KCkge1xuXHRcdHJldHVybiB0aGlzLl9vTWFuYWdlZEhpc3RvcnlbdGhpcy5fb01hbmFnZWRIaXN0b3J5Lmxlbmd0aCAtIDFdO1xuXHR9XG5cblx0aGFzaEd1YXJkKCkge1xuXHRcdGlmICh0aGlzLl9iQ2xlYW5lZFJlc3RvcmUpIHtcblx0XHRcdHRoaXMuX2JDbGVhbmVkUmVzdG9yZSA9IGZhbHNlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRjb25zdCBzSGFzaCA9IHdpbmRvdy5sb2NhdGlvbi5oYXNoO1xuXHRcdGlmIChzSGFzaC5pbmRleE9mKFwicmVzdG9yZUhpc3Rvcnk9dHJ1ZVwiKSAhPT0gLTEpIHtcblx0XHRcdHRoaXMuX2JBcHBseVJlc3RvcmUgPSB0cnVlO1xuXHRcdH0gZWxzZSBpZiAoIXRoaXMuYklzUmVidWlsZEhpc3RvcnlSdW5uaW5nKSB7XG5cdFx0XHRjb25zdCBhSGFzaFNwbGl0ID0gc0hhc2guc3BsaXQoXCImL1wiKTtcblx0XHRcdGNvbnN0IHNBcHBIYXNoID0gYUhhc2hTcGxpdFsxXSA/IGFIYXNoU3BsaXRbMV0gOiBcIlwiO1xuXHRcdFx0aWYgKHRoaXMuY2hlY2tIYXNoV2l0aEd1YXJkKHNBcHBIYXNoKSkge1xuXHRcdFx0XHR0aGlzLl9iRGVsYXllZFJlYnVpbGQgPSB0cnVlO1xuXHRcdFx0XHRjb25zdCBvTmV3U3RhdGUgPSB0aGlzLl9leHRyYWN0U3RhdGVGcm9tSGFzaChzQXBwSGFzaCk7XG5cdFx0XHRcdHRoaXMuX3B1c2hOZXdTdGF0ZShvTmV3U3RhdGUsIGZhbHNlLCBmYWxzZSwgdHJ1ZSk7XG5cblx0XHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5fYkRlbGF5ZWRSZWJ1aWxkID0gZmFsc2U7XG5cdFx0XHRcdH0sIDApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDb21wYXJlcyAyIHN0YXRlcy5cblx0ICpcblx0ICogQHBhcmFtIHtvYmplY3R9IG9TdGF0ZTFcblx0ICogQHBhcmFtIHtvYmplY3R9IG9TdGF0ZTJcblx0ICogQHJldHVybnMge251bWJlcn0gVGhlIHJlc3VsdCBvZiB0aGUgY29tcGFyaXNvbjpcblx0ICogICAgICAgIC0gZW51bVN0YXRlLkVRVUFMIGlmIG9TdGF0ZTEgYW5kIG9TdGF0ZTIgYXJlIGVxdWFsXG5cdCAqICAgICAgICAtIGVudW1TdGF0ZS5DT01QQVRJQkxFIGlmIG9TdGF0ZTEgYW5kIG9TdGF0ZTIgYXJlIGNvbXBhdGlibGVcblx0ICogICAgICAgIC0gZW51bVN0YXRlLkFOQ0VTVE9SIGlmIG9TdGF0ZTEgaXMgYW4gYW5jZXN0b3Igb2Ygb1N0YXRlMlxuXHQgKiAgICAgICAgLSBlbnVtU3RhdGUuRElGRkVSRU5UIGlmIHRoZSAyIHN0YXRlcyBhcmUgZGlmZmVyZW50XG5cdCAqL1xuXG5cdF9jb21wYXJlQ2FjaGVTdGF0ZXMob1N0YXRlMTogYW55LCBvU3RhdGUyOiBhbnkpIHtcblx0XHQvLyBGaXJzdCBjb21wYXJlIG9iamVjdCBrZXlzXG5cdFx0aWYgKG9TdGF0ZTEua2V5cy5sZW5ndGggPiBvU3RhdGUyLmtleXMubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gZW51bVN0YXRlLkRJRkZFUkVOVDtcblx0XHR9XG5cdFx0bGV0IGVxdWFsID0gdHJ1ZTtcblx0XHRsZXQgaW5kZXg7XG5cdFx0Zm9yIChpbmRleCA9IDA7IGVxdWFsICYmIGluZGV4IDwgb1N0YXRlMS5rZXlzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0aWYgKG9TdGF0ZTEua2V5c1tpbmRleF0gIT09IG9TdGF0ZTIua2V5c1tpbmRleF0pIHtcblx0XHRcdFx0ZXF1YWwgPSBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCFlcXVhbCkge1xuXHRcdFx0Ly8gU29tZSBvYmplY3RzIGtleXMgYXJlIGRpZmZlcmVudFxuXHRcdFx0cmV0dXJuIGVudW1TdGF0ZS5ESUZGRVJFTlQ7XG5cdFx0fVxuXG5cdFx0Ly8gQWxsIGtleXMgZnJvbSBvU3RhdGUxIGFyZSBpbiBvU3RhdGUyIC0tPiBjaGVjayBpZiBhbmNlc3RvclxuXHRcdGlmIChvU3RhdGUxLmtleXMubGVuZ3RoIDwgb1N0YXRlMi5rZXlzLmxlbmd0aCB8fCBvU3RhdGUxLnNjcmVlbk1vZGUgPCBvU3RhdGUyLnNjcmVlbk1vZGUpIHtcblx0XHRcdHJldHVybiBlbnVtU3RhdGUuQU5DRVNUT1I7XG5cdFx0fVxuXHRcdGlmIChvU3RhdGUxLnNjcmVlbk1vZGUgPiBvU3RhdGUyLnNjcmVlbk1vZGUpIHtcblx0XHRcdHJldHVybiBlbnVtU3RhdGUuRElGRkVSRU5UOyAvLyBOb3Qgc3VyZSB0aGlzIGNhc2UgY2FuIGhhcHBlbi4uLlxuXHRcdH1cblxuXHRcdC8vIEF0IHRoaXMgc3RhZ2UsIHRoZSAyIHN0YXRlcyBoYXZlIHRoZSBzYW1lIG9iamVjdCBrZXlzIChpbiB0aGUgc2FtZSBvcmRlcikgYW5kIHNhbWUgc2NyZWVubW9kZVxuXHRcdC8vIFRoZXkgY2FuIGJlIGVpdGhlciBjb21wYXRpYmxlIG9yIGVxdWFsXG5cdFx0cmV0dXJuIG9TdGF0ZTEuc0xheW91dCA9PT0gb1N0YXRlMi5zTGF5b3V0ID8gZW51bVN0YXRlLkVRVUFMIDogZW51bVN0YXRlLkNPTVBBVElCTEU7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIGJhY2sgZXhpdHMgdGhlIHByZXNlbnQgZ3VhcmQgc2V0LlxuXHQgKlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc1ByZXNlbnRIYXNoIFRoZSBjdXJyZW50IGhhc2guIE9ubHkgdXNlZCBmb3IgdW5pdCB0ZXN0cy5cblx0ICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiBiYWNrIGV4aXRzIHRoZXJlIGlzIGEgZ3VhcmQgZXhpdCBvbiBiYWNrXG5cdCAqL1xuXHRjaGVja0lmQmFja0lzT3V0T2ZHdWFyZChzUHJlc2VudEhhc2g/OiBzdHJpbmcpIHtcblx0XHRsZXQgc1ByZXZIYXNoO1xuXHRcdGxldCBzQ3VycmVudEhhc2g6IHN0cmluZztcblx0XHRpZiAoc1ByZXNlbnRIYXNoID09PSB1bmRlZmluZWQpIHtcblx0XHRcdC8vIFdlIHVzZSB3aW5kb3cubG9jYXRpb24uaGFzaCBpbnN0ZWFkIG9mIEhhc2hDaGFuZ2VyLmdldEluc3RhbmNlKCkuZ2V0SGFzaCgpIGJlY2F1c2UgdGhlIGxhdHRlclxuXHRcdFx0Ly8gcmVwbGFjZXMgY2hhcmFjdGVycyBpbiB0aGUgVVJMIChlLmcuICUyNCByZXBsYWNlZCBieSAkKSBhbmQgaXQgY2F1c2VzIGlzc3VlcyB3aGVuIGNvbXBhcmluZ1xuXHRcdFx0Ly8gd2l0aCB0aGUgVVJMcyBpbiB0aGUgbWFuYWdlZCBoaXN0b3J5XG5cdFx0XHRjb25zdCBvU3BsaXRIYXNoID0gdGhpcy5fb1NoZWxsU2VydmljZXMuc3BsaXRIYXNoKHdpbmRvdy5sb2NhdGlvbi5oYXNoKSBhcyBhbnk7XG5cdFx0XHRpZiAob1NwbGl0SGFzaCAmJiBvU3BsaXRIYXNoLmFwcFNwZWNpZmljUm91dGUpIHtcblx0XHRcdFx0c0N1cnJlbnRIYXNoID0gb1NwbGl0SGFzaC5hcHBTcGVjaWZpY1JvdXRlO1xuXHRcdFx0XHRpZiAoc0N1cnJlbnRIYXNoLmluZGV4T2YoXCImL1wiKSA9PT0gMCkge1xuXHRcdFx0XHRcdHNDdXJyZW50SGFzaCA9IHNDdXJyZW50SGFzaC5zdWJzdHJpbmcoMik7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNDdXJyZW50SGFzaCA9IHdpbmRvdy5sb2NhdGlvbi5oYXNoLnN1YnN0cmluZygxKTsgLy8gVG8gcmVtb3ZlIHRoZSAnIydcblx0XHRcdFx0aWYgKHNDdXJyZW50SGFzaFswXSA9PT0gXCIvXCIpIHtcblx0XHRcdFx0XHRzQ3VycmVudEhhc2ggPSBzQ3VycmVudEhhc2guc3Vic3RyaW5nKDEpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHNDdXJyZW50SGFzaCA9IHNQcmVzZW50SGFzaDtcblx0XHR9XG5cdFx0c1ByZXNlbnRIYXNoID0gVVJJLmRlY29kZShzQ3VycmVudEhhc2gpO1xuXHRcdGlmICh0aGlzLl9vTmF2aWdhdGlvbkd1YXJkKSB7XG5cdFx0XHRmb3IgKGxldCBpID0gdGhpcy5fb01hbmFnZWRIaXN0b3J5Lmxlbmd0aCAtIDE7IGkgPiAwOyBpLS0pIHtcblx0XHRcdFx0aWYgKHRoaXMuX29NYW5hZ2VkSGlzdG9yeVtpXS5oYXNoID09PSBzUHJlc2VudEhhc2gpIHtcblx0XHRcdFx0XHRzUHJldkhhc2ggPSB0aGlzLl9vTWFuYWdlZEhpc3RvcnlbaSAtIDFdLmhhc2g7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuICFzUHJldkhhc2ggfHwgIXRoaXMuY2hlY2tIYXNoV2l0aEd1YXJkKHNQcmV2SGFzaCk7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGxhc3QgMiBlbnRyaWVzIGluIHRoZSBoaXN0b3J5IHNoYXJlIHRoZSBzYW1lIGNvbnRleHQuXG5cdCAqXG5cdCAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhleSBzaGFyZSB0aGUgc2FtZSBjb250ZXh0LlxuXHQgKi9cblx0Y2hlY2tJZkJhY2tIYXNTYW1lQ29udGV4dCgpIHtcblx0XHRpZiAodGhpcy5fb01hbmFnZWRIaXN0b3J5Lmxlbmd0aCA8IDIpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRjb25zdCBvQ3VycmVudFN0YXRlID0gdGhpcy5fb01hbmFnZWRIaXN0b3J5W3RoaXMuX29NYW5hZ2VkSGlzdG9yeS5sZW5ndGggLSAxXTtcblx0XHRjb25zdCBvUHJldmlvdXNTdGF0ZSA9IHRoaXMuX29NYW5hZ2VkSGlzdG9yeVt0aGlzLl9vTWFuYWdlZEhpc3RvcnkubGVuZ3RoIC0gMl07XG5cblx0XHRyZXR1cm4gb0N1cnJlbnRTdGF0ZS5oYXNoLnNwbGl0KFwiP1wiKVswXSA9PT0gb1ByZXZpb3VzU3RhdGUuaGFzaC5zcGxpdChcIj9cIilbMF07XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUm91dGVyUHJveHk7XG4iXX0=