@energycap/components 0.31.5 → 0.32.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 (292) hide show
  1. package/energycap-components.min.css +2 -2
  2. package/energycap-email.min.css +1 -1
  3. package/esm2020/energycap-components.mjs +5 -0
  4. package/esm2020/lib/components.module.mjs +386 -0
  5. package/esm2020/lib/controls/banner/banner.component.mjs +106 -0
  6. package/esm2020/lib/controls/button/button.component.mjs +106 -0
  7. package/esm2020/lib/controls/button/copy-button.directive.mjs +65 -0
  8. package/esm2020/lib/controls/checkbox/checkbox.component.mjs +139 -0
  9. package/esm2020/lib/controls/collapsible-toggle/collapsible-toggle.component.mjs +38 -0
  10. package/esm2020/lib/controls/combobox/combobox.component.mjs +841 -0
  11. package/esm2020/lib/controls/dropdown/dropdown.component.mjs +237 -0
  12. package/esm2020/lib/controls/file-upload/file-upload.component.mjs +169 -0
  13. package/esm2020/lib/controls/form-control/form-control.component.mjs +86 -0
  14. package/esm2020/lib/controls/form-control-base.mjs +143 -0
  15. package/esm2020/lib/controls/form-control-label/form-control-label.component.mjs +136 -0
  16. package/esm2020/lib/controls/form-group/form-group.component.mjs +252 -0
  17. package/esm2020/lib/controls/help-popover/help-popover.component.mjs +28 -0
  18. package/esm2020/lib/controls/item-picker/item-picker.component.mjs +233 -0
  19. package/esm2020/lib/controls/link-button/link-button.component.mjs +11 -0
  20. package/esm2020/lib/controls/menu/menu.component.mjs +443 -0
  21. package/{esm2015/lib/controls/navigation/link-item.js → esm2020/lib/controls/navigation/link-item.mjs} +0 -0
  22. package/{esm2015/lib/controls/navigation/nav-group.js → esm2020/lib/controls/navigation/nav-group.mjs} +0 -0
  23. package/esm2020/lib/controls/navigation/nav-item-active.directive.mjs +92 -0
  24. package/{esm2015/lib/controls/navigation/nav-item.js → esm2020/lib/controls/navigation/nav-item.mjs} +0 -0
  25. package/esm2020/lib/controls/numericbox/numericbox.component.mjs +371 -0
  26. package/esm2020/lib/controls/popover/popover.component.mjs +84 -0
  27. package/{esm2015/lib/controls/radio-button/radio-button-option.js → esm2020/lib/controls/radio-button/radio-button-option.mjs} +0 -0
  28. package/esm2020/lib/controls/radio-button/radio-button.component.mjs +81 -0
  29. package/esm2020/lib/controls/select/select.component.mjs +87 -0
  30. package/esm2020/lib/controls/tabs/tabs.component.mjs +47 -0
  31. package/esm2020/lib/controls/textbox/textbox.component.mjs +154 -0
  32. package/{esm2015/lib/core/cache.service.js → esm2020/lib/core/cache.service.mjs} +9 -8
  33. package/{esm2015/lib/core/custom-validators.js → esm2020/lib/core/custom-validators.mjs} +0 -0
  34. package/{esm2015/lib/core/date-time-helper.js → esm2020/lib/core/date-time-helper.mjs} +0 -0
  35. package/esm2020/lib/core/error.service.mjs +57 -0
  36. package/esm2020/lib/core/scroll.service.mjs +89 -0
  37. package/esm2020/lib/core/telemetry-tracker.service.mjs +16 -0
  38. package/esm2020/lib/core/telemetry.service.mjs +38 -0
  39. package/esm2020/lib/core/validation-message.service.mjs +181 -0
  40. package/{esm2015/lib/core/validation-patterns.js → esm2020/lib/core/validation-patterns.mjs} +0 -0
  41. package/esm2020/lib/core/window.service.mjs +182 -0
  42. package/esm2020/lib/display/app-bar/app-bar.component.mjs +46 -0
  43. package/esm2020/lib/display/avatar/avatar.component.mjs +67 -0
  44. package/{esm2015/lib/display/avatar/avatar.service.js → esm2020/lib/display/avatar/avatar.service.mjs} +9 -7
  45. package/esm2020/lib/display/confirm/confirm.component.mjs +131 -0
  46. package/{esm2015/lib/display/dialog/dialog-content.js → esm2020/lib/display/dialog/dialog-content.mjs} +0 -0
  47. package/esm2020/lib/display/dialog/dialog-group/dialog-group.component.mjs +63 -0
  48. package/{esm2015/lib/display/dialog/dialog-types.js → esm2020/lib/display/dialog/dialog-types.mjs} +0 -0
  49. package/esm2020/lib/display/dialog/dialog.component.mjs +242 -0
  50. package/esm2020/lib/display/dialog/dialog.service.mjs +71 -0
  51. package/{esm2015/lib/display/help/help-types.js → esm2020/lib/display/help/help-types.mjs} +0 -0
  52. package/esm2020/lib/display/hierarchy/hierarchy-base.mjs +106 -0
  53. package/{esm2015/lib/display/hierarchy/hierarchy-mocks.spec.js → esm2020/lib/display/hierarchy/hierarchy-mocks.spec.mjs} +5 -9
  54. package/esm2020/lib/display/hierarchy/hierarchy-tree/hierarchy-tree.component.mjs +59 -0
  55. package/esm2020/lib/display/item-display/item-display.component.mjs +67 -0
  56. package/esm2020/lib/display/json-display/json-display.component.mjs +47 -0
  57. package/esm2020/lib/display/resizable/resizable-base.mjs +120 -0
  58. package/esm2020/lib/display/resizable/resizable.component.mjs +57 -0
  59. package/esm2020/lib/display/spinner/spinner.component.mjs +12 -0
  60. package/esm2020/lib/display/splash/splash.component.mjs +42 -0
  61. package/esm2020/lib/display/splash/splash.service.mjs +35 -0
  62. package/esm2020/lib/display/table/resizable-column.component.mjs +20 -0
  63. package/esm2020/lib/display/table/resizable-table.directive.mjs +227 -0
  64. package/esm2020/lib/display/table/searchable-table.component.mjs +338 -0
  65. package/esm2020/lib/display/table/table-detail-row.component.mjs +27 -0
  66. package/esm2020/lib/display/table/table-locked-column.component.mjs +58 -0
  67. package/esm2020/lib/display/table/table-master-header-row.component.mjs +11 -0
  68. package/esm2020/lib/display/table/table-master-row.component.mjs +150 -0
  69. package/esm2020/lib/display/table/table-pagination.component.mjs +150 -0
  70. package/esm2020/lib/display/table/table-selectable-row.component.mjs +235 -0
  71. package/esm2020/lib/display/table/table.component.mjs +244 -0
  72. package/esm2020/lib/display/tags/tag.mjs +15 -0
  73. package/esm2020/lib/display/tags/tags.component.mjs +77 -0
  74. package/esm2020/lib/display/toast/toast/toast.component.mjs +77 -0
  75. package/{esm2015/lib/display/toast/toast-types.js → esm2020/lib/display/toast/toast-types.mjs} +0 -0
  76. package/esm2020/lib/display/toast/toast.service.mjs +35 -0
  77. package/esm2020/lib/display/toast/toaster/toaster.component.mjs +114 -0
  78. package/esm2020/lib/display/tooltip/tooltip.component.mjs +25 -0
  79. package/esm2020/lib/display/tooltip/tooltip.service.mjs +63 -0
  80. package/esm2020/lib/display/tree/tree.component.mjs +125 -0
  81. package/esm2020/lib/display/view-overlay/view-overlay.component.mjs +58 -0
  82. package/esm2020/lib/shared/directives/click-area-for/click-area-for.directive.mjs +32 -0
  83. package/esm2020/lib/shared/directives/if-viewport-width/if-viewport-width.directive.mjs +111 -0
  84. package/esm2020/lib/shared/directives/popup/popup-container.directive.mjs +163 -0
  85. package/esm2020/lib/shared/display/pipes/date-display.pipe.mjs +50 -0
  86. package/esm2020/lib/shared/display/pipes/highlight-text.pipe.mjs +30 -0
  87. package/esm2020/lib/shared/display/pipes/relative-date.pipe.mjs +48 -0
  88. package/esm2020/lib/shared/display/pipes/row-count.pipe.mjs +48 -0
  89. package/esm2020/lib/shared/display/pipes/time-display.pipe.mjs +41 -0
  90. package/{esm2015/lib/shared/display.js → esm2020/lib/shared/display.mjs} +0 -0
  91. package/esm2020/lib/shared/form-group.helper.mjs +67 -0
  92. package/{esm2015/lib/shared/json-helper.js → esm2020/lib/shared/json-helper.mjs} +0 -0
  93. package/{esm2015/lib/shared/lodash-helper.js → esm2020/lib/shared/lodash-helper.mjs} +0 -0
  94. package/esm2020/lib/shared/page/page-base/page-base.component.mjs +339 -0
  95. package/{esm2015/lib/shared/page/page-statuses.js → esm2020/lib/shared/page/page-statuses.mjs} +0 -0
  96. package/esm2020/lib/shared/page/page-title/page-title.component.mjs +23 -0
  97. package/esm2020/lib/shared/page/page-view/page-view.component.mjs +121 -0
  98. package/{esm2015/lib/shared/testing/hierarchy-base-test-injector-factory.spec.js → esm2020/lib/shared/testing/hierarchy-base-test-injector-factory.spec.mjs} +0 -0
  99. package/esm2020/lib/shared/testing/page-base-component-test-helper.spec.mjs +30 -0
  100. package/{esm2015/lib/shared/testing/page-base-component-test-injector-factory.spec.js → esm2020/lib/shared/testing/page-base-component-test-injector-factory.spec.mjs} +0 -0
  101. package/esm2020/lib/shared/testing/public-mocks.spec.mjs +132 -0
  102. package/{esm2015/lib/shared/testing/spy-factory.spec.js → esm2020/lib/shared/testing/spy-factory.spec.mjs} +0 -0
  103. package/{esm2015/lib/shared/testing/translation-mocks.spec.js → esm2020/lib/shared/testing/translation-mocks.spec.mjs} +0 -0
  104. package/esm2020/lib/shared/user-preference.service.mjs +17 -0
  105. package/esm2020/lib/shared/wizard/wizard-base/wizard-base.component.mjs +246 -0
  106. package/esm2020/lib/shared/wizard/wizard-buttons/wizard-buttons.component.mjs +68 -0
  107. package/esm2020/lib/shared/wizard/wizard-progress/wizard-progress.component.mjs +18 -0
  108. package/{esm2015/public-api.js → esm2020/public-api.mjs} +0 -0
  109. package/fesm2015/energycap-components.mjs +10090 -0
  110. package/fesm2015/energycap-components.mjs.map +1 -0
  111. package/fesm2020/energycap-components.mjs +9999 -0
  112. package/fesm2020/energycap-components.mjs.map +1 -0
  113. package/index.d.ts +5 -0
  114. package/lib/components.module.d.ts +72 -0
  115. package/lib/controls/banner/banner.component.d.ts +3 -0
  116. package/lib/controls/button/button.component.d.ts +3 -0
  117. package/lib/controls/button/copy-button.directive.d.ts +3 -0
  118. package/lib/controls/checkbox/checkbox.component.d.ts +3 -0
  119. package/lib/controls/collapsible-toggle/collapsible-toggle.component.d.ts +3 -0
  120. package/lib/controls/combobox/combobox.component.d.ts +5 -2
  121. package/lib/controls/dropdown/dropdown.component.d.ts +3 -0
  122. package/lib/controls/file-upload/file-upload.component.d.ts +5 -2
  123. package/lib/controls/form-control/form-control.component.d.ts +3 -0
  124. package/lib/controls/form-control-base.d.ts +3 -0
  125. package/lib/controls/form-control-label/form-control-label.component.d.ts +3 -0
  126. package/lib/controls/form-group/form-group.component.d.ts +6 -3
  127. package/lib/controls/help-popover/help-popover.component.d.ts +3 -0
  128. package/lib/controls/item-picker/item-picker.component.d.ts +5 -2
  129. package/lib/controls/link-button/link-button.component.d.ts +3 -0
  130. package/lib/controls/menu/menu.component.d.ts +3 -0
  131. package/lib/controls/navigation/nav-item-active.directive.d.ts +3 -0
  132. package/lib/controls/numericbox/numericbox.component.d.ts +5 -2
  133. package/lib/controls/popover/popover.component.d.ts +3 -0
  134. package/lib/controls/radio-button/radio-button.component.d.ts +3 -0
  135. package/lib/controls/select/select.component.d.ts +3 -0
  136. package/lib/controls/tabs/tabs.component.d.ts +3 -0
  137. package/lib/controls/textbox/textbox.component.d.ts +3 -0
  138. package/lib/core/cache.service.d.ts +3 -0
  139. package/lib/core/error.service.d.ts +3 -0
  140. package/lib/core/scroll.service.d.ts +3 -0
  141. package/lib/core/telemetry-tracker.service.d.ts +3 -0
  142. package/lib/core/telemetry.service.d.ts +3 -0
  143. package/lib/core/validation-message.service.d.ts +3 -0
  144. package/lib/core/window.service.d.ts +3 -0
  145. package/lib/display/app-bar/app-bar.component.d.ts +3 -0
  146. package/lib/display/avatar/avatar.component.d.ts +3 -0
  147. package/lib/display/avatar/avatar.service.d.ts +3 -0
  148. package/lib/display/confirm/confirm.component.d.ts +5 -2
  149. package/lib/display/dialog/dialog-group/dialog-group.component.d.ts +3 -0
  150. package/lib/display/dialog/dialog.component.d.ts +3 -0
  151. package/lib/display/dialog/dialog.service.d.ts +3 -0
  152. package/lib/display/hierarchy/hierarchy-base.d.ts +3 -0
  153. package/lib/display/hierarchy/hierarchy-tree/hierarchy-tree.component.d.ts +3 -0
  154. package/lib/display/item-display/item-display.component.d.ts +3 -0
  155. package/lib/display/json-display/json-display.component.d.ts +5 -2
  156. package/lib/display/resizable/resizable-base.d.ts +3 -0
  157. package/lib/display/resizable/resizable.component.d.ts +3 -0
  158. package/lib/display/spinner/spinner.component.d.ts +3 -0
  159. package/lib/display/splash/splash.component.d.ts +3 -0
  160. package/lib/display/splash/splash.service.d.ts +3 -0
  161. package/lib/display/table/resizable-column.component.d.ts +3 -0
  162. package/lib/display/table/resizable-table.directive.d.ts +3 -0
  163. package/lib/display/table/searchable-table.component.d.ts +6 -3
  164. package/lib/display/table/table-detail-row.component.d.ts +3 -0
  165. package/lib/display/table/table-locked-column.component.d.ts +3 -0
  166. package/lib/display/table/table-master-header-row.component.d.ts +3 -0
  167. package/lib/display/table/table-master-row.component.d.ts +3 -0
  168. package/lib/display/table/table-pagination.component.d.ts +3 -0
  169. package/lib/display/table/table-selectable-row.component.d.ts +5 -2
  170. package/lib/display/table/table.component.d.ts +3 -0
  171. package/lib/display/tags/tags.component.d.ts +3 -0
  172. package/lib/display/toast/toast/toast.component.d.ts +3 -0
  173. package/lib/display/toast/toast.service.d.ts +3 -0
  174. package/lib/display/toast/toaster/toaster.component.d.ts +3 -0
  175. package/lib/display/tooltip/tooltip.component.d.ts +3 -0
  176. package/lib/display/tooltip/tooltip.service.d.ts +3 -0
  177. package/lib/display/tree/tree.component.d.ts +3 -0
  178. package/lib/display/view-overlay/view-overlay.component.d.ts +3 -0
  179. package/lib/shared/directives/click-area-for/click-area-for.directive.d.ts +3 -0
  180. package/lib/shared/directives/if-viewport-width/if-viewport-width.directive.d.ts +3 -0
  181. package/lib/shared/directives/popup/popup-container.directive.d.ts +3 -0
  182. package/lib/shared/display/pipes/date-display.pipe.d.ts +3 -0
  183. package/lib/shared/display/pipes/highlight-text.pipe.d.ts +3 -0
  184. package/lib/shared/display/pipes/relative-date.pipe.d.ts +3 -0
  185. package/lib/shared/display/pipes/row-count.pipe.d.ts +3 -0
  186. package/lib/shared/display/pipes/time-display.pipe.d.ts +3 -0
  187. package/lib/shared/form-group.helper.d.ts +5 -2
  188. package/lib/shared/page/page-base/page-base.component.d.ts +5 -2
  189. package/lib/shared/page/page-title/page-title.component.d.ts +3 -0
  190. package/lib/shared/page/page-view/page-view.component.d.ts +3 -0
  191. package/lib/shared/testing/public-mocks.spec.d.ts +7 -0
  192. package/lib/shared/user-preference.service.d.ts +3 -0
  193. package/lib/shared/wizard/wizard-base/wizard-base.component.d.ts +3 -0
  194. package/lib/shared/wizard/wizard-buttons/wizard-buttons.component.d.ts +3 -0
  195. package/lib/shared/wizard/wizard-progress/wizard-progress.component.d.ts +3 -0
  196. package/package.json +27 -15
  197. package/src/styles/_functions.scss +6 -4
  198. package/src/styles/_icons.scss +1 -1
  199. package/src/styles/mixins/_control-base.scss +2 -2
  200. package/src/styles/mixins/_form-control-base.scss +3 -1
  201. package/src/styles/mixins/_spinner-base.scss +3 -1
  202. package/bundles/energycap-components.umd.js +0 -10646
  203. package/bundles/energycap-components.umd.js.map +0 -1
  204. package/bundles/energycap-components.umd.min.js +0 -17
  205. package/bundles/energycap-components.umd.min.js.map +0 -1
  206. package/energycap-components.d.ts +0 -7
  207. package/energycap-components.metadata.json +0 -1
  208. package/esm2015/energycap-components.js +0 -8
  209. package/esm2015/lib/components.module.js +0 -238
  210. package/esm2015/lib/controls/banner/banner.component.js +0 -94
  211. package/esm2015/lib/controls/button/button.component.js +0 -89
  212. package/esm2015/lib/controls/button/copy-button.directive.js +0 -63
  213. package/esm2015/lib/controls/checkbox/checkbox.component.js +0 -137
  214. package/esm2015/lib/controls/collapsible-toggle/collapsible-toggle.component.js +0 -35
  215. package/esm2015/lib/controls/combobox/combobox.component.js +0 -819
  216. package/esm2015/lib/controls/dropdown/dropdown.component.js +0 -207
  217. package/esm2015/lib/controls/file-upload/file-upload.component.js +0 -172
  218. package/esm2015/lib/controls/form-control/form-control.component.js +0 -65
  219. package/esm2015/lib/controls/form-control-base.js +0 -140
  220. package/esm2015/lib/controls/form-control-label/form-control-label.component.js +0 -139
  221. package/esm2015/lib/controls/form-group/form-group.component.js +0 -254
  222. package/esm2015/lib/controls/help-popover/help-popover.component.js +0 -22
  223. package/esm2015/lib/controls/item-picker/item-picker.component.js +0 -216
  224. package/esm2015/lib/controls/link-button/link-button.component.js +0 -12
  225. package/esm2015/lib/controls/menu/menu.component.js +0 -424
  226. package/esm2015/lib/controls/navigation/nav-item-active.directive.js +0 -86
  227. package/esm2015/lib/controls/numericbox/numericbox.component.js +0 -362
  228. package/esm2015/lib/controls/popover/popover.component.js +0 -85
  229. package/esm2015/lib/controls/radio-button/radio-button.component.js +0 -78
  230. package/esm2015/lib/controls/select/select.component.js +0 -89
  231. package/esm2015/lib/controls/tabs/tabs.component.js +0 -42
  232. package/esm2015/lib/controls/textbox/textbox.component.js +0 -149
  233. package/esm2015/lib/core/error.service.js +0 -56
  234. package/esm2015/lib/core/scroll.service.js +0 -88
  235. package/esm2015/lib/core/telemetry-tracker.service.js +0 -14
  236. package/esm2015/lib/core/telemetry.service.js +0 -40
  237. package/esm2015/lib/core/validation-message.service.js +0 -185
  238. package/esm2015/lib/core/window.service.js +0 -191
  239. package/esm2015/lib/display/app-bar/app-bar.component.js +0 -42
  240. package/esm2015/lib/display/avatar/avatar.component.js +0 -73
  241. package/esm2015/lib/display/confirm/confirm.component.js +0 -127
  242. package/esm2015/lib/display/dialog/dialog-group/dialog-group.component.js +0 -65
  243. package/esm2015/lib/display/dialog/dialog.component.js +0 -229
  244. package/esm2015/lib/display/dialog/dialog.service.js +0 -69
  245. package/esm2015/lib/display/hierarchy/hierarchy-base.js +0 -106
  246. package/esm2015/lib/display/hierarchy/hierarchy-tree/hierarchy-tree.component.js +0 -58
  247. package/esm2015/lib/display/item-display/item-display.component.js +0 -57
  248. package/esm2015/lib/display/json-display/json-display.component.js +0 -44
  249. package/esm2015/lib/display/resizable/resizable-base.js +0 -119
  250. package/esm2015/lib/display/resizable/resizable.component.js +0 -57
  251. package/esm2015/lib/display/spinner/spinner.component.js +0 -12
  252. package/esm2015/lib/display/splash/splash.component.js +0 -45
  253. package/esm2015/lib/display/splash/splash.service.js +0 -34
  254. package/esm2015/lib/display/table/resizable-column.component.js +0 -23
  255. package/esm2015/lib/display/table/resizable-table.directive.js +0 -223
  256. package/esm2015/lib/display/table/searchable-table.component.js +0 -303
  257. package/esm2015/lib/display/table/table-detail-row.component.js +0 -21
  258. package/esm2015/lib/display/table/table-locked-column.component.js +0 -53
  259. package/esm2015/lib/display/table/table-master-header-row.component.js +0 -11
  260. package/esm2015/lib/display/table/table-master-row.component.js +0 -141
  261. package/esm2015/lib/display/table/table-pagination.component.js +0 -146
  262. package/esm2015/lib/display/table/table-selectable-row.component.js +0 -216
  263. package/esm2015/lib/display/table/table.component.js +0 -210
  264. package/esm2015/lib/display/tags/tag.js +0 -15
  265. package/esm2015/lib/display/tags/tags.component.js +0 -73
  266. package/esm2015/lib/display/toast/toast/toast.component.js +0 -70
  267. package/esm2015/lib/display/toast/toast.service.js +0 -34
  268. package/esm2015/lib/display/toast/toaster/toaster.component.js +0 -117
  269. package/esm2015/lib/display/tooltip/tooltip.component.js +0 -24
  270. package/esm2015/lib/display/tooltip/tooltip.service.js +0 -64
  271. package/esm2015/lib/display/tree/tree.component.js +0 -100
  272. package/esm2015/lib/display/view-overlay/view-overlay.component.js +0 -50
  273. package/esm2015/lib/shared/directives/click-area-for/click-area-for.directive.js +0 -25
  274. package/esm2015/lib/shared/directives/if-viewport-width/if-viewport-width.directive.js +0 -112
  275. package/esm2015/lib/shared/directives/popup/popup-container.directive.js +0 -160
  276. package/esm2015/lib/shared/display/pipes/date-display.pipe.js +0 -49
  277. package/esm2015/lib/shared/display/pipes/highlight-text.pipe.js +0 -26
  278. package/esm2015/lib/shared/display/pipes/relative-date.pipe.js +0 -49
  279. package/esm2015/lib/shared/display/pipes/row-count.pipe.js +0 -47
  280. package/esm2015/lib/shared/display/pipes/time-display.pipe.js +0 -40
  281. package/esm2015/lib/shared/form-group.helper.js +0 -65
  282. package/esm2015/lib/shared/page/page-base/page-base.component.js +0 -356
  283. package/esm2015/lib/shared/page/page-title/page-title.component.js +0 -19
  284. package/esm2015/lib/shared/page/page-view/page-view.component.js +0 -94
  285. package/esm2015/lib/shared/testing/page-base-component-test-helper.spec.js +0 -35
  286. package/esm2015/lib/shared/testing/public-mocks.spec.js +0 -126
  287. package/esm2015/lib/shared/user-preference.service.js +0 -15
  288. package/esm2015/lib/shared/wizard/wizard-base/wizard-base.component.js +0 -260
  289. package/esm2015/lib/shared/wizard/wizard-buttons/wizard-buttons.component.js +0 -54
  290. package/esm2015/lib/shared/wizard/wizard-progress/wizard-progress.component.js +0 -18
  291. package/fesm2015/energycap-components.js +0 -9638
  292. package/fesm2015/energycap-components.js.map +0 -1
@@ -1,819 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, HostListener, TemplateRef } from '@angular/core';
3
- import { FormControl, Validators } from "@angular/forms";
4
- import { TranslateService } from "@ngx-translate/core";
5
- import { FormControlBase } from '../form-control-base';
6
- import { takeUntil, take } from 'rxjs/operators';
7
- import { TextboxComponent } from '../textbox/textbox.component';
8
- import { ValidationMessageService } from '../../core/validation-message.service';
9
- import { FormGroupHelper } from '../../shared/form-group.helper';
10
- import { PopupContainerDirective } from '../../shared/directives/popup/popup-container.directive';
11
- import { ScrollService } from '../../core/scroll.service';
12
- /**
13
- * Select box (select, autocomplete, combobox)
14
- *
15
- * NOTE: Min/max length validation is implemented on the internal ec-textbox.
16
- * Values passed in via input properties (@see maxlength , @see minlength )
17
- * are used to create validators on the textbox. When the validation on the
18
- * textbox fails, the validation error(s) get passed up to the {@see formModel }.
19
- * When setting up this component's {@see FormControl }, you do NOT need to set the
20
- * Validators.minLength or Validators.maxLength validators.
21
- *
22
- * Required is also passed via input property, but you SHOULD also set up the
23
- * Validators.required validator on this component's FormControl.
24
- *
25
- * @export
26
- */
27
- export class ComboboxComponent extends FormControlBase {
28
- constructor(validationMessageService, formGroupHelper, translate, scrollService) {
29
- super(validationMessageService, formGroupHelper);
30
- this.validationMessageService = validationMessageService;
31
- this.formGroupHelper = formGroupHelper;
32
- this.translate = translate;
33
- this.scrollService = scrollService;
34
- /**
35
- * Position of the menu relative to the text box
36
- * @default 'bottom_right'
37
- * @memberof ComboboxComponent
38
- */
39
- this.menuPosition = 'bottom_right';
40
- /**
41
- * Items to show in combobox menu
42
- *
43
- * @memberof ComboboxComponent
44
- */
45
- this.options = [];
46
- /**
47
- * Display template for menu items
48
- *
49
- * @memberof ComboboxComponent
50
- */
51
- this.templateType = 'label';
52
- /**
53
- * Position the menu as fixed, ideal when comboboxes are inside dialogs
54
- * Defaulting to true so all menus will be at least the width of the
55
- * textbox + button, but can grow wider if the inner elements need it
56
- */
57
- this.popupFixed = true;
58
- /**
59
- * If set to true, we will upperCase the text box and apply the class on the add box
60
- */
61
- this.upperCase = false;
62
- /**The placeholder to show in the combobox. Leave empty to use default behavior determined
63
- * by whether Add New is enabled
64
- */
65
- this.placeholder = '';
66
- /** Do not display the toggle button when true */
67
- this.hideToggleButton = false;
68
- /**
69
- * Always show the menu when the formModel has a value. Sets
70
- * hideToggleButton to true and menuStatus to visible as well.
71
- */
72
- this.alwaysOpen = false;
73
- /**
74
- * Additonal classes to apply to the ec-menu element
75
- */
76
- this.menuElementClasses = [];
77
- /**
78
- * Additional classes to apply to the .textbox-group element
79
- */
80
- this.textboxElementClasses = [];
81
- /** Hide 'No matches' message when true */
82
- this.hideNoMatches = false;
83
- /**
84
- * Text to show when the menu is empty. "No matches" is the default.
85
- */
86
- this.noMatchesText = 'NoMatches_SC';
87
- /**
88
- * Notify the parent that the add new button was clicked
89
- * @todo discuss if we need to send along the value or should
90
- * the parent get it from the formModel
91
- * (lwf 2017.07.13): I think we might as well send the value along and
92
- * leave it up to the parent to decide how to handle it.
93
- */
94
- this.addNewClick = new EventEmitter();
95
- /**
96
- * Notify parent when text typed into textbox
97
- */
98
- this.search = new EventEmitter();
99
- /**
100
- * Filtered Items to show in combobox menu
101
- */
102
- this.filteredOptions = [];
103
- /**
104
- * Tracks if the menu is open or hidden
105
- */
106
- this.menuStatus = 'hidden';
107
- /**
108
- * Placeholder to assign to textbox
109
- */
110
- this.effectivePlaceholder = '';
111
- /**
112
- * Reference to the currently-selected menu item
113
- */
114
- this.selectedItem = null;
115
- /**
116
- * FormControl for the textbox
117
- */
118
- this.textboxFormModel = new FormControl('');
119
- /**
120
- * Tracks whether the add new button is selected
121
- */
122
- this.addNewSelected = false;
123
- /**
124
- * Tracks whether the textboxFormModel value matches an item in the filteredOptions
125
- */
126
- this.foundMatch = false;
127
- /**
128
- * Index of the currently-selected options
129
- */
130
- this.selectedItemIndex = -1;
131
- /** Placeholder text for 'Choose or Add...' */
132
- this.chooseOrAddPlaceholder = '';
133
- /** Placeholder text for 'Choose' */
134
- this.choosePlaceholder = '';
135
- this.hasDataBeenLoadedOnOpen = false;
136
- }
137
- /**
138
- * Close the popup menu on resize so the width and positioning can be recalculated
139
- * correctly. Cannot be placed on the popupDirective because of a bug where
140
- * HostListeners for global events don't fire
141
- * @see https://github.com/angular/angular/issues/14191
142
- */
143
- onResize() {
144
- if (this.popup)
145
- this.popup.hide();
146
- }
147
- /**
148
- * The angular onChanges lifecycle event
149
- * @see https://angular.io/guide/lifecycle-hooks
150
- */
151
- ngOnChanges(changes) {
152
- super.ngOnChanges(changes);
153
- // when options changes
154
- if (changes.options) {
155
- this.resetOptions();
156
- // Update the popup position
157
- if (this.popup) {
158
- this.popup.update();
159
- }
160
- }
161
- // update validators on the textbox
162
- if (changes.required || changes.minlength || changes.maxlength) {
163
- this.setTextboxFormModelValidators();
164
- }
165
- // Update placeholder text when 'Add New' is conditional.
166
- // ngOnChanges() kicks off before ngOnInit, so in order
167
- // to not overwrite a user-provided placeholder, do not
168
- // update placeholder on first change (ngOnInit will take care of it).
169
- if ((changes.addNew && !changes.addNew.isFirstChange()) || changes.placeholder) {
170
- this.updatePlaceholderText();
171
- }
172
- }
173
- /**
174
- * The angular onInit lifecycle hook
175
- * @see https://angular.io/guide/lifecycle-hooks
176
- */
177
- ngOnInit() {
178
- super.ngOnInit();
179
- if (this.alwaysOpen) {
180
- this.hideToggleButton = true;
181
- this.menuStatus = 'visible';
182
- }
183
- // Get translated placeholder text
184
- this.chooseOrAddPlaceholder = `${this.translate.instant('Choose or add')}...`;
185
- this.choosePlaceholder = `${this.translate.instant('Choose')}`;
186
- this.formModelChanged(this.formModel.value);
187
- this.setTextboxFormModelValidators();
188
- // Errors for this component are displayed via the validationErrors property, which is
189
- // populated when translateValidationMessages is run.
190
- // When the internal TextboxComponent has validation errors, we set them on the
191
- // formModel as well. This updates the validity of our ComboboxComponent control,
192
- // but does not trigger translation. Subscribe to statusChanges here so component
193
- // validation errors will appear along with the ComboboxComponent's label.
194
- this.formModel.valueChanges.pipe(takeUntil(this.componentDestroyed)).subscribe(data => this.formModelChanged(data));
195
- this.textboxFormModel.statusChanges.pipe(takeUntil(this.componentDestroyed)).subscribe(data => this.setFormModelValidationErrors(data));
196
- // default placeholder
197
- this.updatePlaceholderText();
198
- }
199
- /**
200
- * The angular afterViewInit lifecycle hook
201
- * @see https://angular.io/guide/lifecycle-hooks
202
- */
203
- ngAfterViewInit() {
204
- if (!this.popup) {
205
- return;
206
- }
207
- // allow overflow out of the scrollParent
208
- // prevents menu from obscuring the combobox
209
- let popperOptions = {
210
- modifiers: {
211
- preventOverflow: {
212
- boundariesElement: 'viewport'
213
- }
214
- }
215
- };
216
- // convert the ComboboxMenuPosition into a PopperPlacement
217
- switch (this.menuPosition) {
218
- case ("top_left"):
219
- popperOptions.placement = 'top-start';
220
- break;
221
- case ("top_right"):
222
- popperOptions.placement = 'top-end';
223
- break;
224
- case ("bottom_left"):
225
- popperOptions.placement = 'bottom-start';
226
- break;
227
- case ("bottom_right"):
228
- popperOptions.placement = 'bottom-end';
229
- break;
230
- default:
231
- throw new Error(`Invalid menuPosition for ComboboxComponent.`);
232
- }
233
- // Scroll the menu to the selected item once the popup menu is ready
234
- popperOptions.onCreate = () => {
235
- this.scrollMenu();
236
- if (this.popupFixed) {
237
- this.popup.fixPosition();
238
- }
239
- };
240
- if (this.popupFixed) {
241
- popperOptions.onUpdate = () => {
242
- this.popup.fixPosition();
243
- };
244
- }
245
- this.popup.popperOptions = popperOptions;
246
- this.popup.popperStatusChange.pipe(takeUntil(this.componentDestroyed)).subscribe((event) => {
247
- this.menuStatus = event;
248
- // Synchronize the formModel and textFormModel values when the
249
- // popup menu closes and un-filter the options and reset the
250
- // selectedItem and index
251
- if (event === 'hidden') {
252
- this.syncModelValues();
253
- this.resetOptions();
254
- }
255
- });
256
- }
257
- /**
258
- * Set errors on the textboxFormModel, which will then set errors on the
259
- * formModel. Also mark the formModel as touched to display any errors.
260
- * @param errors key(s) of ValidationMessageService errors to display or remove
261
- * @memberof ComoboboxComponent
262
- */
263
- setErrors(errors) {
264
- this.textboxFormModel.setErrors(errors);
265
- this.formModel.markAsTouched();
266
- }
267
- /**
268
- * Unfilter options and update the selectedItem and selectedItemIndex
269
- * @memberof ComboboxComponent
270
- */
271
- resetOptions(options) {
272
- this.filteredOptions = options || this.options;
273
- //if they have no search term, don't try to select anything so they can clear the box out by hitting enter
274
- //if they have a search term and the options changed, select an option from the menu so they will get it automatically if they hit enter
275
- if (this.textboxFormModel.value !== '') {
276
- this.selectedItemIndex = this.findDefaultSelectionIndex(this.filteredOptions, this.textboxFormModel.value);
277
- this.selectedItem = this.filteredOptions[this.selectedItemIndex] || null;
278
- this.scrollMenu(this.selectedItemIndex);
279
- }
280
- else {
281
- //if they have no search term and the options are reset, don't auto-pick the first one
282
- //so that enter will allow them to wipe out their last selection
283
- this.clearSelectedItem();
284
- }
285
- }
286
- /**
287
- * Listen to the selected changed event from {@link MenuComponent} and update the form
288
- * model and close menu
289
- */
290
- selectedChanged(item) {
291
- this.setFormModelValue(item);
292
- this.toggleMenu();
293
- }
294
- /**
295
- * Show and hide the popup menu
296
- *
297
- * @memberof ComboboxComponent
298
- */
299
- toggleMenu(event) {
300
- if (!this.popup) {
301
- return;
302
- }
303
- if (event) {
304
- event.stopPropagation();
305
- }
306
- if (!this.formModel.disabled) {
307
- if (this.menuStatus === 'visible') {
308
- // When the popup is hidden it will emit its changed status and
309
- // we will reset values if need be.
310
- this.popup.hide();
311
- }
312
- else {
313
- if (this.loadOnOpenObservable && !this.hasDataBeenLoadedOnOpen) {
314
- this.pending = true;
315
- this.loadOnOpenObservable.pipe(take(1)).subscribe((result) => {
316
- this.hasDataBeenLoadedOnOpen = true;
317
- this.pending = false;
318
- this.options = result;
319
- this.resetOptions();
320
- this.popup.show();
321
- });
322
- }
323
- else {
324
- this.popup.show();
325
- }
326
- }
327
- }
328
- }
329
- onBlur() {
330
- this.formModel.markAsTouched();
331
- }
332
- /**
333
- * Control the menu with keyboard navigation
334
- *
335
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key#Example | KeyboardEvent.key}
336
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values | Key Values}
337
- *
338
- * @memberof ComboboxComponent
339
- */
340
- keyNavigate(event) {
341
- switch (event.key) {
342
- case "ArrowDown":
343
- case "Down":
344
- case "ArrowUp":
345
- case "Up":
346
- event.stopPropagation();
347
- event.preventDefault();
348
- this.onArrowDownUp(event);
349
- break;
350
- case "Backspace":
351
- case "Delete":
352
- case "Del":
353
- if (this.menuStatus === 'hidden') {
354
- this.toggleMenu();
355
- }
356
- break;
357
- case "Tab":
358
- // If tabbing from the textbox to the button, override the textbox as being
359
- // marked touched so we don't see the invalid state. Only show the invalid state
360
- // when tabbing out of combobox from the button or back tabbing from the textbox
361
- // if (event.key === 'Tab' && event.srcElement && event.srcElement.tagName === 'INPUT') {
362
- // if (event.shiftKey) {
363
- // this.textboxFormModel.markAsTouched();
364
- // this.formModel.markAsTouched();
365
- // } else {
366
- // this.textboxFormModel.markAsUntouched();
367
- // }
368
- // } else if (event.key === 'Tab' && event.srcElement && event.srcElement.tagName === 'BUTTON') {
369
- // if (!event.shiftKey) {
370
- // this.formModel.markAsTouched();
371
- // }
372
- // }
373
- if (this.menuStatus === 'visible') {
374
- //if the selected option is the add new button let it fire but don't allow
375
- //the tab event to carry them forward from wherever they land - they would skip the first box on the add new form
376
- //In the normal case we want to allow the default behavior or they won't be able to tab out of the control at all.
377
- if (this.addNewSelected) {
378
- event.preventDefault();
379
- }
380
- this.commitSelection(event);
381
- }
382
- break;
383
- case "Enter":
384
- event.preventDefault();
385
- if (this.menuStatus === 'visible') {
386
- this.commitSelection(event);
387
- }
388
- break;
389
- case "Escape":
390
- case "Esc":
391
- if (this.menuStatus === 'visible') {
392
- // Just close the menu, do not focus the next element on tab
393
- // unless the menu is hidden
394
- event.preventDefault();
395
- // Close the menu before we reset selectedItem so we don't see the highlight changing
396
- // when reset the selected item back to the formModel
397
- this.toggleMenu();
398
- }
399
- break;
400
- case " ":
401
- case "Spacebar":
402
- if (this.menuStatus === 'hidden') {
403
- event.preventDefault();
404
- this.toggleMenu();
405
- }
406
- break;
407
- default:
408
- if (this.menuStatus === 'hidden' && event.key !== 'Shift') {
409
- this.toggleMenu();
410
- }
411
- break;
412
- }
413
- }
414
- /**
415
- * Facilitates adding items to a combobox
416
- *
417
- * @param addFn Function from parent that should make an API request to add a new item to the combobox's options
418
- * @memberof ComboboxComponent
419
- */
420
- addNewItem(addFn) {
421
- return __awaiter(this, void 0, void 0, function* () {
422
- this.pending = true;
423
- try {
424
- yield addFn();
425
- }
426
- catch (e) {
427
- // We gave it our best try, something is really whack, so let's just set the error
428
- this.setErrors({ 'addnew': true });
429
- }
430
- this.pending = false;
431
- this.toggleMenu();
432
- });
433
- }
434
- /**
435
- * Figure out whether they are adding new or have an item selected, and commit it to the form model
436
- */
437
- commitSelection(event) {
438
- if (this.addNewSelected) {
439
- event.stopPropagation();
440
- this.onAddNew(event);
441
- }
442
- else {
443
- this.setFormModelValue(this.selectedItem);
444
- this.toggleMenu();
445
- }
446
- }
447
- /**
448
- * Send the current value of the textbox to the parent when the add new button is
449
- * clicked
450
- *
451
- * @param event Add new button click or enter key event
452
- * @memberof ComboboxComponent
453
- */
454
- onAddNew(event) {
455
- event.stopPropagation();
456
- this.addNewSelected = false;
457
- this.addNewClick.emit(this.textboxFormModel.value);
458
- }
459
- /**
460
- * Navigate the dropdown menu using up and down arrow keys
461
- *
462
- * @param event Up or down arrow keydown event
463
- * @memberof ComboboxComponent
464
- */
465
- onArrowDownUp(event) {
466
- switch (event.key) {
467
- case "ArrowDown":
468
- case "Down":
469
- if (this.selectedItemIndex === -1 && this.addNewButton && !this.addNewButton.nativeElement.hidden && !this.addNewSelected) {
470
- this.addNewSelected = true;
471
- }
472
- else if (this.selectedItemIndex < this.filteredOptions.length - 1) {
473
- if (this.addNewSelected) {
474
- this.addNewSelected = false;
475
- }
476
- //if the last item is a heading and we are on the second last item, we shouldn't increment the selectedItemIndex because that would select the heading
477
- if (!(this.selectedItemIndex == this.filteredOptions.length - 2 && this.filteredOptions[this.selectedItemIndex + 1].display === 'heading')) {
478
- this.selectedItemIndex++;
479
- // Skip any in-menu heading items
480
- if (this.selectedItemIndex < this.filteredOptions.length - 1 && this.filteredOptions[this.selectedItemIndex].display === 'heading') {
481
- this.selectedItemIndex++;
482
- }
483
- }
484
- }
485
- break;
486
- case "ArrowUp":
487
- case "Up":
488
- if (this.selectedItemIndex === -1 && this.addNewButton && !this.addNewButton.nativeElement.hidden && this.addNewSelected) {
489
- this.addNewSelected = false;
490
- }
491
- else if (this.selectedItemIndex > -1) {
492
- if (this.selectedItemIndex === 0 && this.addNewButton && !this.addNewButton.nativeElement.hidden) {
493
- this.addNewSelected = true;
494
- }
495
- this.selectedItemIndex--;
496
- // Skip any in-menu heading items
497
- if (this.selectedItemIndex > -1 && this.filteredOptions[this.selectedItemIndex].display === 'heading') {
498
- this.selectedItemIndex--;
499
- //if the selectedItemIndex is -1, that means the very first item was a heading and we just skipped over it.
500
- if (this.selectedItemIndex == -1) {
501
- //if there is an add new button we should select it. otherwise we should lock them at index 1 (right before the heading)
502
- if (this.addNewButton && !this.addNewButton.nativeElement.hidden) {
503
- this.addNewSelected = true;
504
- }
505
- else {
506
- this.selectedItemIndex = 1;
507
- }
508
- }
509
- }
510
- }
511
- break;
512
- default:
513
- return;
514
- }
515
- this.selectedItem = this.filteredOptions[this.selectedItemIndex];
516
- if (this.menuStatus === 'hidden') {
517
- this.setFormModelValue(this.selectedItem);
518
- }
519
- else {
520
- this.scrollMenu();
521
- }
522
- }
523
- /**
524
-
525
- * Filter array of options by label (contains)
526
- *
527
- * @param filterText The value of textbox that we will filter our options by
528
- *
529
- * @memberof ComboboxComponent
530
- */
531
- filterOptionsArray(filterText) {
532
- let searchText = filterText.toLowerCase();
533
- if (filterText && filterText !== '') {
534
- return this.options.filter(item => {
535
- return item.label.toLowerCase().indexOf(searchText) >= 0;
536
- });
537
- }
538
- else {
539
- return this.options;
540
- }
541
- }
542
- /**
543
- * Find a given item's index in the filtered items array.
544
- *
545
- * Returns -1 if not found
546
- * @param item The matching item to find in the
547
- * filterdOptions array. Will use the selectedItem if nothing is passed.
548
- * @memberof ComboboxComponent
549
- */
550
- findSelectedItemIndex(item) {
551
- let itemToFind = item ? item : this.selectedItem;
552
- if (itemToFind) {
553
- return this.filteredOptions.findIndex(item => {
554
- if (item.id && itemToFind.id) {
555
- return item.label === itemToFind.label && item.id === itemToFind.id;
556
- }
557
- else {
558
- return item.label === itemToFind.label;
559
- }
560
- });
561
- }
562
- return -1;
563
- }
564
- /**
565
- * React to our formModel changing
566
- *
567
- * The formModel represents the currently selected ModelItem
568
- * When changed, set the value of the TextboxComponent and
569
- * find index of item in options list.
570
- *
571
- * @memberof ComboboxComponent
572
- */
573
- formModelChanged(data) {
574
- this.synchronizeDisabledAttributes();
575
- if (data) {
576
- this.textboxFormModel.setValue(data.label);
577
- this.selectedItemIndex = this.findSelectedItemIndex(data);
578
- if (this.selectedItemIndex >= 0) {
579
- this.selectedItem = this.filteredOptions[this.selectedItemIndex];
580
- }
581
- }
582
- else {
583
- //The host wiped out the data externally, clear the textbox and the tracking state
584
- this.textboxFormModel.reset();
585
- this.clearSelectedItem();
586
- }
587
- }
588
- /**
589
- * Scroll the menu if the current selectedItemIndex is out of view
590
- *
591
- * @memberof ComboboxComponent
592
- */
593
- scrollMenu(knownIndex) {
594
- if (this.filteredOptions.length > 0) {
595
- // Update the selectedItemIndex in case our options changed
596
- this.selectedItemIndex = knownIndex === undefined ? this.findSelectedItemIndex() : knownIndex;
597
- if (this.selectedItemIndex > -1 && this.selectedItem) {
598
- // The menu component will automatically generate ids for the menu items if they dont have them,
599
- // so they need to be accounted for here since the combobox doesn't know about those ids
600
- let itemSelector = this.selectedItem.id ? `#${this.selectedItem.id}` : `#${this.id}_menu_item${this.selectedItemIndex}`;
601
- //trigger the scrolling after a tick to allow the menu to be up to date (and pending mask cleared) before measuring
602
- setTimeout(() => {
603
- this.scrollService.scrollItemCentered(`#${this.id}_menu_list`, itemSelector);
604
- }, 0);
605
- }
606
- else {
607
- this.selectedItem = null;
608
- }
609
- }
610
- }
611
- /**
612
- * Search/Filter based on textbox input
613
- * NOTE: so as not to receive a notification on every key event, we suggest you debounce your
614
- * subscription
615
- * @see {@link http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-debounceTime | Observable.debounceTime}
616
- *
617
- * @memberof ComboboxComponent
618
- */
619
- searchAndFilter(searchText) {
620
- // always emit
621
- this.search.emit(searchText);
622
- // do internal filtering if no one's subscribed to our search emitter
623
- if (this.search.observers.length === 0 && searchText !== undefined) {
624
- this.resetOptions(this.filterOptionsArray(searchText));
625
- if (this.addNewSelected && !this.addNewButton) {
626
- this.addNewSelected = false;
627
- }
628
- }
629
- }
630
- /**
631
- * Set {@link formModel }'s validation errors equal to the internal textbox's.
632
- *
633
- * When the internal textbox is invalid, need to set this control's
634
- * errors because we are using our own label, not TextboxControl's.
635
- * We use our own label so label text will wrap at the end of the button,
636
- * not at the end of the textbox.
637
- *
638
- * @memberof ComboboxComponent
639
- */
640
- setFormModelValidationErrors(data) {
641
- if (this.textboxFormModel.invalid) {
642
- this.formModel.setErrors(this.textboxFormModel.errors);
643
- }
644
- else {
645
- this.formModel.setErrors(null);
646
- }
647
- }
648
- /**
649
- * Update the form model value with the selected item or reset form model value if item is null
650
- *
651
- * @memberof ComboboxComponent
652
- */
653
- setFormModelValue(item) {
654
- this.textboxFormModel.setValue(item ? item.label : '');
655
- this.formModel.setValue(item);
656
- this.formModel.markAsDirty();
657
- }
658
- /**
659
- * Set validators on the {@see textboxFormModel }
660
- *
661
- * Validators are currently set based on the {@see maxlength },
662
- * {@see minlength }, and {@see required } inputs. This works well
663
- * with {@see TextboxComponent }, which needs these inputs to apply
664
- * the proper attributes to its inputs.
665
- *
666
- * A future release of Angular will supposedly add these attributes
667
- * for you, which will eliminate the need for TextboxComponent to have
668
- * such inputs. This component, however, will still need these inputs
669
- * as there is no current way to know which validators are applied to it
670
- * from its parent View Component.
671
- *
672
- *
673
- * @memberof ComboboxComponent
674
- */
675
- setTextboxFormModelValidators() {
676
- let validators = [];
677
- if (this.required) {
678
- validators.push(Validators.required);
679
- }
680
- if (this.minlength) {
681
- validators.push(Validators.minLength(this.minlength));
682
- }
683
- if (this.maxlength) {
684
- validators.push(Validators.maxLength(this.maxlength));
685
- }
686
- this.textboxFormModel.setValidators(validators);
687
- this.textboxFormModel.updateValueAndValidity();
688
- }
689
- /**
690
- * Keep textbox's disabled status in-sync with combobox's
691
- *
692
- * {@link TextboxComponent} gets its disabled status from its {@link FormControl}
693
- *
694
- * @memberof ComboboxComponent
695
- */
696
- synchronizeDisabledAttributes() {
697
- if (this.formModel.disabled !== this.textboxFormModel.disabled) {
698
- if (this.formModel.disabled) {
699
- this.textboxFormModel.disable();
700
- }
701
- else {
702
- this.textboxFormModel.enable();
703
- }
704
- }
705
- }
706
- /**
707
- * If the formModel value and textbox value do not match, reset the textbox and selectedItem to
708
- * the formModle value. If there is no formModel value, make sure we clear the textbox. Reset the
709
- * filteredOptions to the full list and update the selectedItemIndex
710
- *
711
- */
712
- syncModelValues() {
713
- // If there is a formModel value, reset the selected item. If there isn't, make
714
- // sure we clear the textbox
715
- if (this.formModel.value && this.formModel.value.label !== this.textboxFormModel.value) {
716
- this.textboxFormModel.setValue(this.formModel.value.label);
717
- }
718
- else if (!this.formModel.value) {
719
- this.textboxFormModel.setValue('');
720
- }
721
- }
722
- /**
723
- * Search and filter the options list when the value of the textbox input changes. If addNew is
724
- * set also check for matches in our filteredOptions to conditionally show and hide the add new
725
- * button
726
- *
727
- * @see https://developer.mozilla.org/en-US/docs/Web/Events/input
728
- */
729
- textboxValueChanged(event) {
730
- this.searchAndFilter(this.textboxFormModel.value);
731
- if (this.textboxFormModel.value === '') {
732
- this.clearSelectedItem();
733
- }
734
- if (this.addNew) {
735
- let match = this.filteredOptions.find((option) => {
736
- return option.label.toLowerCase() === this.textboxFormModel.value.toLowerCase();
737
- });
738
- this.foundMatch = match ? true : false;
739
- }
740
- // Update the popup menu position when input value changes
741
- if (this.popup) {
742
- this.popup.update();
743
- }
744
- }
745
- clearSelectedItem() {
746
- this.selectedItem = null;
747
- this.selectedItemIndex = -1;
748
- }
749
- /**Recompute what the placeholder should be based on whether the user provided one and the current state of the addNew input */
750
- updatePlaceholderText() {
751
- if (this.placeholder) {
752
- this.effectivePlaceholder = this.translate.instant(this.placeholder);
753
- }
754
- else if (this.addNew) {
755
- this.effectivePlaceholder = this.chooseOrAddPlaceholder;
756
- }
757
- else {
758
- this.effectivePlaceholder = this.choosePlaceholder;
759
- }
760
- }
761
- /**Find the option we want to be the default selection. If there is an exact match, use that
762
- * otherwise if there are items, return zero to indicate the first item. Otherwise return -1
763
- * to indicate no selection
764
- */
765
- findDefaultSelectionIndex(options, searchText) {
766
- let index = -1;
767
- if (options && options.length) {
768
- index = options.findIndex(option => option != null && option.display !== 'heading');
769
- if (searchText) {
770
- searchText = searchText.toLowerCase().trim();
771
- let exactMatchIndex = options.findIndex(option => option.label.toLowerCase() == searchText && option.display !== 'heading');
772
- if (exactMatchIndex >= 0) {
773
- index = exactMatchIndex;
774
- }
775
- }
776
- }
777
- return index;
778
- }
779
- }
780
- ComboboxComponent.decorators = [
781
- { type: Component, args: [{
782
- selector: 'ec-combobox',
783
- template: "<div class=\"control control-label-{{labelPosition}}\"\r\n [ngClass]=\"{'open': menuStatus === 'visible',\r\n 'invalid': formModel.touched && formModel.invalid,\r\n 'has-icon': (templateType === 'iconAndLabel' && formModel.value && formModel.value.icon && formModel.value.label === textboxFormModel.value),\r\n 'is-readonly': readonly,\r\n 'is-disabled': formModel.disabled,\r\n 'is-always-open': alwaysOpen}\">\r\n\r\n <label *ngIf=\"label\" ngPreserveWhitespaces>\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\">{{validationErrors}}</span>\r\n </label>\r\n\r\n <ng-container *ngIf=\"alwaysOpen; else popupTarget\">\r\n <div class=\"textbox-group control-input\" [ngClass]=\"textboxElementClasses\">\r\n <ng-container *ngTemplateOutlet=\"textbox\"></ng-container>\r\n </div>\r\n\r\n <ng-container *ngIf=\"filteredOptions.length > 0 || textboxFormModel.value\">\r\n <ng-container *ngTemplateOutlet=\"dropdownmenu\"></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<ng-template #popupTarget>\r\n <div class=\"textbox-group control-input\" [ngClass]=\"textboxElementClasses\" *ecPopup=\"dropdownmenu\">\r\n <ng-container *ngTemplateOutlet=\"textbox\"></ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #textbox>\r\n <i class=\"ec-icon {{formModel.value?.icon}}\"></i>\r\n\r\n <ec-textbox class=\"textbox-group-input mb-0\"\r\n #textbox\r\n [id]=\"id\"\r\n [autofocus]=\"autofocus\"\r\n [formModel]=\"textboxFormModel\"\r\n [maxlength]=\"maxlength\"\r\n [minlength]=\"minlength\"\r\n [placeholder]=\"effectivePlaceholder\"\r\n [required]=\"required\"\r\n [tabindex]=\"tabindex\"\r\n [readonly]=\"readonly\"\r\n (input)=\"textboxValueChanged($event)\"\r\n (keydown)=\"keyNavigate($event)\"\r\n (focusout)=\"onBlur()\"\r\n [upperCase]=\"upperCase\"\r\n [pending]=\"pending && alwaysOpen\"\r\n [autocomplete]=\"'off'\"></ec-textbox>\r\n\r\n <ec-button class=\"textbox-group-btn-right\"\r\n *ngIf=\"!hideToggleButton\"\r\n [id]=\"id + '_button'\"\r\n [disabled]=\"formModel.disabled\"\r\n icon=\"icon-caret-down\"\r\n [tabindex]=\"-1\"\r\n type=\"secondary\"\r\n (click)=\"toggleMenu($event)\"\r\n (keydown)=\"keyNavigate($event)\"></ec-button>\r\n</ng-template>\r\n\r\n<ng-template #dropdownmenu>\r\n <div class=\"popup\"\r\n ecOverlay\r\n [status]=\"pending && !alwaysOpen ? 'pending' : 'hasData'\">\r\n\r\n <button class=\"add-new\"\r\n id=\"{{id}}_addNew\"\r\n #addNewButton\r\n [class.is-selected]=\"addNewSelected\"\r\n *ngIf=\"addNew\"\r\n [hidden]=\"foundMatch || (addNew === 'dynamic' && (!textboxFormModel.value || (formModel.value && textboxFormModel.value === formModel.value.label)))\"\r\n\r\n (click)=\"onAddNew($event)\">\r\n <span class=\"add-new-label ec-util-truncate\">\r\n <span *ngIf=\"addNew === 'static' || addNew === true\" translate>Add new...</span>\r\n <span *ngIf=\"addNew === 'dynamic'\">{{'Add' | translate}} <strong class=\"ec-util-truncate\" [ngClass]=\"{'text-uppercase': upperCase}\">{{textboxFormModel.value}}</strong></span>\r\n </span>\r\n <i class=\"ec-icon icon-add\"></i>\r\n </button>\r\n\r\n <ec-menu id=\"{{id}}_menu\"\r\n [class.border-top-0]=\"!filteredOptions.length && hideNoMatches\"\r\n [ngClass]=\"menuElementClasses\"\r\n [templateType]=\"templateType\"\r\n [customMenuTemplate]=\"customMenuTemplate\"\r\n [showNoItems]=\"!hideNoMatches\"\r\n [noDataText]=\"noMatchesText\"\r\n [items]=\"filteredOptions\"\r\n [selected]=\"selectedItem\"\r\n (selectedChanged)=\"selectedChanged($event)\"></ec-menu>\r\n\r\n <footer *ngIf=\"totalRecords && totalRecords > filteredOptions.length && filteredOptions.length > 0\">\r\n <span>{{filteredOptions.length}} {{'of' | translate}} {{totalRecords}}</span>\r\n </footer>\r\n </div>\r\n</ng-template>\r\n",
784
- styles: ["@-webkit-keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}:root{--ec-color-icon:rgba(26,26,35,0.66);--ec-font-size-icon:1rem}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}:host{color:var(--ec-color-primary-dark);display:block;font-family:var(--ec-font-family);font-size:var(--ec-font-size-body);margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{display:flex;flex-direction:column;width:100%}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-bottom:0;margin-top:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;background-clip:border-box;background-color:rgba(26,26,35,.12);background-image:none;border-color:transparent;color:var(--ec-color-primary-dark);opacity:1;overflow:hidden;pointer-events:none;user-select:none;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-background-color-caution);background-image:url('data:image/svg+xml;charset=utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\"><path fill=\"rgba(26, 26, 35, 0.66)\" d=\"M20.21 20.21h-8.42L10.95 0h10.1l-.84 20.21zm-8.42 3.37h8.42V32h-8.42z\"/></svg>');background-position:.25rem;background-repeat:no-repeat;background-size:1rem,1rem;padding-left:1.5rem}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:not(:focus),:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:not(:focus){border-color:var(--ec-color-caution)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-background-color-caution)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-color-caution)}:host .textbox-group{display:flex;position:relative}:host input:focus,:host select:focus,:host textarea:focus{outline:none}:host(.invalid) .control .textbox-group-input ::ng-deep .control input.ng-invalid,:host(.invalid) .control .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-background-color-caution);background-image:url('data:image/svg+xml;charset=utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\"><path fill=\"rgba(26, 26, 35, 0.66)\" d=\"M20.21 20.21h-8.42L10.95 0h10.1l-.84 20.21zm-8.42 3.37h8.42V32h-8.42z\"/></svg>');background-position:.25rem;background-repeat:no-repeat;background-size:1rem,1rem;padding-left:1.5rem}:host(.invalid) .control .textbox-group-input ::ng-deep .control input.ng-invalid:not(:focus),:host(.invalid) .control .textbox-group-input ::ng-deep .control input.ng-valid:not(:focus){border-color:var(--ec-color-caution)}:host(.invalid) .control:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-background-color-caution)}:host(.invalid) .control:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-color-caution)}.control{position:relative}.control ec-textbox ::ng-deep input.ng-invalid.ng-touched{background-image:none;padding-left:.5rem}.control ec-textbox ::ng-deep input.ng-invalid.ng-touched:not(.is-empty)~.units-left{left:0}.control ec-textbox ::ng-deep input:required:not(:disabled).is-empty{background-color:var(--ec-background-color);background-image:url('data:image/svg+xml;charset=utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\"><path fill=\"%23ffe433\" d=\"M31.32 21.69l-.09.18-2.48 4.35c-.36.54-.77.62-1.25.27-.12 0-.2 0-.2-.09L19.53 22v9.37a1.26 1.26 0 0 1-.72.67h-5.26c-.59 0-.83-.3-.83-.89 0-.12.15-.21.15-.27V22l-8 4.71h-.12c-.42.66-.8.21-1.16-.27L1 21.82a.82.82 0 0 1 .35-1.26l.18-.1L9 16 .87 11.47v-.09c0-.36-.39-.74-.09-1.16l2.75-4.35v-.09c0-.42.82-.54 1.29-.36l8 4.62V.89c0-.59.18-.89.77-.89h5c.65 0 .91.3.91.89V10l7.94-4.53c.48-.29.72-.21 1.08.27l2.32 4.35v.09c.66.48.45.89-.08 1.25L23 16l7.91 4.53v.09c-.04.18.53.54.41 1.07z\"/></svg>');background-position:.25rem;background-repeat:no-repeat;background-size:1rem,1rem;border-color:var(--ec-border-color-legacy);padding-left:1.5rem}.control ec-textbox ::ng-deep input:required:not(:disabled).is-empty:focus{border-color:var(--ec-color-interactive);box-shadow:0 0 0 .0625rem var(--ec-color-interactive);position:relative;z-index:1}.control .textbox-group .ec-icon{display:none;left:.5rem;position:absolute;top:.5rem;z-index:2}.control.has-icon:not(.invalid) .ec-icon{display:inline-flex}.control.has-icon:not(.invalid) ec-textbox ::ng-deep input{padding-left:1.75rem}.control.is-disabled .ec-icon{filter:grayscale(100%);opacity:.65}.control.is-readonly ec-textbox ::ng-deep input{border-bottom-right-radius:var(--ec-border-radius);border-right-width:.0625rem;border-top-right-radius:var(--ec-border-radius)}.control.is-readonly ec-button{display:none}.control.is-always-open{height:100%}.control.is-always-open .textbox-group,.control.is-always-open label{margin-left:1rem;margin-right:1rem}.control.is-always-open .textbox-group{margin-bottom:1rem}.control.is-always-open .popup{background-color:transparent;border:0;box-shadow:none;flex:1 1;margin:0;min-height:0;z-index:0}.control.is-always-open ec-menu{border-top:1px solid var(--ec-border-color)}.control.is-always-open ec-menu ::ng-deep ul{max-height:none}label{color:var(--ec-color-secondary-dark);display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label)/2) 0}.popup{background-color:var(--ec-background-color);border-radius:var(--ec-border-radius-card);box-shadow:var(--ec-box-shadow-overlay);margin-top:.25rem;overflow:hidden;z-index:var(--ec-z-index-popup)}ec-menu{display:block}ec-menu:not(:first-child){border-top:1px solid var(--ec-border-color)}ec-menu ::ng-deep ul{max-height:30vh}ec-menu ::ng-deep ul li{white-space:nowrap}.add-new{align-items:center;background-color:var(--ec-background-color);border:0;cursor:pointer;display:flex;height:2rem;line-height:1.25;padding:.25rem .5rem;width:100%}.add-new.is-highlighted,.add-new.is-selected{background-color:#d9edf2}.add-new:focus{background-color:var(--ec-color-disabled-dark);outline:none;position:relative;z-index:1}.add-new:active{background-color:var(--ec-color-interactive);color:var(--ec-color-primary-light)}.add-new.is-disabled,.add-new:disabled{color:var(--ec-color-secondary-dark);cursor:default;opacity:.65}.add-new .label{align-items:center;display:flex;flex:auto}.add-new .ec-icon+.label{margin:0 .375rem}.add-new.is-selected,.add-new:hover:not(:active){background-color:#bfe0e9}.add-new:active .ec-icon{color:inherit}.add-new-label{flex:1 1;margin-right:.5rem;text-align:left}.add-new .ec-icon{flex:0 0 auto}footer{border-top:1px solid var(--ec-border-color);color:var(--ec-color-hint-dark);font-size:var(--ec-font-size-label);line-height:1;padding:.5rem;text-align:right}ec-button ::ng-deep button .ec-icon{background-position:50%;background-size:1em}.open:not(.is-always-open) .textbox-group ec-textbox ::ng-deep input{border-color:var(--ec-border-color-legacy);box-shadow:none}.open:not(.is-always-open) .textbox-group ec-button ::ng-deep button{background-color:var(--ec-background-color-hover);box-shadow:none}"]
785
- },] }
786
- ];
787
- ComboboxComponent.ctorParameters = () => [
788
- { type: ValidationMessageService },
789
- { type: FormGroupHelper },
790
- { type: TranslateService },
791
- { type: ScrollService }
792
- ];
793
- ComboboxComponent.propDecorators = {
794
- onResize: [{ type: HostListener, args: ['window:resize',] }],
795
- addNew: [{ type: Input }],
796
- maxlength: [{ type: Input }],
797
- menuPosition: [{ type: Input }],
798
- minlength: [{ type: Input }],
799
- options: [{ type: Input }],
800
- templateType: [{ type: Input }],
801
- customMenuTemplate: [{ type: Input }],
802
- popupFixed: [{ type: Input }],
803
- totalRecords: [{ type: Input }],
804
- upperCase: [{ type: Input }],
805
- placeholder: [{ type: Input }],
806
- loadOnOpenObservable: [{ type: Input }],
807
- hideToggleButton: [{ type: Input }],
808
- alwaysOpen: [{ type: Input }],
809
- menuElementClasses: [{ type: Input }],
810
- textboxElementClasses: [{ type: Input }],
811
- hideNoMatches: [{ type: Input }],
812
- noMatchesText: [{ type: Input }],
813
- addNewClick: [{ type: Output }],
814
- search: [{ type: Output }],
815
- textbox: [{ type: ViewChild, args: ['textbox',] }],
816
- popup: [{ type: ViewChild, args: [PopupContainerDirective,] }],
817
- addNewButton: [{ type: ViewChild, args: ['addNewButton',] }]
818
- };
819
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tYm9ib3guY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29tcG9uZW50cy9zcmMvbGliL2NvbnRyb2xzL2NvbWJvYm94L2NvbWJvYm94LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBbUQsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFLLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFlLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXZELE9BQU8sRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDaEUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDakYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRWpFLE9BQU8sRUFBRSx1QkFBdUIsRUFBZSxNQUFNLHlEQUF5RCxDQUFDO0FBQy9HLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQWUxRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQU1ILE1BQU0sT0FBTyxpQkFBa0IsU0FBUSxlQUFlO0lBK01yRCxZQUNXLHdCQUFrRCxFQUNsRCxlQUFnQyxFQUNoQyxTQUEyQixFQUMzQixhQUE0QjtRQUV0QyxLQUFLLENBQUMsd0JBQXdCLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFMdkMsNkJBQXdCLEdBQXhCLHdCQUF3QixDQUEwQjtRQUNs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N0lBQXNDOzthQUV0Qzs7O1lBdENRLHdCQUF3QjtZQUN4QixlQUFlO1lBTmYsZ0JBQWdCO1lBU2hCLGFBQWE7Ozt1QkEyQ3BCLFlBQVksU0FBQyxlQUFlO3FCQU81QixLQUFLO3dCQVFMLEtBQUs7MkJBUUwsS0FBSzt3QkFRTCxLQUFLO3NCQVFMLEtBQUs7MkJBUUwsS0FBSztpQ0FVRixLQUFLO3lCQVFSLEtBQUs7MkJBTUwsS0FBSzt3QkFLTCxLQUFLOzBCQU1MLEtBQUs7bUNBR0wsS0FBSzsrQkFHTCxLQUFLO3lCQU1MLEtBQUs7aUNBS0wsS0FBSztvQ0FLTCxLQUFLOzRCQUdMLEtBQUs7NEJBS0YsS0FBSzswQkFTUixNQUFNO3FCQU1OLE1BQU07c0JBR04sU0FBUyxTQUFDLFNBQVM7b0JBS25CLFNBQVMsU0FBQyx1QkFBdUI7MkJBTWpDLFNBQVMsU0FBQyxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE9uSW5pdCwgT25DaGFuZ2VzLCBTaW1wbGVDaGFuZ2VzLCBBZnRlclZpZXdJbml0LCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYsIEhvc3RMaXN0ZW5lciwgVGVtcGxhdGVSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMsIFZhbGlkYXRvckZuIH0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XHJcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tIFwiQG5neC10cmFuc2xhdGUvY29yZVwiO1xyXG5pbXBvcnQgeyBGb3JtQ29udHJvbEJhc2UgfSBmcm9tICcuLi9mb3JtLWNvbnRyb2wtYmFzZSc7XHJcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgdGFrZVVudGlsLCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBUZXh0Ym94Q29tcG9uZW50IH0gZnJvbSAnLi4vdGV4dGJveC90ZXh0Ym94LmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFZhbGlkYXRpb25NZXNzYWdlU2VydmljZSB9IGZyb20gJy4uLy4uL2NvcmUvdmFsaWRhdGlvbi1tZXNzYWdlLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGb3JtR3JvdXBIZWxwZXIgfSBmcm9tICcuLi8uLi9zaGFyZWQvZm9ybS1ncm91cC5oZWxwZXInO1xyXG5pbXBvcnQgeyBNZW51SXRlbSwgTWVudVRlbXBsYXRlVHlwZSwgTWVudUhvc3RFbGVtZW50Q2xhc3NlcyB9IGZyb20gJy4uL21lbnUvbWVudS5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBQb3B1cENvbnRhaW5lckRpcmVjdGl2ZSwgUG9wdXBTdGF0dXMgfSBmcm9tICcuLi8uLi9zaGFyZWQvZGlyZWN0aXZlcy9wb3B1cC9wb3B1cC1jb250YWluZXIuZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgU2Nyb2xsU2VydmljZSB9IGZyb20gJy4uLy4uL2NvcmUvc2Nyb2xsLnNlcnZpY2UnO1xyXG5cclxuLyoqXHJcbiAqIFBvc2l0aW9uIG9mIHRoZSBtZW51IHJlbGF0aXZlIHRvIHRoZSBpbnB1dFxyXG4gKi9cclxuZXhwb3J0IHR5cGUgQ29tYm9ib3hNZW51UG9zaXRpb24gPSBcInRvcF9yaWdodFwiIHwgXCJ0b3BfbGVmdFwiIHwgXCJib3R0b21fbGVmdFwiIHwgXCJib3R0b21fcmlnaHRcIjtcclxuXHJcblxyXG4vKipcclxuICogVGhlIHR5cGUgb2YgYWRkIG5ldyBpbXBsZW1lbnRhdGlvbi4gU3RhdGljIGRpc3BsYXlzIGEgc2ltcGxlIHN0YXRpYyBidXR0b24gd2hpbGUgZHluYW1pYyB1cGRhdGVzXHJcbiAqIHRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHdpdGggdmFsdWUgb2YgdGhlIHRleHRib3hcclxuICovXHJcbnR5cGUgQWRkTmV3VHlwZSA9IFwiZHluYW1pY1wiIHwgXCJzdGF0aWNcIiB8IGJvb2xlYW47XHJcblxyXG5cclxuLyoqXHJcbiAqIFNlbGVjdCBib3ggKHNlbGVjdCwgYXV0b2NvbXBsZXRlLCBjb21ib2JveClcclxuICpcclxuICogTk9URTogTWluL21heCBsZW5ndGggdmFsaWRhdGlvbiBpcyBpbXBsZW1lbnRlZCBvbiB0aGUgaW50ZXJuYWwgZWMtdGV4dGJveC5cclxuICogVmFsdWVzIHBhc3NlZCBpbiB2aWEgaW5wdXQgcHJvcGVydGllcyAoQHNlZSBtYXhsZW5ndGggLCBAc2VlIG1pbmxlbmd0aCApXHJcbiAqIGFyZSB1c2VkIHRvIGNyZWF0ZSB2YWxpZGF0b3JzIG9uIHRoZSB0ZXh0Ym94LiAgV2hlbiB0aGUgdmFsaWRhdGlvbiBvbiB0aGVcclxuICogdGV4dGJveCBmYWlscywgdGhlIHZhbGlkYXRpb24gZXJyb3IocykgZ2V0IHBhc3NlZCB1cCB0byB0aGUge0BzZWUgZm9ybU1vZGVsIH0uXHJcbiAqIFdoZW4gc2V0dGluZyB1cCB0aGlzIGNvbXBvbmVudCdzIHtAc2VlIEZvcm1Db250cm9sIH0sIHlvdSBkbyBOT1QgbmVlZCB0byBzZXQgdGhlXHJcbiAqIFZhbGlkYXRvcnMubWluTGVuZ3RoIG9yIFZhbGlkYXRvcnMubWF4TGVuZ3RoIHZhbGlkYXRvcnMuXHJcbiAqXHJcbiAqIFJlcXVpcmVkIGlzIGFsc28gcGFzc2VkIHZpYSBpbnB1dCBwcm9wZXJ0eSwgYnV0IHlvdSBTSE9VTEQgYWxzbyBzZXQgdXAgdGhlXHJcbiAqIFZhbGlkYXRvcnMucmVxdWlyZWQgdmFsaWRhdG9yIG9uIHRoaXMgY29tcG9uZW50J3MgRm9ybUNvbnRyb2wuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG5cdHNlbGVjdG9yOiAnZWMtY29tYm9ib3gnLFxyXG5cdHRlbXBsYXRlVXJsOiAnY29tYm9ib3guY29tcG9uZW50Lmh0bWwnLFxyXG5cdHN0eWxlVXJsczogWycuL2NvbWJvYm94LmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIENvbWJvYm94Q29tcG9uZW50IGV4dGVuZHMgRm9ybUNvbnRyb2xCYXNlIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQge1xyXG5cclxuXHQvKipcclxuXHQgKiBDbG9zZSB0aGUgcG9wdXAgbWVudSBvbiByZXNpemUgc28gdGhlIHdpZHRoIGFuZCBwb3NpdGlvbmluZyBjYW4gYmUgcmVjYWxjdWxhdGVkXHJcblx0ICogY29ycmVjdGx5LiBDYW5ub3QgYmUgcGxhY2VkIG9uIHRoZSBwb3B1cERpcmVjdGl2ZSBiZWNhdXNlIG9mIGEgYnVnIHdoZXJlXHJcblx0ICogSG9zdExpc3RlbmVycyBmb3IgZ2xvYmFsIGV2ZW50cyBkb24ndCBmaXJlXHJcblx0ICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2lzc3Vlcy8xNDE5MVxyXG5cdCAqL1xyXG5cdEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnKSBvblJlc2l6ZSgpIHtcclxuXHRcdGlmICh0aGlzLnBvcHVwKSB0aGlzLnBvcHVwLmhpZGUoKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFNob3cgdGhlIGFkZCBuZXcgYnV0dG9uIGluIHRoZSBwb3B1cFxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIHB1YmxpYyBhZGROZXc/OiBBZGROZXdUeXBlO1xyXG5cclxuXHJcblx0LyoqXHJcblx0ICogVGhlIG1heGltdW0gbnVtYmVyIG9mIGNoYXJhY3RlcnMgYWxsb3dlZCBpbiB0aGUgaW5wdXQuXHJcblx0ICpcclxuXHQgKiBAbWVtYmVyb2YgVGV4dGJveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIHB1YmxpYyBtYXhsZW5ndGg/OiBudW1iZXI7XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBQb3NpdGlvbiBvZiB0aGUgbWVudSByZWxhdGl2ZSB0byB0aGUgdGV4dCBib3hcclxuXHQgKiBAZGVmYXVsdCAnYm90dG9tX3JpZ2h0J1xyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIHB1YmxpYyBtZW51UG9zaXRpb24/OiBDb21ib2JveE1lbnVQb3NpdGlvbiA9ICdib3R0b21fcmlnaHQnO1xyXG5cclxuXHJcblx0LyoqXHJcblx0ICogVGhlIG1pbmltdW0gbnVtYmVyIG9mIGNoYXJhY3RlcnMgYWxsb3dlZCBpbiB0aGUgaW5wdXRcclxuXHQgKlxyXG5cdCAqIEBtZW1iZXJvZiBUZXh0Ym94Q29tcG9uZW50XHJcblx0ICovXHJcblx0QElucHV0KCkgcHVibGljIG1pbmxlbmd0aD86IG51bWJlcjtcclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIEl0ZW1zIHRvIHNob3cgaW4gY29tYm9ib3ggbWVudVxyXG5cdCAqXHJcblx0ICogQG1lbWJlcm9mIENvbWJvYm94Q29tcG9uZW50XHJcblx0ICovXHJcblx0QElucHV0KCkgcHVibGljIG9wdGlvbnM6IEFycmF5PE1lbnVJdGVtPiA9IFtdO1xyXG5cclxuXHJcblx0LyoqXHJcblx0ICogRGlzcGxheSB0ZW1wbGF0ZSBmb3IgbWVudSBpdGVtc1xyXG5cdCAqXHJcblx0ICogQG1lbWJlcm9mIENvbWJvYm94Q29tcG9uZW50XHJcblx0ICovXHJcblx0QElucHV0KCkgcHVibGljIHRlbXBsYXRlVHlwZTogTWVudVRlbXBsYXRlVHlwZSA9ICdsYWJlbCc7XHJcblxyXG5cdC8qKlxyXG4gICAgICogT3B0aW9uYWwgY3VzdG9tIHRlbXBsYXRlIGZvciB0aGUgbWVudSBpdGVtcy4gTXVzdCBkZWNsYXJlIGEgdGVtcGxhdGUgXHJcblx0ICogaW5wdXQgdmFyaWFibGUgY2FsbGVkIFwiaXRlbVwiIGxpa2Ugc286IDxuZy10ZW1wbGF0ZSAjdGVtcGxhdGVOYW1lIGxldC1pdGVtPiwgXHJcblx0ICogd2hlcmUgaXRlbSByZXByZXNlbnRzIHRoZSBtZW51SXRlbS5cclxuICAgICAqIFdpbGwgb3ZlcnJpZGUgdGhlIGNob2ljZSBmb3IgdGVtcGxhdGVUeXBlIGlmIHByb3ZpZGVkLlxyXG5cdCAqIFxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBwdWJsaWMgY3VzdG9tTWVudVRlbXBsYXRlPzogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFBvc2l0aW9uIHRoZSBtZW51IGFzIGZpeGVkLCBpZGVhbCB3aGVuIGNvbWJvYm94ZXMgYXJlIGluc2lkZSBkaWFsb2dzXHJcblx0ICogRGVmYXVsdGluZyB0byB0cnVlIHNvIGFsbCBtZW51cyB3aWxsIGJlIGF0IGxlYXN0IHRoZSB3aWR0aCBvZiB0aGVcclxuXHQgKiB0ZXh0Ym94ICsgYnV0dG9uLCBidXQgY2FuIGdyb3cgd2lkZXIgaWYgdGhlIGlubmVyIGVsZW1lbnRzIG5lZWQgaXRcclxuXHQgKi9cclxuXHRASW5wdXQoKSBwdWJsaWMgcG9wdXBGaXhlZDogYm9vbGVhbiA9IHRydWU7XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBUaGUgdG90YWwgbnVtYmVyIG9mIHJlY29yZHMgZnJvbSB0aGUgZGF0YXNvdXJjZVxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIHB1YmxpYyB0b3RhbFJlY29yZHM/OiBudW1iZXI7XHJcblxyXG5cdC8qKlxyXG5cdCAqIElmIHNldCB0byB0cnVlLCB3ZSB3aWxsIHVwcGVyQ2FzZSB0aGUgdGV4dCBib3ggYW5kIGFwcGx5IHRoZSBjbGFzcyBvbiB0aGUgYWRkIGJveFxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIHB1YmxpYyB1cHBlckNhc2U6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcblxyXG5cdC8qKlRoZSBwbGFjZWhvbGRlciB0byBzaG93IGluIHRoZSBjb21ib2JveC4gTGVhdmUgZW1wdHkgdG8gdXNlIGRlZmF1bHQgYmVoYXZpb3IgZGV0ZXJtaW5lZFxyXG5cdCAqIGJ5IHdoZXRoZXIgQWRkIE5ldyBpcyBlbmFibGVkXHJcblx0ICovXHJcblx0QElucHV0KCkgcHVibGljIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnJztcclxuXHJcblx0LyoqIE9ic2VydmFibGUgdG8gc3Vic2NyaWJlIHRvIHdoZW4gdGhlIGNvbWJvYm94IG1lbnUgaXMgb3BlbmVkIGZvciB0aGUgZmlyc3QgdGltZSAqL1xyXG5cdEBJbnB1dCgpIHB1YmxpYyBsb2FkT25PcGVuT2JzZXJ2YWJsZT86IE9ic2VydmFibGU8TWVudUl0ZW1bXT4gfCB1bmRlZmluZWQ7XHJcblxyXG5cdC8qKiBEbyBub3QgZGlzcGxheSB0aGUgdG9nZ2xlIGJ1dHRvbiB3aGVuIHRydWUgKi9cclxuXHRASW5wdXQoKSBwdWJsaWMgaGlkZVRvZ2dsZUJ1dHRvbiA9IGZhbHNlO1xyXG5cclxuXHQvKipcclxuXHQgKiBBbHdheXMgc2hvdyB0aGUgbWVudSB3aGVuIHRoZSBmb3JtTW9kZWwgaGFzIGEgdmFsdWUuIFNldHNcclxuXHQgKiBoaWRlVG9nZ2xlQnV0dG9uIHRvIHRydWUgYW5kIG1lbnVTdGF0dXMgdG8gdmlzaWJsZSBhcyB3ZWxsLlxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIHB1YmxpYyBhbHdheXNPcGVuID0gZmFsc2U7XHJcblxyXG5cdC8qKlxyXG5cdCAqIEFkZGl0b25hbCBjbGFzc2VzIHRvIGFwcGx5IHRvIHRoZSBlYy1tZW51IGVsZW1lbnRcclxuXHQgKi9cclxuXHRASW5wdXQoKSBwdWJsaWMgbWVudUVsZW1lbnRDbGFzc2VzOiBNZW51SG9zdEVsZW1lbnRDbGFzc2VzIHwgc3RyaW5nW10gPSBbXTtcclxuXHJcblx0LyoqXHJcblx0ICogQWRkaXRpb25hbCBjbGFzc2VzIHRvIGFwcGx5IHRvIHRoZSAudGV4dGJveC1ncm91cCBlbGVtZW50XHJcblx0ICovXHJcblx0QElucHV0KCkgcHVibGljIHRleHRib3hFbGVtZW50Q2xhc3Nlczogc3RyaW5nW10gPSBbXTtcclxuXHJcblx0LyoqIEhpZGUgJ05vIG1hdGNoZXMnIG1lc3NhZ2Ugd2hlbiB0cnVlICovXHJcblx0QElucHV0KCkgcHVibGljIGhpZGVOb01hdGNoZXM6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcblx0LyoqXHJcbiAgICAgKiBUZXh0IHRvIHNob3cgd2hlbiB0aGUgbWVudSBpcyBlbXB0eS4gXCJObyBtYXRjaGVzXCIgaXMgdGhlIGRlZmF1bHQuXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIHB1YmxpYyBub01hdGNoZXNUZXh0OiBzdHJpbmcgPSAnTm9NYXRjaGVzX1NDJztcclxuXHJcblx0LyoqXHJcblx0ICogTm90aWZ5IHRoZSBwYXJlbnQgdGhhdCB0aGUgYWRkIG5ldyBidXR0b24gd2FzIGNsaWNrZWRcclxuXHQgKiBAdG9kbyBkaXNjdXNzIGlmIHdlIG5lZWQgdG8gc2VuZCBhbG9uZyB0aGUgdmFsdWUgb3Igc2hvdWxkXHJcblx0ICogdGhlIHBhcmVudCBnZXQgaXQgZnJvbSB0aGUgZm9ybU1vZGVsXHJcblx0ICogKGx3ZiAyMDE3LjA3LjEzKTogSSB0aGluayB3ZSBtaWdodCBhcyB3ZWxsIHNlbmQgdGhlIHZhbHVlIGFsb25nIGFuZFxyXG5cdCAqIGxlYXZlIGl0IHVwIHRvIHRoZSBwYXJlbnQgdG8gZGVjaWRlIGhvdyB0byBoYW5kbGUgaXQuXHJcblx0ICovXHJcblx0QE91dHB1dCgpIHB1YmxpYyBhZGROZXdDbGljazogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIE5vdGlmeSBwYXJlbnQgd2hlbiB0ZXh0IHR5cGVkIGludG8gdGV4dGJveFxyXG5cdCAqL1xyXG5cdEBPdXRwdXQoKSBwdWJsaWMgc2VhcmNoOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG5cclxuXHJcblx0QFZpZXdDaGlsZCgndGV4dGJveCcpIHB1YmxpYyB0ZXh0Ym94ITogVGV4dGJveENvbXBvbmVudDtcclxuXHJcblx0LyoqXHJcblx0ICogQWNjZXNzIHRvIHRoZSBtZW51J3MgY29tcG9uZW50IHZpYSB0aGUgIHtAbGluayBQb3B1cENvbnRhaW5lckRpcmVjdGl2ZX1cclxuXHQgKi9cclxuXHRAVmlld0NoaWxkKFBvcHVwQ29udGFpbmVyRGlyZWN0aXZlKSBwcml2YXRlIHBvcHVwPzogUG9wdXBDb250YWluZXJEaXJlY3RpdmU7XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBSZWZlcmVuY2UgdGhlIGFkZC1uZXcgYnV0dG9uIGVsZW1lbnRcclxuXHQgKi9cclxuXHRAVmlld0NoaWxkKCdhZGROZXdCdXR0b24nKSBwcml2YXRlIGFkZE5ld0J1dHRvbiE6IEVsZW1lbnRSZWY7XHJcblxyXG5cclxuXHQvKipcclxuXHQgICAqIEZpbHRlcmVkIEl0ZW1zIHRvIHNob3cgaW4gY29tYm9ib3ggbWVudVxyXG5cdCAgICovXHJcblx0cHVibGljIGZpbHRlcmVkT3B0aW9uczogQXJyYXk8TWVudUl0ZW0+ID0gW107XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBUcmFja3MgaWYgdGhlIG1lbnUgaXMgb3BlbiBvciBoaWRkZW5cclxuXHQgKi9cclxuXHRwdWJsaWMgbWVudVN0YXR1czogUG9wdXBTdGF0dXMgPSAnaGlkZGVuJztcclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFBsYWNlaG9sZGVyIHRvIGFzc2lnbiB0byB0ZXh0Ym94XHJcblx0ICovXHJcblx0cHVibGljIGVmZmVjdGl2ZVBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnJztcclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFJlZmVyZW5jZSB0byB0aGUgY3VycmVudGx5LXNlbGVjdGVkIG1lbnUgaXRlbVxyXG5cdCAqL1xyXG5cdHB1YmxpYyBzZWxlY3RlZEl0ZW06IE1lbnVJdGVtIHwgbnVsbCA9IG51bGw7XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBGb3JtQ29udHJvbCBmb3IgdGhlIHRleHRib3hcclxuXHQgKi9cclxuXHRwdWJsaWMgdGV4dGJveEZvcm1Nb2RlbDogRm9ybUNvbnRyb2wgPSBuZXcgRm9ybUNvbnRyb2woJycpO1xyXG5cclxuXHJcblx0LyoqXHJcblx0ICogVHJhY2tzIHdoZXRoZXIgdGhlIGFkZCBuZXcgYnV0dG9uIGlzIHNlbGVjdGVkXHJcblx0ICovXHJcblx0cHVibGljIGFkZE5ld1NlbGVjdGVkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBUcmFja3Mgd2hldGhlciB0aGUgdGV4dGJveEZvcm1Nb2RlbCB2YWx1ZSBtYXRjaGVzIGFuIGl0ZW0gaW4gdGhlIGZpbHRlcmVkT3B0aW9uc1xyXG5cdCAqL1xyXG5cdHB1YmxpYyBmb3VuZE1hdGNoOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBJbmRleCBvZiB0aGUgY3VycmVudGx5LXNlbGVjdGVkIG9wdGlvbnNcclxuXHQgKi9cclxuXHRwcml2YXRlIHNlbGVjdGVkSXRlbUluZGV4OiBudW1iZXIgPSAtMTtcclxuXHJcblx0LyoqIFBsYWNlaG9sZGVyIHRleHQgZm9yICdDaG9vc2Ugb3IgQWRkLi4uJyAqL1xyXG5cdHByaXZhdGUgY2hvb3NlT3JBZGRQbGFjZWhvbGRlcjogc3RyaW5nID0gJyc7XHJcblxyXG5cdC8qKiBQbGFjZWhvbGRlciB0ZXh0IGZvciAnQ2hvb3NlJyAqL1xyXG5cdHByaXZhdGUgY2hvb3NlUGxhY2Vob2xkZXI6IHN0cmluZyA9ICcnO1xyXG5cclxuXHRwcml2YXRlIGhhc0RhdGFCZWVuTG9hZGVkT25PcGVuOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG5cdGNvbnN0cnVjdG9yKFxyXG5cdFx0cHJvdGVjdGVkIHZhbGlkYXRpb25NZXNzYWdlU2VydmljZTogVmFsaWRhdGlvbk1lc3NhZ2VTZXJ2aWNlLFxyXG5cdFx0cHJvdGVjdGVkIGZvcm1Hcm91cEhlbHBlcjogRm9ybUdyb3VwSGVscGVyLFxyXG5cdFx0cHJvdGVjdGVkIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcclxuXHRcdHByb3RlY3RlZCBzY3JvbGxTZXJ2aWNlOiBTY3JvbGxTZXJ2aWNlXHJcblx0KSB7XHJcblx0XHRzdXBlcih2YWxpZGF0aW9uTWVzc2FnZVNlcnZpY2UsIGZvcm1Hcm91cEhlbHBlcik7XHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogVGhlIGFuZ3VsYXIgb25DaGFuZ2VzIGxpZmVjeWNsZSBldmVudFxyXG5cdCAqIEBzZWUgaHR0cHM6Ly9hbmd1bGFyLmlvL2d1aWRlL2xpZmVjeWNsZS1ob29rc1xyXG5cdCAqL1xyXG5cdHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcblx0XHRzdXBlci5uZ09uQ2hhbmdlcyhjaGFuZ2VzKTtcclxuXHJcblx0XHQvLyB3aGVuIG9wdGlvbnMgY2hhbmdlc1xyXG5cdFx0aWYgKGNoYW5nZXMub3B0aW9ucykge1xyXG5cdFx0XHR0aGlzLnJlc2V0T3B0aW9ucygpO1xyXG5cclxuXHRcdFx0Ly8gVXBkYXRlIHRoZSBwb3B1cCBwb3NpdGlvblxyXG5cdFx0XHRpZiAodGhpcy5wb3B1cCkge1xyXG5cdFx0XHRcdHRoaXMucG9wdXAudXBkYXRlKCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHQvLyB1cGRhdGUgdmFsaWRhdG9ycyBvbiB0aGUgdGV4dGJveFxyXG5cdFx0aWYgKGNoYW5nZXMucmVxdWlyZWQgfHwgY2hhbmdlcy5taW5sZW5ndGggfHwgY2hhbmdlcy5tYXhsZW5ndGgpIHtcclxuXHRcdFx0dGhpcy5zZXRUZXh0Ym94Rm9ybU1vZGVsVmFsaWRhdG9ycygpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFVwZGF0ZSBwbGFjZWhvbGRlciB0ZXh0IHdoZW4gJ0FkZCBOZXcnIGlzIGNvbmRpdGlvbmFsLlxyXG5cdFx0Ly8gbmdPbkNoYW5nZXMoKSBraWNrcyBvZmYgYmVmb3JlIG5nT25Jbml0LCBzbyBpbiBvcmRlclxyXG5cdFx0Ly8gdG8gbm90IG92ZXJ3cml0ZSBhIHVzZXItcHJvdmlkZWQgcGxhY2Vob2xkZXIsIGRvIG5vdFxyXG5cdFx0Ly8gdXBkYXRlIHBsYWNlaG9sZGVyIG9uIGZpcnN0IGNoYW5nZSAobmdPbkluaXQgd2lsbCB0YWtlIGNhcmUgb2YgaXQpLlxyXG5cdFx0aWYgKChjaGFuZ2VzLmFkZE5ldyAmJiAhY2hhbmdlcy5hZGROZXcuaXNGaXJzdENoYW5nZSgpKSB8fCBjaGFuZ2VzLnBsYWNlaG9sZGVyKSB7XHJcblx0XHRcdHRoaXMudXBkYXRlUGxhY2Vob2xkZXJUZXh0KCk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBUaGUgYW5ndWxhciBvbkluaXQgbGlmZWN5Y2xlIGhvb2tcclxuXHQgKiBAc2VlIGh0dHBzOi8vYW5ndWxhci5pby9ndWlkZS9saWZlY3ljbGUtaG9va3NcclxuXHQgKi9cclxuXHRwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XHJcblx0XHRzdXBlci5uZ09uSW5pdCgpO1xyXG5cclxuXHRcdGlmICh0aGlzLmFsd2F5c09wZW4pIHtcclxuXHRcdFx0dGhpcy5oaWRlVG9nZ2xlQnV0dG9uID0gdHJ1ZTtcclxuXHRcdFx0dGhpcy5tZW51U3RhdHVzID0gJ3Zpc2libGUnO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEdldCB0cmFuc2xhdGVkIHBsYWNlaG9sZGVyIHRleHRcclxuXHRcdHRoaXMuY2hvb3NlT3JBZGRQbGFjZWhvbGRlciA9IGAke3RoaXMudHJhbnNsYXRlLmluc3RhbnQoJ0Nob29zZSBvciBhZGQnKX0uLi5gO1xyXG5cdFx0dGhpcy5jaG9vc2VQbGFjZWhvbGRlciA9IGAke3RoaXMudHJhbnNsYXRlLmluc3RhbnQoJ0Nob29zZScpfWA7XHJcblxyXG5cdFx0dGhpcy5mb3JtTW9kZWxDaGFuZ2VkKHRoaXMuZm9ybU1vZGVsLnZhbHVlKTtcclxuXHRcdHRoaXMuc2V0VGV4dGJveEZvcm1Nb2RlbFZhbGlkYXRvcnMoKTtcclxuXHJcblx0XHQvLyBFcnJvcnMgZm9yIHRoaXMgY29tcG9uZW50IGFyZSBkaXNwbGF5ZWQgdmlhIHRoZSB2YWxpZGF0aW9uRXJyb3JzIHByb3BlcnR5LCB3aGljaCBpc1xyXG5cdFx0Ly8gcG9wdWxhdGVkIHdoZW4gdHJhbnNsYXRlVmFsaWRhdGlvbk1lc3NhZ2VzIGlzIHJ1bi5cclxuXHRcdC8vIFdoZW4gdGhlIGludGVybmFsIFRleHRib3hDb21wb25lbnQgaGFzIHZhbGlkYXRpb24gZXJyb3JzLCB3ZSBzZXQgdGhlbSBvbiB0aGVcclxuXHRcdC8vIGZvcm1Nb2RlbCBhcyB3ZWxsLiAgVGhpcyB1cGRhdGVzIHRoZSB2YWxpZGl0eSBvZiBvdXIgQ29tYm9ib3hDb21wb25lbnQgY29udHJvbCxcclxuXHRcdC8vIGJ1dCBkb2VzIG5vdCB0cmlnZ2VyIHRyYW5zbGF0aW9uLiAgU3Vic2NyaWJlIHRvIHN0YXR1c0NoYW5nZXMgaGVyZSBzbyBjb21wb25lbnRcclxuXHRcdC8vIHZhbGlkYXRpb24gZXJyb3JzIHdpbGwgYXBwZWFyIGFsb25nIHdpdGggdGhlIENvbWJvYm94Q29tcG9uZW50J3MgbGFiZWwuXHJcblx0XHR0aGlzLmZvcm1Nb2RlbC52YWx1ZUNoYW5nZXMucGlwZShcclxuXHRcdFx0dGFrZVVudGlsKHRoaXMuY29tcG9uZW50RGVzdHJveWVkKVxyXG5cdFx0KS5zdWJzY3JpYmUoZGF0YSA9PiB0aGlzLmZvcm1Nb2RlbENoYW5nZWQoZGF0YSkpO1xyXG5cclxuXHRcdHRoaXMudGV4dGJveEZvcm1Nb2RlbC5zdGF0dXNDaGFuZ2VzLnBpcGUoXHJcblx0XHRcdHRha2VVbnRpbCh0aGlzLmNvbXBvbmVudERlc3Ryb3llZClcclxuXHRcdCkuc3Vic2NyaWJlKGRhdGEgPT4gdGhpcy5zZXRGb3JtTW9kZWxWYWxpZGF0aW9uRXJyb3JzKGRhdGEpKTtcclxuXHJcblx0XHQvLyBkZWZhdWx0IHBsYWNlaG9sZGVyXHJcblx0XHR0aGlzLnVwZGF0ZVBsYWNlaG9sZGVyVGV4dCgpO1xyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFRoZSBhbmd1bGFyIGFmdGVyVmlld0luaXQgbGlmZWN5Y2xlIGhvb2tcclxuXHQgKiBAc2VlIGh0dHBzOi8vYW5ndWxhci5pby9ndWlkZS9saWZlY3ljbGUtaG9va3NcclxuXHQgKi9cclxuXHRwdWJsaWMgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG5cdFx0aWYgKCF0aGlzLnBvcHVwKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBhbGxvdyBvdmVyZmxvdyBvdXQgb2YgdGhlIHNjcm9sbFBhcmVudFxyXG5cdFx0Ly8gcHJldmVudHMgbWVudSBmcm9tIG9ic2N1cmluZyB0aGUgY29tYm9ib3hcclxuXHRcdGxldCBwb3BwZXJPcHRpb25zOiBQb3BwZXIuUG9wcGVyT3B0aW9ucyA9IHtcclxuXHRcdFx0bW9kaWZpZXJzOiB7XHJcblx0XHRcdFx0cHJldmVudE92ZXJmbG93OiB7XHJcblx0XHRcdFx0XHRib3VuZGFyaWVzRWxlbWVudDogJ3ZpZXdwb3J0J1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fTtcclxuXHJcblx0XHQvLyBjb252ZXJ0IHRoZSBDb21ib2JveE1lbnVQb3NpdGlvbiBpbnRvIGEgUG9wcGVyUGxhY2VtZW50XHJcblx0XHRzd2l0Y2ggKHRoaXMubWVudVBvc2l0aW9uKSB7XHJcblx0XHRcdGNhc2UgKFwidG9wX2xlZnRcIik6XHJcblx0XHRcdFx0cG9wcGVyT3B0aW9ucy5wbGFjZW1lbnQgPSAndG9wLXN0YXJ0JztcclxuXHRcdFx0XHRicmVhaztcclxuXHRcdFx0Y2FzZSAoXCJ0b3BfcmlnaHRcIik6XHJcblx0XHRcdFx0cG9wcGVyT3B0aW9ucy5wbGFjZW1lbnQgPSAndG9wLWVuZCc7XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdGNhc2UgKFwiYm90dG9tX2xlZnRcIik6XHJcblx0XHRcdFx0cG9wcGVyT3B0aW9ucy5wbGFjZW1lbnQgPSAnYm90dG9tLXN0YXJ0JztcclxuXHRcdFx0XHRicmVhaztcclxuXHRcdFx0Y2FzZSAoXCJib3R0b21fcmlnaHRcIik6XHJcblx0XHRcdFx0cG9wcGVyT3B0aW9ucy5wbGFjZW1lbnQgPSAnYm90dG9tLWVuZCc7XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdGRlZmF1bHQ6XHJcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIG1lbnVQb3NpdGlvbiBmb3IgQ29tYm9ib3hDb21wb25lbnQuYClcclxuXHRcdH1cclxuXHJcblx0XHQvLyBTY3JvbGwgdGhlIG1lbnUgdG8gdGhlIHNlbGVjdGVkIGl0ZW0gb25jZSB0aGUgcG9wdXAgbWVudSBpcyByZWFkeVxyXG5cdFx0cG9wcGVyT3B0aW9ucy5vbkNyZWF0ZSA9ICgpID0+IHtcclxuXHRcdFx0dGhpcy5zY3JvbGxNZW51KCk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5wb3B1cEZpeGVkKSB7XHJcblx0XHRcdFx0dGhpcy5wb3B1cCEuZml4UG9zaXRpb24oKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLnBvcHVwRml4ZWQpIHtcclxuXHRcdFx0cG9wcGVyT3B0aW9ucy5vblVwZGF0ZSA9ICgpID0+IHtcclxuXHRcdFx0XHR0aGlzLnBvcHVwIS5maXhQb3NpdGlvbigpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5wb3B1cC5wb3BwZXJPcHRpb25zID0gcG9wcGVyT3B0aW9ucztcclxuXHJcblx0XHR0aGlzLnBvcHVwLnBvcHBlclN0YXR1c0NoYW5nZS5waXBlKFxyXG5cdFx0XHR0YWtlVW50aWwodGhpcy5jb21wb25lbnREZXN0cm95ZWQpXHJcblx0XHQpLnN1YnNjcmliZSgoZXZlbnQ6ICd2aXNpYmxlJyB8ICdoaWRkZW4nKSA9PiB7XHJcblx0XHRcdFx0dGhpcy5tZW51U3RhdHVzID0gZXZlbnQ7XHJcblxyXG5cdFx0XHRcdC8vIFN5bmNocm9uaXplIHRoZSBmb3JtTW9kZWwgYW5kIHRleHRGb3JtTW9kZWwgdmFsdWVzIHdoZW4gdGhlXHJcblx0XHRcdFx0Ly8gcG9wdXAgbWVudSBjbG9zZXMgYW5kIHVuLWZpbHRlciB0aGUgb3B0aW9ucyBhbmQgcmVzZXQgdGhlXHJcblx0XHRcdFx0Ly8gc2VsZWN0ZWRJdGVtIGFuZCBpbmRleFxyXG5cdFx0XHRcdGlmIChldmVudCA9PT0gJ2hpZGRlbicpIHtcclxuXHRcdFx0XHRcdHRoaXMuc3luY01vZGVsVmFsdWVzKCk7XHJcblx0XHRcdFx0XHR0aGlzLnJlc2V0T3B0aW9ucygpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSk7XHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogU2V0IGVycm9ycyBvbiB0aGUgdGV4dGJveEZvcm1Nb2RlbCwgd2hpY2ggd2lsbCB0aGVuIHNldCBlcnJvcnMgb24gdGhlXHJcblx0ICogZm9ybU1vZGVsLiBBbHNvIG1hcmsgdGhlIGZvcm1Nb2RlbCBhcyB0b3VjaGVkIHRvIGRpc3BsYXkgYW55IGVycm9ycy5cclxuXHQgKiBAcGFyYW0gZXJyb3JzIGtleShzKSBvZiBWYWxpZGF0aW9uTWVzc2FnZVNlcnZpY2UgZXJyb3JzIHRvIGRpc3BsYXkgb3IgcmVtb3ZlXHJcblx0ICogQG1lbWJlcm9mIENvbW9ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHB1YmxpYyBzZXRFcnJvcnMoZXJyb3JzOiB7IFtrZXk6IHN0cmluZ106IGJvb2xlYW4gfSk6IHZvaWQge1xyXG5cdFx0dGhpcy50ZXh0Ym94Rm9ybU1vZGVsLnNldEVycm9ycyhlcnJvcnMpO1xyXG5cdFx0dGhpcy5mb3JtTW9kZWwubWFya0FzVG91Y2hlZCgpO1xyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFVuZmlsdGVyIG9wdGlvbnMgYW5kIHVwZGF0ZSB0aGUgc2VsZWN0ZWRJdGVtIGFuZCBzZWxlY3RlZEl0ZW1JbmRleFxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHB1YmxpYyByZXNldE9wdGlvbnMob3B0aW9ucz86IE1lbnVJdGVtW10pOiB2b2lkIHtcclxuXHRcdHRoaXMuZmlsdGVyZWRPcHRpb25zID0gb3B0aW9ucyB8fCB0aGlzLm9wdGlvbnM7XHJcblxyXG5cdFx0Ly9pZiB0aGV5IGhhdmUgbm8gc2VhcmNoIHRlcm0sIGRvbid0IHRyeSB0byBzZWxlY3QgYW55dGhpbmcgc28gdGhleSBjYW4gY2xlYXIgdGhlIGJveCBvdXQgYnkgaGl0dGluZyBlbnRlclxyXG5cdFx0Ly9pZiB0aGV5IGhhdmUgYSBzZWFyY2ggdGVybSBhbmQgdGhlIG9wdGlvbnMgY2hhbmdlZCwgc2VsZWN0IGFuIG9wdGlvbiBmcm9tIHRoZSBtZW51IHNvIHRoZXkgd2lsbCBnZXQgaXQgYXV0b21hdGljYWxseSBpZiB0aGV5IGhpdCBlbnRlclxyXG5cdFx0aWYgKHRoaXMudGV4dGJveEZvcm1Nb2RlbC52YWx1ZSAhPT0gJycpIHtcclxuXHRcdFx0dGhpcy5zZWxlY3RlZEl0ZW1JbmRleCA9IHRoaXMuZmluZERlZmF1bHRTZWxlY3Rpb25JbmRleCh0aGlzLmZpbHRlcmVkT3B0aW9ucywgdGhpcy50ZXh0Ym94Rm9ybU1vZGVsLnZhbHVlKTtcclxuXHRcdFx0dGhpcy5zZWxlY3RlZEl0ZW0gPSB0aGlzLmZpbHRlcmVkT3B0aW9uc1t0aGlzLnNlbGVjdGVkSXRlbUluZGV4XSB8fCBudWxsO1xyXG5cdFx0XHR0aGlzLnNjcm9sbE1lbnUodGhpcy5zZWxlY3RlZEl0ZW1JbmRleCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHQvL2lmIHRoZXkgaGF2ZSBubyBzZWFyY2ggdGVybSBhbmQgdGhlIG9wdGlvbnMgYXJlIHJlc2V0LCBkb24ndCBhdXRvLXBpY2sgdGhlIGZpcnN0IG9uZVxyXG5cdFx0XHQvL3NvIHRoYXQgZW50ZXIgd2lsbCBhbGxvdyB0aGVtIHRvIHdpcGUgb3V0IHRoZWlyIGxhc3Qgc2VsZWN0aW9uXHJcblx0XHRcdHRoaXMuY2xlYXJTZWxlY3RlZEl0ZW0oKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIExpc3RlbiB0byB0aGUgc2VsZWN0ZWQgY2hhbmdlZCBldmVudCBmcm9tIHtAbGluayBNZW51Q29tcG9uZW50fSBhbmQgdXBkYXRlIHRoZSBmb3JtXHJcblx0ICogbW9kZWwgYW5kIGNsb3NlIG1lbnVcclxuXHQgKi9cclxuXHRwdWJsaWMgc2VsZWN0ZWRDaGFuZ2VkKGl0ZW06IE1lbnVJdGVtKTogdm9pZCB7XHJcblx0XHR0aGlzLnNldEZvcm1Nb2RlbFZhbHVlKGl0ZW0pO1xyXG5cdFx0dGhpcy50b2dnbGVNZW51KCk7XHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogU2hvdyBhbmQgaGlkZSB0aGUgcG9wdXAgbWVudVxyXG5cdCAqXHJcblx0ICogQG1lbWJlcm9mIENvbWJvYm94Q29tcG9uZW50XHJcblx0ICovXHJcblx0cHVibGljIHRvZ2dsZU1lbnUoZXZlbnQ/OiBFdmVudCk6IHZvaWQge1xyXG5cdFx0aWYgKCF0aGlzLnBvcHVwKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoZXZlbnQpIHtcclxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCF0aGlzLmZvcm1Nb2RlbC5kaXNhYmxlZCkge1xyXG5cdFx0XHRpZiAodGhpcy5tZW51U3RhdHVzID09PSAndmlzaWJsZScpIHtcclxuXHRcdFx0XHQvLyBXaGVuIHRoZSBwb3B1cCBpcyBoaWRkZW4gaXQgd2lsbCBlbWl0IGl0cyBjaGFuZ2VkIHN0YXR1cyBhbmRcclxuXHRcdFx0XHQvLyB3ZSB3aWxsIHJlc2V0IHZhbHVlcyBpZiBuZWVkIGJlLlxyXG5cdFx0XHRcdHRoaXMucG9wdXAuaGlkZSgpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdGlmICh0aGlzLmxvYWRPbk9wZW5PYnNlcnZhYmxlICYmICF0aGlzLmhhc0RhdGFCZWVuTG9hZGVkT25PcGVuKSB7XHJcblx0XHRcdFx0XHR0aGlzLnBlbmRpbmcgPSB0cnVlO1xyXG5cclxuXHRcdFx0XHRcdHRoaXMubG9hZE9uT3Blbk9ic2VydmFibGUucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoKHJlc3VsdDogTWVudUl0ZW1bXSkgPT4ge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmhhc0RhdGFCZWVuTG9hZGVkT25PcGVuID0gdHJ1ZTtcclxuXHJcblx0XHRcdFx0XHRcdHRoaXMucGVuZGluZyA9IGZhbHNlO1xyXG5cdFx0XHRcdFx0XHR0aGlzLm9wdGlvbnMgPSByZXN1bHQ7XHJcblxyXG5cdFx0XHRcdFx0XHR0aGlzLnJlc2V0T3B0aW9ucygpO1xyXG5cdFx0XHRcdFx0XHR0aGlzLnBvcHVwIS5zaG93KCk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0dGhpcy5wb3B1cC5zaG93KCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwdWJsaWMgb25CbHVyKCk6IHZvaWQge1xyXG5cdFx0dGhpcy5mb3JtTW9kZWwubWFya0FzVG91Y2hlZCgpO1xyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIENvbnRyb2wgdGhlIG1lbnUgd2l0aCBrZXlib2FyZCBuYXZpZ2F0aW9uXHJcblx0ICpcclxuXHQgKiBAc2VlIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvS2V5Ym9hcmRFdmVudC9rZXkjRXhhbXBsZSB8IEtleWJvYXJkRXZlbnQua2V5fVxyXG5cdCAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleS9LZXlfVmFsdWVzIHwgS2V5IFZhbHVlc31cclxuXHQgKlxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHB1YmxpYyBrZXlOYXZpZ2F0ZShldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xyXG5cdFx0c3dpdGNoIChldmVudC5rZXkpIHtcclxuXHRcdFx0Y2FzZSBcIkFycm93RG93blwiOlxyXG5cdFx0XHRjYXNlIFwiRG93blwiOlxyXG5cdFx0XHRjYXNlIFwiQXJyb3dVcFwiOlxyXG5cdFx0XHRjYXNlIFwiVXBcIjpcclxuXHRcdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdHRoaXMub25BcnJvd0Rvd25VcChldmVudCk7XHJcblx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRjYXNlIFwiQmFja3NwYWNlXCI6XHJcblx0XHRcdGNhc2UgXCJEZWxldGVcIjpcclxuXHRcdFx0Y2FzZSBcIkRlbFwiOlxyXG5cdFx0XHRcdGlmICh0aGlzLm1lbnVTdGF0dXMgPT09ICdoaWRkZW4nKSB7XHJcblx0XHRcdFx0XHR0aGlzLnRvZ2dsZU1lbnUoKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdGNhc2UgXCJUYWJcIjpcclxuXHRcdFx0XHQvLyBJZiB0YWJiaW5nIGZyb20gdGhlIHRleHRib3ggdG8gdGhlIGJ1dHRvbiwgb3ZlcnJpZGUgdGhlIHRleHRib3ggYXMgYmVpbmdcclxuXHRcdFx0XHQvLyBtYXJrZWQgdG91Y2hlZCBzbyB3ZSBkb24ndCBzZWUgdGhlIGludmFsaWQgc3RhdGUuIE9ubHkgc2hvdyB0aGUgaW52YWxpZCBzdGF0ZVxyXG5cdFx0XHRcdC8vIHdoZW4gdGFiYmluZyBvdXQgb2YgY29tYm9ib3ggZnJvbSB0aGUgYnV0dG9uIG9yIGJhY2sgdGFiYmluZyBmcm9tIHRoZSB0ZXh0Ym94XHJcblx0XHRcdFx0Ly8gaWYgKGV2ZW50LmtleSA9PT0gJ1RhYicgJiYgZXZlbnQuc3JjRWxlbWVudCAmJiBldmVudC5zcmNFbGVtZW50LnRhZ05hbWUgPT09ICdJTlBVVCcpIHtcclxuXHRcdFx0XHQvLyBcdGlmIChldmVudC5zaGlmdEtleSkge1xyXG5cdFx0XHRcdC8vIFx0XHR0aGlzLnRleHRib3hGb3JtTW9kZWwubWFya0FzVG91Y2hlZCgpO1xyXG5cdFx0XHRcdC8vIFx0XHR0aGlzLmZvcm1Nb2RlbC5tYXJrQXNUb3VjaGVkKCk7XHJcblx0XHRcdFx0Ly8gXHR9IGVsc2Uge1xyXG5cdFx0XHRcdC8vIFx0XHR0aGlzLnRleHRib3hGb3JtTW9kZWwubWFya0FzVW50b3VjaGVkKCk7XHJcblx0XHRcdFx0Ly8gXHR9XHJcblx0XHRcdFx0Ly8gfSBlbHNlIGlmIChldmVudC5rZXkgPT09ICdUYWInICYmIGV2ZW50LnNyY0VsZW1lbnQgJiYgZXZlbnQuc3JjRWxlbWVudC50YWdOYW1lID09PSAnQlVUVE9OJykge1xyXG5cdFx0XHRcdC8vIFx0aWYgKCFldmVudC5zaGlmdEtleSkge1xyXG5cdFx0XHRcdC8vIFx0XHR0aGlzLmZvcm1Nb2RlbC5tYXJrQXNUb3VjaGVkKCk7XHJcblx0XHRcdFx0Ly8gXHR9XHJcblx0XHRcdFx0Ly8gfVxyXG5cclxuXHRcdFx0XHRpZiAodGhpcy5tZW51U3RhdHVzID09PSAndmlzaWJsZScpIHtcclxuXHRcdFx0XHRcdC8vaWYgdGhlIHNlbGVjdGVkIG9wdGlvbiBpcyB0aGUgYWRkIG5ldyBidXR0b24gbGV0IGl0IGZpcmUgYnV0IGRvbid0IGFsbG93XHJcblx0XHRcdFx0XHQvL3RoZSB0YWIgZXZlbnQgdG8gY2FycnkgdGhlbSBmb3J3YXJkIGZyb20gd2hlcmV2ZXIgdGhleSBsYW5kIC0gdGhleSB3b3VsZCBza2lwIHRoZSBmaXJzdCBib3ggb24gdGhlIGFkZCBuZXcgZm9ybVxyXG5cdFx0XHRcdFx0Ly9JbiB0aGUgbm9ybWFsIGNhc2Ugd2Ugd2FudCB0byBhbGxvdyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvciB0aGV5IHdvbid0IGJlIGFibGUgdG8gdGFiIG91dCBvZiB0aGUgY29udHJvbCBhdCBhbGwuXHJcblx0XHRcdFx0XHRpZih0aGlzLmFkZE5ld1NlbGVjdGVkKXtcclxuXHRcdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHR0aGlzLmNvbW1pdFNlbGVjdGlvbihldmVudCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0Y2FzZSBcIkVudGVyXCI6XHJcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuXHJcblx0XHRcdFx0aWYgKHRoaXMubWVudVN0YXR1cyA9PT0gJ3Zpc2libGUnKSB7XHJcblx0XHRcdFx0XHR0aGlzLmNvbW1pdFNlbGVjdGlvbihldmVudCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0Y2FzZSBcIkVzY2FwZVwiOlxyXG5cdFx0XHRjYXNlIFwiRXNjXCI6XHJcblx0XHRcdFx0aWYgKHRoaXMubWVudVN0YXR1cyA9PT0gJ3Zpc2libGUnKSB7XHJcblx0XHRcdFx0XHQvLyBKdXN0IGNsb3NlIHRoZSBtZW51LCBkbyBub3QgZm9jdXMgdGhlIG5leHQgZWxlbWVudCBvbiB0YWJcclxuXHRcdFx0XHRcdC8vIHVubGVzcyB0aGUgbWVudSBpcyBoaWRkZW5cclxuXHRcdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcblxyXG5cdFx0XHRcdFx0Ly8gQ2xvc2UgdGhlIG1lbnUgYmVmb3JlIHdlIHJlc2V0IHNlbGVjdGVkSXRlbSBzbyB3ZSBkb24ndCBzZWUgdGhlIGhpZ2hsaWdodCBjaGFuZ2luZ1xyXG5cdFx0XHRcdFx0Ly8gd2hlbiByZXNldCB0aGUgc2VsZWN0ZWQgaXRlbSBiYWNrIHRvIHRoZSBmb3JtTW9kZWxcclxuXHRcdFx0XHRcdHRoaXMudG9nZ2xlTWVudSgpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdGNhc2UgXCIgXCI6XHJcblx0XHRcdGNhc2UgXCJTcGFjZWJhclwiOlxyXG5cdFx0XHRcdGlmICh0aGlzLm1lbnVTdGF0dXMgPT09ICdoaWRkZW4nKSB7XHJcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0dGhpcy50b2dnbGVNZW51KCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0XHRpZiAodGhpcy5tZW51U3RhdHVzID09PSAnaGlkZGVuJyAmJiBldmVudC5rZXkgIT09ICdTaGlmdCcpIHtcclxuXHRcdFx0XHRcdHRoaXMudG9nZ2xlTWVudSgpO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBGYWNpbGl0YXRlcyBhZGRpbmcgaXRlbXMgdG8gYSBjb21ib2JveFxyXG5cdCAqXHJcblx0ICogQHBhcmFtIGFkZEZuIEZ1bmN0aW9uIGZyb20gcGFyZW50IHRoYXQgc2hvdWxkIG1ha2UgYW4gQVBJIHJlcXVlc3QgdG8gYWRkIGEgbmV3IGl0ZW0gdG8gdGhlIGNvbWJvYm94J3Mgb3B0aW9uc1xyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHB1YmxpYyBhc3luYyBhZGROZXdJdGVtKGFkZEZuOiAoKSA9PiBQcm9taXNlPHZvaWQ+KSB7XHJcbiAgICAgICAgdGhpcy5wZW5kaW5nID0gdHJ1ZTtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBhd2FpdCBhZGRGbigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAvLyBXZSBnYXZlIGl0IG91ciBiZXN0IHRyeSwgc29tZXRoaW5nIGlzIHJlYWxseSB3aGFjaywgc28gbGV0J3MganVzdCBzZXQgdGhlIGVycm9yXHJcbiAgICAgICAgICAgIHRoaXMuc2V0RXJyb3JzKHsgJ2FkZG5ldyc6IHRydWUgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMucGVuZGluZyA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMudG9nZ2xlTWVudSgpO1xyXG4gICAgfVxyXG5cclxuXHQvKipcclxuXHQgKiBGaWd1cmUgb3V0IHdoZXRoZXIgdGhleSBhcmUgYWRkaW5nIG5ldyBvciBoYXZlIGFuIGl0ZW0gc2VsZWN0ZWQsIGFuZCBjb21taXQgaXQgdG8gdGhlIGZvcm0gbW9kZWxcclxuXHQgKi9cclxuICBwcml2YXRlIGNvbW1pdFNlbGVjdGlvbihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xyXG5cdFx0aWYgKHRoaXMuYWRkTmV3U2VsZWN0ZWQpIHtcclxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblx0XHRcdHRoaXMub25BZGROZXcoZXZlbnQpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0dGhpcy5zZXRGb3JtTW9kZWxWYWx1ZSh0aGlzLnNlbGVjdGVkSXRlbSk7XHJcblx0XHRcdHRoaXMudG9nZ2xlTWVudSgpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogU2VuZCB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgdGV4dGJveCB0byB0aGUgcGFyZW50IHdoZW4gdGhlIGFkZCBuZXcgYnV0dG9uIGlzXHJcblx0ICogY2xpY2tlZFxyXG5cdCAqXHJcblx0ICogQHBhcmFtIGV2ZW50IEFkZCBuZXcgYnV0dG9uIGNsaWNrIG9yIGVudGVyIGtleSBldmVudFxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHB1YmxpYyBvbkFkZE5ldyhldmVudDogRXZlbnQpOiB2b2lkIHtcclxuXHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cdFx0dGhpcy5hZGROZXdTZWxlY3RlZCA9IGZhbHNlO1xyXG5cdFx0dGhpcy5hZGROZXdDbGljay5lbWl0KHRoaXMudGV4dGJveEZvcm1Nb2RlbC52YWx1ZSk7XHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogTmF2aWdhdGUgdGhlIGRyb3Bkb3duIG1lbnUgdXNpbmcgdXAgYW5kIGRvd24gYXJyb3cga2V5c1xyXG5cdCAqXHJcblx0ICogQHBhcmFtIGV2ZW50IFVwIG9yIGRvd24gYXJyb3cga2V5ZG93biBldmVudFxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHByaXZhdGUgb25BcnJvd0Rvd25VcChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xyXG5cdFx0c3dpdGNoIChldmVudC5rZXkpIHtcclxuXHRcdFx0Y2FzZSBcIkFycm93RG93blwiOlxyXG5cdFx0XHRjYXNlIFwiRG93blwiOlxyXG5cclxuXHRcdFx0XHRpZiAodGhpcy5zZWxlY3RlZEl0ZW1JbmRleCA9PT0gLTEgJiYgdGhpcy5hZGROZXdCdXR0b24gJiYgIXRoaXMuYWRkTmV3QnV0dG9uLm5hdGl2ZUVsZW1lbnQuaGlkZGVuICYmICF0aGlzLmFkZE5ld1NlbGVjdGVkKSB7XHJcblx0XHRcdFx0XHR0aGlzLmFkZE5ld1NlbGVjdGVkID0gdHJ1ZTtcclxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRJdGVtSW5kZXggPCB0aGlzLmZpbHRlcmVkT3B0aW9ucy5sZW5ndGggLSAxKSB7XHJcblx0XHRcdFx0XHRpZiAodGhpcy5hZGROZXdTZWxlY3RlZCkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmFkZE5ld1NlbGVjdGVkID0gZmFsc2U7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHQvL2lmIHRoZSBsYXN0IGl0ZW0gaXMgYSBoZWFkaW5nIGFuZCB3ZSBhcmUgb24gdGhlIHNlY29uZCBsYXN0IGl0ZW0sIHdlIHNob3VsZG4ndCBpbmNyZW1lbnQgdGhlIHNlbGVjdGVkSXRlbUluZGV4IGJlY2F1c2UgdGhhdCB3b3VsZCBzZWxlY3QgdGhlIGhlYWRpbmdcclxuXHRcdFx0XHRcdGlmKCAhKHRoaXMuc2VsZWN0ZWRJdGVtSW5kZXggPT0gdGhpcy5maWx0ZXJlZE9wdGlvbnMubGVuZ3RoIC0gMiAmJiB0aGlzLmZpbHRlcmVkT3B0aW9uc1t0aGlzLnNlbGVjdGVkSXRlbUluZGV4KzFdLmRpc3BsYXkgPT09ICdoZWFkaW5nJykgKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuc2VsZWN0ZWRJdGVtSW5kZXgrKztcclxuXHRcdFx0XHRcdFx0Ly8gU2tpcCBhbnkgaW4tbWVudSBoZWFkaW5nIGl0ZW1zXHJcblx0XHRcdFx0XHRcdGlmICh0aGlzLnNlbGVjdGVkSXRlbUluZGV4IDwgdGhpcy5maWx0ZXJlZE9wdGlvbnMubGVuZ3RoIC0gMSAmJiB0aGlzLmZpbHRlcmVkT3B0aW9uc1t0aGlzLnNlbGVjdGVkSXRlbUluZGV4XS5kaXNwbGF5ID09PSAnaGVhZGluZycpIHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnNlbGVjdGVkSXRlbUluZGV4Kys7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRjYXNlIFwiQXJyb3dVcFwiOlxyXG5cdFx0XHRjYXNlIFwiVXBcIjpcclxuXHRcdFx0XHRpZiAodGhpcy5zZWxlY3RlZEl0ZW1JbmRleCA9PT0gLTEgJiYgdGhpcy5hZGROZXdCdXR0b24gJiYgIXRoaXMuYWRkTmV3QnV0dG9uLm5hdGl2ZUVsZW1lbnQuaGlkZGVuICYmIHRoaXMuYWRkTmV3U2VsZWN0ZWQpIHtcclxuXHRcdFx0XHRcdHRoaXMuYWRkTmV3U2VsZWN0ZWQgPSBmYWxzZTtcclxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRJdGVtSW5kZXggPiAtMSkge1xyXG5cdFx0XHRcdFx0aWYgKHRoaXMuc2VsZWN0ZWRJdGVtSW5kZXggPT09IDAgJiYgdGhpcy5hZGROZXdCdXR0b24gJiYgIXRoaXMuYWRkTmV3QnV0dG9uLm5hdGl2ZUVsZW1lbnQuaGlkZGVuKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuYWRkTmV3U2VsZWN0ZWQgPSB0cnVlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0dGhpcy5zZWxlY3RlZEl0ZW1JbmRleC0tO1xyXG5cdFx0XHRcdFx0Ly8gU2tpcCBhbnkgaW4tbWVudSBoZWFkaW5nIGl0ZW1zXHJcblx0XHRcdFx0XHRpZiAodGhpcy5zZWxlY3RlZEl0ZW1JbmRleCA+IC0xICYmIHRoaXMuZmlsdGVyZWRPcHRpb25zW3RoaXMuc2VsZWN0ZWRJdGVtSW5kZXhdLmRpc3BsYXkgPT09ICdoZWFkaW5nJykge1xyXG5cdFx0XHRcdFx0XHR0aGlzLnNlbGVjdGVkSXRlbUluZGV4LS07XHJcblxyXG5cdFx0XHRcdFx0XHQvL2lmIHRoZSBzZWxlY3RlZEl0ZW1JbmRleCBpcyAtMSwgdGhhdCBtZWFucyB0aGUgdmVyeSBmaXJzdCBpdGVtIHdhcyBhIGhlYWRpbmcgYW5kIHdlIGp1c3Qgc2tpcHBlZCBvdmVyIGl0LlxyXG5cdFx0XHRcdFx0XHRpZih0aGlzLnNlbGVjdGVkSXRlbUluZGV4ID09IC0xKSB7XHJcblx0XHRcdFx0XHRcdFx0Ly9pZiB0aGVyZSBpcyBhbiBhZGQgbmV3IGJ1dHRvbiB3ZSBzaG91bGQgc2VsZWN0IGl0LiBvdGhlcndpc2Ugd2Ugc2hvdWxkIGxvY2sgdGhlbSBhdCBpbmRleCAxIChyaWdodCBiZWZvcmUgdGhlIGhlYWRpbmcpXHJcblx0XHRcdFx0XHRcdFx0aWYodGhpcy5hZGROZXdCdXR0b24gJiYgIXRoaXMuYWRkTmV3QnV0dG9uLm5hdGl2ZUVsZW1lbnQuaGlkZGVuKSB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmFkZE5ld1NlbGVjdGVkID0gdHJ1ZTtcclxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5zZWxlY3RlZEl0ZW1JbmRleCA9IDE7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9XHJcbiAgICAgICAgICBcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5zZWxlY3RlZEl0ZW0gPSB0aGlzLmZpbHRlcmVkT3B0aW9uc1t0aGlzLnNlbGVjdGVkSXRlbUluZGV4XTtcclxuXHJcblx0XHRpZiAodGhpcy5tZW51U3RhdHVzID09PSAnaGlkZGVuJykge1xyXG5cclxuXHRcdFx0dGhpcy5zZXRGb3JtTW9kZWxWYWx1ZSh0aGlzLnNlbGVjdGVkSXRlbSk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHR0aGlzLnNjcm9sbE1lbnUoKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cclxuXHJcblx0LyoqXHJcblxyXG5cdCAqIEZpbHRlciBhcnJheSBvZiBvcHRpb25zIGJ5IGxhYmVsIChjb250YWlucylcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSBmaWx0ZXJUZXh0IFRoZSB2YWx1ZSBvZiB0ZXh0Ym94IHRoYXQgd2Ugd2lsbCBmaWx0ZXIgb3VyIG9wdGlvbnMgYnlcclxuXHQgKlxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHByaXZhdGUgZmlsdGVyT3B0aW9uc0FycmF5KGZpbHRlclRleHQ6IHN0cmluZyk6IEFycmF5PE1lbnVJdGVtPiB7XHJcblx0XHRsZXQgc2VhcmNoVGV4dCA9IGZpbHRlclRleHQudG9Mb3dlckNhc2UoKTtcclxuXHRcdGlmIChmaWx0ZXJUZXh0ICYmIGZpbHRlclRleHQgIT09ICcnKSB7XHJcblx0XHRcdHJldHVybiB0aGlzLm9wdGlvbnMuZmlsdGVyKGl0ZW0gPT4ge1xyXG5cdFx0XHRcdHJldHVybiBpdGVtLmxhYmVsLnRvTG93ZXJDYXNlKCkuaW5kZXhPZihzZWFyY2hUZXh0KSA+PSAwO1xyXG5cdFx0XHR9KVxyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmV0dXJuIHRoaXMub3B0aW9ucztcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBGaW5kIGEgZ2l2ZW4gaXRlbSdzIGluZGV4IGluIHRoZSBmaWx0ZXJlZCBpdGVtcyBhcnJheS5cclxuXHQgKlxyXG5cdCAqIFJldHVybnMgLTEgaWYgbm90IGZvdW5kXHJcblx0ICogQHBhcmFtIGl0ZW0gVGhlIG1hdGNoaW5nIGl0ZW0gdG8gZmluZCBpbiB0aGVcclxuXHQgKiBmaWx0ZXJkT3B0aW9ucyBhcnJheS4gV2lsbCB1c2UgdGhlIHNlbGVjdGVkSXRlbSBpZiBub3RoaW5nIGlzIHBhc3NlZC5cclxuXHQgKiBAbWVtYmVyb2YgQ29tYm9ib3hDb21wb25lbnRcclxuXHQgKi9cclxuXHRwcml2YXRlIGZpbmRTZWxlY3RlZEl0ZW1JbmRleChpdGVtPzogTWVudUl0ZW0pOiBudW1iZXIge1xyXG5cdFx0bGV0IGl0ZW1Ub0ZpbmQgPSBpdGVtID8gaXRlbSA6IHRoaXMuc2VsZWN0ZWRJdGVtO1xyXG5cclxuXHRcdGlmIChpdGVtVG9GaW5kKSB7XHJcblx0XHRcdHJldHVybiB0aGlzLmZpbHRlcmVkT3B0aW9ucy5maW5kSW5kZXgoaXRlbSA9PiB7XHJcblx0XHRcdFx0aWYoaXRlbS5pZCAmJiAoPE1lbnVJdGVtPml0ZW1Ub0ZpbmQpLmlkKSB7XHJcblx0XHRcdFx0XHRyZXR1cm4gaXRlbS5sYWJlbCA9PT0gKDxNZW51SXRlbT5pdGVtVG9GaW5kKS5sYWJlbCAmJiBpdGVtLmlkID09PSAoPE1lbnVJdGVtPml0ZW1Ub0ZpbmQpLmlkXHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdHJldHVybiBpdGVtLmxhYmVsID09PSAoPE1lbnVJdGVtPml0ZW1Ub0ZpbmQpLmxhYmVsO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIC0xO1xyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFJlYWN0IHRvIG91ciBmb3JtTW9kZWwgY2hhbmdpbmdcclxuXHQgKlxyXG5cdCAqIFRoZSBmb3JtTW9kZWwgcmVwcmVzZW50cyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIE1vZGVsSXRlbVxyXG5cdCAqIFdoZW4gY2hhbmdlZCwgc2V0IHRoZSB2YWx1ZSBvZiB0aGUgVGV4dGJveENvbXBvbmVudCBhbmRcclxuXHQgKiBmaW5kIGluZGV4IG9mIGl0ZW0gaW4gb3B0aW9ucyBsaXN0LlxyXG5cdCAqXHJcblx0ICogQG1lbWJlcm9mIENvbWJvYm94Q29tcG9uZW50XHJcblx0ICovXHJcblx0cHJpdmF0ZSBmb3JtTW9kZWxDaGFuZ2VkKGRhdGE/OiBNZW51SXRlbSk6IHZvaWQge1xyXG5cdFx0dGhpcy5zeW5jaHJvbml6ZURpc2FibGVkQXR0cmlidXRlcygpO1xyXG5cclxuXHRcdGlmIChkYXRhKSB7XHJcblx0XHRcdHRoaXMudGV4dGJveEZvcm1Nb2RlbC5zZXRWYWx1ZShkYXRhLmxhYmVsKTtcclxuXHJcblx0XHRcdHRoaXMuc2VsZWN0ZWRJdGVtSW5kZXggPSB0aGlzLmZpbmRTZWxlY3RlZEl0ZW1JbmRleChkYXRhKTtcclxuXHRcdFx0aWYgKHRoaXMuc2VsZWN0ZWRJdGVtSW5kZXggPj0gMCkge1xyXG5cdFx0XHRcdHRoaXMuc2VsZWN0ZWRJdGVtID0gdGhpcy5maWx0ZXJlZE9wdGlvbnNbdGhpcy5zZWxlY3RlZEl0ZW1JbmRleF07XHJcblx0XHRcdH1cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdC8vVGhlIGhvc3Qgd2lwZWQgb3V0IHRoZSBkYXRhIGV4dGVybmFsbHksIGNsZWFyIHRoZSB0ZXh0Ym94IGFuZCB0aGUgdHJhY2tpbmcgc3RhdGVcclxuXHRcdFx0dGhpcy50ZXh0Ym94Rm9ybU1vZGVsLnJlc2V0KCk7XHJcblx0XHRcdHRoaXMuY2xlYXJTZWxlY3RlZEl0ZW0oKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBTY3JvbGwgdGhlIG1lbnUgaWYgdGhlIGN1cnJlbnQgc2VsZWN0ZWRJdGVtSW5kZXggaXMgb3V0IG9mIHZpZXdcclxuXHQgKlxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHByaXZhdGUgc2Nyb2xsTWVudShrbm93bkluZGV4PzogbnVtYmVyKTogdm9pZCB7XHJcblx0XHRpZiAodGhpcy5maWx0ZXJlZE9wdGlvbnMubGVuZ3RoID4gMCkge1xyXG5cdFx0XHQvLyBVcGRhdGUgdGhlIHNlbGVjdGVkSXRlbUluZGV4IGluIGNhc2Ugb3VyIG9wdGlvbnMgY2hhbmdlZFxyXG5cdFx0XHR0aGlzLnNlbGVjdGVkSXRlbUluZGV4ID0ga25vd25JbmRleCA9PT0gdW5kZWZpbmVkID8gdGhpcy5maW5kU2VsZWN0ZWRJdGVtSW5kZXgoKSA6IGtub3duSW5kZXg7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5zZWxlY3RlZEl0ZW1JbmRleCA+IC0xICYmIHRoaXMuc2VsZWN0ZWRJdGVtKSB7XHJcblx0XHRcdFx0Ly8gVGhlIG1lbnUgY29tcG9uZW50IHdpbGwgYXV0b21hdGljYWxseSBnZW5lcmF0ZSBpZHMgZm9yIHRoZSBtZW51IGl0ZW1zIGlmIHRoZXkgZG9udCBoYXZlIHRoZW0sXHJcblx0XHRcdFx0Ly8gc28gdGhleSBuZWVkIHRvIGJlIGFjY291bnRlZCBmb3IgaGVyZSBzaW5jZSB0aGUgY29tYm9ib3ggZG9lc24ndCBrbm93IGFib3V0IHRob3NlIGlkc1xyXG5cdFx0XHRcdGxldCBpdGVtU2VsZWN0b3IgPSB0aGlzLnNlbGVjdGVkSXRlbS5pZCA/IGAjJHt0aGlzLnNlbGVjdGVkSXRlbS5pZH1gIDogYCMke3RoaXMuaWR9X21lbnVfaXRlbSR7dGhpcy5zZWxlY3RlZEl0ZW1JbmRleH1gO1xyXG5cclxuXHRcdFx0XHQvL3RyaWdnZXIgdGhlIHNjcm9sbGluZyBhZnRlciBhIHRpY2sgdG8gYWxsb3cgdGhlIG1lbnUgdG8gYmUgdXAgdG8gZGF0ZSAoYW5kIHBlbmRpbmcgbWFzayBjbGVhcmVkKSBiZWZvcmUgbWVhc3VyaW5nXHJcblx0XHRcdFx0c2V0VGltZW91dCgoKT0+e1xyXG5cdFx0XHRcdFx0dGhpcy5zY3JvbGxTZXJ2aWNlLnNjcm9sbEl0ZW1DZW50ZXJlZChgIyR7dGhpcy5pZH1fbWVudV9saXN0YCwgaXRlbVNlbGVjdG9yKTtcclxuXHRcdFx0XHR9LCAwKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHR0aGlzLnNlbGVjdGVkSXRlbSA9IG51bGw7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBTZWFyY2gvRmlsdGVyIGJhc2VkIG9uIHRleHRib3ggaW5wdXRcclxuXHQgKiBOT1RFOiBzbyBhcyBub3QgdG8gcmVjZWl2ZSBhIG5vdGlmaWNhdGlvbiBvbiBldmVyeSBrZXkgZXZlbnQsIHdlIHN1Z2dlc3QgeW91IGRlYm91bmNlIHlvdXJcclxuXHQgKiBzdWJzY3JpcHRpb25cclxuXHQgKiBAc2VlIHtAbGluayBodHRwOi8vcmVhY3RpdmV4LmlvL3J4anMvY2xhc3MvZXM2L09ic2VydmFibGUuanN+T2JzZXJ2YWJsZS5odG1sI2luc3RhbmNlLW1ldGhvZC1kZWJvdW5jZVRpbWUgfCBPYnNlcnZhYmxlLmRlYm91bmNlVGltZX1cclxuXHQgKlxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHByaXZhdGUgc2VhcmNoQW5kRmlsdGVyKHNlYXJjaFRleHQ/OiBzdHJpbmcpOiB2b2lkIHtcclxuXHJcblx0XHQvLyBhbHdheXMgZW1pdFxyXG5cdFx0dGhpcy5zZWFyY2guZW1pdChzZWFyY2hUZXh0KTtcclxuXHJcblx0XHQvLyBkbyBpbnRlcm5hbCBmaWx0ZXJpbmcgaWYgbm8gb25lJ3Mgc3Vic2NyaWJlZCB0byBvdXIgc2VhcmNoIGVtaXR0ZXJcclxuXHRcdGlmICh0aGlzLnNlYXJjaC5vYnNlcnZlcnMubGVuZ3RoID09PSAwICYmIHNlYXJjaFRleHQgIT09IHVuZGVmaW5lZCkge1xyXG5cdFx0XHR0aGlzLnJlc2V0T3B0aW9ucyh0aGlzLmZpbHRlck9wdGlvbnNBcnJheShzZWFyY2hUZXh0KSk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5hZGROZXdTZWxlY3RlZCAmJiAhdGhpcy5hZGROZXdCdXR0b24pIHtcclxuXHRcdFx0XHR0aGlzLmFkZE5ld1NlbGVjdGVkID0gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBTZXQge0BsaW5rIGZvcm1Nb2RlbCB9J3MgdmFsaWRhdGlvbiBlcnJvcnMgZXF1YWwgdG8gdGhlIGludGVybmFsIHRleHRib3gncy5cclxuXHQgKlxyXG5cdCAqIFdoZW4gdGhlIGludGVybmFsIHRleHRib3ggaXMgaW52YWxpZCwgbmVlZCB0byBzZXQgdGhpcyBjb250cm9sJ3NcclxuXHQgKiBlcnJvcnMgYmVjYXVzZSB3ZSBhcmUgdXNpbmcgb3VyIG93biBsYWJlbCwgbm90IFRleHRib3hDb250cm9sJ3MuXHJcblx0ICogV2UgdXNlIG91ciBvd24gbGFiZWwgc28gbGFiZWwgdGV4dCB3aWxsIHdyYXAgYXQgdGhlIGVuZCBvZiB0aGUgYnV0dG9uLFxyXG5cdCAqIG5vdCBhdCB0aGUgZW5kIG9mIHRoZSB0ZXh0Ym94LlxyXG5cdCAqXHJcblx0ICogQG1lbWJlcm9mIENvbWJvYm94Q29tcG9uZW50XHJcblx0ICovXHJcblx0cHJpdmF0ZSBzZXRGb3JtTW9kZWxWYWxpZGF0aW9uRXJyb3JzKGRhdGE/OiBhbnkpOiB2b2lkIHtcclxuXHRcdGlmICh0aGlzLnRleHRib3hGb3JtTW9kZWwuaW52YWxpZCkge1xyXG5cdFx0XHR0aGlzLmZvcm1Nb2RlbC5zZXRFcnJvcnModGhpcy50ZXh0Ym94Rm9ybU1vZGVsLmVycm9ycyk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHR0aGlzLmZvcm1Nb2RlbC5zZXRFcnJvcnMobnVsbCk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBVcGRhdGUgdGhlIGZvcm0gbW9kZWwgdmFsdWUgd2l0aCB0aGUgc2VsZWN0ZWQgaXRlbSBvciByZXNldCBmb3JtIG1vZGVsIHZhbHVlIGlmIGl0ZW0gaXMgbnVsbFxyXG5cdCAqXHJcblx0ICogQG1lbWJlcm9mIENvbWJvYm94Q29tcG9uZW50XHJcblx0ICovXHJcblx0cHJpdmF0ZSBzZXRGb3JtTW9kZWxWYWx1ZShpdGVtOiBNZW51SXRlbSB8IG51bGwpOiB2b2lkIHtcclxuXHRcdHRoaXMudGV4dGJveEZvcm1Nb2RlbC5zZXRWYWx1ZShpdGVtID8gaXRlbS5sYWJlbCA6ICcnKTtcclxuXHRcdHRoaXMuZm9ybU1vZGVsLnNldFZhbHVlKGl0ZW0pO1xyXG5cdFx0dGhpcy5mb3JtTW9kZWwubWFya0FzRGlydHkoKTtcclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBTZXQgdmFsaWRhdG9ycyBvbiB0aGUge0BzZWUgdGV4dGJveEZvcm1Nb2RlbCB9XHJcblx0ICpcclxuXHQgKiBWYWxpZGF0b3JzIGFyZSBjdXJyZW50bHkgc2V0IGJhc2VkIG9uIHRoZSB7QHNlZSBtYXhsZW5ndGggfSxcclxuXHQgKiB7QHNlZSBtaW5sZW5ndGggfSwgYW5kIHtAc2VlIHJlcXVpcmVkIH0gaW5wdXRzLiAgVGhpcyB3b3JrcyB3ZWxsXHJcblx0ICogd2l0aCB7QHNlZSBUZXh0Ym94Q29tcG9uZW50IH0sIHdoaWNoIG5lZWRzIHRoZXNlIGlucHV0cyB0byBhcHBseVxyXG5cdCAqIHRoZSBwcm9wZXIgYXR0cmlidXRlcyB0byBpdHMgaW5wdXRzLlxyXG5cdCAqXHJcblx0ICogQSBmdXR1cmUgcmVsZWFzZSBvZiBBbmd1bGFyIHdpbGwgc3VwcG9zZWRseSBhZGQgdGhlc2UgYXR0cmlidXRlc1xyXG5cdCAqIGZvciB5b3UsIHdoaWNoIHdpbGwgZWxpbWluYXRlIHRoZSBuZWVkIGZvciBUZXh0Ym94Q29tcG9uZW50IHRvIGhhdmVcclxuXHQgKiBzdWNoIGlucHV0cy4gIFRoaXMgY29tcG9uZW50LCBob3dldmVyLCB3aWxsIHN0aWxsIG5lZWQgdGhlc2UgaW5wdXRzXHJcblx0ICogYXMgdGhlcmUgaXMgbm8gY3VycmVudCB3YXkgdG8ga25vdyB3aGljaCB2YWxpZGF0b3JzIGFyZSBhcHBsaWVkIHRvIGl0XHJcblx0ICogZnJvbSBpdHMgcGFyZW50IFZpZXcgQ29tcG9uZW50LlxyXG5cdCAqXHJcblx0ICpcclxuXHQgKiBAbWVtYmVyb2YgQ29tYm9ib3hDb21wb25lbnRcclxuXHQgKi9cclxuXHRwcml2YXRlIHNldFRleHRib3hGb3JtTW9kZWxWYWxpZGF0b3JzKCk6IHZvaWQge1xyXG5cdFx0bGV0IHZhbGlkYXRvcnM6IEFycmF5PFZhbGlkYXRvckZuPiA9IFtdO1xyXG5cclxuXHRcdGlmICh0aGlzLnJlcXVpcmVkKSB7XHJcblx0XHRcdHZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3JzLnJlcXVpcmVkKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5taW5sZW5ndGgpIHtcclxuXHRcdFx0dmFsaWRhdG9ycy5wdXNoKFZhbGlkYXRvcnMubWluTGVuZ3RoKHRoaXMubWlubGVuZ3RoKSk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRoaXMubWF4bGVuZ3RoKSB7XHJcblx0XHRcdHZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3JzLm1heExlbmd0aCh0aGlzLm1heGxlbmd0aCkpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMudGV4dGJveEZvcm1Nb2RlbC5zZXRWYWxpZGF0b3JzKHZhbGlkYXRvcnMpO1xyXG5cclxuXHRcdHRoaXMudGV4dGJveEZvcm1Nb2RlbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogS2VlcCB0ZXh0Ym94J3MgZGlzYWJsZWQgc3RhdHVzIGluLXN5bmMgd2l0aCBjb21ib2JveCdzXHJcblx0ICpcclxuXHQgKiB7QGxpbmsgVGV4dGJveENvbXBvbmVudH0gZ2V0cyBpdHMgZGlzYWJsZWQgc3RhdHVzIGZyb20gaXRzIHtAbGluayBGb3JtQ29udHJvbH1cclxuXHQgKlxyXG5cdCAqIEBtZW1iZXJvZiBDb21ib2JveENvbXBvbmVudFxyXG5cdCAqL1xyXG5cdHByaXZhdGUgc3luY2hyb25pemVEaXNhYmxlZEF0dHJpYnV0ZXMoKTogdm9pZCB7XHJcblx0XHRpZiAodGhpcy5mb3JtTW9kZWwuZGlzYWJsZWQgIT09IHRoaXMudGV4dGJveEZvcm1Nb2RlbC5kaXNhYmxlZCkge1xyXG5cdFx0XHRpZiAodGhpcy5mb3JtTW9kZWwuZGlzYWJsZWQpIHtcclxuXHRcdFx0XHR0aGlzLnRleHRib3hGb3JtTW9kZWwuZGlzYWJsZSgpO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHRoaXMudGV4dGJveEZvcm1Nb2RlbC5lbmFibGUoKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIElmIHRoZSBmb3JtTW9kZWwgdmFsdWUgYW5kIHRleHRib3ggdmFsdWUgZG8gbm90IG1hdGNoLCByZXNldCB0aGUgdGV4dGJveCBhbmQgc2VsZWN0ZWRJdGVtIHRvXHJcblx0ICogdGhlIGZvcm1Nb2RsZSB2YWx1ZS4gSWYgdGhlcmUgaXMgbm8gZm9ybU1vZGVsIHZhbHVlLCBtYWtlIHN1cmUgd2UgY2xlYXIgdGhlIHRleHRib3guIFJlc2V0IHRoZVxyXG5cdCAqIGZpbHRlcmVkT3B0aW9ucyB0byB0aGUgZnVsbCBsaXN0IGFuZCB1cGRhdGUgdGhlIHNlbGVjdGVkSXRlbUluZGV4XHJcblx0ICpcclxuXHQgKi9cclxuXHRwcml2YXRlIHN5bmNNb2RlbFZhbHVlcygpOiB2b2lkIHtcclxuXHRcdC8vIElmIHRoZXJlIGlzIGEgZm9ybU1vZGVsIHZhbHVlLCByZXNldCB0aGUgc2VsZWN0ZWQgaXRlbS4gSWYgdGhlcmUgaXNuJ3QsIG1ha2VcclxuXHRcdC8vIHN1cmUgd2UgY2xlYXIgdGhlIHRleHRib3hcclxuXHRcdGlmICh0aGlzLmZvcm1Nb2RlbC52YWx1ZSAmJiB0aGlzLmZvcm1Nb2RlbC52YWx1ZS5sYWJlbCAhPT0gdGhpcy50ZXh0Ym94Rm9ybU1vZGVsLnZhbHVlKSB7XHJcblx0XHRcdHRoaXMudGV4dGJveEZvcm1Nb2RlbC5zZXRWYWx1ZSh0aGlzLmZvcm1Nb2RlbC52YWx1ZS5sYWJlbCk7XHJcblx0XHR9IGVsc2UgaWYgKCF0aGlzLmZvcm1Nb2RlbC52YWx1ZSkge1xyXG5cdFx0XHR0aGlzLnRleHRib3hGb3JtTW9kZWwuc2V0VmFsdWUoJycpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFNlYXJjaCBhbmQgZmlsdGVyIHRoZSBvcHRpb25zIGxpc3Qgd2hlbiB0aGUgdmFsdWUgb2YgdGhlIHRleHRib3ggaW5wdXQgY2hhbmdlcy4gSWYgYWRkTmV3IGlzXHJcblx0ICogc2V0IGFsc28gY2hlY2sgZm9yIG1hdGNoZXMgaW4gb3VyIGZpbHRlcmVkT3B0aW9ucyB0byBjb25kaXRpb25hbGx5IHNob3cgYW5kIGhpZGUgdGhlIGFkZCBuZXdcclxuXHQgKiBidXR0b25cclxuXHQgKlxyXG5cdCAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvRXZlbnRzL2lucHV0XHJcblx0ICovXHJcblx0cHVibGljIHRleHRib3hWYWx1ZUNoYW5nZWQoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XHJcblx0XHR0aGlzLnNlYXJjaEFuZEZpbHRlcih0aGlzLnRleHRib3hGb3JtTW9kZWwudmFsdWUpO1xyXG5cclxuXHRcdGlmICh0aGlzLnRleHRib3hGb3JtTW9kZWwudmFsdWUgPT09ICcnKSB7XHJcblx0XHRcdHRoaXMuY2xlYXJTZWxlY3RlZEl0ZW0oKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5hZGROZXcpIHtcclxuXHRcdFx0bGV0IG1hdGNoID0gdGhpcy5maWx0ZXJlZE9wdGlvbnMuZmluZCgob3B0aW9uKSA9PiB7XHJcblx0XHRcdFx0cmV0dXJuIG9wdGlvbi5sYWJlbC50b0xvd2VyQ2FzZSgpID09PSB0aGlzLnRleHRib3hGb3JtTW9kZWwudmFsdWUudG9Mb3dlckNhc2UoKTtcclxuXHRcdFx0fSk7XHJcblx0XHRcdHRoaXMuZm91bmRNYXRjaCA9IG1hdGNoID8gdHJ1ZSA6IGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFVwZGF0ZSB0aGUgcG9wdXAgbWVudSBwb3NpdGlvbiB3aGVuIGlucHV0IHZhbHVlIGNoYW5nZXNcclxuXHRcdGlmICh0aGlzLnBvcHVwKSB7XHJcblx0XHRcdHRoaXMucG9wdXAudXBkYXRlKCk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGNsZWFyU2VsZWN0ZWRJdGVtKCk6IHZvaWQge1xyXG5cdFx0dGhpcy5zZWxlY3RlZEl0ZW0gPSBudWxsO1xyXG5cdFx0dGhpcy5zZWxlY3RlZEl0ZW1JbmRleCA9IC0xO1xyXG5cdH1cclxuXHJcblx0LyoqUmVjb21wdXRlIHdoYXQgdGhlIHBsYWNlaG9sZGVyIHNob3VsZCBiZSBiYXNlZCBvbiB3aGV0aGVyIHRoZSB1c2VyIHByb3ZpZGVkIG9uZSBhbmQgdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIGFkZE5ldyBpbnB1dCAqL1xyXG5cdHByaXZhdGUgdXBkYXRlUGxhY2Vob2xkZXJUZXh0KCl7XHJcblx0XHRpZiAodGhpcy5wbGFjZWhvbGRlcikge1xyXG5cdFx0XHR0aGlzLmVmZmVjdGl2ZVBsYWNlaG9sZGVyID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudCh0aGlzLnBsYWNlaG9sZGVyKTtcclxuXHRcdH0gZWxzZSBpZiAodGhpcy5hZGROZXcpIHtcclxuXHRcdFx0dGhpcy5lZmZlY3RpdmVQbGFjZWhvbGRlciA9IHRoaXMuY2hvb3NlT3JBZGRQbGFjZWhvbGRlcjtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHRoaXMuZWZmZWN0aXZlUGxhY2Vob2xkZXIgPSB0aGlzLmNob29zZVBsYWNlaG9sZGVyO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqRmluZCB0aGUgb3B0aW9uIHdlIHdhbnQgdG8gYmUgdGhlIGRlZmF1bHQgc2VsZWN0aW9uLiBJZiB0aGVyZSBpcyBhbiBleGFjdCBtYXRjaCwgdXNlIHRoYXRcclxuXHQgKiBvdGhlcndpc2UgaWYgdGhlcmUgYXJlIGl0ZW1zLCByZXR1cm4gemVybyB0byBpbmRpY2F0ZSB0aGUgZmlyc3QgaXRlbS4gT3RoZXJ3aXNlIHJldHVybiAtMVxyXG5cdCAqIHRvIGluZGljYXRlIG5vIHNlbGVjdGlvblxyXG5cdCAqL1xyXG5cdHByaXZhdGUgZmluZERlZmF1bHRTZWxlY3Rpb25JbmRleChvcHRpb25zOiBNZW51SXRlbVtdLCBzZWFyY2hUZXh0OiBzdHJpbmcpOiBudW1iZXIge1xyXG5cdFx0bGV0IGluZGV4ID0gLTE7XHJcblxyXG5cdFx0aWYob3B0aW9ucyAmJiBvcHRpb25zLmxlbmd0aCl7XHJcblx0XHRcdGluZGV4ID0gb3B0aW9ucy5maW5kSW5kZXgob3B0aW9uPT5vcHRpb24gIT0gbnVsbCAmJiBvcHRpb24uZGlzcGxheSAhPT0gJ2hlYWRpbmcnKTtcclxuXHRcdFx0XHJcblx0XHRcdGlmKHNlYXJjaFRleHQpe1xyXG5cdFx0XHRcdHNlYXJjaFRleHQgPSBzZWFyY2hUZXh0LnRvTG93ZXJDYXNlKCkudHJpbSgpO1xyXG5cdFx0XHRcdGxldCBleGFjdE1hdGNoSW5kZXggPSBvcHRpb25zLmZpbmRJbmRleChvcHRpb249Pm9wdGlvbi5sYWJlbC50b0xvd2VyQ2FzZSgpID09IHNlYXJjaFRleHQgJiYgb3B0aW9uLmRpc3BsYXkgIT09ICdoZWFkaW5nJyk7XHJcblx0XHRcdFx0aWYoZXhhY3RNYXRjaEluZGV4ID49MCl7XHJcblx0XHRcdFx0XHRpbmRleCA9IGV4YWN0TWF0Y2hJbmRleDtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdHJldHVybiBpbmRleDtcclxuXHR9XHJcblxyXG59XHJcbiJdfQ==