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