@jax-data-science/sci-image-visualizer 0.8.3 → 0.10.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 (579) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +34 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  13. package/esm2022/lib/contracts/intensity.mjs +48 -5
  14. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  15. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  16. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  17. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  18. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  19. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  20. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  21. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  25. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  26. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  28. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  29. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  30. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  31. package/esm2022/lib/geometry/contour.mjs +63 -0
  32. package/esm2022/lib/geometry/loft.mjs +128 -0
  33. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  34. package/esm2022/lib/geometry/raster.mjs +98 -0
  35. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  36. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  37. package/esm2022/lib/geometry/ring.mjs +201 -0
  38. package/esm2022/lib/geometry/section.mjs +215 -0
  39. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  40. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  41. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  42. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  43. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  45. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +12 -9
  46. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +83 -0
  47. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  48. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +180 -591
  49. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  50. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  51. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  52. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  53. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +270 -0
  54. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  55. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  56. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  57. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  58. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  59. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +347 -0
  60. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +427 -4207
  61. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  62. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +550 -0
  63. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  64. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  65. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  66. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  67. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +194 -0
  68. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  69. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  70. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  71. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  72. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  73. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  74. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  75. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  76. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  77. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  78. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  79. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  80. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  81. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  82. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  83. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  84. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  85. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  86. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +164 -0
  87. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +213 -716
  88. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  89. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  90. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  91. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  92. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  93. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  94. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  95. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  96. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  97. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  98. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  99. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  100. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  101. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  102. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  103. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  104. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  105. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  106. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  107. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  108. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  109. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  110. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  111. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  112. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  113. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  114. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  115. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  116. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  117. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  118. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  119. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  120. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  121. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  122. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  123. package/esm2022/lib/models/bezier.mjs +1 -11
  124. package/esm2022/lib/models/class-preset.mjs +41 -3
  125. package/esm2022/lib/models/geometry.mjs +27 -164
  126. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  127. package/esm2022/lib/models/polygon-factory.mjs +134 -0
  128. package/esm2022/lib/models/region-clone.mjs +68 -0
  129. package/esm2022/lib/models/region-geojson.mjs +411 -0
  130. package/esm2022/lib/models/region.mjs +34 -33
  131. package/esm2022/lib/models/shape.mjs +18 -16
  132. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  133. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  134. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  135. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  136. package/esm2022/lib/plot.utilities.mjs +296 -473
  137. package/esm2022/lib/processing/image-crop.mjs +1 -1
  138. package/esm2022/lib/processing/processing-image.mjs +28 -15
  139. package/esm2022/lib/provide-visualization.mjs +40 -14
  140. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  141. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  142. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +163 -0
  143. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  144. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  145. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  146. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  147. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  148. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  149. package/esm2022/lib/region-editor/region-editor.component.mjs +896 -660
  150. package/esm2022/lib/region-editor/region-metrics.mjs +86 -0
  151. package/esm2022/lib/region-editor/region-persistence.service.mjs +160 -0
  152. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +169 -0
  153. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  154. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  155. package/esm2022/lib/region-ops.service.mjs +28 -70
  156. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  157. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  158. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  159. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  160. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  161. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  162. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  163. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  164. package/esm2022/lib/region-source/region-source.mjs +67 -0
  165. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  166. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  167. package/esm2022/lib/render-orchestrator.mjs +14 -11
  168. package/esm2022/lib/render-session.mjs +207 -0
  169. package/esm2022/lib/routing-visualizer.service.mjs +858 -414
  170. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  171. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  172. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  173. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  174. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  175. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  176. package/esm2022/lib/spatial/lod.mjs +187 -0
  177. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  178. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  179. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  180. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  181. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  182. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  183. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  184. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  185. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  186. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  187. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  188. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  189. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  190. package/esm2022/lib/spatial/stats.mjs +71 -0
  191. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  192. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  193. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  194. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  195. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  196. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  197. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  198. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  199. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  200. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  201. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  202. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  203. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  204. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  205. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  206. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  207. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  208. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  209. package/esm2022/lib/store/class-color.util.mjs +53 -5
  210. package/esm2022/lib/store/class-signatures.mjs +63 -0
  211. package/esm2022/lib/store/region-history.mjs +146 -0
  212. package/esm2022/lib/store/region-scope-cache.mjs +144 -0
  213. package/esm2022/lib/store/region-selection.mjs +82 -0
  214. package/esm2022/lib/store/region-source-scope.mjs +171 -0
  215. package/esm2022/lib/store/region-store.service.mjs +986 -670
  216. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  217. package/esm2022/lib/store/visualizer-store.service.mjs +81 -76
  218. package/esm2022/lib/toast-outlets.mjs +5 -4
  219. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  220. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  221. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  222. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  223. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  224. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +120 -0
  225. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  226. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  227. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  228. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  229. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  230. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  231. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  232. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  233. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  234. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  235. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  236. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  237. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  238. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +121 -0
  239. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  240. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  241. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  242. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  243. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  244. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  245. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  246. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  247. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  248. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  249. package/esm2022/lib/toolbar/toolbar.component.mjs +84 -119
  250. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  251. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  252. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  253. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  254. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  255. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  256. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  257. package/esm2022/lib/util/supersede.mjs +56 -0
  258. package/esm2022/lib/visualization.module.mjs +39 -141
  259. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  260. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  261. package/esm2022/lib/visualizer/region-load.mjs +123 -0
  262. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  263. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  264. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  265. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  266. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  267. package/esm2022/lib/visualizer.component.mjs +602 -1902
  268. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  269. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  270. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  271. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs +47169 -0
  272. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
  273. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs +238 -0
  274. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map +1 -0
  275. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  276. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  277. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  278. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  279. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
  280. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  281. package/fesm2022/mask.worker.js +36 -917
  282. package/fesm2022/onnx-sam.worker.js +52 -16
  283. package/fesm2022/region-source.worker.js +1067 -0
  284. package/fesm2022/spatial-math.worker.js +471 -0
  285. package/fesm2022/tsne.worker.js +32 -15
  286. package/index.d.ts +19 -10
  287. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  288. package/lib/contracts/capabilities.contract.d.ts +4 -2
  289. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  290. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  291. package/lib/contracts/color.d.ts +27 -0
  292. package/lib/contracts/colormap-lut.d.ts +19 -4
  293. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  294. package/lib/contracts/display-types.d.ts +21 -0
  295. package/lib/contracts/image.contract.d.ts +4 -0
  296. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  297. package/lib/contracts/intensity.d.ts +13 -2
  298. package/lib/contracts/plot-type.d.ts +3 -1
  299. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  300. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  301. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  302. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  303. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  304. package/lib/contracts/region-editor-api.contract.d.ts +85 -1
  305. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  306. package/lib/contracts/region-store.contract.d.ts +22 -0
  307. package/lib/contracts/sam.contract.d.ts +7 -0
  308. package/lib/contracts/section-view.contract.d.ts +44 -0
  309. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  310. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  311. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  312. package/lib/contracts/visualizer.contract.d.ts +231 -54
  313. package/lib/contracts/viz-config.d.ts +9 -0
  314. package/lib/geometry/contour.d.ts +24 -0
  315. package/lib/geometry/loft.d.ts +22 -0
  316. package/lib/geometry/polylabel.d.ts +23 -0
  317. package/lib/geometry/raster.d.ts +42 -0
  318. package/lib/geometry/reconstruct.d.ts +54 -0
  319. package/lib/geometry/reslice-image.d.ts +33 -0
  320. package/lib/geometry/ring.d.ts +67 -0
  321. package/lib/geometry/section.d.ts +52 -0
  322. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  323. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  324. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  325. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  326. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  327. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  328. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -3
  329. package/lib/implementations/napari-js/napari-loading-state.d.ts +37 -0
  330. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  331. package/lib/implementations/napari-js/napari-region-overlay.d.ts +68 -71
  332. package/lib/implementations/napari-js/napari-scene.d.ts +126 -0
  333. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  334. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  335. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  336. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +91 -0
  337. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  338. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  339. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  340. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  341. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  342. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  343. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +169 -883
  344. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  345. package/lib/implementations/napari-js/napari-volume-scene.d.ts +148 -0
  346. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  347. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  348. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  349. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  350. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  351. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  352. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  353. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  354. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  355. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  356. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  357. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  358. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  359. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  360. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  361. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  362. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  363. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  364. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  365. package/lib/implementations/osd/osd-export.d.ts +36 -0
  366. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  367. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  368. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  369. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +38 -0
  370. package/lib/implementations/osd/osd-region-overlay.d.ts +46 -51
  371. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  372. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  373. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  374. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  375. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  376. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  377. package/lib/implementations/osd/simple-source.d.ts +161 -0
  378. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  379. package/lib/implementations/osd/tile-client.d.ts +11 -14
  380. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  381. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  382. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  383. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  384. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  385. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  386. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  387. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  388. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  389. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  390. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  391. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  392. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  393. package/lib/implementations/region-centroids.d.ts +14 -0
  394. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  395. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  396. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  397. package/lib/implementations/tile-server/index.d.ts +5 -0
  398. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  399. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  400. package/lib/implementations/tile-server/tile-protocol.d.ts +83 -0
  401. package/lib/implementations/tile-server/transport.d.ts +62 -0
  402. package/lib/intensity/intensity-profile.d.ts +66 -0
  403. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  404. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  405. package/lib/models/bezier.d.ts +0 -5
  406. package/lib/models/class-preset.d.ts +25 -0
  407. package/lib/models/geometry.d.ts +14 -48
  408. package/lib/models/polygon-edit.d.ts +72 -0
  409. package/lib/models/polygon-factory.d.ts +45 -0
  410. package/lib/models/region-clone.d.ts +20 -0
  411. package/lib/models/region-geojson.d.ts +57 -0
  412. package/lib/models/region.d.ts +59 -4
  413. package/lib/models/shape.d.ts +8 -0
  414. package/lib/plot-mode/contribution-host.d.ts +125 -0
  415. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  416. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  417. package/lib/plot.utilities.d.ts +19 -30
  418. package/lib/processing/processing-image.d.ts +5 -2
  419. package/lib/provide-visualization.d.ts +19 -2
  420. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  421. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  422. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +86 -0
  423. package/lib/region-editor/file-stem.d.ts +7 -0
  424. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  425. package/lib/region-editor/mask-export.service.d.ts +54 -0
  426. package/lib/region-editor/mask-raster.d.ts +2 -8
  427. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  428. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  429. package/lib/region-editor/region-editor.component.d.ts +283 -200
  430. package/lib/region-editor/region-metrics.d.ts +34 -0
  431. package/lib/region-editor/region-persistence.service.d.ts +77 -0
  432. package/lib/region-editor/region-table/region-table.component.d.ts +89 -0
  433. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  434. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  435. package/lib/region-ops.service.d.ts +1 -7
  436. package/lib/region-overlay/region-geometry.d.ts +158 -0
  437. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  438. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  439. package/lib/region-overlay/region-style.d.ts +52 -0
  440. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  441. package/lib/region-source/http-region-source.d.ts +45 -0
  442. package/lib/region-source/region-source-ops.d.ts +89 -0
  443. package/lib/region-source/region-source-worker.d.ts +7 -0
  444. package/lib/region-source/region-source.d.ts +82 -0
  445. package/lib/region-source/region-tiles.d.ts +289 -0
  446. package/lib/region-source/worker-region-source.d.ts +65 -0
  447. package/lib/render-orchestrator.d.ts +6 -2
  448. package/lib/render-session.d.ts +75 -0
  449. package/lib/routing-visualizer.service.d.ts +248 -59
  450. package/lib/section-pane/section-pane.component.d.ts +47 -0
  451. package/lib/spatial/density-raster.d.ts +6 -0
  452. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  453. package/lib/spatial/embedding-compute.d.ts +21 -2
  454. package/lib/spatial/glyphs.d.ts +16 -0
  455. package/lib/spatial/lod.d.ts +94 -0
  456. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  457. package/lib/spatial/spatial-density.d.ts +15 -5
  458. package/lib/spatial/spatial-encoding.d.ts +11 -44
  459. package/lib/spatial/spatial-expression.d.ts +40 -22
  460. package/lib/spatial/spatial-framing.d.ts +1 -0
  461. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  462. package/lib/spatial/spatial-hover.d.ts +4 -16
  463. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  464. package/lib/spatial/spatial-selection.d.ts +21 -26
  465. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  466. package/lib/spatial/spatial-tiles.d.ts +9 -256
  467. package/lib/spatial/stats.d.ts +38 -0
  468. package/lib/spatial/transcript-grouping.d.ts +119 -0
  469. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  470. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  471. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  472. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  473. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  474. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  475. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  476. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  477. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  478. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  479. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  480. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  481. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  482. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  483. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  484. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  485. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  486. package/lib/store/class-color.util.d.ts +39 -2
  487. package/lib/store/class-signatures.d.ts +11 -0
  488. package/lib/store/region-history.d.ts +66 -0
  489. package/lib/store/region-scope-cache.d.ts +65 -0
  490. package/lib/store/region-selection.d.ts +36 -0
  491. package/lib/store/region-source-scope.d.ts +68 -0
  492. package/lib/store/region-store.service.d.ts +312 -116
  493. package/lib/store/visualizer-store.service.d.ts +32 -33
  494. package/lib/toast-outlets.d.ts +4 -3
  495. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  496. package/lib/toolbar/canvas-tools.d.ts +20 -0
  497. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  498. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  499. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  500. package/lib/toolbar/region-tools/region-tools.component.d.ts +62 -0
  501. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  502. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  503. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  504. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  505. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  506. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  507. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  508. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  509. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  510. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  511. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  512. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  513. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  514. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +51 -0
  515. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  516. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  517. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  518. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  519. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  520. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  521. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  522. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  523. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  524. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  525. package/lib/toolbar/toolbar.component.d.ts +55 -84
  526. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  527. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  528. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  529. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  530. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  531. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  532. package/lib/util/mark-for-check.d.ts +11 -0
  533. package/lib/util/supersede.d.ts +53 -0
  534. package/lib/visualization.module.d.ts +18 -39
  535. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  536. package/lib/visualizer/region-actions.d.ts +54 -0
  537. package/lib/visualizer/region-load.d.ts +46 -0
  538. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  539. package/lib/visualizer/tool-modes.d.ts +49 -0
  540. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  541. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  542. package/lib/visualizer/volume-sections.d.ts +64 -0
  543. package/lib/visualizer.component.d.ts +232 -447
  544. package/lib/workers/spatial-math-ops.d.ts +65 -0
  545. package/lib/workers/spatial-math-worker.d.ts +7 -0
  546. package/lib/workers/spatial-math.d.ts +74 -0
  547. package/package.json +12 -3
  548. package/src/lib/assets/slice.svg +23 -0
  549. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  550. package/src/lib/styles/viz-icons.scss +14 -0
  551. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  552. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  553. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  554. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  555. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  556. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  557. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  558. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  559. package/src/lib/assets/cell-detection.svg +0 -37
  560. package/src/lib/assets/click.svg +0 -1
  561. package/src/lib/assets/colormap-luts.json +0 -1
  562. package/src/lib/assets/edit-selection-white.svg +0 -47
  563. package/src/lib/assets/icons/colormap-earth.png +0 -0
  564. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  565. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  566. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  567. package/src/lib/assets/picture-segmentation.svg +0 -43
  568. package/src/lib/assets/test/download-379.svg +0 -1
  569. package/src/lib/assets/test/download-98.svg +0 -1
  570. package/src/lib/assets/test/json-1.svg +0 -1
  571. package/src/lib/assets/test/load-53.svg +0 -1
  572. package/src/lib/assets/test/mask-44.svg +0 -1
  573. package/src/lib/assets/test/mask-download-44.svg +0 -15
  574. package/src/lib/assets/test/mask-save-44.svg +0 -11
  575. package/src/lib/assets/test/overlay-1.svg +0 -1
  576. package/src/lib/assets/test/overlay-4.svg +0 -1
  577. package/src/lib/assets/test/region-26.svg +0 -1
  578. package/src/lib/assets/test/save-56.svg +0 -1
  579. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -1,20 +1,24 @@
1
1
  import { Inject, Injectable, Optional } from '@angular/core';
2
- import { combineLatest, firstValueFrom } from 'rxjs';
2
+ import { EMPTY, Subject, Subscription, combineLatest, merge, BehaviorSubject } from 'rxjs';
3
3
  import { map } from 'rxjs/operators';
4
+ import { resolveColormap } from 'napari-js';
4
5
  import { PlotlyService } from './implementations/plotly/plotly.service';
5
6
  import { OpenSeadragonVisualizerService } from './implementations/osd/openseadragon-visualizer.service';
6
- import { PlotType, isNapari3d, isNapariScatter, isSpatialOmics, isSpatialOmics3d } from './contracts/plot-type';
7
+ import { PlotType, isNapari3d, isNapariScatter, isSpatialOmics, isSpatialOmics3d, isNapariIsosurface, isNapariVolume, } from './contracts/plot-type';
7
8
  import { SPATIAL_DATA_PORT } from './contracts/ports/spatial-data.port';
8
- import { isCategoricalColumn } from './contracts/spatial-dataset.contract';
9
- import { resolveCategoryColors } from './spatial/spatial-encoding';
10
- import { sectionsOf } from './spatial/spatial-sections';
11
- import { observationsInSlice, volumeImageRef, } from './spatial/spatial-volume-image';
12
- import { emptySelection, selectByCategory, selectByIndices, selectInRegions, selectInRegionsProjected, } from './spatial/spatial-selection';
9
+ import { SpatialControlsFacade } from './spatial/spatial-controls.facade';
13
10
  import { RegionStore } from './store/region-store.service';
11
+ import { REGION_SOURCE_MIN_CHARS } from './region-source/region-source';
12
+ import { openGeoJsonRegionSource } from './region-source/worker-region-source';
14
13
  import { SpatialSelectionStore } from './store/spatial-selection.service';
14
+ import { autoWindowFromHistogram } from './contracts/intensity';
15
15
  import { VisualizerStore } from './store/visualizer-store.service';
16
16
  import { NapariVisualizerService } from './implementations/napari-js/napari-visualizer.service';
17
+ import { channelTintColormap, volumeColormap } from './implementations/napari-js/napari-display-state';
17
18
  import { VIZ_CONFIG } from './contracts/viz-config';
19
+ import { IntensityProfileService } from './intensity/intensity-profile.service';
20
+ import { changedClasses, classSignatures } from './store/class-signatures';
21
+ import { VolumeSections } from './visualizer/volume-sections';
18
22
  import * as i0 from "@angular/core";
19
23
  import * as i1 from "./implementations/plotly/plotly.service";
20
24
  import * as i2 from "./implementations/osd/openseadragon-visualizer.service";
@@ -22,72 +26,41 @@ import * as i3 from "./implementations/napari-js/napari-visualizer.service";
22
26
  import * as i4 from "./store/visualizer-store.service";
23
27
  import * as i5 from "./store/region-store.service";
24
28
  import * as i6 from "./store/spatial-selection.service";
25
- /**
26
- * Backend selector. Routes per plot type:
27
- * - the **Image** plot type renders through OpenSeadragon — a natively-tiled,
28
- * zoomable raster backed by the jit-service tile endpoints. It's the default
29
- * view and supports the region overlay/tools and (for grayscale) the
30
- * colormap, applied client-side via the tile pixel pipeline.
31
- * - every other plot type (heatmap, surface, contour, scatter, line,
32
- * scatter3d, isosurface) renders through Plotly.
33
- *
34
- * Only the **render + viewport** path is routed. Region state, display options
35
- * (colormap/LUT), and the long-lived observables always live in Plotly (the
36
- * shared store) so both backends stay in sync; OSD reads them to drive its own
37
- * overlay and tile recoloring.
38
- *
39
- * The Image type renders through OpenSeadragon; a failed OSD load falls back to
40
- * Plotly for that image only (see `osdFellBack`) so it still renders.
41
- */
29
+ import * as i7 from "./intensity/intensity-profile.service";
30
+ /** How long after the last edit the surfaces of the classes it touched are rebuilt (ms). */
31
+ export const REGION_SURFACE_REBUILD_MS = 600;
42
32
  /** Intensity-profile line ROIs are owned by the intensity tool, not the editor.
43
33
  * Package-internal predicate (property-based so it also matches plain objects
44
34
  * after a drag round-trip). */
45
35
  function isProfileRegion(r) {
46
36
  return r?.kind === 'profile';
47
37
  }
48
- /** Saturation-based auto-window: pick [min,max] so ~`saturation` of pixels clip
49
- * at each end of the histogram. A dominant first/last bin (unscanned padding /
50
- * clipped background) is dropped so it doesn't skew the range. */
51
- function autoWindowFromHistogram(h, saturation) {
52
- const counts = h.counts.slice();
53
- const n = counts.length;
54
- if (n === 0)
55
- return [0, 255];
56
- if (n > 2 && counts[0] > counts[1])
57
- counts[0] = 0;
58
- if (n > 2 && counts[n - 1] > counts[n - 2])
59
- counts[n - 1] = 0;
60
- let total = 0;
61
- for (const c of counts)
62
- total += c;
63
- if (total <= 0)
64
- return [0, 255];
65
- const target = total * Math.max(0, Math.min(0.5, saturation));
66
- let acc = 0;
67
- let min = h.bins[0];
68
- for (let i = 0; i < n; i++) {
69
- acc += counts[i];
70
- if (acc > target) {
71
- min = h.bins[i];
72
- break;
73
- }
74
- }
75
- acc = 0;
76
- let max = h.bins[n - 1];
77
- for (let i = n - 1; i >= 0; i--) {
78
- acc += counts[i];
79
- if (acc > target) {
80
- max = h.bins[i];
81
- break;
82
- }
83
- }
84
- return [min, max];
85
- }
38
+ /**
39
+ * The visualizer chain's front door: implements `IVisualizer`, `IRegionEditorApi`
40
+ * and `IChannelHistogramApi` (bound to the `VISUALIZER` / `REGION_EDITOR_API` /
41
+ * `CHANNEL_HISTOGRAM_API` tokens) over three rendering backends, chosen per plot type:
42
+ * - **Image** renders through OpenSeadragon (natively tiled, region tools,
43
+ * client-side colormap), or through napari-js when `VizConfig.useNapariRenderer`
44
+ * opts in; the napari image types and the 2D spatial-omics mode render through
45
+ * napari-js. A failed load falls back napari-js → OSD → Plotly for that image only
46
+ * (see `napariFellBack` / `osdFellBack`, cleared by `reset()`).
47
+ * - the napari 3D types (volume, isosurface, surface, 3D scatter, the 3D spatial
48
+ * cloud) render through napari-js, falling back to Plotly.
49
+ * - every other plot type (heatmap, contour, surface, scatter, line, …) renders
50
+ * through Plotly.
51
+ *
52
+ * Only rendering and the viewport are routed to the backend on screen. Region state
53
+ * lives in the shared `RegionStore` and display state (colormap, channels, presets,
54
+ * spatial view) in the shared `VisualizerStore`, so every backend sees the same
55
+ * values; the backends subscribe to them to redraw.
56
+ *
57
+ * Package-internal: hosts depend on the tokens, not on this class.
58
+ */
86
59
  export class RoutingVisualizerService {
87
60
  constructor(plotly, osd, napari, store, config,
88
61
  // Optional: a host that serves no spatial-omics data binds nothing,
89
62
  // and `getSpatialControls()` then returns null.
90
- regionStore, selectionStore, spatialData = null) {
63
+ regionStore, selectionStore, intensity, spatialData = null) {
91
64
  this.plotly = plotly;
92
65
  this.osd = osd;
93
66
  this.napari = napari;
@@ -95,6 +68,7 @@ export class RoutingVisualizerService {
95
68
  this.config = config;
96
69
  this.regionStore = regionStore;
97
70
  this.selectionStore = selectionStore;
71
+ this.intensity = intensity;
98
72
  this.spatialData = spatialData;
99
73
  this.currentPlotType = PlotType.IMAGE;
100
74
  this.lastRendered = null;
@@ -107,15 +81,123 @@ export class RoutingVisualizerService {
107
81
  /** napari-js failed for the current render cycle → fall back to OSD (then Plotly).
108
82
  * Reset by reset() at the start of every cycle, like {@link osdFellBack}. */
109
83
  this.napariFellBack = false;
110
- /** Memoised so consumers can hold the object across calls. */
111
- this.spatialControls = null;
112
- /** Latest dataset, mirrored so `selectFromRegions()` can answer synchronously
113
- * — it runs from a button click and must not await a round-trip. */
114
- this.currentSpatialDataset = null;
84
+ /** The div the backends render into (every backend shares it); '' before the first plot. */
85
+ this.plotDiv = '';
86
+ /** Whether a napari volume view is the current plot type. */
87
+ this.volumeView$ = new BehaviorSubject(false);
88
+ /** Whether the volume view's slice pane is wanted (see {@link setSliceEditor}). */
89
+ this.sliceEditor$ = new BehaviorSubject(false);
90
+ /** Whether the volume view draws the region reconstructions through the volume. */
91
+ this.regionsThroughVolume$ = new BehaviorSubject(false);
92
+ /** Region reconstructions built so far, by image, resolution and classes (with those classes). */
93
+ this.meshCache = new Map();
94
+ /** Bumped per {@link showRegionClasses3d} (and per new image), so only the latest one shows. */
95
+ this.meshRequest = 0;
96
+ /** The class groups shown in 3D, and the image they belong to. */
97
+ this.classes3d$ = new BehaviorSubject([]);
98
+ /** The groups last asked for in 3D, with their colours: what an edit's rebuild shows again. */
99
+ this.shown3d = [];
100
+ /**
101
+ * Each class's fingerprint on the live slice (see classSignatures), which image and slice, and
102
+ * what the region sources hold (see RegionStore.getSourceStateKey). Null while nothing follows
103
+ * the edits (no surface built, no sections).
104
+ */
105
+ this.liveClasses = null;
106
+ /** The pending rebuild of the surfaces an edit touched. */
107
+ this.rebuildTimer = null;
108
+ // ── The slice pane (the volume view's split): OSD editing one slice beside the 3D view ──
109
+ /** The div the slice pane renders into while it is wanted (null: no split). */
110
+ this.sliceDiv = null;
111
+ /** Whether OSD is mounted in the slice pane: region, tool and overlay calls go to it. */
112
+ this.sliceMounted = false;
113
+ /** Bumped per slice-pane mount or teardown, so only the latest one lands. */
114
+ this.sliceRequest = 0;
115
+ /** The z plane dragged in the volume: the slice to show (see {@link getSliceDrag$}). */
116
+ this.sliceDrag$ = new Subject();
117
+ this.sectionSubs = new Subscription();
118
+ /** The image info and screen height of the last plot (what the slice pane mounts). */
119
+ this.plottedInfo = null;
120
+ this.plottedHeight = 0;
121
+ this.viewOptions = {
122
+ setNavigatorVisible: (visible) => {
123
+ for (const b of this.backends())
124
+ b.getOsdViewOptions()?.setNavigatorVisible(visible);
125
+ },
126
+ setImageSmoothingEnabled: (enabled) => {
127
+ for (const b of this.backends())
128
+ b.getOsdViewOptions()?.setImageSmoothingEnabled(enabled);
129
+ },
130
+ };
131
+ /** Created on first use; owns the dataset subscription. */
132
+ this.spatialFacade = null;
115
133
  /** Displayed slice. Only a volume-backed spatial dataset reads it, to keep a
116
134
  * region drawn over one section from selecting the whole depth behind it. */
117
135
  this.currentZIndex = 0;
118
- this.spatialDatasetSub = null;
136
+ this.intensitySampling = {
137
+ // Load the displayed slice's pixels for a backend that has no frames of its own
138
+ // (OpenSeadragon, napari-js; Plotly feeds its frames to the service when it plots).
139
+ ensureIntensitySampling: (imageInfo, zIndex) => {
140
+ this.pointSamplingAtPlot();
141
+ return this.intensity.ensureIntensitySampling(imageInfo, zIndex);
142
+ },
143
+ // Re-sample from a fresh crop of the image-pixel ROI at display resolution.
144
+ refreshIntensitySamplingForRoi: (x, y, width, height, zIndex) => {
145
+ this.pointSamplingAtPlot();
146
+ this.intensity.refreshIntensitySamplingForRoi(x, y, width, height, zIndex);
147
+ },
148
+ getViewportChange$: () => merge(...this.backends().map((b) => b.getIntensitySampling()?.getViewportChange$() ?? EMPTY)),
149
+ };
150
+ this.regionUpdates = this.regionStore.getRegionUpdateEvent().subscribe(() => this.onRegionsChanged());
151
+ this.sections = new VolumeSections({
152
+ volume: () => this.napari.volumeVoxels(),
153
+ image: () => this.plottedFileName,
154
+ showPlanes: (planes) => this.napari.setSlicePlanes(planes),
155
+ outlinesByClass: (level) => this.regionStore.outlinesByClass(level),
156
+ isClassHidden: (label) => this.regionStore.isClassHidden(label),
157
+ colorOf: (label) => this.classColor(label),
158
+ channelStates: () => this.store.currentChannelStates(),
159
+ colormap: (st, multichannel) => {
160
+ // As the volume scene colours the channel (invert is applied before the colormap).
161
+ const display = {
162
+ colormap: this.store.currentColormap(),
163
+ reverse: this.store.currentReverseScale(),
164
+ invert: false,
165
+ };
166
+ return resolveColormap(multichannel ? channelTintColormap(st?.color ?? '#ffffff', display) : volumeColormap(st, display));
167
+ },
168
+ invert: () => this.store.currentInvert(),
169
+ slice: () => this.currentZIndex,
170
+ });
171
+ // A plane dragged in the volume: the z plane picks the slice (through the host's slider, so
172
+ // the store and the slice pane follow), the others move their section.
173
+ this.sectionSubs.add(this.napari.getSlicePlaneMove$().subscribe(({ axis, value }) => {
174
+ if (axis === 'z')
175
+ this.sliceDrag$.next(Math.round(value));
176
+ else
177
+ this.sections.setPlane(axis, value);
178
+ }));
179
+ this.sectionSubs.add(this.store.getChannelStates().subscribe(() => this.sections.schedule()));
180
+ this.sectionSubs.add(this.store.getInvert().subscribe(() => this.sections.schedule()));
181
+ this.sectionSubs.add(this.store.getColormap().subscribe(() => this.sections.schedule()));
182
+ this.sectionSubs.add(this.store.getReverseScale().subscribe(() => this.sections.schedule()));
183
+ }
184
+ /** A class's colour: its classification colour, else its region source's, else a default. */
185
+ classColor(label) {
186
+ return (this.store.getClassificationColors().get(label) ??
187
+ this.regionStore.getRegionSourceView()?.colorOf({ label, color: null }) ??
188
+ '#ffcc00');
189
+ }
190
+ /** The sections beside the split volume view (nulls while it is not split). */
191
+ getSectionViews$() {
192
+ return this.sections.getViews$();
193
+ }
194
+ /** Move a section's plane to `at` (image px). */
195
+ setSectionPlane(axis, at) {
196
+ this.sections.setPlane(axis, at);
197
+ }
198
+ /** The slice picked by dragging the z plane in the volume: the host shows it (its slider). */
199
+ getSliceDrag$() {
200
+ return this.sliceDrag$.asObservable();
119
201
  }
120
202
  isImageType(t) {
121
203
  return t === PlotType.IMAGE;
@@ -167,50 +249,77 @@ export class RoutingVisualizerService {
167
249
  renderer() {
168
250
  return this.lastRendered ?? this.plotly;
169
251
  }
252
+ /**
253
+ * Backend region, tool and overlay calls act on: the slice pane's OSD while the volume view is
254
+ * split (regions are edited there), else the backend on screen. View calls (zoom, fit, colour,
255
+ * export) stay with {@link renderer}.
256
+ */
257
+ regionBackend() {
258
+ return this.sliceMounted ? this.osd : this.renderer();
259
+ }
170
260
  // System capabilities are Plotly's (the full-featured backend) so the UI
171
261
  // keeps offering every plot type regardless of which one is on screen.
172
- get capabilities() { return this.plotly.capabilities; }
262
+ get capabilities() {
263
+ return this.plotly.capabilities;
264
+ }
173
265
  // ── render / viewport → active renderer ──────────────────────────────
174
- async load(imageInfo, zIndex) {
266
+ async load(imageInfo, zIndex, signal) {
175
267
  // A stack can open away from slice 0 (`initialZIndex` — a volume opens
176
268
  // mid-specimen), and that arrives here rather than through setZIndex.
177
269
  this.currentZIndex = zIndex;
178
270
  const backend = this.imageBackend();
179
271
  if (backend === this.napari) {
180
272
  try {
181
- return await this.napari.load(imageInfo, zIndex);
273
+ return await this.napari.load(imageInfo, zIndex, signal);
182
274
  }
183
275
  catch (err) {
276
+ // Aborted: nobody wants this image any more, so don't go on to load it elsewhere.
277
+ if (signal?.aborted)
278
+ throw err;
184
279
  this.napariFellBack = true;
185
280
  // Mirror imageBackend()'s fallback so load + plot pick the same backend:
186
281
  // - 3D napari types have no 2D fallback → straight to Plotly.
187
282
  // - 2D image → OSD, then Plotly.
188
283
  if (this.isNapari3dType(this.currentPlotType)) {
189
284
  console.warn('[visualizer] napari-js load failed — falling back to Plotly.', err);
190
- return this.plotly.load(imageInfo, zIndex);
285
+ return this.plotly.load(imageInfo, zIndex, signal);
191
286
  }
192
287
  console.warn('[visualizer] napari-js load failed — falling back to OpenSeadragon.', err);
193
- return this.loadViaOsdThenPlotly(imageInfo, zIndex);
288
+ return this.loadViaOsdThenPlotly(imageInfo, zIndex, signal);
194
289
  }
195
290
  }
196
291
  if (backend === this.osd) {
197
- return this.loadViaOsdThenPlotly(imageInfo, zIndex);
292
+ return this.loadViaOsdThenPlotly(imageInfo, zIndex, signal);
198
293
  }
199
- return this.plotly.load(imageInfo, zIndex);
294
+ return this.plotly.load(imageInfo, zIndex, signal);
200
295
  }
201
296
  /** Try OSD; on failure fall back to Plotly for this image (not permanent — see reset()). */
202
- async loadViaOsdThenPlotly(imageInfo, zIndex) {
297
+ async loadViaOsdThenPlotly(imageInfo, zIndex, signal) {
203
298
  try {
204
- return await this.osd.load(imageInfo, zIndex);
299
+ return await this.osd.load(imageInfo, zIndex, signal);
205
300
  }
206
301
  catch (err) {
302
+ if (signal?.aborted)
303
+ throw err;
207
304
  console.warn('[visualizer] OpenSeadragon load failed — falling back to Plotly for this image.', err);
208
305
  this.osdFellBack = true;
209
- return this.plotly.load(imageInfo, zIndex);
306
+ return this.plotly.load(imageInfo, zIndex, signal);
210
307
  }
211
308
  }
212
309
  plot(plotDiv, imageLoaded, imageInfo, screenHeight, plotType, inPlace) {
213
310
  this.currentPlotType = plotType;
311
+ this.volumeView$.next(isNapariVolume(plotType) || isNapariIsosurface(plotType));
312
+ this.plottedFileName = imageInfo?.fileName;
313
+ this.plottedInfo = imageInfo ?? null;
314
+ this.plottedHeight = screenHeight;
315
+ // The slice pane belongs to the volume view: another plot type takes it down (OSD may be
316
+ // about to draw the main view, which must not find the pane's viewer still mounted).
317
+ if (!this.volumeView$.value)
318
+ this.unmountSlice();
319
+ // Region surfaces belong to the image they were built from: another image drops them.
320
+ if (this.classes3d$.value.length && this.plottedFileName !== this.classes3dImage)
321
+ this.clearRegionClasses3d();
322
+ this.plotDiv = plotDiv;
214
323
  // Apply the per-image region cache (snapshot old regions, restore the new
215
324
  // image's, clear selection) for whichever backend renders — Plotly does
216
325
  // this inside its own plot(), but OSD doesn't, so drive it here. Idempotent
@@ -227,9 +336,78 @@ export class RoutingVisualizerService {
227
336
  this.lastRendered.reset();
228
337
  }
229
338
  this.lastRendered = next;
230
- return next.plot(plotDiv, imageLoaded, imageInfo, screenHeight, plotType, inPlace);
339
+ const plotted = next.plot(plotDiv, imageLoaded, imageInfo, screenHeight, plotType, inPlace);
340
+ if (!this.sliceDiv || !this.volumeView$.value)
341
+ return plotted;
342
+ // The split volume view: the slice pane follows the image (a new one, or its sharper pass).
343
+ return plotted.then((ok) => {
344
+ if (ok && (!this.sliceMounted || this.sliceFile !== imageInfo?.fileName || inPlace)) {
345
+ void this.mountSlice(!!inPlace && this.sliceMounted && this.sliceFile === imageInfo?.fileName);
346
+ }
347
+ // The volume was assembled again (another image, or resolution): cut the sections from it.
348
+ if (ok)
349
+ this.sections.schedule();
350
+ return ok;
351
+ });
352
+ }
353
+ /**
354
+ * Split the volume view: show the slice being edited in `div` (OpenSeadragon, with every region
355
+ * tool) beside the 3D view, or stop (null). Kept across re-plots of a volume view; another plot
356
+ * type takes the pane down and a volume view brings it back. Resolves whether the pane shows.
357
+ */
358
+ async setSliceEditor(div) {
359
+ this.sliceDiv = div;
360
+ if (this.sliceEditor$.value !== !!div)
361
+ this.sliceEditor$.next(!!div);
362
+ if (!div) {
363
+ this.unmountSlice();
364
+ return false;
365
+ }
366
+ return this.mountSlice(false);
367
+ }
368
+ /** Mount (or refresh in place) OSD in the slice pane on the displayed slice. */
369
+ async mountSlice(inPlace) {
370
+ const div = this.sliceDiv;
371
+ const info = this.plottedInfo;
372
+ if (!div || !info?.urls?.length || !this.volumeView$.value)
373
+ return false;
374
+ const request = ++this.sliceRequest;
375
+ try {
376
+ const loaded = await this.osd.load(info, this.currentZIndex);
377
+ if (request !== this.sliceRequest)
378
+ return false;
379
+ const ok = await this.osd.plot(div, loaded, info, this.plottedHeight, PlotType.IMAGE, inPlace);
380
+ if (request !== this.sliceRequest)
381
+ return false;
382
+ this.sliceMounted = ok;
383
+ this.sliceFile = info.fileName;
384
+ if (ok) {
385
+ // The slice may have moved while the pane loaded.
386
+ this.osd.setZIndex(this.currentZIndex);
387
+ this.trackLiveClasses();
388
+ this.sections.start();
389
+ }
390
+ return ok;
391
+ }
392
+ catch (err) {
393
+ if (request === this.sliceRequest)
394
+ console.warn('[visualizer] The slice pane could not show the image.', err);
395
+ return false;
396
+ }
397
+ }
398
+ /** Take the slice pane's viewer down (the split stays wanted while {@link sliceDiv} is set). */
399
+ unmountSlice() {
400
+ this.sliceRequest++;
401
+ if (this.sliceMounted) {
402
+ this.osd.reset();
403
+ this.sections.stop();
404
+ }
405
+ this.sliceMounted = false;
406
+ this.sliceFile = undefined;
407
+ }
408
+ reloadAndPlot() {
409
+ this.plotly.reloadAndPlot();
231
410
  }
232
- reloadAndPlot() { this.plotly.reloadAndPlot(); }
233
411
  reset() {
234
412
  // Start of a render cycle: re-enable napari-js/OSD attempts (clear any prior
235
413
  // per-image fallback) and tear down whatever's on screen.
@@ -237,47 +415,105 @@ export class RoutingVisualizerService {
237
415
  this.napariFellBack = false;
238
416
  this.renderer().reset();
239
417
  }
240
- relayout(trueImageSize) { this.renderer().relayout(trueImageSize); }
241
- resetAxes() { this.renderer().resetAxes(); }
242
- autoscale() { this.renderer().autoscale(); }
243
- zoomIn() { this.renderer().zoomIn(); }
244
- zoomOut() { this.renderer().zoomOut(); }
245
- setDragMode(mode) { this.renderer().setDragMode(mode); }
246
- // Set on both backends (not just the active renderer): consumers call this
247
- // before the first render, when `renderer()` is still the Plotly default, so
248
- // OSD must receive the flag to honour it at viewer creation.
418
+ relayout(trueImageSize) {
419
+ this.renderer().relayout(trueImageSize);
420
+ }
421
+ resetAxes() {
422
+ this.renderer().resetAxes();
423
+ }
424
+ fitToView() {
425
+ this.renderer().fitToView();
426
+ }
427
+ /** @deprecated Use {@link fitToView}. */
428
+ autoscale() {
429
+ this.fitToView();
430
+ }
431
+ zoomIn() {
432
+ this.renderer().zoomIn();
433
+ }
434
+ zoomOut() {
435
+ this.renderer().zoomOut();
436
+ }
437
+ setDragMode(mode) {
438
+ this.renderer().setDragMode(mode);
439
+ if (this.sliceMounted)
440
+ this.osd.setDragMode(mode);
441
+ }
442
+ /** Every backend, on screen or not. */
443
+ backends() {
444
+ return [this.plotly, this.osd, this.napari];
445
+ }
446
+ /**
447
+ * The navigator / smoothing options, applied to EVERY backend that has them (not
448
+ * just the active renderer): consumers set them before the first render, when
449
+ * `renderer()` is still the Plotly default, and OSD/napari-js must receive them
450
+ * to honour them at viewer creation.
451
+ */
452
+ getOsdViewOptions() {
453
+ return this.viewOptions;
454
+ }
455
+ /** @deprecated Use `getOsdViewOptions().setNavigatorVisible()`. */
249
456
  setNavigatorVisible(visible) {
250
- this.osd.setNavigatorVisible(visible);
251
- this.plotly.setNavigatorVisible(visible);
252
- this.napari.setNavigatorVisible(visible);
457
+ this.viewOptions.setNavigatorVisible(visible);
253
458
  }
254
- // Set on both backends (see setNavigatorVisible): consumers may set it before
255
- // the first render, when the active renderer is still Plotly.
459
+ /** @deprecated Use `getOsdViewOptions().setImageSmoothingEnabled()`. */
256
460
  setImageSmoothingEnabled(enabled) {
257
- this.osd.setImageSmoothingEnabled(enabled);
258
- this.plotly.setImageSmoothingEnabled(enabled);
461
+ this.viewOptions.setImageSmoothingEnabled(enabled);
462
+ }
463
+ setShowStack(showstack) {
464
+ this.renderer().setShowStack(showstack);
259
465
  }
260
- setShowStack(showstack) { this.renderer().setShowStack(showstack); }
261
466
  setZIndex(zIndex) {
262
467
  this.currentZIndex = zIndex;
263
468
  this.renderer().setZIndex(zIndex);
469
+ if (this.sliceMounted) {
470
+ this.osd.setZIndex(zIndex);
471
+ this.sections.schedule();
472
+ }
473
+ }
474
+ getTrueImageSize() {
475
+ return this.renderer().getTrueImageSize();
476
+ }
477
+ getCurrentImage() {
478
+ return this.renderer().getCurrentImage();
479
+ }
480
+ getDisplayedPixelData() {
481
+ return this.renderer().getDisplayedPixelData();
264
482
  }
265
- getTrueImageSize() { return this.renderer().getTrueImageSize(); }
266
- getCurrentImage() { return this.renderer().getCurrentImage(); }
267
- getDisplayedPixelData() { return this.renderer().getDisplayedPixelData(); }
268
483
  getDisplayedSourceRect() {
269
484
  return this.renderer().getDisplayedSourceRect();
270
485
  }
271
- downloadImage() { this.renderer().downloadImage(); }
272
- exportComposite() { this.renderer().exportComposite(); }
486
+ downloadImage() {
487
+ this.renderer().downloadImage();
488
+ }
489
+ exportComposite() {
490
+ this.renderer().exportComposite();
491
+ }
273
492
  setPlotType(plotType) {
274
493
  this.currentPlotType = plotType;
494
+ this.volumeView$.next(isNapariVolume(plotType) || isNapariIsosurface(plotType));
275
495
  this.plotly.setPlotType(plotType);
276
496
  }
277
- setSurfaceDragMode(mode) { this.renderer().setSurfaceDragMode(mode); }
278
- resetSurfaceCamera() { this.renderer().resetSurfaceCamera(); }
279
- setResolutionScale(scale) { this.renderer().setResolutionScale?.(scale); }
280
- getResolutionScale() { return this.renderer().getResolutionScale?.() ?? 1; }
497
+ /** @deprecated Use `getSurface3dControls()`. */
498
+ setSurfaceDragMode(mode) {
499
+ this.getSurface3dControls()?.setSurfaceDragMode(mode);
500
+ }
501
+ /** @deprecated Use `getSurface3dControls()`. */
502
+ resetSurfaceCamera() {
503
+ this.getSurface3dControls()?.resetSurfaceCamera();
504
+ }
505
+ /** The 3D decimate factor of the backend on screen (napari-js), else null. */
506
+ getVolumeResolution() {
507
+ return this.renderer().getVolumeResolution();
508
+ }
509
+ /** @deprecated Use `getVolumeResolution()?.set()`. */
510
+ setResolutionScale(scale) {
511
+ this.getVolumeResolution()?.set(scale);
512
+ }
513
+ /** @deprecated Use `getVolumeResolution()?.get()`. */
514
+ getResolutionScale() {
515
+ return this.getVolumeResolution()?.get() ?? 1;
516
+ }
281
517
  /** The viewport of the backend on screen, for a contributed plot mode. Null
282
518
  * when that backend cannot provide one (e.g. OSD fell back to Plotly). */
283
519
  getPlotModeViewport() {
@@ -289,10 +525,12 @@ export class RoutingVisualizerService {
289
525
  return this.plotly.getPlotTypeDescriptors();
290
526
  }
291
527
  // ── long-lived observables + stack flags ──────────────────────────────────
292
- setStackLoading(b) { this.plotly.setStackLoading(b); }
528
+ setStackLoading(b) {
529
+ this.plotly.setStackLoading(b);
530
+ }
293
531
  // Cancel in-flight loading on every backend — the user's Cancel shouldn't depend on which one is
294
532
  // active. Only backends that stream frames (napari-js) do real work; the rest no-op. The concrete
295
- // backend classes don't all declare the optional contract method, so call it via IVisualizer.
533
+ // backend classes don't all declare the optional contract method, so call it via IViewerBackend.
296
534
  cancelLoading() {
297
535
  for (const backend of [this.plotly, this.osd, this.napari]) {
298
536
  backend.cancelLoading?.();
@@ -319,82 +557,351 @@ export class RoutingVisualizerService {
319
557
  return active.length ? Math.max(...active) : 0;
320
558
  }));
321
559
  }
322
- getAutoscaleEvent() { return this.plotly.getAutoscaleEvent(); }
323
- getIntensityProfile$() { return this.plotly.getIntensityProfile$(); }
324
- // The intensity inset is a Plotly LINE chart — render it through Plotly, which
325
- // owns the profile stream regardless of which backend draws the main image.
560
+ // Every backend fits to view on its own (Plotly's autoscale, OSD's goHome, napari's camera
561
+ // fit) and each emits from its own subject, so merge all three: listening to Plotly alone
562
+ // missed the context-menu Autoscale on the Image and napari views.
563
+ getAutoscaleEvent() {
564
+ return merge(this.plotly.getAutoscaleEvent(), this.osd.getAutoscaleEvent(), this.napari.getAutoscaleEvent()).pipe(map(() => undefined));
565
+ }
566
+ /** The line-ROI profiles: sampled by the backend-neutral IntensityProfileService. */
567
+ getIntensityProfile$() {
568
+ return this.intensity.getIntensityProfile$();
569
+ }
570
+ // The intensity inset is a Plotly LINE chart — render it through Plotly whichever
571
+ // backend draws the main image.
326
572
  renderIntensityInset(divId, profiles) {
327
573
  this.plotly.renderIntensityInset(divId, profiles);
328
574
  }
329
- // ── regions → active renderer ────────────────────────────────────────
330
- // Region *state* lives in the shared RegionStore; both backends implement
331
- // IRegionStore by delegating to it. We route through the active renderer
332
- // (not hardcoded Plotly) so the backend on screen also *renders* the change:
333
- // Plotly relayouts its shapes, OpenSeadragon's overlay redraws from the store
334
- // update event. Either way the same store is the single source of truth.
575
+ // ── regions ──────────────────────────────────────────────────────────
576
+ // Region state lives in the shared RegionStore, so every read and write goes
577
+ // straight to it. Every backend draws from the store's events: the OSD and
578
+ // napari-js overlays and Plotly's shape projection redraw on its region-update
579
+ // and selection streams, and the canvas tools reset on getRegionSetReplaced$
580
+ // (undo, redo, a slice switch).
335
581
  setRegions(regions, showRegionLabel, isRegionSaveOn, fillColor, append) {
336
- this.renderer().setRegions(regions, showRegionLabel, isRegionSaveOn, fillColor, append);
337
- }
338
- getRegions() { return this.renderer().getRegions(); }
339
- getRegionPolygons() { return this.renderer().getRegionPolygons(); }
340
- getRegionUpdateEvent() { return this.renderer().getRegionUpdateEvent(); }
341
- setSelectedShapeIndices(indices) { this.renderer().setSelectedShapeIndices(indices); }
342
- selectRegion(region) { this.renderer().selectRegion(region); }
343
- getSelectedShapeIndices$() { return this.renderer().getSelectedShapeIndices$(); }
344
- deleteActiveShape() { this.renderer().deleteActiveShape(); }
345
- getShowShapeLabel() { return this.renderer().getShowShapeLabel(); }
346
- getShapeColor() { return this.renderer().getShapeColor(); }
347
- getFillColor() { return this.renderer().getFillColor(); }
348
- getClassificationColors() { return this.renderer().getClassificationColors(); }
582
+ this.regionStore.setRegions(regions, showRegionLabel, isRegionSaveOn, fillColor, append);
583
+ }
584
+ getRegions() {
585
+ return this.regionStore.getRegions();
586
+ }
587
+ getRegionPolygons() {
588
+ return this.regionStore.getRegionPolygons();
589
+ }
590
+ getRegionUpdateEvent() {
591
+ return this.regionStore.getRegionUpdateEvent();
592
+ }
593
+ setSelectedShapeIndices(indices) {
594
+ this.regionStore.setSelectedShapeIndices(indices);
595
+ }
596
+ selectRegion(region) {
597
+ this.regionStore.selectRegion(region);
598
+ }
599
+ getSelectedShapeIndices$() {
600
+ return this.regionStore.getSelectedShapeIndices$();
601
+ }
602
+ deleteActiveShape() {
603
+ this.regionStore.deleteActiveShape();
604
+ }
605
+ getShowShapeLabel() {
606
+ return this.regionStore.getShowShapeLabel();
607
+ }
608
+ getShapeColor() {
609
+ return this.regionStore.getShapeColor();
610
+ }
611
+ getFillColor() {
612
+ return this.regionStore.getFillColor();
613
+ }
614
+ getClassificationColors() {
615
+ return this.store.getClassificationColors();
616
+ }
349
617
  setClassificationColor(label, color) {
350
- this.renderer().setClassificationColor(label, color);
618
+ this.store.setClassificationColor(label, color);
351
619
  }
352
620
  // Annotation-class presets live in the shared VisualizerStore (backend-neutral
353
621
  // session state), so route straight to it rather than through renderer(). (jit-ui#70)
354
- getPresetSet() { return this.store.getPresetSet(); }
355
- getPresetSet$() { return this.store.getPresetSet$(); }
356
- setPresetSet(set) { this.store.setPresetSet(set); }
357
- upsertClass(preset) { this.store.upsertClass(preset); }
358
- removeClass(name) { this.store.removeClass(name); }
359
- resetPresets() { this.store.resetPresets(); }
360
- plotPreviousShapes() { this.renderer().plotPreviousShapes(); }
361
- setPreviousShapes(shapes) { this.renderer().setPreviousShapes(shapes); }
362
- getPreviousShapes() { return this.renderer().getPreviousShapes(); }
363
- // Undo state is owned by the shared RegionStore (same instance for both
364
- // backends), so routing through the active renderer is safe and stable.
365
- undo() { this.renderer().undo(); }
366
- redo() { this.renderer().redo(); }
367
- canUndo() { return this.renderer().canUndo(); }
368
- canRedo() { return this.renderer().canRedo(); }
369
- getCanUndo$() { return this.renderer().getCanUndo$(); }
370
- getCanRedo$() { return this.renderer().getCanRedo$(); }
371
- resetUndoHistory() { this.renderer().resetUndoHistory(); }
372
- importRegions(geoJsonStr) { return this.renderer().importRegions(geoJsonStr); }
373
- exportRegions(regions) { this.renderer().exportRegions(regions); }
374
- getGeoJsonString(regions) { return this.renderer().getGeoJsonString(regions); }
375
- // ── Per-slice z-stack regions (jit-ui#93) — the RegionStore is shared across
376
- // backends, so routing to the active renderer hits the same store. ──────
622
+ getPresetSet() {
623
+ return this.store.getPresetSet();
624
+ }
625
+ getPresetSet$() {
626
+ return this.store.getPresetSet$();
627
+ }
628
+ setPresetSet(set) {
629
+ this.store.setPresetSet(set);
630
+ }
631
+ upsertClass(preset) {
632
+ this.store.upsertClass(preset);
633
+ }
634
+ removeClass(name) {
635
+ this.store.removeClass(name);
636
+ }
637
+ resetPresets() {
638
+ this.store.resetPresets();
639
+ }
640
+ undo() {
641
+ this.regionStore.undo();
642
+ }
643
+ redo() {
644
+ this.regionStore.redo();
645
+ }
646
+ canUndo() {
647
+ return this.regionStore.canUndo();
648
+ }
649
+ canRedo() {
650
+ return this.regionStore.canRedo();
651
+ }
652
+ getCanUndo$() {
653
+ return this.regionStore.getCanUndo$();
654
+ }
655
+ getCanRedo$() {
656
+ return this.regionStore.getCanRedo$();
657
+ }
658
+ resetUndoHistory() {
659
+ this.regionStore.resetUndoHistory();
660
+ }
661
+ importRegions(geoJsonStr) {
662
+ return this.regionStore.importRegions(geoJsonStr);
663
+ }
664
+ /** Download `regions` as GeoJSON, named after the image last plotted. */
665
+ exportRegions(regions) {
666
+ this.regionStore.exportRegions(regions, this.plottedFileName);
667
+ }
668
+ getGeoJsonString(regions) {
669
+ return this.regionStore.getGeoJsonString(regions);
670
+ }
671
+ /** Hold a large region set as a tiled region source (see RegionStore.attachRegionSource). */
672
+ attachRegionSource(source, slices) {
673
+ this.regionStore.attachRegionSource(source, slices);
674
+ }
675
+ async importRegionSource(geoJsonStr) {
676
+ if (geoJsonStr.length < (this.config?.regionSourceMinChars ?? REGION_SOURCE_MIN_CHARS))
677
+ return false;
678
+ let opened = await openGeoJsonRegionSource(geoJsonStr);
679
+ // The first open is the one just made; a source closed to save memory parses again.
680
+ this.regionStore.attachRegionSource(() => {
681
+ const source = opened;
682
+ opened = null;
683
+ return source ? Promise.resolve(source) : openGeoJsonRegionSource(geoJsonStr);
684
+ });
685
+ return true;
686
+ }
687
+ dropRegionSource() {
688
+ return this.regionStore.dropSliceRegionSource();
689
+ }
690
+ getRegionSourceView$() {
691
+ return this.regionStore.getRegionSourceView$();
692
+ }
693
+ getRegionSourceIndex(query) {
694
+ return this.regionStore.getRegionSourceIndex(query);
695
+ }
696
+ selectSourceFeatures(ids, additive) {
697
+ return this.regionStore.selectSourceFeatures(ids, additive);
698
+ }
699
+ deleteSourceFeatures(ids) {
700
+ this.regionStore.deleteSourceFeatures(ids);
701
+ }
702
+ getRegionStyle$() {
703
+ return this.regionStore.getRegionStyle$();
704
+ }
705
+ setRegionStyle(patch) {
706
+ this.regionStore.setRegionStyle(patch);
707
+ }
708
+ // ── Regions in 3D: their reconstructions shown in the volume view ─────
709
+ /** Whether a napari volume (or isosurface) view is on screen: regions can be shown in 3D. */
710
+ getVolumeView$() {
711
+ return this.volumeView$.asObservable();
712
+ }
713
+ /** Whether the volume view's slice pane is wanted (it shows while a volume view is on screen). */
714
+ getSliceEditor$() {
715
+ return this.sliceEditor$.asObservable();
716
+ }
717
+ /** Whether the volume view draws the region reconstructions through the volume. */
718
+ getRegionsThroughVolume$() {
719
+ return this.regionsThroughVolume$.asObservable();
720
+ }
721
+ /**
722
+ * Draw the region reconstructions through the volume (it hides none of them: surfaces inside its
723
+ * bright structures, an OCT's layer boundaries) or hidden behind what it shows (the default).
724
+ */
725
+ setRegionsThroughVolume(through) {
726
+ if (this.regionsThroughVolume$.value === through)
727
+ return;
728
+ this.regionsThroughVolume$.next(through);
729
+ this.napari.setRegionsThroughVolume(through);
730
+ }
731
+ /** The class groups shown in 3D on this image ([] after a switch to another image). */
732
+ getRegionClasses3d$() {
733
+ return this.classes3d$.asObservable();
734
+ }
735
+ /** Hide every region surface and forget them (a build still running is dropped). */
736
+ clearRegionClasses3d() {
737
+ this.meshRequest++;
738
+ this.shown3d = [];
739
+ this.classes3d$.next([]);
740
+ this.classes3dImage = undefined;
741
+ this.napari.setRegionMeshes([], undefined);
742
+ this.napari.setRegionHighlight([]);
743
+ }
744
+ /** Highlight the surfaces of these group keys in the volume view (none: all as usual). */
745
+ highlightRegionClasses3d(keys) {
746
+ this.napari.setRegionHighlight(keys);
747
+ }
748
+ /** A surface clicked in the volume view with the selection tool (its group key), or none (null). */
749
+ getRegionPicked3d$() {
750
+ return this.napari.getRegionMeshPick$();
751
+ }
752
+ /**
753
+ * Show these groups of classes in the volume view as 3D reconstructions (each group one surface
754
+ * in its colour: an atlas structure with its substructures), and only these; [] hides them.
755
+ * Reconstructed from every slice's outlines at the volume's resolution, cached per image.
756
+ */
757
+ async showRegionClasses3d(groups) {
758
+ const request = ++this.meshRequest;
759
+ this.classes3dImage = this.plottedFileName;
760
+ this.shown3d = groups;
761
+ // What an edit from now on is compared with (the live slice may not have changed yet).
762
+ this.liveClasses = null;
763
+ this.trackLiveClasses();
764
+ this.classes3d$.next(groups.map((g) => ({ key: g.key, classes: g.classes })));
765
+ const width = this.getTrueImageSize()?.width ?? 1024;
766
+ const step = this.napari.regionVoxelStep() ?? Math.max(1, width / 256);
767
+ const image = this.plottedFileName ?? '';
768
+ const cacheKey = (g) => `${image}|${step.toFixed(3)}|${g.classes.join(',')}`;
769
+ const missing = groups.filter((g) => !this.meshCache.has(cacheKey(g)));
770
+ if (missing.length) {
771
+ const names = missing.map((g) => g.key);
772
+ const what = names.length > 3 ? `${names.length} regions` : names.join(', ');
773
+ const done = this.napari.beginTask(`Building ${what} in 3D…`);
774
+ try {
775
+ const built = await this.regionStore.reconstructClasses(missing.map((g) => ({ key: cacheKey(g), classes: g.classes })), step);
776
+ const classesOf = new Map(missing.map((g) => [cacheKey(g), g.classes]));
777
+ for (const b of built)
778
+ this.meshCache.set(b.key, { mesh: b.mesh, classes: classesOf.get(b.key) ?? [] });
779
+ }
780
+ finally {
781
+ done();
782
+ }
783
+ }
784
+ if (request !== this.meshRequest)
785
+ return;
786
+ this.napari.setRegionMeshes(groups.map((g) => {
787
+ const mesh = this.meshCache.get(cacheKey(g)).mesh;
788
+ return { key: g.key, color: g.color, label: g.label, vertices: mesh.vertices, faces: mesh.faces };
789
+ }), this.plottedFileName);
790
+ }
791
+ /**
792
+ * The regions changed: when the live slice's regions of some classes did (an edit, an undo, not
793
+ * a slice or image switch), their reconstructions are stale. They are dropped, and those shown
794
+ * in 3D are rebuilt once the edits pause.
795
+ */
796
+ onRegionsChanged() {
797
+ // Nothing follows the edits (no surface built or shown, no sections): skip the fingerprints.
798
+ if (!this.sliceMounted && !this.shown3d.length && !this.meshCache.size) {
799
+ this.liveClasses = null;
800
+ return;
801
+ }
802
+ const before = this.liveClasses;
803
+ this.liveClasses = null;
804
+ const now = this.trackLiveClasses();
805
+ // Another slice or image came up: no region changed (the sections recut for the slice).
806
+ if (!before || before.at !== now.at)
807
+ return;
808
+ const changed = changedClasses(before.signatures, now.signatures);
809
+ // Source features deleted (or that undone) change no live region, and which classes they were
810
+ // is not known here: every class is stale. A feature taken shows as its class's change.
811
+ const everyClass = !changed.size && before.sources !== now.sources;
812
+ if (!changed.size && !everyClass)
813
+ return;
814
+ const touched = (c) => everyClass || changed.has(c);
815
+ if (this.sliceMounted)
816
+ this.sections.regionsChanged();
817
+ for (const [key, entry] of [...this.meshCache]) {
818
+ if (entry.classes.some(touched))
819
+ this.meshCache.delete(key);
820
+ }
821
+ if (!this.shown3d.some((g) => g.classes.some(touched)))
822
+ return;
823
+ if (this.rebuildTimer)
824
+ clearTimeout(this.rebuildTimer);
825
+ this.rebuildTimer = setTimeout(() => {
826
+ this.rebuildTimer = null;
827
+ if (this.shown3d.length && this.classes3dImage === this.plottedFileName) {
828
+ void this.showRegionClasses3d(this.shown3d);
829
+ }
830
+ }, REGION_SURFACE_REBUILD_MS);
831
+ }
832
+ /** Fingerprint the live slice's classes, unless already: what the next edit is compared with. */
833
+ trackLiveClasses() {
834
+ this.liveClasses ??= {
835
+ at: this.liveSliceKey(),
836
+ signatures: classSignatures(this.regionStore.getRegions()),
837
+ sources: this.regionStore.getSourceStateKey(),
838
+ };
839
+ return this.liveClasses;
840
+ }
841
+ /** Which slice of which image the live regions are. */
842
+ liveSliceKey() {
843
+ return `${this.regionStore.getDisplaySlice()}\n${this.plottedFileName ?? ''}`;
844
+ }
845
+ /** Each class's volume over the whole stack, in px² × slices (see RegionStore.classVolumes). */
846
+ async getClassVolumes(classes) {
847
+ return Object.fromEntries(await this.regionStore.classVolumes(classes));
848
+ }
849
+ getRegionSourceClassCounts(stack) {
850
+ return this.regionStore.getRegionSourceClassCounts(stack);
851
+ }
852
+ getHiddenClasses$() {
853
+ return this.regionStore.getHiddenClasses$();
854
+ }
855
+ setClassesHidden(classes, hidden) {
856
+ this.regionStore.setClassesHidden(classes, hidden);
857
+ // A surface is its class's (its group key is the class name).
858
+ this.napari.setRegionHidden([...this.regionStore.getHiddenClasses()]);
859
+ this.sections.schedule();
860
+ }
861
+ async selectRegionClasses(classes, additive) {
862
+ await this.regionStore.selectClasses(classes, additive);
863
+ }
864
+ getGeoJsonStringWithSource(regions, slice) {
865
+ return this.regionStore.getGeoJsonWithSource(regions, slice);
866
+ }
867
+ // ── Per-slice z-stack regions (jit-ui#93), from the shared RegionStore. ──
377
868
  enterStackMode(slices, initialZ, saveLayout) {
378
- this.renderer().enterStackMode(slices, initialZ, saveLayout);
379
- }
380
- exitStackMode() { this.renderer().exitStackMode(); }
381
- isStackMode() { return this.renderer().isStackMode(); }
382
- getStackSaveLayout() { return this.renderer().getStackSaveLayout(); }
383
- setDisplaySlice(z) { this.renderer().setDisplaySlice(z); }
384
- getSliceRegions() { return this.renderer().getSliceRegions(); }
385
- getStackSaveSlices() { return this.renderer().getStackSaveSlices(); }
869
+ this.regionStore.enterStackMode(slices, initialZ, saveLayout);
870
+ }
871
+ exitStackMode() {
872
+ this.regionStore.exitStackMode();
873
+ }
874
+ isStackMode() {
875
+ return this.regionStore.isStackMode();
876
+ }
877
+ /** The slice the regions are shown for (recorded outside stack mode too). */
878
+ getDisplaySlice() {
879
+ return this.regionStore.getDisplaySlice();
880
+ }
881
+ getStackSaveLayout() {
882
+ return this.regionStore.getStackSaveLayout();
883
+ }
884
+ setDisplaySlice(z) {
885
+ this.regionStore.setDisplaySlice(z);
886
+ }
887
+ getSliceRegions() {
888
+ return this.regionStore.getSliceRegions();
889
+ }
890
+ getStackSaveSlices() {
891
+ return this.regionStore.getStackSaveSlices();
892
+ }
386
893
  /** All slices' ANNOTATION regions for a z-stack save (jit-ui#93), each tagged
387
894
  * with its zero-based Region.z; profile lines excluded. Flat annotation set
388
895
  * outside stack mode. */
389
896
  getSliceAnnotationRegions() {
390
- return this.renderer().getSliceRegions().filter((r) => !isProfileRegion(r));
897
+ return this.regionStore.getSliceRegions().filter((r) => !isProfileRegion(r));
391
898
  }
392
899
  /** Per-slice annotation regions to write on a folder-stack save (jit-ui#93):
393
900
  * slice index → that slice's annotation regions (profile lines excluded),
394
901
  * including now-empty slices that were loaded non-empty (so they overwrite). */
395
902
  getStackSaveAnnotationSlices() {
396
903
  const out = new Map();
397
- for (const [z, regs] of this.renderer().getStackSaveSlices()) {
904
+ for (const [z, regs] of this.regionStore.getStackSaveSlices()) {
398
905
  out.set(z, regs.filter((r) => !isProfileRegion(r)));
399
906
  }
400
907
  return out;
@@ -405,81 +912,126 @@ export class RoutingVisualizerService {
405
912
  * or non-positive sizes — the Plotly bounds can yield NaN before a plot is
406
913
  * fully laid out, which would otherwise crash mask creation. */
407
914
  getMaskImageSize() {
408
- const valid = (s) => s && Number.isFinite(s.width) && Number.isFinite(s.height) &&
409
- s.width >= 1 && s.height >= 1
915
+ const valid = (s) => s && Number.isFinite(s.width) && Number.isFinite(s.height) && s.width >= 1 && s.height >= 1
410
916
  ? { width: Math.round(s.width), height: Math.round(s.height) }
411
917
  : null;
412
918
  const fromRenderer = valid(this.getTrueImageSize());
413
919
  if (fromRenderer)
414
920
  return fromRenderer;
415
921
  let meta = [];
416
- this.getImageMeta().subscribe((m) => (meta = m)).unsubscribe();
922
+ this.getImageMeta()
923
+ .subscribe((m) => (meta = m))
924
+ .unsubscribe();
417
925
  const m0 = meta?.[0];
418
926
  return m0 ? valid({ width: m0.x, height: m0.y }) : null;
419
927
  }
420
928
  // ── IRegionEditorApi: annotation-only surface for the Region Editor ───
421
929
  // Intensity-profile lines (kind='profile') belong to the intensity tool, not
422
930
  // the editor. These methods give external consumers an annotation-only view
423
- // and guarantee profile lines are preserved. Routing (not the store) owns this
424
- // so writes/selection go through renderer() and the active backend re-renders
425
- // (Plotly relayouts its shapes in setRegions; it doesn't on regionUpdate$).
931
+ // and guarantee profile lines are preserved. The writes land in the store like
932
+ // any other, and every backend redraws from its events.
426
933
  getAnnotationRegions() {
427
- return this.renderer().getRegions().filter((r) => !isProfileRegion(r));
934
+ return this.regionStore.getRegions().filter((r) => !isProfileRegion(r));
428
935
  }
429
936
  setAnnotationRegions(regions, showRegionLabel, isRegionSaveOn, fillColor) {
430
- // Re-append the store's profile lines so an editor save/delete can't drop
431
- // them, then route through setRegions so the active backend re-renders.
432
- const profiles = this.renderer().getRegions().filter((r) => isProfileRegion(r));
937
+ // Re-append the store's profile lines so an editor save/delete can't drop them.
938
+ const profiles = this.regionStore.getRegions().filter((r) => isProfileRegion(r));
433
939
  const annotations = (regions || []).filter((r) => !isProfileRegion(r));
434
940
  this.setRegions([...annotations, ...profiles], showRegionLabel, isRegionSaveOn, fillColor, false);
435
941
  }
436
942
  getSelectedRegions$() {
437
943
  // Map the internal index-based selection to the selected annotation regions.
438
944
  return this.getSelectedShapeIndices$().pipe(map((idxs) => {
439
- const regs = this.renderer().getRegions();
440
- return idxs
441
- .map((i) => regs[i])
442
- .filter((r) => !!r && !isProfileRegion(r));
945
+ const regs = this.regionStore.getRegions();
946
+ return idxs.map((i) => regs[i]).filter((r) => !!r && !isProfileRegion(r));
443
947
  }));
444
948
  }
445
949
  setSelectedRegions(regions) {
446
- const regs = this.renderer().getRegions();
447
- const indices = (regions || [])
448
- .map((r) => regs.findIndex((x) => x.id === r.id))
449
- .filter((i) => i >= 0);
950
+ const regs = this.regionStore.getRegions();
951
+ const indices = (regions || []).map((r) => regs.findIndex((x) => x.id === r.id)).filter((i) => i >= 0);
450
952
  this.setSelectedShapeIndices(indices);
451
953
  }
452
954
  // ── tools → active renderer (run on either backend) ─────────────────
453
955
  // The wand, vertex eraser and zoom-to-box are implemented on both backends
454
956
  // via ICoordinateTransform (+ a viewport pixel readback for the wand), so they
455
- // follow the active renderer.
456
- setWandMode(active, options) { this.renderer().setWandMode(active, options); }
457
- setWandOptions(options) { this.renderer().setWandOptions(options); }
458
- clearActiveWandRegion() { this.renderer().clearActiveWandRegion(); }
459
- setBrushMode(active, options) { this.renderer().setBrushMode(active, options); }
460
- setBrushOptions(options) { this.renderer().setBrushOptions(options); }
461
- setVertexEraserMode(active) { this.renderer().setVertexEraserMode(active); }
462
- setVertexEraserRadius(radius) { this.renderer().setVertexEraserRadius(radius); }
463
- setZoomToBoxMode(active) { this.renderer().setZoomToBoxMode(active); }
464
- segmentRectangles() { return this.renderer().segmentRectangles(); }
465
- segmentRectanglesCellpose() { return this.renderer().segmentRectanglesCellpose(); }
466
- setSamModel(id) { this.renderer().setSamModel(id); }
467
- setSamPointMode(active) { this.renderer().setSamPointMode(active); }
468
- commitSamPoints() { this.renderer().commitSamPoints(); }
469
- clearSamPoints() { this.renderer().clearSamPoints(); }
957
+ // follow the active renderer — the slice pane's while the volume view is split.
958
+ setActiveTool(id, options) {
959
+ this.regionBackend().setActiveTool(id, options);
960
+ }
961
+ /** @deprecated Use {@link setActiveTool}. */
962
+ setWandMode(active, options) {
963
+ this.regionBackend().setWandMode(active, options);
964
+ }
965
+ setWandOptions(options) {
966
+ this.regionBackend().setWandOptions(options);
967
+ }
968
+ clearActiveWandRegion() {
969
+ this.regionBackend().clearActiveWandRegion();
970
+ }
971
+ /** @deprecated Use {@link setActiveTool}. */
972
+ setBrushMode(active, options) {
973
+ this.regionBackend().setBrushMode(active, options);
974
+ }
975
+ setBrushOptions(options) {
976
+ this.regionBackend().setBrushOptions(options);
977
+ }
978
+ /** @deprecated Use {@link setActiveTool}. */
979
+ setVertexEraserMode(active) {
980
+ this.regionBackend().setVertexEraserMode(active);
981
+ }
982
+ setVertexEraserRadius(radius) {
983
+ this.regionBackend().setVertexEraserRadius(radius);
984
+ }
985
+ /** @deprecated Use {@link setActiveTool}. */
986
+ setZoomToBoxMode(active) {
987
+ this.regionBackend().setZoomToBoxMode(active);
988
+ }
989
+ segmentRectangles() {
990
+ return this.regionBackend().segmentRectangles();
991
+ }
992
+ segmentRectanglesCellpose() {
993
+ return this.regionBackend().segmentRectanglesCellpose();
994
+ }
995
+ setSamModel(id) {
996
+ this.regionBackend().setSamModel(id);
997
+ }
998
+ /** @deprecated Use {@link setActiveTool}. */
999
+ setSamPointMode(active) {
1000
+ this.regionBackend().setSamPointMode(active);
1001
+ }
1002
+ commitSamPoints() {
1003
+ this.regionBackend().commitSamPoints();
1004
+ }
1005
+ clearSamPoints() {
1006
+ this.regionBackend().clearSamPoints();
1007
+ }
470
1008
  // ── display options ──────────────────────────────────────────────────
471
1009
  // State lives in the shared VisualizerStore — reads go straight to it.
472
1010
  // The two SETTERS still route through Plotly because its implementations
473
1011
  // carry render glue beyond the store write (a live Plotly.restyle of
474
1012
  // colorscale/reversescale on the mounted heatmap); OSD recolors via its own
475
1013
  // store subscription either way.
476
- getColormap() { return this.store.getColormap(); }
477
- setColormap(colormap) { this.plotly.setColormap(colormap); }
478
- getColormapOptions() { return this.store.getColormapOptions(); }
479
- getReverseScale() { return this.store.getReverseScale(); }
480
- setReverseScale(reverscale) { this.plotly.setReverseScale(reverscale); }
481
- setImageMeta(imageMeta) { this.store.setImageMeta(imageMeta); }
482
- getImageMeta() { return this.store.getImageMeta(); }
1014
+ getColormap() {
1015
+ return this.store.getColormap();
1016
+ }
1017
+ setColormap(colormap) {
1018
+ this.plotly.setColormap(colormap);
1019
+ }
1020
+ getColormapOptions() {
1021
+ return this.store.getColormapOptions();
1022
+ }
1023
+ getReverseScale() {
1024
+ return this.store.getReverseScale();
1025
+ }
1026
+ setReverseScale(reverse) {
1027
+ this.plotly.setReverseScale(reverse);
1028
+ }
1029
+ setImageMeta(imageMeta, imageKey) {
1030
+ this.store.setImageMeta(imageMeta, imageKey);
1031
+ }
1032
+ getImageMeta() {
1033
+ return this.store.getImageMeta();
1034
+ }
483
1035
  // ── IChannelHistogramApi: Channels & Histogram pane surface ───────────
484
1036
  // Channel/grayscale/invert state lives in the shared VisualizerStore; both
485
1037
  // backends subscribe and recolor live, so setters just write the store. The
@@ -491,9 +1043,15 @@ export class RoutingVisualizerService {
491
1043
  return this.renderer().getHistogram$(channelIndex, bins);
492
1044
  }
493
1045
  /** Export the underlying data (16-bit multi-band TIFF) via the active backend. */
494
- exportData() { this.renderer().exportData(); }
495
- getChannels$() { return this.store.getChannelStates(); }
496
- setSelectedChannel(index) { this.store.setSelectedChannel(index); }
1046
+ exportData() {
1047
+ this.renderer().exportData();
1048
+ }
1049
+ getChannels$() {
1050
+ return this.store.getChannelStates();
1051
+ }
1052
+ setSelectedChannel(index) {
1053
+ this.store.setSelectedChannel(index);
1054
+ }
497
1055
  setChannelState(index, partial) {
498
1056
  this.store.setChannelState(index, partial);
499
1057
  }
@@ -509,22 +1067,31 @@ export class RoutingVisualizerService {
509
1067
  const h = this.renderer().getHistogram(i, 256);
510
1068
  if (!h)
511
1069
  continue;
512
- const [min, max] = autoWindowFromHistogram(h, saturation);
1070
+ const [min, max] = autoWindowFromHistogram(h, saturation, [0, 255]);
513
1071
  if (max > min)
514
1072
  this.store.setChannelState(i, { min, max });
515
1073
  }
516
1074
  }
517
- getGrayscale$() { return this.store.getGrayscale(); }
518
- setGrayscale(on) { this.store.setGrayscale(on); }
519
- getInvert$() { return this.store.getInvert(); }
520
- setInvert(on) { this.store.setInvert(on); }
1075
+ getGrayscale$() {
1076
+ return this.store.getGrayscale();
1077
+ }
1078
+ setGrayscale(on) {
1079
+ this.store.setGrayscale(on);
1080
+ }
1081
+ getInvert$() {
1082
+ return this.store.getInvert();
1083
+ }
1084
+ setInvert(on) {
1085
+ this.store.setInvert(on);
1086
+ }
521
1087
  /**
522
- * The active backend's region overlay. Falls back to Plotly's when the active backend
1088
+ * The active backend's region overlay (the slice pane's while the volume view is split). Falls
1089
+ * back to Plotly's when the active backend
523
1090
  * (OSD or napari-js) is selected but a plot isn't mounted yet, so callers always get a
524
1091
  * usable overlay.
525
1092
  */
526
1093
  getRegionOverlay() {
527
- const r = this.renderer();
1094
+ const r = this.regionBackend();
528
1095
  if (r === this.osd) {
529
1096
  return this.osd.getRegionOverlay() ?? this.plotly.getRegionOverlay();
530
1097
  }
@@ -533,219 +1100,96 @@ export class RoutingVisualizerService {
533
1100
  }
534
1101
  return this.plotly.getRegionOverlay();
535
1102
  }
1103
+ /** Isosurface controls of the backend on screen, when it renders isosurfaces. */
1104
+ getIsosurfaceControls() {
1105
+ return this.renderer().getIsosurfaceControls();
1106
+ }
1107
+ /** 3D scene controls of the backend on screen (Plotly or napari-js), or null on a
1108
+ * 2D-only one. */
1109
+ getSurface3dControls() {
1110
+ return this.renderer().getSurface3dControls();
1111
+ }
1112
+ /** Intensity (line-ROI) controls, whichever backend draws the image: the
1113
+ * IntensityProfileService adds the line to the store, and every backend
1114
+ * (Plotly included) draws it from the store's update event. */
1115
+ getIntensityControls() {
1116
+ return this.intensity;
1117
+ }
536
1118
  /**
537
- * Isosurface controls when available — always Plotly's, since the isosurface
538
- * plot type renders on Plotly (OSD only handles the image type).
539
- */
540
- getIsosurfaceControls() { return this.renderer().getIsosurfaceControls(); }
541
- /** 3D scene controls — always Plotly's, since the 3D plot types render on
542
- * Plotly (OSD only handles the image type). */
543
- getSurface3dControls() { return this.renderer().getSurface3dControls(); }
544
- /** Intensity (line-ROI) controls — always Plotly's, since the line profiles
545
- * render their inset on Plotly regardless of which backend draws the image. */
546
- getIntensityControls() { return this.plotly.getIntensityControls(); }
547
- /**
548
- * Spatial-omics controls, or null when no `SPATIAL_DATA_PORT` is bound.
549
- *
550
- * Implemented HERE rather than on a backend because the state is
551
- * backend-neutral: the view state lives in the shared `VisualizerStore` (like
552
- * the colormap), so the controls keep working across a plot-type switch and a
553
- * host can drive them before any backend has mounted.
1119
+ * Spatial-omics controls, or null when no `SPATIAL_DATA_PORT` is bound. Served by a
1120
+ * backend-neutral {@link SpatialControlsFacade} (state in the shared stores), so the
1121
+ * controls work across a plot-type switch and before any backend has mounted.
554
1122
  */
555
1123
  getSpatialControls() {
556
- const port = this.spatialData;
557
- if (!port)
1124
+ if (!this.spatialData)
558
1125
  return null;
559
- // Mirror the dataset (and drop a stale selection when it changes — the masks
560
- // are index-based, so they are meaningless against different observations).
561
- this.spatialDatasetSub ??= port.getDataset$().subscribe((dataset) => {
562
- const changed = dataset?.id !== this.currentSpatialDataset?.id;
563
- this.currentSpatialDataset = dataset;
564
- if (!changed)
565
- return;
566
- this.selectionStore.set(emptySelection(dataset?.observations.count ?? 0));
567
- // A colour source the new dataset cannot satisfy would leave the map flat
568
- // while the panel and the charts kept naming the old column — so drop it,
569
- // and only it: point size, opacity and the rest are the user's preferences,
570
- // not the previous dataset's state.
571
- const by = this.store.currentSpatialView().colorBy;
572
- if (by && !this.canColorBy(dataset, by))
573
- this.store.setSpatialView({ colorBy: null });
1126
+ this.spatialFacade ??= new SpatialControlsFacade(this.spatialData, {
1127
+ store: this.store,
1128
+ regionStore: this.regionStore,
1129
+ selectionStore: this.selectionStore,
1130
+ napari: this.napari,
1131
+ plotType: () => this.currentPlotType,
1132
+ zIndex: () => this.currentZIndex,
574
1133
  });
575
- this.spatialControls ??= {
576
- getDataset$: () => port.getDataset$(),
577
- getViewState$: () => this.store.getSpatialView$(),
578
- viewState: () => this.store.currentSpatialView(),
579
- setViewState: (partial) => this.store.setSpatialView(partial),
580
- // The hint SEEDS the toggle when the source changes, and nothing consults it
581
- // afterwards. It used to be ORed in at render time, which meant an unchecked
582
- // box could not turn log scaling off for a hinted column — and the linked
583
- // chart, which reads `logScale` alone, disagreed with the map about what it
584
- // was showing. One authority, set once per source.
585
- colorByColumn: (name) => {
586
- const meta = this.currentSpatialDataset?.columns.find((c) => c.name === name);
587
- const hint = meta?.kind === 'continuous' ? !!meta.logScaleHint : false;
588
- this.store.setSpatialView({ colorBy: { kind: 'column', name }, logScale: hint });
589
- },
590
- colorByFeature: (name) => this.store.setSpatialView({
591
- colorBy: { kind: 'feature', name },
592
- logScale: !!this.currentSpatialDataset?.features?.logScaleHint,
593
- }),
594
- clearColorBy: () => this.store.setSpatialView({ colorBy: null }),
595
- searchFeatures: async (query, limit = 50) => {
596
- // Prefer the port's search (a 31k-gene dataset does not ship its names);
597
- // otherwise filter whatever the manifest inlined.
598
- if (port.searchFeatures)
599
- return port.searchFeatures(query, limit);
600
- const dataset = await firstValueFrom(port.getDataset$());
601
- const names = dataset?.features?.names ?? [];
602
- const q = query.toLowerCase();
603
- return names.filter((n) => n.toLowerCase().includes(q)).slice(0, limit);
604
- },
605
- ...(port.importGroups ? {
606
- importGroups: (label, table) => port.importGroups(label, table),
607
- } : {}),
608
- ...(port.getTranscriptCounts ? {
609
- transcriptCounts: (genes) => port.getTranscriptCounts(genes),
610
- } : {}),
611
- ...(port.getMarkerGenes ? {
612
- markerGenes: (column, perGroup) => port.getMarkerGenes(column, perGroup),
613
- } : {}),
614
- getTranscriptEstimate$: () => this.napari.transcriptEstimate$.asObservable(),
615
- getGeneCountsInView$: () => this.napari.geneCountsInView$.asObservable(),
616
- getDensityStats$: () => this.napari.densityStats$.asObservable(),
617
- categoryColors: async (name) => {
618
- const column = await port.getColumn(name);
619
- if (!isCategoricalColumn(column)) {
620
- throw new Error(`[spatial] column "${name}" is continuous — it has no categories`);
621
- }
622
- // Resolved by the SAME function the renderer uses, so a legend swatch
623
- // can never disagree with the colour on screen.
624
- return resolveCategoryColors(column.meta);
625
- },
626
- continuousValues: async (source) => {
627
- if (source.kind === 'feature')
628
- return port.getFeatureVector(source.name);
629
- const column = await port.getColumn(source.name);
630
- if (isCategoricalColumn(column)) {
631
- throw new Error(`[spatial] column "${source.name}" is categorical — it has no values to chart`);
632
- }
633
- return column.values;
634
- },
635
- categoricalView: async (name) => {
636
- const column = await port.getColumn(name);
637
- if (!isCategoricalColumn(column)) {
638
- throw new Error(`[spatial] column "${name}" is continuous — it has no categories`);
639
- }
640
- return {
641
- name,
642
- categories: column.meta.categories,
643
- colors: resolveCategoryColors(column.meta),
644
- codes: column.codes,
645
- };
646
- },
647
- // Spread rather than always defined: `getEmbedding` is optional on both the port
648
- // and this facade, and a panel checks for its presence to decide whether the view
649
- // is offered at all. Defining it as a function that rejects would make an
650
- // embedding-less source look like a broken one.
651
- ...(port.getEmbedding
652
- ? { getEmbedding: (name) => port.getEmbedding(name) }
653
- : {}),
654
- categoricalColumns: () => (this.currentSpatialDataset?.columns ?? [])
655
- .filter((c) => c.kind === 'categorical')
656
- .map((c) => c.name),
657
- // Memoized on the observations object, so the renderer's own lookup and
658
- // this one are the same single scan of up to 3.7M z values.
659
- sampledSections: () => {
660
- const obs = this.currentSpatialDataset?.observations;
661
- return obs ? sectionsOf(obs) : null;
662
- },
663
- getSelection$: () => this.selectionStore.getSelection$(),
664
- selectFromRegions: () => {
665
- const dataset = this.currentSpatialDataset;
666
- if (!dataset)
667
- return 0;
668
- const regions = this.regionStore.getRegions();
669
- // The union of every drawn region — so every ROI tool the library
670
- // already has doubles as a spatial selection tool.
671
- //
672
- // In the 3D cloud there is no data-space affine to push a drawn shape
673
- // through, so the observations are projected to canvas pixels by the
674
- // renderer (which owns the camera) and tested in screen space instead.
675
- // Falls back to the 2D path whenever the cloud is not mounted.
676
- const projected = isSpatialOmics3d(this.currentPlotType)
677
- ? this.napari.getSpatialScreenProjection(dataset.observations)
678
- : null;
679
- // In the 2D view of a volume-backed dataset the shape was drawn over ONE
680
- // section, in the volume's pixel grid: it selects the cells of that
681
- // section, not the whole depth of brain standing behind them.
682
- const volume = !dataset.imageRef ? dataset.volume : undefined;
683
- const selection = projected
684
- ? selectInRegionsProjected(projected, dataset.observations.count, regions)
685
- : selectInRegions(dataset.observations, volume ? volumeImageRef(volume, dataset.micronsPerUnit) : dataset.imageRef, regions, volume
686
- ? observationsInSlice(dataset.observations, volume, this.currentZIndex)
687
- : undefined);
688
- this.selectionStore.set(selection);
689
- return selection.count;
690
- },
691
- selectCategory: async (column, categoryIndex) => {
692
- const loaded = await port.getColumn(column);
693
- if (!isCategoricalColumn(loaded)) {
694
- throw new Error(`[spatial] column "${column}" is continuous — it has no categories`);
695
- }
696
- const selection = selectByCategory(loaded.codes, categoryIndex);
697
- this.selectionStore.set(selection);
698
- return selection.count;
699
- },
700
- selectIndices: (indices) => {
701
- const count = this.currentSpatialDataset?.observations.count ?? 0;
702
- if (count === 0)
703
- return 0;
704
- const selection = selectByIndices(indices, count);
705
- this.selectionStore.set(selection);
706
- return selection.count;
707
- },
708
- clearSelection: () => this.selectionStore.clear(),
709
- };
710
- return this.spatialControls;
1134
+ return this.spatialFacade.controls;
1135
+ }
1136
+ /** Angular calls this when the injector providing the router is destroyed — the host
1137
+ * component for a `provideVisualization()` chain. The dataset subscription would
1138
+ * otherwise keep the whole isolated chain reachable from the root data port. */
1139
+ ngOnDestroy() {
1140
+ this.spatialFacade?.dispose();
1141
+ this.spatialFacade = null;
1142
+ this.regionUpdates.unsubscribe();
1143
+ this.sectionSubs.unsubscribe();
1144
+ this.sections.stop();
1145
+ if (this.rebuildTimer)
1146
+ clearTimeout(this.rebuildTimer);
711
1147
  }
712
1148
  /**
713
- * Whether `dataset` can answer this colour source.
714
- *
715
- * A column is checkable against the declared list. A gene is checkable only when
716
- * the dataset inlines its feature names — a dataset too wide to inline them
717
- * (typeahead-only) keeps the source, and a name that turns out not to exist
718
- * surfaces as the chart's "could not be charted" rather than as a silent reset.
1149
+ * Intensity-profile sampling, whichever backend is on screen: the sampling is the
1150
+ * backend-neutral IntensityProfileService's; the viewport changes come from every
1151
+ * backend that reports them (OpenSeadragon, napari-js), merged into one stable
1152
+ * stream the inset subscribes to once.
719
1153
  */
720
- canColorBy(dataset, by) {
721
- if (!dataset)
722
- return false;
723
- if (by.kind === 'column')
724
- return dataset.columns.some((c) => c.name === by.name);
725
- const names = dataset.features?.names;
726
- return !!dataset.features && (!names || names.includes(by.name));
1154
+ getIntensitySampling() {
1155
+ return this.intensitySampling;
727
1156
  }
728
- /** Load pixel frames for intensity sampling when OpenSeadragon owns the image
729
- * (it doesn't feed Plotly's frame cache). No-op needed when Plotly renders. */
1157
+ /** @deprecated Use `getIntensitySampling().ensureIntensitySampling()`. */
730
1158
  ensureIntensitySampling(imageInfo, zIndex) {
731
- return this.plotly.ensureIntensitySampling(imageInfo, zIndex);
1159
+ return this.intensitySampling.ensureIntensitySampling(imageInfo, zIndex);
732
1160
  }
733
- /** Visible-region changes from the OpenSeadragon viewer (image-pixel coords),
734
- * so the intensity inset can re-sample at the current zoom level. Plotly's own
735
- * high-def zoom updates the sampling cache inline, so only OSD feeds this. */
1161
+ /** Crops for sampling are sized from the plot div (whichever backend renders into it). */
1162
+ pointSamplingAtPlot() {
1163
+ if (this.plotDiv)
1164
+ this.intensity.setSamplingElement(this.plotDiv);
1165
+ }
1166
+ /** @deprecated Use `getIntensitySampling().getViewportChange$()`. */
736
1167
  getViewportChange$() {
737
- return this.osd.getViewportChange$();
1168
+ return this.intensitySampling.getViewportChange$();
738
1169
  }
739
- /** Re-sample the intensity profiles from a fresh crop of the given image-pixel
740
- * ROI at display resolution (sampling always lives in Plotly). */
1170
+ /** @deprecated Use `getIntensitySampling().refreshIntensitySamplingForRoi()`. */
741
1171
  refreshIntensitySamplingForRoi(x, y, width, height, zIndex) {
742
- this.plotly.refreshIntensitySamplingForRoi(x, y, width, height, zIndex);
1172
+ this.intensitySampling.refreshIntensitySamplingForRoi(x, y, width, height, zIndex);
1173
+ }
1174
+ /** The visualizer view is going away: detach every backend — dropping their view-bound
1175
+ * subscriptions and disposing the napari-js viewer, whose canvas, render loop and GPU
1176
+ * buffers would otherwise outlive the view (for a component-scoped chain, forever).
1177
+ * Nothing is on screen afterwards, so the next plot starts from the default backend. */
1178
+ detach() {
1179
+ this.sliceRequest++;
1180
+ this.sections.stop();
1181
+ this.sliceMounted = false;
1182
+ this.sliceDiv = null;
1183
+ this.plotly.detach();
1184
+ this.osd.detach();
1185
+ this.napari.detach();
1186
+ this.lastRendered = null;
743
1187
  }
1188
+ /** @deprecated Use {@link detach}. */
744
1189
  unsubscribe() {
745
- this.plotly.unsubscribe();
746
- this.osd.unsubscribe();
1190
+ this.detach();
747
1191
  }
748
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: RoutingVisualizerService, deps: [{ token: i1.PlotlyService }, { token: i2.OpenSeadragonVisualizerService }, { token: i3.NapariVisualizerService }, { token: i4.VisualizerStore }, { token: VIZ_CONFIG }, { token: i5.RegionStore }, { token: i6.SpatialSelectionStore }, { token: SPATIAL_DATA_PORT, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
1192
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: RoutingVisualizerService, deps: [{ token: i1.PlotlyService }, { token: i2.OpenSeadragonVisualizerService }, { token: i3.NapariVisualizerService }, { token: i4.VisualizerStore }, { token: VIZ_CONFIG }, { token: i5.RegionStore }, { token: i6.SpatialSelectionStore }, { token: i7.IntensityProfileService }, { token: SPATIAL_DATA_PORT, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
749
1193
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: RoutingVisualizerService, providedIn: 'root' }); }
750
1194
  }
751
1195
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: RoutingVisualizerService, decorators: [{
@@ -754,10 +1198,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
754
1198
  }], ctorParameters: () => [{ type: i1.PlotlyService }, { type: i2.OpenSeadragonVisualizerService }, { type: i3.NapariVisualizerService }, { type: i4.VisualizerStore }, { type: undefined, decorators: [{
755
1199
  type: Inject,
756
1200
  args: [VIZ_CONFIG]
757
- }] }, { type: i5.RegionStore }, { type: i6.SpatialSelectionStore }, { type: undefined, decorators: [{
1201
+ }] }, { type: i5.RegionStore }, { type: i6.SpatialSelectionStore }, { type: i7.IntensityProfileService }, { type: undefined, decorators: [{
758
1202
  type: Optional
759
1203
  }, {
760
1204
  type: Inject,
761
1205
  args: [SPATIAL_DATA_PORT]
762
1206
  }] }] });
763
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGluZy12aXN1YWxpemVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3JvdXRpbmctdmlzdWFsaXplci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3RCxPQUFPLEVBQTRCLGFBQWEsRUFBRSxjQUFjLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0UsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBTXJDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUN4RSxPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSx3REFBd0QsQ0FBQztBQUN4RyxPQUFPLEVBQUUsUUFBUSxFQUFzQixVQUFVLEVBQUUsZUFBZSxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXBJLE9BQU8sRUFBRSxpQkFBaUIsRUFBbUIsTUFBTSxxQ0FBcUMsQ0FBQztBQUV6RixPQUFPLEVBQWtCLG1CQUFtQixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDM0YsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDbkUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3hELE9BQU8sRUFDTCxtQkFBbUIsRUFBRSxjQUFjLEdBQ3BDLE1BQU0sZ0NBQWdDLENBQUM7QUFDeEMsT0FBTyxFQUNMLGNBQWMsRUFDZCxnQkFBZ0IsRUFDaEIsZUFBZSxFQUNmLGVBQWUsRUFDZix3QkFBd0IsR0FDekIsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDM0QsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFLMUUs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RSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkFtQm5CLE1BQU07MkJBQUMsVUFBVTs7MEJBS2pCLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsaUJBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBPcHRpb25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9uLCBjb21iaW5lTGF0ZXN0LCBmaXJzdFZhbHVlRnJvbSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSW1hZ2UgfSBmcm9tICdpbWFnZS1qcyc7XG5cbmltcG9ydCB7IElJbWFnZUluZm8sIElJbWFnZU1ldGFkYXRhIH0gZnJvbSAnLi9jb250cmFjdHMvaW1hZ2UuY29udHJhY3QnO1xuaW1wb3J0IHsgUmVnaW9uIH0gZnJvbSAnLi9tb2RlbHMvcmVnaW9uJztcbmltcG9ydCB7IENsYXNzUHJlc2V0LCBQcmVzZXRTZXQgfSBmcm9tICcuL21vZGVscy9jbGFzcy1wcmVzZXQnO1xuaW1wb3J0IHsgUGxvdGx5U2VydmljZSB9IGZyb20gJy4vaW1wbGVtZW50YXRpb25zL3Bsb3RseS9wbG90bHkuc2VydmljZSc7XG5pbXBvcnQgeyBPcGVuU2VhZHJhZ29uVmlzdWFsaXplclNlcnZpY2UgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9ucy9vc2Qvb3BlbnNlYWRyYWdvbi12aXN1YWxpemVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgUGxvdFR5cGUsIFBsb3RUeXBlRGVzY3JpcHRvciwgaXNOYXBhcmkzZCwgaXNOYXBhcmlTY2F0dGVyLCBpc1NwYXRpYWxPbWljcywgaXNTcGF0aWFsT21pY3MzZCB9IGZyb20gJy4vY29udHJhY3RzL3Bsb3QtdHlwZSc7XG5pbXBvcnQgeyBJVmlzdWFsaXplciwgUGl4ZWxEYXRhLCBJbnRlbnNpdHlQcm9maWxlLCBJSXNvc3VyZmFjZUNvbnRyb2xzLCBJSW50ZW5zaXR5Q29udHJvbHMsIElTdXJmYWNlM2RDb250cm9scywgSVNwYXRpYWxDb250cm9scyB9IGZyb20gJy4vY29udHJhY3RzL3Zpc3VhbGl6ZXIuY29udHJhY3QnO1xuaW1wb3J0IHsgU1BBVElBTF9EQVRBX1BPUlQsIFNwYXRpYWxEYXRhUG9ydCB9IGZyb20gJy4vY29udHJhY3RzL3BvcnRzL3NwYXRpYWwtZGF0YS5wb3J0JztcbmltcG9ydCB7IFNwYXRpYWxDb2xvckJ5IH0gZnJvbSAnLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQgeyBTcGF0aWFsRGF0YXNldCwgaXNDYXRlZ29yaWNhbENvbHVtbiB9IGZyb20gJy4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5pbXBvcnQgeyByZXNvbHZlQ2F0ZWdvcnlDb2xvcnMgfSBmcm9tICcuL3NwYXRpYWwvc3BhdGlhbC1lbmNvZGluZyc7XG5pbXBvcnQgeyBzZWN0aW9uc09mIH0gZnJvbSAnLi9zcGF0aWFsL3NwYXRpYWwtc2VjdGlvbnMnO1xuaW1wb3J0IHtcbiAgb2JzZXJ2YXRpb25zSW5TbGljZSwgdm9sdW1lSW1hZ2VSZWYsXG59IGZyb20gJy4vc3BhdGlhbC9zcGF0aWFsLXZvbHVtZS1pbWFnZSc7XG5pbXBvcnQge1xuICBlbXB0eVNlbGVjdGlvbixcbiAgc2VsZWN0QnlDYXRlZ29yeSxcbiAgc2VsZWN0QnlJbmRpY2VzLFxuICBzZWxlY3RJblJlZ2lvbnMsXG4gIHNlbGVjdEluUmVnaW9uc1Byb2plY3RlZCxcbn0gZnJvbSAnLi9zcGF0aWFsL3NwYXRpYWwtc2VsZWN0aW9uJztcbmltcG9ydCB7IFJlZ2lvblN0b3JlIH0gZnJvbSAnLi9zdG9yZS9yZWdpb24tc3RvcmUuc2VydmljZSc7XG5pbXBvcnQgeyBTcGF0aWFsU2VsZWN0aW9uU3RvcmUgfSBmcm9tICcuL3N0b3JlL3NwYXRpYWwtc2VsZWN0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgVmlld2VyQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi9jb250cmFjdHMvY2FwYWJpbGl0aWVzLmNvbnRyYWN0JztcbmltcG9ydCB7IElSZWdpb25PdmVybGF5IH0gZnJvbSAnLi9jb250cmFjdHMvcmVnaW9uLW92ZXJsYXkuY29udHJhY3QnO1xuaW1wb3J0IHsgSVJlZ2lvbkVkaXRvckFwaSB9IGZyb20gJy4vY29udHJhY3RzL3JlZ2lvbi1lZGl0b3ItYXBpLmNvbnRyYWN0JztcbmltcG9ydCB7IElDaGFubmVsSGlzdG9ncmFtQXBpLCBJQ2hhbm5lbFN0YXRlLCBJSGlzdG9ncmFtIH0gZnJvbSAnLi9jb250cmFjdHMvY2hhbm5lbC1oaXN0b2dyYW0tYXBpLmNvbnRyYWN0JztcbmltcG9ydCB7IFZpc3VhbGl6ZXJTdG9yZSB9IGZyb20gJy4vc3RvcmUvdmlzdWFsaXplci1zdG9yZS5zZXJ2aWNlJztcbmltcG9ydCB7IE5hcGFyaVZpc3VhbGl6ZXJTZXJ2aWNlIH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbnMvbmFwYXJpLWpzL25hcGFyaS12aXN1YWxpemVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgVklaX0NPTkZJRywgVml6Q29uZmlnIH0gZnJvbSAnLi9jb250cmFjdHMvdml6LWNvbmZpZyc7XG5pbXBvcnQgeyBQbG90TW9kZVZpZXdwb3J0IH0gZnJvbSAnLi9jb250cmFjdHMvcGxvdC10eXBlLWNvbnRyaWJ1dGlvbi5jb250cmFjdCc7XG5cbi8qKlxuICogQmFja2VuZCBzZWxlY3Rvci4gUm91dGVzIHBlciBwbG90IHR5cGU6XG4gKiAgLSB0aGUgKipJbWFnZSoqIHBsb3QgdHlwZSByZW5kZXJzIHRocm91Z2ggT3BlblNlYWRyYWdvbiDigJQgYSBuYXRpdmVseS10aWxlZCxcbiAqICAgIHpvb21hYmxlIHJhc3RlciBiYWNrZWQgYnkgdGhlIGppdC1zZXJ2aWNlIHRpbGUgZW5kcG9pbnRzLiBJdCdzIHRoZSBkZWZhdWx0XG4gKiAgICB2aWV3IGFuZCBzdXBwb3J0cyB0aGUgcmVnaW9uIG92ZXJsYXkvdG9vbHMgYW5kIChmb3IgZ3JheXNjYWxlKSB0aGVcbiAqICAgIGNvbG9ybWFwLCBhcHBsaWVkIGNsaWVudC1zaWRlIHZpYSB0aGUgdGlsZSBwaXhlbCBwaXBlbGluZS5cbiAqICAtIGV2ZXJ5IG90aGVyIHBsb3QgdHlwZSAoaGVhdG1hcCwgc3VyZmFjZSwgY29udG91ciwgc2NhdHRlciwgbGluZSxcbiAqICAgIHNjYXR0ZXIzZCwgaXNvc3VyZmFjZSkgcmVuZGVycyB0aHJvdWdoIFBsb3RseS5cbiAqXG4gKiBPbmx5IHRoZSAqKnJlbmRlciArIHZpZXdwb3J0KiogcGF0aCBpcyByb3V0ZWQuIFJlZ2lvbiBzdGF0ZSwgZGlzcGxheSBvcHRpb25zXG4gKiAoY29sb3JtYXAvTFVUKSwgYW5kIHRoZSBsb25nLWxpdmVkIG9ic2VydmFibGVzIGFsd2F5cyBsaXZlIGluIFBsb3RseSAodGhlXG4gKiBzaGFyZWQgc3RvcmUpIHNvIGJvdGggYmFja2VuZHMgc3RheSBpbiBzeW5jOyBPU0QgcmVhZHMgdGhlbSB0byBkcml2ZSBpdHMgb3duXG4gKiBvdmVybGF5IGFuZCB0aWxlIHJlY29sb3JpbmcuXG4gKlxuICogVGhlIEltYWdlIHR5cGUgcmVuZGVycyB0aHJvdWdoIE9wZW5TZWFkcmFnb247IGEgZmFpbGVkIE9TRCBsb2FkIGZhbGxzIGJhY2sgdG9cbiAqIFBsb3RseSBmb3IgdGhhdCBpbWFnZSBvbmx5IChzZWUgYG9zZEZlbGxCYWNrYCkgc28gaXQgc3RpbGwgcmVuZGVycy5cbiAqL1xuLyoqIEludGVuc2l0eS1wcm9maWxlIGxpbmUgUk9JcyBhcmUgb3duZWQgYnkgdGhlIGludGVuc2l0eSB0b29sLCBub3QgdGhlIGVkaXRvci5cbiAqICBQYWNrYWdlLWludGVybmFsIHByZWRpY2F0ZSAocHJvcGVydHktYmFzZWQgc28gaXQgYWxzbyBtYXRjaGVzIHBsYWluIG9iamVjdHNcbiAqICBhZnRlciBhIGRyYWcgcm91bmQtdHJpcCkuICovXG5mdW5jdGlvbiBpc1Byb2ZpbGVSZWdpb24ocjogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiByPy5raW5kID09PSAncHJvZmlsZSc7XG59XG5cbi8qKiBTYXR1cmF0aW9uLWJhc2VkIGF1dG8td2luZG93OiBwaWNrIFttaW4sbWF4XSBzbyB+YHNhdHVyYXRpb25gIG9mIHBpeGVscyBjbGlwXG4gKiAgYXQgZWFjaCBlbmQgb2YgdGhlIGhpc3RvZ3JhbS4gQSBkb21pbmFudCBmaXJzdC9sYXN0IGJpbiAodW5zY2FubmVkIHBhZGRpbmcgL1xuICogIGNsaXBwZWQgYmFja2dyb3VuZCkgaXMgZHJvcHBlZCBzbyBpdCBkb2Vzbid0IHNrZXcgdGhlIHJhbmdlLiAqL1xuZnVuY3Rpb24gYXV0b1dpbmRvd0Zyb21IaXN0b2dyYW0oaDogSUhpc3RvZ3JhbSwgc2F0dXJhdGlvbjogbnVtYmVyKTogW251bWJlciwgbnVtYmVyXSB7XG4gIGNvbnN0IGNvdW50cyA9IGguY291bnRzLnNsaWNlKCk7XG4gIGNvbnN0IG4gPSBjb3VudHMubGVuZ3RoO1xuICBpZiAobiA9PT0gMCkgcmV0dXJuIFswLCAyNTVdO1xuICBpZiAobiA+IDIgJiYgY291bnRzWzBdID4gY291bnRzWzFdKSBjb3VudHNbMF0gPSAwO1xuICBpZiAobiA+IDIgJiYgY291bnRzW24gLSAxXSA+IGNvdW50c1tuIC0gMl0pIGNvdW50c1tuIC0gMV0gPSAwO1xuICBsZXQgdG90YWwgPSAwO1xuICBmb3IgKGNvbnN0IGMgb2YgY291bnRzKSB0b3RhbCArPSBjO1xuICBpZiAodG90YWwgPD0gMCkgcmV0dXJuIFswLCAyNTVdO1xuICBjb25zdCB0YXJnZXQgPSB0b3RhbCAqIE1hdGgubWF4KDAsIE1hdGgubWluKDAuNSwgc2F0dXJhdGlvbikpO1xuICBsZXQgYWNjID0gMDtcbiAgbGV0IG1pbiA9IGguYmluc1swXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBhY2MgKz0gY291bnRzW2ldO1xuICAgIGlmIChhY2MgPiB0YXJnZXQpIHsgbWluID0gaC5iaW5zW2ldOyBicmVhazsgfVxuICB9XG4gIGFjYyA9IDA7XG4gIGxldCBtYXggPSBoLmJpbnNbbiAtIDFdO1xuICBmb3IgKGxldCBpID0gbiAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYWNjICs9IGNvdW50c1tpXTtcbiAgICBpZiAoYWNjID4gdGFyZ2V0KSB7IG1heCA9IGguYmluc1tpXTsgYnJlYWs7IH1cbiAgfVxuICByZXR1cm4gW21pbiwgbWF4XTtcbn1cblxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBSb3V0aW5nVmlzdWFsaXplclNlcnZpY2UgaW1wbGVtZW50cyBJVmlzdWFsaXplciwgSVJlZ2lvbkVkaXRvckFwaSwgSUNoYW5uZWxIaXN0b2dyYW1BcGkge1xuXG4gIHByaXZhdGUgY3VycmVudFBsb3RUeXBlOiBQbG90VHlwZSA9IFBsb3RUeXBlLklNQUdFO1xuICBwcml2YXRlIGxhc3RSZW5kZXJlZDogSVZpc3VhbGl6ZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqIE9TRCBmYWlsZWQgZm9yIHRoZSAqY3VycmVudCogcmVuZGVyIGN5Y2xlIChlLmcuIGEgZnJlc2ggZmlsZSBzdGlsbCBjYWNoaW5nXG4gICAqICBwYXN0IHRoZSBkZWFkbGluZSkg4oaSIGZhbGwgYmFjayB0byBQbG90bHkgZm9yIHRoaXMgaW1hZ2Ugb25seS4gUmVzZXQgYnlcbiAgICogIHJlc2V0KCkgYXQgdGhlIHN0YXJ0IG9mIGV2ZXJ5IHJlbmRlciBjeWNsZSwgc28gdGhlIG5leHQgZmlsZSDigJQgb3IgYVxuICAgKiAgcmUtc2VsZWN0IG9uY2UgdGhlIGZpbGUgaXMgY2FjaGVkIOKAlCByZXRyaWVzIE9TRC4gKFdhcyBhIHBlcm1hbmVudCBmbGFnLFxuICAgKiAgd2hpY2ggbGVmdCB0aGUgd2hvbGUgc2Vzc2lvbiBzdHVjayBvbiBQbG90bHkgYWZ0ZXIgb25lIHNsb3cgbG9hZC4pICovXG4gIHByaXZhdGUgb3NkRmVsbEJhY2sgPSBmYWxzZTtcbiAgLyoqIG5hcGFyaS1qcyBmYWlsZWQgZm9yIHRoZSBjdXJyZW50IHJlbmRlciBjeWNsZSDihpIgZmFsbCBiYWNrIHRvIE9TRCAodGhlbiBQbG90bHkpLlxuICAgKiAgUmVzZXQgYnkgcmVzZXQoKSBhdCB0aGUgc3RhcnQgb2YgZXZlcnkgY3ljbGUsIGxpa2Uge0BsaW5rIG9zZEZlbGxCYWNrfS4gKi9cbiAgcHJpdmF0ZSBuYXBhcmlGZWxsQmFjayA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcGxvdGx5OiBQbG90bHlTZXJ2aWNlLFxuICAgICAgICAgICAgICBwcml2YXRlIG9zZDogT3BlblNlYWRyYWdvblZpc3VhbGl6ZXJTZXJ2aWNlLFxuICAgICAgICAgICAgICBwcml2YXRlIG5hcGFyaTogTmFwYXJpVmlzdWFsaXplclNlcnZpY2UsXG4gICAgICAgICAgICAgIHByaXZhdGUgc3RvcmU6IFZpc3VhbGl6ZXJTdG9yZSxcbiAgICAgICAgICAgICAgQEluamVjdChWSVpfQ09ORklHKSBwcml2YXRlIGNvbmZpZzogVml6Q29uZmlnLFxuICAgICAgICAgICAgICAvLyBPcHRpb25hbDogYSBob3N0IHRoYXQgc2VydmVzIG5vIHNwYXRpYWwtb21pY3MgZGF0YSBiaW5kcyBub3RoaW5nLFxuICAgICAgICAgICAgICAvLyBhbmQgYGdldFNwYXRpYWxDb250cm9scygpYCB0aGVuIHJldHVybnMgbnVsbC5cbiAgICAgICAgICAgICAgcHJpdmF0ZSByZWdpb25TdG9yZTogUmVnaW9uU3RvcmUsXG4gICAgICAgICAgICAgIHByaXZhdGUgc2VsZWN0aW9uU3RvcmU6IFNwYXRpYWxTZWxlY3Rpb25TdG9yZSxcbiAgICAgICAgICAgICAgQE9wdGlvbmFsKCkgQEluamVjdChTUEFUSUFMX0RBVEFfUE9SVClcbiAgICAgICAgICAgICAgcHJpdmF0ZSBzcGF0aWFsRGF0YTogU3BhdGlhbERhdGFQb3J0IHwgbnVsbCA9IG51bGwpIHt9XG5cbiAgcHJpdmF0ZSBpc0ltYWdlVHlwZSh0OiBQbG90VHlwZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0ID09PSBQbG90VHlwZS5JTUFHRTtcbiAgfVxuXG4gIC8qKiBUaGUgMkQgbmFwYXJpIHR5cGVzIChpbWFnZSwgcmVnaW9uLWNlbnRyb2lkIHNjYXR0ZXIsIHNwYXRpYWwgb21pY3MpIOKAlCBhIDJEIGZhbGxiYWNrIGNoYWluXG4gICAqICAoT1NELCB0aGVuIFBsb3RseSkuXG4gICAqXG4gICAqICBOT1RFIGZvciBTUEFUSUFMX09NSUNTOiBvbmx5IG5hcGFyaS1qcyBkcmF3cyB0aGUgb2JzZXJ2YXRpb24gbWFya2Vycy4gSWYgaXQgZmFpbHMgKG5vIFdlYkdQVSxcbiAgICogIGRldmljZSBsb3NzKSB0aGUgZmFsbGJhY2sgcmVuZGVycyB0aGUgdGlzc3VlIGltYWdlIEFMT05FIOKAlCB0aGUgc3BhdGlhbCBsYXllciBpcyBhYnNlbnQsIG5vdFxuICAgKiAgZGVncmFkZWQuIFRoYXQgaXMgZGVsaWJlcmF0ZSBmb3Igbm93OiBzaG93aW5nIHRoZSBzbGlkZSBiZWF0cyBzaG93aW5nIG5vdGhpbmcsIGFuZCBhIFBsb3RseVxuICAgKiAgYHNjYXR0ZXJnbGAgc3BhdGlhbCBtb2RlIGlzIHRoZSBwbGFubmVkIHJlYWwgZmFsbGJhY2sgKHNlZSB0aGUgcGxvdC1tb2RlIGRlc2lnbiBkb2MpLiAqL1xuICBwcml2YXRlIGlzTmFwYXJpSW1hZ2VUeXBlKHQ6IFBsb3RUeXBlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHQgPT09IFBsb3RUeXBlLk5BUEFSSV9JTUFHRSB8fCBpc05hcGFyaVNjYXR0ZXIodCkgfHwgaXNTcGF0aWFsT21pY3ModCk7XG4gIH1cblxuICAvKiogVGhlIDNEIG5hcGFyaSB0eXBlcyAodm9sdW1lL2lzb3N1cmZhY2Uvc3VyZmFjZS9zY2F0dGVyLCBwbHVzIHRoZSAzRCBzcGF0aWFsIGNsb3VkKSDigJQgbm8gMkRcbiAgICogIGZhbGxiYWNrIGV4aXN0cyAoT1NEIGlzIGltYWdlLW9ubHkpLCBzbyB0aGV5IGZhbGwgc3RyYWlnaHQgdG8gUGxvdGx5LiAqL1xuICBwcml2YXRlIGlzTmFwYXJpM2RUeXBlKHQ6IFBsb3RUeXBlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzTmFwYXJpM2QodCkgfHwgaXNTcGF0aWFsT21pY3MzZCh0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCYWNrZW5kIHRvIGF0dGVtcHQgZm9yIHRoZSBjdXJyZW50IHBsb3QgdHlwZSB0aGlzIHJlbmRlci4gVGhlIGZhbGxiYWNrIGNoYWlucyBiZWxvdyBhcmVcbiAgICogbWlycm9yZWQgZXhhY3RseSBieSB7QGxpbmsgbG9hZH0gc28gdGhlIGhhbmRsZSBgcGxvdCgpYCByZWNlaXZlcyBhbHdheXMgY29tZXMgZnJvbSB0aGVcbiAgICogYmFja2VuZCBgcGxvdCgpYCBzZWxlY3RzIChubyBsb2FkL3Bsb3QgYmFja2VuZCBtaXNtYXRjaCk6XG4gICAqICAtIDJEIGltYWdlIChleHBsaWNpdCBgTkFQQVJJX0lNQUdFYCwgb3IgYElNQUdFYCB3aXRoIHRoZSBXZWJHUFUgb3B0LWluKTogbmFwYXJpLWpzIOKGkiBPU0Qg4oaSIFBsb3RseS5cbiAgICogIC0gcGxhaW4gYElNQUdFYCAobm8gb3B0LWluKTogT1NEIOKGkiBQbG90bHkuXG4gICAqICAtIDNEIG5hcGFyaSAoYE5BUEFSSV9WT0xVTUVgL2BOQVBBUklfSVNPU1VSRkFDRWApOiBuYXBhcmktanMg4oaSIFBsb3RseSAoT1NEIGNhbid0IHJlbmRlciAzRCkuXG4gICAqL1xuICBwcml2YXRlIGltYWdlQmFja2VuZCgpOiBJVmlzdWFsaXplciB7XG4gICAgY29uc3QgdCA9IHRoaXMuY3VycmVudFBsb3RUeXBlO1xuICAgIC8vIDJEIGltYWdlIHdpdGggYSBuYXBhcmktanMgYXR0ZW1wdCAoZXhwbGljaXQgbmFwYXJpIGltYWdlLCBvciBvcHQtaW4gb24gdGhlIEltYWdlIHR5cGUpLlxuICAgIGlmICh0aGlzLmlzTmFwYXJpSW1hZ2VUeXBlKHQpIHx8ICh0aGlzLmlzSW1hZ2VUeXBlKHQpICYmIHRoaXMuY29uZmlnLnVzZU5hcGFyaVJlbmRlcmVyKSkge1xuICAgICAgaWYgKCF0aGlzLm5hcGFyaUZlbGxCYWNrKSByZXR1cm4gdGhpcy5uYXBhcmk7XG4gICAgICBpZiAoIXRoaXMub3NkRmVsbEJhY2spIHJldHVybiB0aGlzLm9zZDtcbiAgICAgIHJldHVybiB0aGlzLnBsb3RseTtcbiAgICB9XG4gICAgLy8gUGxhaW4gSW1hZ2UgdHlwZSAobm8gbmFwYXJpIG9wdC1pbik6IE9TRCwgdGhlbiBQbG90bHkuXG4gICAgaWYgKHRoaXMuaXNJbWFnZVR5cGUodCkpIHtcbiAgICAgIHJldHVybiB0aGlzLm9zZEZlbGxCYWNrID8gdGhpcy5wbG90bHkgOiB0aGlzLm9zZDtcbiAgICB9XG4gICAgLy8gM0QgbmFwYXJpIHR5cGVzOiBuYXBhcmktanMsIHdpdGggUGxvdGx5IGFzIHRoZSBvbmx5IHZpYWJsZSBmYWxsYmFjay5cbiAgICBpZiAodGhpcy5pc05hcGFyaTNkVHlwZSh0KSkge1xuICAgICAgcmV0dXJuIHRoaXMubmFwYXJpRmVsbEJhY2sgPyB0aGlzLnBsb3RseSA6IHRoaXMubmFwYXJpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wbG90bHk7XG4gIH1cblxuICAvKiogQmFja2VuZCBjdXJyZW50bHkgb24gc2NyZWVuIOKAlCB3aGF0IG9uZ29pbmcgem9vbS90b29sL3JlZ2lvbiBvcHMgYWN0IG9uLiAqL1xuICBwcml2YXRlIHJlbmRlcmVyKCk6IElWaXN1YWxpemVyIHtcbiAgICByZXR1cm4gdGhpcy5sYXN0UmVuZGVyZWQgPz8gdGhpcy5wbG90bHk7XG4gIH1cblxuICAvLyBTeXN0ZW0gY2FwYWJpbGl0aWVzIGFyZSBQbG90bHkncyAodGhlIGZ1bGwtZmVhdHVyZWQgYmFja2VuZCkgc28gdGhlIFVJXG4gIC8vIGtlZXBzIG9mZmVyaW5nIGV2ZXJ5IHBsb3QgdHlwZSByZWdhcmRsZXNzIG9mIHdoaWNoIG9uZSBpcyBvbiBzY3JlZW4uXG4gIGdldCBjYXBhYmlsaXRpZXMoKTogVmlld2VyQ2FwYWJpbGl0aWVzIHsgcmV0dXJuIHRoaXMucGxvdGx5LmNhcGFiaWxpdGllczsgfVxuXG4gIC8vIOKUgOKUgCByZW5kZXIgLyB2aWV3cG9ydCDihpIgYWN0aXZlIHJlbmRlcmVyIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICBhc3luYyBsb2FkKGltYWdlSW5mbzogSUltYWdlSW5mbywgekluZGV4OiBudW1iZXIpOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIEEgc3RhY2sgY2FuIG9wZW4gYXdheSBmcm9tIHNsaWNlIDAgKGBpbml0aWFsWkluZGV4YCDigJQgYSB2b2x1bWUgb3BlbnNcbiAgICAvLyBtaWQtc3BlY2ltZW4pLCBhbmQgdGhhdCBhcnJpdmVzIGhlcmUgcmF0aGVyIHRoYW4gdGhyb3VnaCBzZXRaSW5kZXguXG4gICAgdGhpcy5jdXJyZW50WkluZGV4ID0gekluZGV4O1xuICAgIGNvbnN0IGJhY2tlbmQgPSB0aGlzLmltYWdlQmFja2VuZCgpO1xuICAgIGlmIChiYWNrZW5kID09PSB0aGlzLm5hcGFyaSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMubmFwYXJpLmxvYWQoaW1hZ2VJbmZvLCB6SW5kZXgpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHRoaXMubmFwYXJpRmVsbEJhY2sgPSB0cnVlO1xuICAgICAgICAvLyBNaXJyb3IgaW1hZ2VCYWNrZW5kKCkncyBmYWxsYmFjayBzbyBsb2FkICsgcGxvdCBwaWNrIHRoZSBzYW1lIGJhY2tlbmQ6XG4gICAgICAgIC8vICAtIDNEIG5hcGFyaSB0eXBlcyBoYXZlIG5vIDJEIGZhbGxiYWNrIOKGkiBzdHJhaWdodCB0byBQbG90bHkuXG4gICAgICAgIC8vICAtIDJEIGltYWdlIOKGkiBPU0QsIHRoZW4gUGxvdGx5LlxuICAgICAgICBpZiAodGhpcy5pc05hcGFyaTNkVHlwZSh0aGlzLmN1cnJlbnRQbG90VHlwZSkpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1t2aXN1YWxpemVyXSBuYXBhcmktanMgbG9hZCBmYWlsZWQg4oCUIGZhbGxpbmcgYmFjayB0byBQbG90bHkuJywgZXJyKTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5wbG90bHkubG9hZChpbWFnZUluZm8sIHpJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS53YXJuKCdbdmlzdWFsaXplcl0gbmFwYXJpLWpzIGxvYWQgZmFpbGVkIOKAlCBmYWxsaW5nIGJhY2sgdG8gT3BlblNlYWRyYWdvbi4nLCBlcnIpO1xuICAgICAgICByZXR1cm4gdGhpcy5sb2FkVmlhT3NkVGhlblBsb3RseShpbWFnZUluZm8sIHpJbmRleCk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChiYWNrZW5kID09PSB0aGlzLm9zZCkge1xuICAgICAgcmV0dXJuIHRoaXMubG9hZFZpYU9zZFRoZW5QbG90bHkoaW1hZ2VJbmZvLCB6SW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wbG90bHkubG9hZChpbWFnZUluZm8sIHpJbmRleCk7XG4gIH1cblxuICAvKiogVHJ5IE9TRDsgb24gZmFpbHVyZSBmYWxsIGJhY2sgdG8gUGxvdGx5IGZvciB0aGlzIGltYWdlIChub3QgcGVybWFuZW50IOKAlCBzZWUgcmVzZXQoKSkuICovXG4gIHByaXZhdGUgYXN5bmMgbG9hZFZpYU9zZFRoZW5QbG90bHkoaW1hZ2VJbmZvOiBJSW1hZ2VJbmZvLCB6SW5kZXg6IG51bWJlcik6IFByb21pc2U8YW55PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLm9zZC5sb2FkKGltYWdlSW5mbywgekluZGV4KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUud2FybignW3Zpc3VhbGl6ZXJdIE9wZW5TZWFkcmFnb24gbG9hZCBmYWlsZWQg4oCUIGZhbGxpbmcgYmFjayB0byBQbG90bHkgZm9yIHRoaXMgaW1hZ2UuJywgZXJyKTtcbiAgICAgIHRoaXMub3NkRmVsbEJhY2sgPSB0cnVlO1xuICAgICAgcmV0dXJuIHRoaXMucGxvdGx5LmxvYWQoaW1hZ2VJbmZvLCB6SW5kZXgpO1xuICAgIH1cbiAgfVxuICBwbG90KHBsb3REaXY6IHN0cmluZywgaW1hZ2VMb2FkZWQ6IGFueSwgaW1hZ2VJbmZvOiBJSW1hZ2VJbmZvLCBzY3JlZW5IZWlnaHQ6IG51bWJlcixcbiAgICAgICBwbG90VHlwZTogUGxvdFR5cGUsIGluUGxhY2U/OiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgdGhpcy5jdXJyZW50UGxvdFR5cGUgPSBwbG90VHlwZTtcbiAgICAvLyBBcHBseSB0aGUgcGVyLWltYWdlIHJlZ2lvbiBjYWNoZSAoc25hcHNob3Qgb2xkIHJlZ2lvbnMsIHJlc3RvcmUgdGhlIG5ld1xuICAgIC8vIGltYWdlJ3MsIGNsZWFyIHNlbGVjdGlvbikgZm9yIHdoaWNoZXZlciBiYWNrZW5kIHJlbmRlcnMg4oCUIFBsb3RseSBkb2VzXG4gICAgLy8gdGhpcyBpbnNpZGUgaXRzIG93biBwbG90KCksIGJ1dCBPU0QgZG9lc24ndCwgc28gZHJpdmUgaXQgaGVyZS4gSWRlbXBvdGVudFxuICAgIC8vIGZvciB0aGUgc2FtZSBpbWFnZSwgc28gaXQncyBzYWZlIHRvIGNhbGwgb24gZXZlcnkgKHJlKXBsb3QuXG4gICAgdGhpcy5wbG90bHkuc2V0QWN0aXZlSW1hZ2UoaW1hZ2VJbmZvKTtcbiAgICBjb25zdCBuZXh0ID0gdGhpcy5pbWFnZUJhY2tlbmQoKTtcbiAgICAvLyBCb3RoIGJhY2tlbmRzIHNoYXJlIHRoZSBzYW1lIGRpdiDigJQgdGVhciBkb3duIHRoZSBvdXRnb2luZyBvbmUgb24gc3dpdGNoLlxuICAgIC8vIFBsb3RseSBtdXN0IGJlICpwdXJnZWQqIChub3QgcmVzZXQsIHdoaWNoIHJlLWRyYXdzIGVtcHR5IGF4ZXMpIGJlZm9yZSBPU0RcbiAgICAvLyB0YWtlcyB0aGUgZGl2LlxuICAgIGlmICh0aGlzLmxhc3RSZW5kZXJlZCAmJiB0aGlzLmxhc3RSZW5kZXJlZCAhPT0gbmV4dCkge1xuICAgICAgaWYgKHRoaXMubGFzdFJlbmRlcmVkID09PSB0aGlzLnBsb3RseSkgdGhpcy5wbG90bHkucHVyZ2VQbG90KCk7XG4gICAgICBlbHNlIHRoaXMubGFzdFJlbmRlcmVkLnJlc2V0KCk7XG4gICAgfVxuICAgIHRoaXMubGFzdFJlbmRlcmVkID0gbmV4dDtcbiAgICByZXR1cm4gbmV4dC5wbG90KHBsb3REaXYsIGltYWdlTG9hZGVkLCBpbWFnZUluZm8sIHNjcmVlbkhlaWdodCwgcGxvdFR5cGUsIGluUGxhY2UpO1xuICB9XG4gIHJlbG9hZEFuZFBsb3QoKTogdm9pZCB7IHRoaXMucGxvdGx5LnJlbG9hZEFuZFBsb3QoKTsgfVxuICByZXNldCgpOiB2b2lkIHtcbiAgICAvLyBTdGFydCBvZiBhIHJlbmRlciBjeWNsZTogcmUtZW5hYmxlIG5hcGFyaS1qcy9PU0QgYXR0ZW1wdHMgKGNsZWFyIGFueSBwcmlvclxuICAgIC8vIHBlci1pbWFnZSBmYWxsYmFjaykgYW5kIHRlYXIgZG93biB3aGF0ZXZlcidzIG9uIHNjcmVlbi5cbiAgICB0aGlzLm9zZEZlbGxCYWNrID0gZmFsc2U7XG4gICAgdGhpcy5uYXBhcmlGZWxsQmFjayA9IGZhbHNlO1xuICAgIHRoaXMucmVuZGVyZXIoKS5yZXNldCgpO1xuICB9XG4gIHJlbGF5b3V0KHRydWVJbWFnZVNpemU/OiBudW1iZXJbXSk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkucmVsYXlvdXQodHJ1ZUltYWdlU2l6ZSk7IH1cbiAgcmVzZXRBeGVzKCk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkucmVzZXRBeGVzKCk7IH1cbiAgYXV0b3NjYWxlKCk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuYXV0b3NjYWxlKCk7IH1cbiAgem9vbUluKCk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuem9vbUluKCk7IH1cbiAgem9vbU91dCgpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnpvb21PdXQoKTsgfVxuICBzZXREcmFnTW9kZShtb2RlOiBzdHJpbmcgfCBmYWxzZSk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuc2V0RHJhZ01vZGUobW9kZSk7IH1cbiAgLy8gU2V0IG9uIGJvdGggYmFja2VuZHMgKG5vdCBqdXN0IHRoZSBhY3RpdmUgcmVuZGVyZXIpOiBjb25zdW1lcnMgY2FsbCB0aGlzXG4gIC8vIGJlZm9yZSB0aGUgZmlyc3QgcmVuZGVyLCB3aGVuIGByZW5kZXJlcigpYCBpcyBzdGlsbCB0aGUgUGxvdGx5IGRlZmF1bHQsIHNvXG4gIC8vIE9TRCBtdXN0IHJlY2VpdmUgdGhlIGZsYWcgdG8gaG9ub3VyIGl0IGF0IHZpZXdlciBjcmVhdGlvbi5cbiAgc2V0TmF2aWdhdG9yVmlzaWJsZSh2aXNpYmxlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5vc2Quc2V0TmF2aWdhdG9yVmlzaWJsZSh2aXNpYmxlKTtcbiAgICB0aGlzLnBsb3RseS5zZXROYXZpZ2F0b3JWaXNpYmxlKHZpc2libGUpO1xuICAgIHRoaXMubmFwYXJpLnNldE5hdmlnYXRvclZpc2libGUodmlzaWJsZSk7XG4gIH1cbiAgLy8gU2V0IG9uIGJvdGggYmFja2VuZHMgKHNlZSBzZXROYXZpZ2F0b3JWaXNpYmxlKTogY29uc3VtZXJzIG1heSBzZXQgaXQgYmVmb3JlXG4gIC8vIHRoZSBmaXJzdCByZW5kZXIsIHdoZW4gdGhlIGFjdGl2ZSByZW5kZXJlciBpcyBzdGlsbCBQbG90bHkuXG4gIHNldEltYWdlU21vb3RoaW5nRW5hYmxlZChlbmFibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5vc2Quc2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKGVuYWJsZWQpO1xuICAgIHRoaXMucGxvdGx5LnNldEltYWdlU21vb3RoaW5nRW5hYmxlZChlbmFibGVkKTtcbiAgfVxuICBzZXRTaG93U3RhY2soc2hvd3N0YWNrOiBib29sZWFuKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5zZXRTaG93U3RhY2soc2hvd3N0YWNrKTsgfVxuICBzZXRaSW5kZXgoekluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRaSW5kZXggPSB6SW5kZXg7XG4gICAgdGhpcy5yZW5kZXJlcigpLnNldFpJbmRleCh6SW5kZXgpO1xuICB9XG4gIGdldFRydWVJbWFnZVNpemUoKTogeyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHwgbnVsbCB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0VHJ1ZUltYWdlU2l6ZSgpOyB9XG4gIGdldEN1cnJlbnRJbWFnZSgpOiBQcm9taXNlPEltYWdlIHwgbnVsbD4geyByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldEN1cnJlbnRJbWFnZSgpOyB9XG4gIGdldERpc3BsYXllZFBpeGVsRGF0YSgpOiBQaXhlbERhdGEgfCBudWxsIHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXREaXNwbGF5ZWRQaXhlbERhdGEoKTsgfVxuICBnZXREaXNwbGF5ZWRTb3VyY2VSZWN0KCk6IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH0gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldERpc3BsYXllZFNvdXJjZVJlY3QoKTtcbiAgfVxuICBkb3dubG9hZEltYWdlKCk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuZG93bmxvYWRJbWFnZSgpOyB9XG4gIGV4cG9ydENvbXBvc2l0ZSgpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLmV4cG9ydENvbXBvc2l0ZSgpOyB9XG5cbiAgc2V0UGxvdFR5cGUocGxvdFR5cGU6IFBsb3RUeXBlKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50UGxvdFR5cGUgPSBwbG90VHlwZTtcbiAgICB0aGlzLnBsb3RseS5zZXRQbG90VHlwZShwbG90VHlwZSk7XG4gIH1cbiAgc2V0U3VyZmFjZURyYWdNb2RlKG1vZGU6IHN0cmluZyk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuc2V0U3VyZmFjZURyYWdNb2RlKG1vZGUpOyB9XG4gIHJlc2V0U3VyZmFjZUNhbWVyYSgpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnJlc2V0U3VyZmFjZUNhbWVyYSgpOyB9XG4gIHNldFJlc29sdXRpb25TY2FsZShzY2FsZTogbnVtYmVyKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5zZXRSZXNvbHV0aW9uU2NhbGU/LihzY2FsZSk7IH1cbiAgZ2V0UmVzb2x1dGlvblNjYWxlKCk6IG51bWJlciB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0UmVzb2x1dGlvblNjYWxlPy4oKSA/PyAxOyB9XG4gIC8qKiBUaGUgdmlld3BvcnQgb2YgdGhlIGJhY2tlbmQgb24gc2NyZWVuLCBmb3IgYSBjb250cmlidXRlZCBwbG90IG1vZGUuIE51bGxcbiAgICogIHdoZW4gdGhhdCBiYWNrZW5kIGNhbm5vdCBwcm92aWRlIG9uZSAoZS5nLiBPU0QgZmVsbCBiYWNrIHRvIFBsb3RseSkuICovXG4gIGdldFBsb3RNb2RlVmlld3BvcnQoKTogUGxvdE1vZGVWaWV3cG9ydCB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0UGxvdE1vZGVWaWV3cG9ydD8uKCkgPz8gbnVsbDtcbiAgfVxuICBnZXRQbG90VHlwZURlc2NyaXB0b3JzKCk6IFBsb3RUeXBlRGVzY3JpcHRvcltdIHtcbiAgICAvLyBQbG90bHkgZW51bWVyYXRlcyB0aGUgZnVsbCBQTE9UX1RZUEVfREVTQ1JJUFRPUlMgbWFwLCB3aGljaCBhbHJlYWR5IGluY2x1ZGVzIHRoZVxuICAgIC8vIG5hcGFyaS1qcyBXZWJHUFUgdHlwZXMgKGppdC11aSMxMDIpIOKAlCBzbyB0aGlzIHNpbmdsZSBzb3VyY2UgY292ZXJzIHRoZW0gKG5vIGR1cGxpY2F0ZXMpLlxuICAgIHJldHVybiB0aGlzLnBsb3RseS5nZXRQbG90VHlwZURlc2NyaXB0b3JzKCk7XG4gIH1cblxuICAvLyDilIDilIAgbG9uZy1saXZlZCBvYnNlcnZhYmxlcyArIHN0YWNrIGZsYWdzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICBzZXRTdGFja0xvYWRpbmcoYjogYm9vbGVhbik6IHZvaWQgeyB0aGlzLnBsb3RseS5zZXRTdGFja0xvYWRpbmcoYik7IH1cbiAgLy8gQ2FuY2VsIGluLWZsaWdodCBsb2FkaW5nIG9uIGV2ZXJ5IGJhY2tlbmQg4oCUIHRoZSB1c2VyJ3MgQ2FuY2VsIHNob3VsZG4ndCBkZXBlbmQgb24gd2hpY2ggb25lIGlzXG4gIC8vIGFjdGl2ZS4gT25seSBiYWNrZW5kcyB0aGF0IHN0cmVhbSBmcmFtZXMgKG5hcGFyaS1qcykgZG8gcmVhbCB3b3JrOyB0aGUgcmVzdCBuby1vcC4gVGhlIGNvbmNyZXRlXG4gIC8vIGJhY2tlbmQgY2xhc3NlcyBkb24ndCBhbGwgZGVjbGFyZSB0aGUgb3B0aW9uYWwgY29udHJhY3QgbWV0aG9kLCBzbyBjYWxsIGl0IHZpYSBJVmlzdWFsaXplci5cbiAgY2FuY2VsTG9hZGluZygpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGJhY2tlbmQgb2YgW3RoaXMucGxvdGx5LCB0aGlzLm9zZCwgdGhpcy5uYXBhcmldIGFzIElWaXN1YWxpemVyW10pIHtcbiAgICAgIGJhY2tlbmQuY2FuY2VsTG9hZGluZz8uKCk7XG4gICAgfVxuICB9XG4gIC8vIExvYWRpbmcgc3RhdGUgaXMgc3VyZmFjZWQgZnJvbSB3aGljaGV2ZXIgYmFja2VuZCBpcyBkb2luZyB0aGUgd29yazogT1NEIGFuZCBuYXBhcmktanMgKHZvbHVtZVxuICAvLyBhc3NlbWJseSkgZHJpdmUgdGhlaXIgb3duIHN1YmplY3RzLCBzbyBtZXJnZSBhbGwgdGhyZWUgaW50byBvbmUgc3RhYmxlIHN0cmVhbSB0aGUgaG9zdFxuICAvLyBzdWJzY3JpYmVzIHRvIG9uY2UuIChQcmV2aW91c2x5IGhhcmRjb2RlZCB0byBQbG90bHksIHNvIG5hcGFyaS9PU0QgcHJvZ3Jlc3MgbmV2ZXIgc2hvd2VkLilcbiAgaXNTdGFja0xvYWRpbmcoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIGNvbWJpbmVMYXRlc3QoW1xuICAgICAgdGhpcy5wbG90bHkuaXNTdGFja0xvYWRpbmcoKSxcbiAgICAgIHRoaXMub3NkLmlzU3RhY2tMb2FkaW5nKCksXG4gICAgICB0aGlzLm5hcGFyaS5pc1N0YWNrTG9hZGluZygpLFxuICAgIF0pLnBpcGUobWFwKChmbGFncykgPT4gZmxhZ3Muc29tZShCb29sZWFuKSkpO1xuICB9XG4gIGdldFN0YWNrTG9hZGluZ1Byb2dyZXNzKCk6IE9ic2VydmFibGU8bnVtYmVyPiB7XG4gICAgLy8gUmVwb3J0IHRoZSBwcm9ncmVzcyBvZiB3aGljaGV2ZXIgYmFja2VuZCBpcyBBQ1RJVkVMWSBsb2FkaW5nIChtYXggYWNyb3NzIGFjdGl2ZSBvbmVzKS4gQSBwbGFpblxuICAgIC8vIG1lcmdlIGxldCBhbiBpZGxlIGJhY2tlbmQncyBzdGFsZSB2YWx1ZSB3aW4gdGhlIHN0cmVhbSBvbiBhIHJlLWxvYWQg4oCUIGxlYXZpbmcgdGhlIGJhciBiZWxvdyB0aGVcbiAgICAvLyBhY3RpdmUgYmFja2VuZCdzIHJlYWwgcHJvZ3Jlc3MgKGUuZy4gc3R1Y2sgfuKFkyB3aGlsZSB0aGUgJSByZWFkIDEwMCkuIEdhdGluZyBieSB0aGUgbG9hZGluZyBmbGFnXG4gICAgLy8gaWdub3JlcyBpZGxlIGJhY2tlbmRzLCBzbyB0aGUgYmFyIHRyYWNrcyB0aGUgb25lIGRvaW5nIHRoZSB3b3JrIGFuZCByZWFjaGVzIDEwMCUuXG4gICAgY29uc3QgdHJhY2sgPSAodjogSVZpc3VhbGl6ZXIpOiBPYnNlcnZhYmxlPFtudW1iZXIsIGJvb2xlYW5dPiA9PlxuICAgICAgY29tYmluZUxhdGVzdChbdi5nZXRTdGFja0xvYWRpbmdQcm9ncmVzcygpLCB2LmlzU3RhY2tMb2FkaW5nKCldKTtcbiAgICByZXR1cm4gY29tYmluZUxhdGVzdChbdHJhY2sodGhpcy5wbG90bHkpLCB0cmFjayh0aGlzLm9zZCksIHRyYWNrKHRoaXMubmFwYXJpKV0pLnBpcGUoXG4gICAgICBtYXAoKHBhaXJzKSA9PiB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZSA9IHBhaXJzLmZpbHRlcigoWywgbG9hZGluZ10pID0+IGxvYWRpbmcpLm1hcCgoW3BdKSA9PiBwKTtcbiAgICAgICAgcmV0dXJuIGFjdGl2ZS5sZW5ndGggPyBNYXRoLm1heCguLi5hY3RpdmUpIDogMDtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cbiAgZ2V0QXV0b3NjYWxlRXZlbnQoKTogT2JzZXJ2YWJsZTxhbnk+IHsgcmV0dXJuIHRoaXMucGxvdGx5LmdldEF1dG9zY2FsZUV2ZW50KCk7IH1cbiAgZ2V0SW50ZW5zaXR5UHJvZmlsZSQoKTogT2JzZXJ2YWJsZTxJbnRlbnNpdHlQcm9maWxlW10+IHsgcmV0dXJuIHRoaXMucGxvdGx5LmdldEludGVuc2l0eVByb2ZpbGUkKCk7IH1cbiAgLy8gVGhlIGludGVuc2l0eSBpbnNldCBpcyBhIFBsb3RseSBMSU5FIGNoYXJ0IOKAlCByZW5kZXIgaXQgdGhyb3VnaCBQbG90bHksIHdoaWNoXG4gIC8vIG93bnMgdGhlIHByb2ZpbGUgc3RyZWFtIHJlZ2FyZGxlc3Mgb2Ygd2hpY2ggYmFja2VuZCBkcmF3cyB0aGUgbWFpbiBpbWFnZS5cbiAgcmVuZGVySW50ZW5zaXR5SW5zZXQoZGl2SWQ6IHN0cmluZywgcHJvZmlsZXM6IEludGVuc2l0eVByb2ZpbGVbXSk6IHZvaWQge1xuICAgIHRoaXMucGxvdGx5LnJlbmRlckludGVuc2l0eUluc2V0KGRpdklkLCBwcm9maWxlcyk7IH1cblxuICAvLyDilIDilIAgcmVnaW9ucyDihpIgYWN0aXZlIHJlbmRlcmVyIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICAvLyBSZWdpb24gKnN0YXRlKiBsaXZlcyBpbiB0aGUgc2hhcmVkIFJlZ2lvblN0b3JlOyBib3RoIGJhY2tlbmRzIGltcGxlbWVudFxuICAvLyBJUmVnaW9uU3RvcmUgYnkgZGVsZWdhdGluZyB0byBpdC4gV2Ugcm91dGUgdGhyb3VnaCB0aGUgYWN0aXZlIHJlbmRlcmVyXG4gIC8vIChub3QgaGFyZGNvZGVkIFBsb3RseSkgc28gdGhlIGJhY2tlbmQgb24gc2NyZWVuIGFsc28gKnJlbmRlcnMqIHRoZSBjaGFuZ2U6XG4gIC8vIFBsb3RseSByZWxheW91dHMgaXRzIHNoYXBlcywgT3BlblNlYWRyYWdvbidzIG92ZXJsYXkgcmVkcmF3cyBmcm9tIHRoZSBzdG9yZVxuICAvLyB1cGRhdGUgZXZlbnQuIEVpdGhlciB3YXkgdGhlIHNhbWUgc3RvcmUgaXMgdGhlIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGguXG4gIHNldFJlZ2lvbnMocmVnaW9uczogUmVnaW9uW10sIHNob3dSZWdpb25MYWJlbD86IGJvb2xlYW4sIGlzUmVnaW9uU2F2ZU9uPzogYm9vbGVhbixcbiAgICAgICAgICAgICBmaWxsQ29sb3I/OiBzdHJpbmcsIGFwcGVuZD86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlcmVyKCkuc2V0UmVnaW9ucyhyZWdpb25zLCBzaG93UmVnaW9uTGFiZWwsIGlzUmVnaW9uU2F2ZU9uLCBmaWxsQ29sb3IsIGFwcGVuZCk7XG4gIH1cbiAgZ2V0UmVnaW9ucygpOiBSZWdpb25bXSB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0UmVnaW9ucygpOyB9XG4gIGdldFJlZ2lvblBvbHlnb25zKCk6IGFueVtdIHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXRSZWdpb25Qb2x5Z29ucygpOyB9XG4gIGdldFJlZ2lvblVwZGF0ZUV2ZW50KCk6IE9ic2VydmFibGU8YW55W10+IHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXRSZWdpb25VcGRhdGVFdmVudCgpOyB9XG4gIHNldFNlbGVjdGVkU2hhcGVJbmRpY2VzKGluZGljZXM6IG51bWJlcltdKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5zZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyhpbmRpY2VzKTsgfVxuICBzZWxlY3RSZWdpb24ocmVnaW9uOiBSZWdpb24pOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnNlbGVjdFJlZ2lvbihyZWdpb24pOyB9XG4gIGdldFNlbGVjdGVkU2hhcGVJbmRpY2VzJCgpOiBPYnNlcnZhYmxlPG51bWJlcltdPiB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0U2VsZWN0ZWRTaGFwZUluZGljZXMkKCk7IH1cbiAgZGVsZXRlQWN0aXZlU2hhcGUoKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5kZWxldGVBY3RpdmVTaGFwZSgpOyB9XG4gIGdldFNob3dTaGFwZUxhYmVsKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldFNob3dTaGFwZUxhYmVsKCk7IH1cbiAgZ2V0U2hhcGVDb2xvcigpOiBzdHJpbmcgeyByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldFNoYXBlQ29sb3IoKTsgfVxuICBnZXRGaWxsQ29sb3IoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXRGaWxsQ29sb3IoKTsgfVxuICBnZXRDbGFzc2lmaWNhdGlvbkNvbG9ycygpOiBNYXA8c3RyaW5nLCBzdHJpbmc+IHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXRDbGFzc2lmaWNhdGlvbkNvbG9ycygpOyB9XG4gIHNldENsYXNzaWZpY2F0aW9uQ29sb3IobGFiZWw6IHN0cmluZywgY29sb3I6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVuZGVyZXIoKS5zZXRDbGFzc2lmaWNhdGlvbkNvbG9yKGxhYmVsLCBjb2xvcik7IH1cbiAgLy8gQW5ub3RhdGlvbi1jbGFzcyBwcmVzZXRzIGxpdmUgaW4gdGhlIHNoYXJlZCBWaXN1YWxpemVyU3RvcmUgKGJhY2tlbmQtbmV1dHJhbFxuICAvLyBzZXNzaW9uIHN0YXRlKSwgc28gcm91dGUgc3RyYWlnaHQgdG8gaXQgcmF0aGVyIHRoYW4gdGhyb3VnaCByZW5kZXJlcigpLiAoaml0LXVpIzcwKVxuICBnZXRQcmVzZXRTZXQoKTogUHJlc2V0U2V0IHsgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0UHJlc2V0U2V0KCk7IH1cbiAgZ2V0UHJlc2V0U2V0JCgpOiBPYnNlcnZhYmxlPFByZXNldFNldD4geyByZXR1cm4gdGhpcy5zdG9yZS5nZXRQcmVzZXRTZXQkKCk7IH1cbiAgc2V0UHJlc2V0U2V0KHNldDogUHJlc2V0U2V0KTogdm9pZCB7IHRoaXMuc3RvcmUuc2V0UHJlc2V0U2V0KHNldCk7IH1cbiAgdXBzZXJ0Q2xhc3MocHJlc2V0OiBDbGFzc1ByZXNldCk6IHZvaWQgeyB0aGlzLnN0b3JlLnVwc2VydENsYXNzKHByZXNldCk7IH1cbiAgcmVtb3ZlQ2xhc3MobmFtZTogc3RyaW5nKTogdm9pZCB7IHRoaXMuc3RvcmUucmVtb3ZlQ2xhc3MobmFtZSk7IH1cbiAgcmVzZXRQcmVzZXRzKCk6IHZvaWQgeyB0aGlzLnN0b3JlLnJlc2V0UHJlc2V0cygpOyB9XG4gIHBsb3RQcmV2aW91c1NoYXBlcygpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnBsb3RQcmV2aW91c1NoYXBlcygpOyB9XG4gIHNldFByZXZpb3VzU2hhcGVzKHNoYXBlczogYW55W10pOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnNldFByZXZpb3VzU2hhcGVzKHNoYXBlcyk7IH1cbiAgZ2V0UHJldmlvdXNTaGFwZXMoKTogYW55W10geyByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldFByZXZpb3VzU2hhcGVzKCk7IH1cbiAgLy8gVW5kbyBzdGF0ZSBpcyBvd25lZCBieSB0aGUgc2hhcmVkIFJlZ2lvblN0b3JlIChzYW1lIGluc3RhbmNlIGZvciBib3RoXG4gIC8vIGJhY2tlbmRzKSwgc28gcm91dGluZyB0aHJvdWdoIHRoZSBhY3RpdmUgcmVuZGVyZXIgaXMgc2FmZSBhbmQgc3RhYmxlLlxuICB1bmRvKCk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkudW5kbygpOyB9XG4gIHJlZG8oKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5yZWRvKCk7IH1cbiAgY2FuVW5kbygpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5jYW5VbmRvKCk7IH1cbiAgY2FuUmVkbygpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5jYW5SZWRvKCk7IH1cbiAgZ2V0Q2FuVW5kbyQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0Q2FuVW5kbyQoKTsgfVxuICBnZXRDYW5SZWRvJCgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXRDYW5SZWRvJCgpOyB9XG4gIHJlc2V0VW5kb0hpc3RvcnkoKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5yZXNldFVuZG9IaXN0b3J5KCk7IH1cbiAgaW1wb3J0UmVnaW9ucyhnZW9Kc29uU3RyOiBzdHJpbmcpOiBSZWdpb25bXSB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuaW1wb3J0UmVnaW9ucyhnZW9Kc29uU3RyKTsgfVxuICBleHBvcnRSZWdpb25zKHJlZ2lvbnM6IFJlZ2lvbltdKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5leHBvcnRSZWdpb25zKHJlZ2lvbnMpOyB9XG4gIGdldEdlb0pzb25TdHJpbmcocmVnaW9uczogUmVnaW9uW10pOiBzdHJpbmcgeyByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldEdlb0pzb25TdHJpbmcocmVnaW9ucyk7IH1cblxuICAvLyDilIDilIAgUGVyLXNsaWNlIHotc3RhY2sgcmVnaW9ucyAoaml0LXVpIzkzKSDigJQgdGhlIFJlZ2lvblN0b3JlIGlzIHNoYXJlZCBhY3Jvc3NcbiAgLy8gICAgYmFja2VuZHMsIHNvIHJvdXRpbmcgdG8gdGhlIGFjdGl2ZSByZW5kZXJlciBoaXRzIHRoZSBzYW1lIHN0b3JlLiDilIDilIDilIDilIDilIDilIBcbiAgZW50ZXJTdGFja01vZGUoc2xpY2VzOiBNYXA8bnVtYmVyLCBSZWdpb25bXT4sIGluaXRpYWxaPzogbnVtYmVyLFxuICAgICAgICAgICAgICAgICBzYXZlTGF5b3V0PzogJ2NvbWJpbmVkJyB8ICdwZXItc2xpY2UtZmlsZScpOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlcmVyKCkuZW50ZXJTdGFja01vZGUoc2xpY2VzLCBpbml0aWFsWiwgc2F2ZUxheW91dCk7XG4gIH1cbiAgZXhpdFN0YWNrTW9kZSgpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLmV4aXRTdGFja01vZGUoKTsgfVxuICBpc1N0YWNrTW9kZSgpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5pc1N0YWNrTW9kZSgpOyB9XG4gIGdldFN0YWNrU2F2ZUxheW91dCgpOiAnY29tYmluZWQnIHwgJ3Blci1zbGljZS1maWxlJyB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0U3RhY2tTYXZlTGF5b3V0KCk7IH1cbiAgc2V0RGlzcGxheVNsaWNlKHo6IG51bWJlcik6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuc2V0RGlzcGxheVNsaWNlKHopOyB9XG4gIGdldFNsaWNlUmVnaW9ucygpOiBSZWdpb25bXSB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0U2xpY2VSZWdpb25zKCk7IH1cbiAgZ2V0U3RhY2tTYXZlU2xpY2VzKCk6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0U3RhY2tTYXZlU2xpY2VzKCk7IH1cbiAgLyoqIEFsbCBzbGljZXMnIEFOTk9UQVRJT04gcmVnaW9ucyBmb3IgYSB6LXN0YWNrIHNhdmUgKGppdC11aSM5MyksIGVhY2ggdGFnZ2VkXG4gICAqICB3aXRoIGl0cyB6ZXJvLWJhc2VkIFJlZ2lvbi56OyBwcm9maWxlIGxpbmVzIGV4Y2x1ZGVkLiBGbGF0IGFubm90YXRpb24gc2V0XG4gICAqICBvdXRzaWRlIHN0YWNrIG1vZGUuICovXG4gIGdldFNsaWNlQW5ub3RhdGlvblJlZ2lvbnMoKTogUmVnaW9uW10ge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0U2xpY2VSZWdpb25zKCkuZmlsdGVyKChyKSA9PiAhaXNQcm9maWxlUmVnaW9uKHIpKTtcbiAgfVxuICAvKiogUGVyLXNsaWNlIGFubm90YXRpb24gcmVnaW9ucyB0byB3cml0ZSBvbiBhIGZvbGRlci1zdGFjayBzYXZlIChqaXQtdWkjOTMpOlxuICAgKiAgc2xpY2UgaW5kZXgg4oaSIHRoYXQgc2xpY2UncyBhbm5vdGF0aW9uIHJlZ2lvbnMgKHByb2ZpbGUgbGluZXMgZXhjbHVkZWQpLFxuICAgKiAgaW5jbHVkaW5nIG5vdy1lbXB0eSBzbGljZXMgdGhhdCB3ZXJlIGxvYWRlZCBub24tZW1wdHkgKHNvIHRoZXkgb3ZlcndyaXRlKS4gKi9cbiAgZ2V0U3RhY2tTYXZlQW5ub3RhdGlvblNsaWNlcygpOiBNYXA8bnVtYmVyLCBSZWdpb25bXT4ge1xuICAgIGNvbnN0IG91dCA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgICBmb3IgKGNvbnN0IFt6LCByZWdzXSBvZiB0aGlzLnJlbmRlcmVyKCkuZ2V0U3RhY2tTYXZlU2xpY2VzKCkpIHtcbiAgICAgIG91dC5zZXQoeiwgcmVncy5maWx0ZXIoKHIpID0+ICFpc1Byb2ZpbGVSZWdpb24ocikpKTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIC8qKiBBdXRob3JpdGF0aXZlIGZ1bGwtcmVzb2x1dGlvbiBpbWFnZSBzaXplIGZvciBtYXNrIGV4cG9ydC4gUHJlZmVycyB0aGVcbiAgICogIGFjdGl2ZSByZW5kZXJlcidzIHJlcG9ydGVkIHNpemUsIGZhbGxpbmcgYmFjayB0byB0aGUgaW1hZ2UgbWV0YWRhdGEgKHgveVxuICAgKiAgYXJlIHRoZSBmdWxsLXJlcyBwaXhlbCBkaW1lbnNpb25zIHVzZWQgYWNyb3NzIHRoZSBhcHApLiBSZWplY3RzIG5vbi1maW5pdGVcbiAgICogIG9yIG5vbi1wb3NpdGl2ZSBzaXplcyDigJQgdGhlIFBsb3RseSBib3VuZHMgY2FuIHlpZWxkIE5hTiBiZWZvcmUgYSBwbG90IGlzXG4gICAqICBmdWxseSBsYWlkIG91dCwgd2hpY2ggd291bGQgb3RoZXJ3aXNlIGNyYXNoIG1hc2sgY3JlYXRpb24uICovXG4gIGdldE1hc2tJbWFnZVNpemUoKTogeyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHwgbnVsbCB7XG4gICAgY29uc3QgdmFsaWQgPSAoczogeyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHwgbnVsbCB8IHVuZGVmaW5lZCkgPT5cbiAgICAgIHMgJiYgTnVtYmVyLmlzRmluaXRlKHMud2lkdGgpICYmIE51bWJlci5pc0Zpbml0ZShzLmhlaWdodCkgJiZcbiAgICAgIHMud2lkdGggPj0gMSAmJiBzLmhlaWdodCA+PSAxXG4gICAgICAgID8geyB3aWR0aDogTWF0aC5yb3VuZChzLndpZHRoKSwgaGVpZ2h0OiBNYXRoLnJvdW5kKHMuaGVpZ2h0KSB9XG4gICAgICAgIDogbnVsbDtcblxuICAgIGNvbnN0IGZyb21SZW5kZXJlciA9IHZhbGlkKHRoaXMuZ2V0VHJ1ZUltYWdlU2l6ZSgpKTtcbiAgICBpZiAoZnJvbVJlbmRlcmVyKSByZXR1cm4gZnJvbVJlbmRlcmVyO1xuXG4gICAgbGV0IG1ldGE6IElJbWFnZU1ldGFkYXRhW10gPSBbXTtcbiAgICB0aGlzLmdldEltYWdlTWV0YSgpLnN1YnNjcmliZSgobSkgPT4gKG1ldGEgPSBtKSkudW5zdWJzY3JpYmUoKTtcbiAgICBjb25zdCBtMCA9IG1ldGE/LlswXTtcbiAgICByZXR1cm4gbTAgPyB2YWxpZCh7IHdpZHRoOiBtMC54LCBoZWlnaHQ6IG0wLnkgfSkgOiBudWxsO1xuICB9XG5cbiAgLy8g4pSA4pSAIElSZWdpb25FZGl0b3JBcGk6IGFubm90YXRpb24tb25seSBzdXJmYWNlIGZvciB0aGUgUmVnaW9uIEVkaXRvciDilIDilIDilIBcbiAgLy8gSW50ZW5zaXR5LXByb2ZpbGUgbGluZXMgKGtpbmQ9J3Byb2ZpbGUnKSBiZWxvbmcgdG8gdGhlIGludGVuc2l0eSB0b29sLCBub3RcbiAgLy8gdGhlIGVkaXRvci4gVGhlc2UgbWV0aG9kcyBnaXZlIGV4dGVybmFsIGNvbnN1bWVycyBhbiBhbm5vdGF0aW9uLW9ubHkgdmlld1xuICAvLyBhbmQgZ3VhcmFudGVlIHByb2ZpbGUgbGluZXMgYXJlIHByZXNlcnZlZC4gUm91dGluZyAobm90IHRoZSBzdG9yZSkgb3ducyB0aGlzXG4gIC8vIHNvIHdyaXRlcy9zZWxlY3Rpb24gZ28gdGhyb3VnaCByZW5kZXJlcigpIGFuZCB0aGUgYWN0aXZlIGJhY2tlbmQgcmUtcmVuZGVyc1xuICAvLyAoUGxvdGx5IHJlbGF5b3V0cyBpdHMgc2hhcGVzIGluIHNldFJlZ2lvbnM7IGl0IGRvZXNuJ3Qgb24gcmVnaW9uVXBkYXRlJCkuXG5cbiAgZ2V0QW5ub3RhdGlvblJlZ2lvbnMoKTogUmVnaW9uW10ge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0UmVnaW9ucygpLmZpbHRlcigocikgPT4gIWlzUHJvZmlsZVJlZ2lvbihyKSk7XG4gIH1cbiAgc2V0QW5ub3RhdGlvblJlZ2lvbnMocmVnaW9uczogUmVnaW9uW10sIHNob3dSZWdpb25MYWJlbD86IGJvb2xlYW4sXG4gICAgICAgICAgICAgICAgICAgICAgIGlzUmVnaW9uU2F2ZU9uPzogYm9vbGVhbiwgZmlsbENvbG9yPzogc3RyaW5nKTogdm9pZCB7XG4gICAgLy8gUmUtYXBwZW5kIHRoZSBzdG9yZSdzIHByb2ZpbGUgbGluZXMgc28gYW4gZWRpdG9yIHNhdmUvZGVsZXRlIGNhbid0IGRyb3BcbiAgICAvLyB0aGVtLCB0aGVuIHJvdXRlIHRocm91Z2ggc2V0UmVnaW9ucyBzbyB0aGUgYWN0aXZlIGJhY2tlbmQgcmUtcmVuZGVycy5cbiAgICBjb25zdCBwcm9maWxlcyA9IHRoaXMucmVuZGVyZXIoKS5nZXRSZWdpb25zKCkuZmlsdGVyKChyKSA9PiBpc1Byb2ZpbGVSZWdpb24ocikpO1xuICAgIGNvbnN0IGFubm90YXRpb25zID0gKHJlZ2lvbnMgfHwgW10pLmZpbHRlcigocikgPT4gIWlzUHJvZmlsZVJlZ2lvbihyKSk7XG4gICAgdGhpcy5zZXRSZWdpb25zKFsuLi5hbm5vdGF0aW9ucywgLi4ucHJvZmlsZXNdLCBzaG93UmVnaW9uTGFiZWwsIGlzUmVnaW9uU2F2ZU9uLCBmaWxsQ29sb3IsIGZhbHNlKTtcbiAgfVxuICBnZXRTZWxlY3RlZFJlZ2lvbnMkKCk6IE9ic2VydmFibGU8UmVnaW9uW10+IHtcbiAgICAvLyBNYXAgdGhlIGludGVybmFsIGluZGV4LWJhc2VkIHNlbGVjdGlvbiB0byB0aGUgc2VsZWN0ZWQgYW5ub3RhdGlvbiByZWdpb25zLlxuICAgIHJldHVybiB0aGlzLmdldFNlbGVjdGVkU2hhcGVJbmRpY2VzJCgpLnBpcGUoXG4gICAgICBtYXAoKGlkeHMpID0+IHtcbiAgICAgICAgY29uc3QgcmVncyA9IHRoaXMucmVuZGVyZXIoKS5nZXRSZWdpb25zKCk7XG4gICAgICAgIHJldHVybiBpZHhzXG4gICAgICAgICAgLm1hcCgoaSkgPT4gcmVnc1tpXSlcbiAgICAgICAgICAuZmlsdGVyKChyKTogciBpcyBSZWdpb24gPT4gISFyICYmICFpc1Byb2ZpbGVSZWdpb24ocikpO1xuICAgICAgfSksXG4gICAgKTtcbiAgfVxuICBzZXRTZWxlY3RlZFJlZ2lvbnMocmVnaW9uczogUmVnaW9uW10pOiB2b2lkIHtcbiAgICBjb25zdCByZWdzID0gdGhpcy5yZW5kZXJlcigpLmdldFJlZ2lvbnMoKTtcbiAgICBjb25zdCBpbmRpY2VzID0gKHJlZ2lvbnMgfHwgW10pXG4gICAgICAubWFwKChyKSA9PiByZWdzLmZpbmRJbmRleCgoeCkgPT4geC5pZCA9PT0gci5pZCkpXG4gICAgICAuZmlsdGVyKChpKSA9PiBpID49IDApO1xuICAgIHRoaXMuc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoaW5kaWNlcyk7XG4gIH1cblxuICAvLyDilIDilIAgdG9vbHMg4oaSIGFjdGl2ZSByZW5kZXJlciAocnVuIG9uIGVpdGhlciBiYWNrZW5kKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gVGhlIHdhbmQsIHZlcnRleCBlcmFzZXIgYW5kIHpvb20tdG8tYm94IGFyZSBpbXBsZW1lbnRlZCBvbiBib3RoIGJhY2tlbmRzXG4gIC8vIHZpYSBJQ29vcmRpbmF0ZVRyYW5zZm9ybSAoKyBhIHZpZXdwb3J0IHBpeGVsIHJlYWRiYWNrIGZvciB0aGUgd2FuZCksIHNvIHRoZXlcbiAgLy8gZm9sbG93IHRoZSBhY3RpdmUgcmVuZGVyZXIuXG4gIHNldFdhbmRNb2RlKGFjdGl2ZTogYm9vbGVhbiwgb3B0aW9ucz86IGFueSk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuc2V0V2FuZE1vZGUoYWN0aXZlLCBvcHRpb25zKTsgfVxuICBzZXRXYW5kT3B0aW9ucyhvcHRpb25zOiBhbnkpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnNldFdhbmRPcHRpb25zKG9wdGlvbnMpOyB9XG4gIGNsZWFyQWN0aXZlV2FuZFJlZ2lvbigpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLmNsZWFyQWN0aXZlV2FuZFJlZ2lvbigpOyB9XG4gIHNldEJydXNoTW9kZShhY3RpdmU6IGJvb2xlYW4sIG9wdGlvbnM/OiBhbnkpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnNldEJydXNoTW9kZShhY3RpdmUsIG9wdGlvbnMpOyB9XG4gIHNldEJydXNoT3B0aW9ucyhvcHRpb25zOiBhbnkpOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnNldEJydXNoT3B0aW9ucyhvcHRpb25zKTsgfVxuICBzZXRWZXJ0ZXhFcmFzZXJNb2RlKGFjdGl2ZTogYm9vbGVhbik6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuc2V0VmVydGV4RXJhc2VyTW9kZShhY3RpdmUpOyB9XG4gIHNldFZlcnRleEVyYXNlclJhZGl1cyhyYWRpdXM6IG51bWJlcik6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuc2V0VmVydGV4RXJhc2VyUmFkaXVzKHJhZGl1cyk7IH1cbiAgc2V0Wm9vbVRvQm94TW9kZShhY3RpdmU6IGJvb2xlYW4pOiB2b2lkIHsgdGhpcy5yZW5kZXJlcigpLnNldFpvb21Ub0JveE1vZGUoYWN0aXZlKTsgfVxuICBzZWdtZW50UmVjdGFuZ2xlcygpOiBQcm9taXNlPG51bWJlcj4geyByZXR1cm4gdGhpcy5yZW5kZXJlcigpLnNlZ21lbnRSZWN0YW5nbGVzKCk7IH1cbiAgc2VnbWVudFJlY3RhbmdsZXNDZWxscG9zZSgpOiBQcm9taXNlPG51bWJlcj4geyByZXR1cm4gdGhpcy5yZW5kZXJlcigpLnNlZ21lbnRSZWN0YW5nbGVzQ2VsbHBvc2UoKTsgfVxuICBzZXRTYW1Nb2RlbChpZDogc3RyaW5nKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5zZXRTYW1Nb2RlbChpZCk7IH1cbiAgc2V0U2FtUG9pbnRNb2RlKGFjdGl2ZTogYm9vbGVhbik6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuc2V0U2FtUG9pbnRNb2RlKGFjdGl2ZSk7IH1cbiAgY29tbWl0U2FtUG9pbnRzKCk6IHZvaWQgeyB0aGlzLnJlbmRlcmVyKCkuY29tbWl0U2FtUG9pbnRzKCk7IH1cbiAgY2xlYXJTYW1Qb2ludHMoKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5jbGVhclNhbVBvaW50cygpOyB9XG5cbiAgLy8g4pSA4pSAIGRpc3BsYXkgb3B0aW9ucyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gU3RhdGUgbGl2ZXMgaW4gdGhlIHNoYXJlZCBWaXN1YWxpemVyU3RvcmUg4oCUIHJlYWRzIGdvIHN0cmFpZ2h0IHRvIGl0LlxuICAvLyBUaGUgdHdvIFNFVFRFUlMgc3RpbGwgcm91dGUgdGhyb3VnaCBQbG90bHkgYmVjYXVzZSBpdHMgaW1wbGVtZW50YXRpb25zXG4gIC8vIGNhcnJ5IHJlbmRlciBnbHVlIGJleW9uZCB0aGUgc3RvcmUgd3JpdGUgKGEgbGl2ZSBQbG90bHkucmVzdHlsZSBvZlxuICAvLyBjb2xvcnNjYWxlL3JldmVyc2VzY2FsZSBvbiB0aGUgbW91bnRlZCBoZWF0bWFwKTsgT1NEIHJlY29sb3JzIHZpYSBpdHMgb3duXG4gIC8vIHN0b3JlIHN1YnNjcmlwdGlvbiBlaXRoZXIgd2F5LlxuICBnZXRDb2xvcm1hcCgpOiBPYnNlcnZhYmxlPGFueT4geyByZXR1cm4gdGhpcy5zdG9yZS5nZXRDb2xvcm1hcCgpOyB9XG4gIHNldENvbG9ybWFwKGNvbG9ybWFwOiBhbnkpOiB2b2lkIHsgdGhpcy5wbG90bHkuc2V0Q29sb3JtYXAoY29sb3JtYXApOyB9XG4gIGdldENvbG9ybWFwT3B0aW9ucygpOiBhbnkgeyByZXR1cm4gdGhpcy5zdG9yZS5nZXRDb2xvcm1hcE9wdGlvbnMoKTsgfVxuICBnZXRSZXZlcnNlU2NhbGUoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7IHJldHVybiB0aGlzLnN0b3JlLmdldFJldmVyc2VTY2FsZSgpOyB9XG4gIHNldFJldmVyc2VTY2FsZShyZXZlcnNjYWxlOiBhbnkpOiB2b2lkIHsgdGhpcy5wbG90bHkuc2V0UmV2ZXJzZVNjYWxlKHJldmVyc2NhbGUpOyB9XG4gIHNldEltYWdlTWV0YShpbWFnZU1ldGE6IElJbWFnZU1ldGFkYXRhW10pOiB2b2lkIHsgdGhpcy5zdG9yZS5zZXRJbWFnZU1ldGEoaW1hZ2VNZXRhKTsgfVxuICBnZXRJbWFnZU1ldGEoKTogT2JzZXJ2YWJsZTxJSW1hZ2VNZXRhZGF0YVtdPiB7IHJldHVybiB0aGlzLnN0b3JlLmdldEltYWdlTWV0YSgpOyB9XG5cbiAgLy8g4pSA4pSAIElDaGFubmVsSGlzdG9ncmFtQXBpOiBDaGFubmVscyAmIEhpc3RvZ3JhbSBwYW5lIHN1cmZhY2Ug4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIC8vIENoYW5uZWwvZ3JheXNjYWxlL2ludmVydCBzdGF0ZSBsaXZlcyBpbiB0aGUgc2hhcmVkIFZpc3VhbGl6ZXJTdG9yZTsgYm90aFxuICAvLyBiYWNrZW5kcyBzdWJzY3JpYmUgYW5kIHJlY29sb3IgbGl2ZSwgc28gc2V0dGVycyBqdXN0IHdyaXRlIHRoZSBzdG9yZS4gVGhlXG4gIC8vIGhpc3RvZ3JhbSBjb21lcyBmcm9tIHdoaWNoZXZlciBiYWNrZW5kIGlzIG9uIHNjcmVlbiAoaXRzIG5hdGl2ZSBwaXhlbHMpLlxuICBnZXRIaXN0b2dyYW0oY2hhbm5lbEluZGV4OiBudW1iZXIsIGJpbnM6IG51bWJlcik6IElIaXN0b2dyYW0gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldEhpc3RvZ3JhbShjaGFubmVsSW5kZXgsIGJpbnMpO1xuICB9XG4gIGdldEhpc3RvZ3JhbSQoY2hhbm5lbEluZGV4OiBudW1iZXIsIGJpbnM6IG51bWJlcik6IE9ic2VydmFibGU8SUhpc3RvZ3JhbSB8IG51bGw+IHtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldEhpc3RvZ3JhbSQoY2hhbm5lbEluZGV4LCBiaW5zKTtcbiAgfVxuICAvKiogRXhwb3J0IHRoZSB1bmRlcmx5aW5nIGRhdGEgKDE2LWJpdCBtdWx0aS1iYW5kIFRJRkYpIHZpYSB0aGUgYWN0aXZlIGJhY2tlbmQuICovXG4gIGV4cG9ydERhdGEoKTogdm9pZCB7IHRoaXMucmVuZGVyZXIoKS5leHBvcnREYXRhKCk7IH1cbiAgZ2V0Q2hhbm5lbHMkKCk6IE9ic2VydmFibGU8SUNoYW5uZWxTdGF0ZVtdPiB7IHJldHVybiB0aGlzLnN0b3JlLmdldENoYW5uZWxTdGF0ZXMoKTsgfVxuICBzZXRTZWxlY3RlZENoYW5uZWwoaW5kZXg6IG51bWJlcik6IHZvaWQgeyB0aGlzLnN0b3JlLnNldFNlbGVjdGVkQ2hhbm5lbChpbmRleCk7IH1cbiAgc2V0Q2hhbm5lbFN0YXRlKGluZGV4OiBudW1iZXIsIHBhcnRpYWw6IFBhcnRpYWw8SUNoYW5uZWxTdGF0ZT4pOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JlLnNldENoYW5uZWxTdGF0ZShpbmRleCwgcGFydGlhbCk7XG4gIH1cbiAgcmVzZXRDb250cmFzdChpbmRpY2VzOiBudW1iZXJbXSk6IHZvaWQge1xuICAgIC8vIEZ1bGwgcmVzZXQ6IHdpbmRvdyAoMC4uMjU1KSwgZ2FtbWEgKDEpIEFORCB0aGUgY2hhbm5lbCdzIGRlZmF1bHQgdGludC5cbiAgICBmb3IgKGNvbnN0IGkgb2YgaW5kaWNlcykgdGhpcy5zdG9yZS5yZXNldENoYW5uZWxTdGF0ZShpKTtcbiAgfVxuICAvKiogQXV0by13aW5kb3cgZWFjaCBjaGFubmVsIGJ5IHNhdHVyYXRpbmcgYHNhdHVyYXRpb25gICgwLi4xKSBvZiBwaXhlbHMgYXQgZWFjaFxuICAgKiAgZW5kIG9mIGl0cyBoaXN0b2dyYW0gKHNraXBwaW5nIG91dGxpZXIgZmlyc3QvbGFzdCBiaW5zKS4gKi9cbiAgYXV0b0NvbnRyYXN0KGluZGljZXM6IG51bWJlcltdLCBzYXR1cmF0aW9uOiBudW1iZXIpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGkgb2YgaW5kaWNlcykge1xuICAgICAgY29uc3QgaCA9IHRoaXMucmVuZGVyZXIoKS5nZXRIaXN0b2dyYW0oaSwgMjU2KTtcbiAgICAgIGlmICghaCkgY29udGludWU7XG4gICAgICBjb25zdCBbbWluLCBtYXhdID0gYXV0b1dpbmRvd0Zyb21IaXN0b2dyYW0oaCwgc2F0dXJhdGlvbik7XG4gICAgICBpZiAobWF4ID4gbWluKSB0aGlzLnN0b3JlLnNldENoYW5uZWxTdGF0ZShpLCB7IG1pbiwgbWF4IH0pO1xuICAgIH1cbiAgfVxuICBnZXRHcmF5c2NhbGUkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4geyByZXR1cm4gdGhpcy5zdG9yZS5nZXRHcmF5c2NhbGUoKTsgfVxuICBzZXRHcmF5c2NhbGUob246IGJvb2xlYW4pOiB2b2lkIHsgdGhpcy5zdG9yZS5zZXRHcmF5c2NhbGUob24pOyB9XG4gIGdldEludmVydCQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7IHJldHVybiB0aGlzLnN0b3JlLmdldEludmVydCgpOyB9XG4gIHNldEludmVydChvbjogYm9vbGVhbik6IHZvaWQgeyB0aGlzLnN0b3JlLnNldEludmVydChvbik7IH1cblxuICAvKipcbiAgICogVGhlIGFjdGl2ZSBiYWNrZW5kJ3MgcmVnaW9uIG92ZXJsYXkuIEZhbGxzIGJhY2sgdG8gUGxvdGx5J3Mgd2hlbiB0aGUgYWN0aXZlIGJhY2tlbmRcbiAgICogKE9TRCBvciBuYXBhcmktanMpIGlzIHNlbGVjdGVkIGJ1dCBhIHBsb3QgaXNuJ3QgbW91bnRlZCB5ZXQsIHNvIGNhbGxlcnMgYWx3YXlzIGdldCBhXG4gICAqIHVzYWJsZSBvdmVybGF5LlxuICAgKi9cbiAgZ2V0UmVnaW9uT3ZlcmxheSgpOiBJUmVnaW9uT3ZlcmxheSB7XG4gICAgY29uc3QgciA9IHRoaXMucmVuZGVyZXIoKTtcbiAgICBpZiAociA9PT0gdGhpcy5vc2QpIHtcbiAgICAgIHJldHVybiB0aGlzLm9zZC5nZXRSZWdpb25PdmVybGF5KCkgPz8gdGhpcy5wbG90bHkuZ2V0UmVnaW9uT3ZlcmxheSgpO1xuICAgIH1cbiAgICBpZiAociA9PT0gdGhpcy5uYXBhcmkpIHtcbiAgICAgIHJldHVybiB0aGlzLm5hcGFyaS5nZXRSZWdpb25PdmVybGF5KCkgPz8gdGhpcy5wbG90bHkuZ2V0UmVnaW9uT3ZlcmxheSgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wbG90bHkuZ2V0UmVnaW9uT3ZlcmxheSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIElzb3N1cmZhY2UgY29udHJvbHMgd2hlbiBhdmFpbGFibGUg4oCUIGFsd2F5cyBQbG90bHkncywgc2luY2UgdGhlIGlzb3N1cmZhY2VcbiAgICogcGxvdCB0eXBlIHJlbmRlcnMgb24gUGxvdGx5IChPU0Qgb25seSBoYW5kbGVzIHRoZSBpbWFnZSB0eXBlKS5cbiAgICovXG4gIGdldElzb3N1cmZhY2VDb250cm9scygpOiBJSXNvc3VyZmFjZUNvbnRyb2xzIHwgbnVsbCB7IHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0SXNvc3VyZmFjZUNvbnRyb2xzKCk7IH1cblxuICAvKiogM0Qgc2NlbmUgY29udHJvbHMg4oCUIGFsd2F5cyBQbG90bHkncywgc2luY2UgdGhlIDNEIHBsb3QgdHlwZXMgcmVuZGVyIG9uXG4gICAqICBQbG90bHkgKE9TRCBvbmx5IGhhbmRsZXMgdGhlIGltYWdlIHR5cGUpLiAqL1xuICBnZXRTdXJmYWNlM2RDb250cm9scygpOiBJU3VyZmFjZTNkQ29udHJvbHMgfCBudWxsIHsgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXRTdXJmYWNlM2RDb250cm9scygpOyB9XG5cbiAgLyoqIEludGVuc2l0eSAobGluZS1ST0kpIGNvbnRyb2xzIOKAlCBhbHdheXMgUGxvdGx5J3MsIHNpbmNlIHRoZSBsaW5lIHByb2ZpbGVzXG4gICAqICByZW5kZXIgdGhlaXIgaW5zZXQgb24gUGxvdGx5IHJlZ2FyZGxlc3Mgb2Ygd2hpY2ggYmFja2VuZCBkcmF3cyB0aGUgaW1hZ2UuICovXG4gIGdldEludGVuc2l0eUNvbnRyb2xzKCk6IElJbnRlbnNpdHlDb250cm9scyB8IG51bGwgeyByZXR1cm4gdGhpcy5wbG90bHkuZ2V0SW50ZW5zaXR5Q29udHJvbHMoKTsgfVxuXG4gIC8qKlxuICAgKiBTcGF0aWFsLW9taWNzIGNvbnRyb2xzLCBvciBudWxsIHdoZW4gbm8gYFNQQVRJQUxfREFUQV9QT1JUYCBpcyBib3VuZC5cbiAgICpcbiAgICogSW1wbGVtZW50ZWQgSEVSRSByYXRoZXIgdGhhbiBvbiBhIGJhY2tlbmQgYmVjYXVzZSB0aGUgc3RhdGUgaXNcbiAgICogYmFja2VuZC1uZXV0cmFsOiB0aGUgdmlldyBzdGF0ZSBsaXZlcyBpbiB0aGUgc2hhcmVkIGBWaXN1YWxpemVyU3RvcmVgIChsaWtlXG4gICAqIHRoZSBjb2xvcm1hcCksIHNvIHRoZSBjb250cm9scyBrZWVwIHdvcmtpbmcgYWNyb3NzIGEgcGxvdC10eXBlIHN3aXRjaCBhbmQgYVxuICAgKiBob3N0IGNhbiBkcml2ZSB0aGVtIGJlZm9yZSBhbnkgYmFja2VuZCBoYXMgbW91bnRlZC5cbiAgICovXG4gIGdldFNwYXRpYWxDb250cm9scygpOiBJU3BhdGlhbENvbnRyb2xzIHwgbnVsbCB7XG4gICAgY29uc3QgcG9ydCA9IHRoaXMuc3BhdGlhbERhdGE7XG4gICAgaWYgKCFwb3J0KSByZXR1cm4gbnVsbDtcbiAgICAvLyBNaXJyb3IgdGhlIGRhdGFzZXQgKGFuZCBkcm9wIGEgc3RhbGUgc2VsZWN0aW9uIHdoZW4gaXQgY2hhbmdlcyDigJQgdGhlIG1hc2tzXG4gICAgLy8gYXJlIGluZGV4LWJhc2VkLCBzbyB0aGV5IGFyZSBtZWFuaW5nbGVzcyBhZ2FpbnN0IGRpZmZlcmVudCBvYnNlcnZhdGlvbnMpLlxuICAgIHRoaXMuc3BhdGlhbERhdGFzZXRTdWIgPz89IHBvcnQuZ2V0RGF0YXNldCQoKS5zdWJzY3JpYmUoKGRhdGFzZXQpID0+IHtcbiAgICAgIGNvbnN0IGNoYW5nZWQgPSBkYXRhc2V0Py5pZCAhPT0gdGhpcy5jdXJyZW50U3BhdGlhbERhdGFzZXQ/LmlkO1xuICAgICAgdGhpcy5jdXJyZW50U3BhdGlhbERhdGFzZXQgPSBkYXRhc2V0O1xuICAgICAgaWYgKCFjaGFuZ2VkKSByZXR1cm47XG4gICAgICB0aGlzLnNlbGVjdGlvblN0b3JlLnNldChlbXB0eVNlbGVjdGlvbihkYXRhc2V0Py5vYnNlcnZhdGlvbnMuY291bnQgPz8gMCkpO1xuICAgICAgLy8gQSBjb2xvdXIgc291cmNlIHRoZSBuZXcgZGF0YXNldCBjYW5ub3Qgc2F0aXNmeSB3b3VsZCBsZWF2ZSB0aGUgbWFwIGZsYXRcbiAgICAgIC8vIHdoaWxlIHRoZSBwYW5lbCBhbmQgdGhlIGNoYXJ0cyBrZXB0IG5hbWluZyB0aGUgb2xkIGNvbHVtbiDigJQgc28gZHJvcCBpdCxcbiAgICAgIC8vIGFuZCBvbmx5IGl0OiBwb2ludCBzaXplLCBvcGFjaXR5IGFuZCB0aGUgcmVzdCBhcmUgdGhlIHVzZXIncyBwcmVmZXJlbmNlcyxcbiAgICAgIC8vIG5vdCB0aGUgcHJldmlvdXMgZGF0YXNldCdzIHN0YXRlLlxuICAgICAgY29uc3QgYnkgPSB0aGlzLnN0b3JlLmN1cnJlbnRTcGF0aWFsVmlldygpLmNvbG9yQnk7XG4gICAgICBpZiAoYnkgJiYgIXRoaXMuY2FuQ29sb3JCeShkYXRhc2V0LCBieSkpIHRoaXMuc3RvcmUuc2V0U3BhdGlhbFZpZXcoeyBjb2xvckJ5OiBudWxsIH0pO1xuICAgIH0pO1xuICAgIHRoaXMuc3BhdGlhbENvbnRyb2xzID8/PSB7XG4gICAgICBnZXREYXRhc2V0JDogKCkgPT4gcG9ydC5nZXREYXRhc2V0JCgpLFxuICAgICAgZ2V0Vmlld1N0YXRlJDogKCkgPT4gdGhpcy5zdG9yZS5nZXRTcGF0aWFsVmlldyQoKSxcbiAgICAgIHZpZXdTdGF0ZTogKCkgPT4gdGhpcy5zdG9yZS5jdXJyZW50U3BhdGlhbFZpZXcoKSxcbiAgICAgIHNldFZpZXdTdGF0ZTogKHBhcnRpYWwpID0+IHRoaXMuc3RvcmUuc2V0U3BhdGlhbFZpZXcocGFydGlhbCksXG4gICAgICAvLyBUaGUgaGludCBTRUVEUyB0aGUgdG9nZ2xlIHdoZW4gdGhlIHNvdXJjZSBjaGFuZ2VzLCBhbmQgbm90aGluZyBjb25zdWx0cyBpdFxuICAgICAgLy8gYWZ0ZXJ3YXJkcy4gSXQgdXNlZCB0byBiZSBPUmVkIGluIGF0IHJlbmRlciB0aW1lLCB3aGljaCBtZWFudCBhbiB1bmNoZWNrZWRcbiAgICAgIC8vIGJveCBjb3VsZCBub3QgdHVybiBsb2cgc2NhbGluZyBvZmYgZm9yIGEgaGludGVkIGNvbHVtbiDigJQgYW5kIHRoZSBsaW5rZWRcbiAgICAgIC8vIGNoYXJ0LCB3aGljaCByZWFkcyBgbG9nU2NhbGVgIGFsb25lLCBkaXNhZ3JlZWQgd2l0aCB0aGUgbWFwIGFib3V0IHdoYXQgaXRcbiAgICAgIC8vIHdhcyBzaG93aW5nLiBPbmUgYXV0aG9yaXR5LCBzZXQgb25jZSBwZXIgc291cmNlLlxuICAgICAgY29sb3JCeUNvbHVtbjogKG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5jdXJyZW50U3BhdGlhbERhdGFzZXQ/LmNvbHVtbnMuZmluZCgoYykgPT4gYy5uYW1lID09PSBuYW1lKTtcbiAgICAgICAgY29uc3QgaGludCA9IG1ldGE/LmtpbmQgPT09ICdjb250aW51b3VzJyA/ICEhbWV0YS5sb2dTY2FsZUhpbnQgOiBmYWxzZTtcbiAgICAgICAgdGhpcy5zdG9yZS5zZXRTcGF0aWFsVmlldyh7IGNvbG9yQnk6IHsga2luZDogJ2NvbHVtbicsIG5hbWUgfSwgbG9nU2NhbGU6IGhpbnQgfSk7XG4gICAgICB9LFxuICAgICAgY29sb3JCeUZlYXR1cmU6IChuYW1lOiBzdHJpbmcpID0+XG4gICAgICAgIHRoaXMuc3RvcmUuc2V0U3BhdGlhbFZpZXcoe1xuICAgICAgICAgIGNvbG9yQnk6IHsga2luZDogJ2ZlYXR1cmUnLCBuYW1lIH0sXG4gICAgICAgICAgbG9nU2NhbGU6ICEhdGhpcy5jdXJyZW50U3BhdGlhbERhdGFzZXQ/LmZlYXR1cmVzPy5sb2dTY2FsZUhpbnQsXG4gICAgICAgIH0pLFxuICAgICAgY2xlYXJDb2xvckJ5OiAoKSA9PiB0aGlzLnN0b3JlLnNldFNwYXRpYWxWaWV3KHsgY29sb3JCeTogbnVsbCB9KSxcbiAgICAgIHNlYXJjaEZlYXR1cmVzOiBhc3luYyAocXVlcnk6IHN0cmluZywgbGltaXQgPSA1MCkgPT4ge1xuICAgICAgICAvLyBQcmVmZXIgdGhlIHBvcnQncyBzZWFyY2ggKGEgMzFrLWdlbmUgZGF0YXNldCBkb2VzIG5vdCBzaGlwIGl0cyBuYW1lcyk7XG4gICAgICAgIC8vIG90aGVyd2lzZSBmaWx0ZXIgd2hhdGV2ZXIgdGhlIG1hbmlmZXN0IGlubGluZWQuXG4gICAgICAgIGlmIChwb3J0LnNlYXJjaEZlYXR1cmVzKSByZXR1cm4gcG9ydC5zZWFyY2hGZWF0dXJlcyhxdWVyeSwgbGltaXQpO1xuICAgICAgICBjb25zdCBkYXRhc2V0ID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20ocG9ydC5nZXREYXRhc2V0JCgpKTtcbiAgICAgICAgY29uc3QgbmFtZXMgPSBkYXRhc2V0Py5mZWF0dXJlcz8ubmFtZXMgPz8gW107XG4gICAgICAgIGNvbnN0IHEgPSBxdWVyeS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICByZXR1cm4gbmFtZXMuZmlsdGVyKChuKSA9PiBuLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMocSkpLnNsaWNlKDAsIGxpbWl0KTtcbiAgICAgIH0sXG4gICAgICAuLi4ocG9ydC5pbXBvcnRHcm91cHMgPyB7XG4gICAgICAgIGltcG9ydEdyb3VwczogKGxhYmVsOiBzdHJpbmcsIHRhYmxlOiBzdHJpbmcpID0+IHBvcnQuaW1wb3J0R3JvdXBzIShsYWJlbCwgdGFibGUpLFxuICAgICAgfSA6IHt9KSxcbiAgICAgIC4uLihwb3J0LmdldFRyYW5zY3JpcHRDb3VudHMgPyB7XG4gICAgICAgIHRyYW5zY3JpcHRDb3VudHM6IChnZW5lczogc3RyaW5nW10pID0+IHBvcnQuZ2V0VHJhbnNjcmlwdENvdW50cyEoZ2VuZXMpLFxuICAgICAgfSA6IHt9KSxcbiAgICAgIC4uLihwb3J0LmdldE1hcmtlckdlbmVzID8ge1xuICAgICAgICBtYXJrZXJHZW5lczogKGNvbHVtbjogc3RyaW5nLCBwZXJHcm91cD86IG51bWJlcikgPT4gcG9ydC5nZXRNYXJrZXJHZW5lcyEoY29sdW1uLCBwZXJHcm91cCksXG4gICAgICB9IDoge30pLFxuICAgICAgZ2V0VHJhbnNjcmlwdEVzdGltYXRlJDogKCkgPT4gdGhpcy5uYXBhcmkudHJhbnNjcmlwdEVzdGltYXRlJC5hc09ic2VydmFibGUoKSxcbiAgICAgIGdldEdlbmVDb3VudHNJblZpZXckOiAoKSA9PiB0aGlzLm5hcGFyaS5nZW5lQ291bnRzSW5WaWV3JC5hc09ic2VydmFibGUoKSxcbiAgICAgIGdldERlbnNpdHlTdGF0cyQ6ICgpID0+IHRoaXMubmFwYXJpLmRlbnNpdHlTdGF0cyQuYXNPYnNlcnZhYmxlKCksXG4gICAgICBjYXRlZ29yeUNvbG9yczogYXN5bmMgKG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBjb2x1bW4gPSBhd2FpdCBwb3J0LmdldENvbHVtbihuYW1lKTtcbiAgICAgICAgaWYgKCFpc0NhdGVnb3JpY2FsQ29sdW1uKGNvbHVtbikpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFtzcGF0aWFsXSBjb2x1bW4gXCIke25hbWV9XCIgaXMgY29udGludW91cyDigJQgaXQgaGFzIG5vIGNhdGVnb3JpZXNgKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZXNvbHZlZCBieSB0aGUgU0FNRSBmdW5jdGlvbiB0aGUgcmVuZGVyZXIgdXNlcywgc28gYSBsZWdlbmQgc3dhdGNoXG4gICAgICAgIC8vIGNhbiBuZXZlciBkaXNhZ3JlZSB3aXRoIHRoZSBjb2xvdXIgb24gc2NyZWVuLlxuICAgICAgICByZXR1cm4gcmVzb2x2ZUNhdGVnb3J5Q29sb3JzKGNvbHVtbi5tZXRhKTtcbiAgICAgIH0sXG5cbiAgICAgIGNvbnRpbnVvdXNWYWx1ZXM6IGFzeW5jIChzb3VyY2UpID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZS5raW5kID09PSAnZmVhdHVyZScpIHJldHVybiBwb3J0LmdldEZlYXR1cmVWZWN0b3Ioc291cmNlLm5hbWUpO1xuICAgICAgICBjb25zdCBjb2x1bW4gPSBhd2FpdCBwb3J0LmdldENvbHVtbihzb3VyY2UubmFtZSk7XG4gICAgICAgIGlmIChpc0NhdGVnb3JpY2FsQ29sdW1uKGNvbHVtbikpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgW3NwYXRpYWxdIGNvbHVtbiBcIiR7c291cmNlLm5hbWV9XCIgaXMgY2F0ZWdvcmljYWwg4oCUIGl0IGhhcyBubyB2YWx1ZXMgdG8gY2hhcnRgLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbHVtbi52YWx1ZXM7XG4gICAgICB9LFxuXG4gICAgICBjYXRlZ29yaWNhbFZpZXc6IGFzeW5jIChuYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgY29sdW1uID0gYXdhaXQgcG9ydC5nZXRDb2x1bW4obmFtZSk7XG4gICAgICAgIGlmICghaXNDYXRlZ29yaWNhbENvbHVtbihjb2x1bW4pKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBbc3BhdGlhbF0gY29sdW1uIFwiJHtuYW1lfVwiIGlzIGNvbnRpbnVvdXMg4oCUIGl0IGhhcyBubyBjYXRlZ29yaWVzYCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGNhdGVnb3JpZXM6IGNvbHVtbi5tZXRhLmNhdGVnb3JpZXMsXG4gICAgICAgICAgY29sb3JzOiByZXNvbHZlQ2F0ZWdvcnlDb2xvcnMoY29sdW1uLm1ldGEpLFxuICAgICAgICAgIGNvZGVzOiBjb2x1bW4uY29kZXMsXG4gICAgICAgIH07XG4gICAgICB9LFxuXG4gICAgICAvLyBTcHJlYWQgcmF0aGVyIHRoYW4gYWx3YXlzIGRlZmluZWQ6IGBnZXRFbWJlZGRpbmdgIGlzIG9wdGlvbmFsIG9uIGJvdGggdGhlIHBvcnRcbiAgICAgIC8vIGFuZCB0aGlzIGZhY2FkZSwgYW5kIGEgcGFuZWwgY2hlY2tzIGZvciBpdHMgcHJlc2VuY2UgdG8gZGVjaWRlIHdoZXRoZXIgdGhlIHZpZXdcbiAgICAgIC8vIGlzIG9mZmVyZWQgYXQgYWxsLiBEZWZpbmluZyBpdCBhcyBhIGZ1bmN0aW9uIHRoYXQgcmVqZWN0cyB3b3VsZCBtYWtlIGFuXG4gICAgICAvLyBlbWJlZGRpbmctbGVzcyBzb3VyY2UgbG9vayBsaWtlIGEgYnJva2VuIG9uZS5cbiAgICAgIC4uLihwb3J0LmdldEVtYmVkZGluZ1xuICAgICAgICA/IHsgZ2V0RW1iZWRkaW5nOiAobmFtZTogc3RyaW5nKSA9PiBwb3J0LmdldEVtYmVkZGluZyEobmFtZSkgfVxuICAgICAgICA6IHt9KSxcblxuICAgICAgY2F0ZWdvcmljYWxDb2x1bW5zOiAoKSA9PiAodGhpcy5jdXJyZW50U3BhdGlhbERhdGFzZXQ/LmNvbHVtbnMgPz8gW10pXG4gICAgICAgIC5maWx0ZXIoKGMpID0+IGMua2luZCA9PT0gJ2NhdGVnb3JpY2FsJylcbiAgICAgICAgLm1hcCgoYykgPT4gYy5uYW1lKSxcblxuICAgICAgLy8gTWVtb2l6ZWQgb24gdGhlIG9ic2VydmF0aW9ucyBvYmplY3QsIHNvIHRoZSByZW5kZXJlcidzIG93biBsb29rdXAgYW5kXG4gICAgICAvLyB0aGlzIG9uZSBhcmUgdGhlIHNhbWUgc2luZ2xlIHNjYW4gb2YgdXAgdG8gMy43TSB6IHZhbHVlcy5cbiAgICAgIHNhbXBsZWRTZWN0aW9uczogKCkgPT4ge1xuICAgICAgICBjb25zdCBvYnMgPSB0aGlzLmN1cnJlbnRTcGF0aWFsRGF0YXNldD8ub2JzZXJ2YXRpb25zO1xuICAgICAgICByZXR1cm4gb2JzID8gc2VjdGlvbnNPZihvYnMpIDogbnVsbDtcbiAgICAgIH0sXG5cbiAgICAgIGdldFNlbGVjdGlvbiQ6ICgpID0+IHRoaXMuc2VsZWN0aW9uU3RvcmUuZ2V0U2VsZWN0aW9uJCgpLFxuXG4gICAgICBzZWxlY3RGcm9tUmVnaW9uczogKCkgPT4ge1xuICAgICAgICBjb25zdCBkYXRhc2V0ID0gdGhpcy5jdXJyZW50U3BhdGlhbERhdGFzZXQ7XG4gICAgICAgIGlmICghZGF0YXNldCkgcmV0dXJuIDA7XG4gICAgICAgIGNvbnN0IHJlZ2lvbnMgPSB0aGlzLnJlZ2lvblN0b3JlLmdldFJlZ2lvbnMoKTtcbiAgICAgICAgLy8gVGhlIHVuaW9uIG9mIGV2ZXJ5IGRyYXduIHJlZ2lvbiDigJQgc28gZXZlcnkgUk9JIHRvb2wgdGhlIGxpYnJhcnlcbiAgICAgICAgLy8gYWxyZWFkeSBoYXMgZG91YmxlcyBhcyBhIHNwYXRpYWwgc2VsZWN0aW9uIHRvb2wuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEluIHRoZSAzRCBjbG91ZCB0aGVyZSBpcyBubyBkYXRhLXNwYWNlIGFmZmluZSB0byBwdXNoIGEgZHJhd24gc2hhcGVcbiAgICAgICAgLy8gdGhyb3VnaCwgc28gdGhlIG9ic2VydmF0aW9ucyBhcmUgcHJvamVjdGVkIHRvIGNhbnZhcyBwaXhlbHMgYnkgdGhlXG4gICAgICAgIC8vIHJlbmRlcmVyICh3aGljaCBvd25zIHRoZSBjYW1lcmEpIGFuZCB0ZXN0ZWQgaW4gc2NyZWVuIHNwYWNlIGluc3RlYWQuXG4gICAgICAgIC8vIEZhbGxzIGJhY2sgdG8gdGhlIDJEIHBhdGggd2hlbmV2ZXIgdGhlIGNsb3VkIGlzIG5vdCBtb3VudGVkLlxuICAgICAgICBjb25zdCBwcm9qZWN0ZWQgPSBpc1NwYXRpYWxPbWljczNkKHRoaXMuY3VycmVudFBsb3RUeXBlKVxuICAgICAgICAgID8gdGhpcy5uYXBhcmkuZ2V0U3BhdGlhbFNjcmVlblByb2plY3Rpb24oZGF0YXNldC5vYnNlcnZhdGlvbnMpXG4gICAgICAgICAgOiBudWxsO1xuICAgICAgICAvLyBJbiB0aGUgMkQgdmlldyBvZiBhIHZvbHVtZS1iYWNrZWQgZGF0YXNldCB0aGUgc2hhcGUgd2FzIGRyYXduIG92ZXIgT05FXG4gICAgICAgIC8vIHNlY3Rpb24sIGluIHRoZSB2b2x1bWUncyBwaXhlbCBncmlkOiBpdCBzZWxlY3RzIHRoZSBjZWxscyBvZiB0aGF0XG4gICAgICAgIC8vIHNlY3Rpb24sIG5vdCB0aGUgd2hvbGUgZGVwdGggb2YgYnJhaW4gc3RhbmRpbmcgYmVoaW5kIHRoZW0uXG4gICAgICAgIGNvbnN0IHZvbHVtZSA9ICFkYXRhc2V0LmltYWdlUmVmID8gZGF0YXNldC52b2x1bWUgOiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IHByb2plY3RlZFxuICAgICAgICAgID8gc2VsZWN0SW5SZWdpb25zUHJvamVjdGVkKHByb2plY3RlZCwgZGF0YXNldC5vYnNlcnZhdGlvbnMuY291bnQsIHJlZ2lvbnMpXG4gICAgICAgICAgOiBzZWxlY3RJblJlZ2lvbnMoXG4gICAgICAgICAgICAgIGRhdGFzZXQub2JzZXJ2YXRpb25zLFxuICAgICAgICAgICAgICB2b2x1bWUgPyB2b2x1bWVJbWFnZVJlZih2b2x1bWUsIGRhdGFzZXQubWljcm9uc1BlclVuaXQpIDogZGF0YXNldC5pbWFnZVJlZixcbiAgICAgICAgICAgICAgcmVnaW9ucyxcbiAgICAgICAgICAgICAgdm9sdW1lXG4gICAgICAgICAgICAgICAgPyBvYnNlcnZhdGlvbnNJblNsaWNlKGRhdGFzZXQub2JzZXJ2YXRpb25zLCB2b2x1bWUsIHRoaXMuY3VycmVudFpJbmRleClcbiAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uU3RvcmUuc2V0KHNlbGVjdGlvbik7XG4gICAgICAgIHJldHVybiBzZWxlY3Rpb24uY291bnQ7XG4gICAgICB9LFxuXG4gICAgICBzZWxlY3RDYXRlZ29yeTogYXN5bmMgKGNvbHVtbjogc3RyaW5nLCBjYXRlZ29yeUluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgY29uc3QgbG9hZGVkID0gYXdhaXQgcG9ydC5nZXRDb2x1bW4oY29sdW1uKTtcbiAgICAgICAgaWYgKCFpc0NhdGVnb3JpY2FsQ29sdW1uKGxvYWRlZCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFtzcGF0aWFsXSBjb2x1bW4gXCIke2NvbHVtbn1cIiBpcyBjb250aW51b3VzIOKAlCBpdCBoYXMgbm8gY2F0ZWdvcmllc2ApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IHNlbGVjdEJ5Q2F0ZWdvcnkobG9hZGVkLmNvZGVzLCBjYXRlZ29yeUluZGV4KTtcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25TdG9yZS5zZXQoc2VsZWN0aW9uKTtcbiAgICAgICAgcmV0dXJuIHNlbGVjdGlvbi5jb3VudDtcbiAgICAgIH0sXG5cbiAgICAgIHNlbGVjdEluZGljZXM6IChpbmRpY2VzOiBJdGVyYWJsZTxudW1iZXI+KSA9PiB7XG4gICAgICAgIGNvbnN0IGNvdW50ID0gdGhpcy5jdXJyZW50U3BhdGlhbERhdGFzZXQ/Lm9ic2VydmF0aW9ucy5jb3VudCA/PyAwO1xuICAgICAgICBpZiAoY291bnQgPT09IDApIHJldHVybiAwO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSBzZWxlY3RCeUluZGljZXMoaW5kaWNlcywgY291bnQpO1xuICAgICAgICB0aGlzLnNlbGVjdGlvblN0b3JlLnNldChzZWxlY3Rpb24pO1xuICAgICAgICByZXR1cm4gc2VsZWN0aW9uLmNvdW50O1xuICAgICAgfSxcblxuICAgICAgY2xlYXJTZWxlY3Rpb246ICgpID0+IHRoaXMuc2VsZWN0aW9uU3RvcmUuY2xlYXIoKSxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLnNwYXRpYWxDb250cm9scztcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGBkYXRhc2V0YCBjYW4gYW5zd2VyIHRoaXMgY29sb3VyIHNvdXJjZS5cbiAgICpcbiAgICogQSBjb2x1bW4gaXMgY2hlY2thYmxlIGFnYWluc3QgdGhlIGRlY2xhcmVkIGxpc3QuIEEgZ2VuZSBpcyBjaGVja2FibGUgb25seSB3aGVuXG4gICAqIHRoZSBkYXRhc2V0IGlubGluZXMgaXRzIGZlYXR1cmUgbmFtZXMg4oCUIGEgZGF0YXNldCB0b28gd2lkZSB0byBpbmxpbmUgdGhlbVxuICAgKiAodHlwZWFoZWFkLW9ubHkpIGtlZXBzIHRoZSBzb3VyY2UsIGFuZCBhIG5hbWUgdGhhdCB0dXJucyBvdXQgbm90IHRvIGV4aXN0XG4gICAqIHN1cmZhY2VzIGFzIHRoZSBjaGFydCdzIFwiY291bGQgbm90IGJlIGNoYXJ0ZWRcIiByYXRoZXIgdGhhbiBhcyBhIHNpbGVudCByZXNldC5cbiAgICovXG4gIHByaXZhdGUgY2FuQ29sb3JCeShkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCB8IG51bGwsIGJ5OiBTcGF0aWFsQ29sb3JCeSk6IGJvb2xlYW4ge1xuICAgIGlmICghZGF0YXNldCkgcmV0dXJuIGZhbHNlO1xuICAgIGlmIChieS5raW5kID09PSAnY29sdW1uJykgcmV0dXJuIGRhdGFzZXQuY29sdW1ucy5zb21lKChjKSA9PiBjLm5hbWUgPT09IGJ5Lm5hbWUpO1xuICAgIGNvbnN0IG5hbWVzID0gZGF0YXNldC5mZWF0dXJlcz8ubmFtZXM7XG4gICAgcmV0dXJuICEhZGF0YXNldC5mZWF0dXJlcyAmJiAoIW5hbWVzIHx8IG5hbWVzLmluY2x1ZGVzKGJ5Lm5hbWUpKTtcbiAgfVxuXG4gIC8qKiBNZW1vaXNlZCBzbyBjb25zdW1lcnMgY2FuIGhvbGQgdGhlIG9iamVjdCBhY3Jvc3MgY2FsbHMuICovXG4gIHByaXZhdGUgc3BhdGlhbENvbnRyb2xzOiBJU3BhdGlhbENvbnRyb2xzIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBMYXRlc3QgZGF0YXNldCwgbWlycm9yZWQgc28gYHNlbGVjdEZyb21SZWdpb25zKClgIGNhbiBhbnN3ZXIgc3luY2hyb25vdXNseVxuICAgKiAg4oCUIGl0IHJ1bnMgZnJvbSBhIGJ1dHRvbiBjbGljayBhbmQgbXVzdCBub3QgYXdhaXQgYSByb3VuZC10cmlwLiAqL1xuICBwcml2YXRlIGN1cnJlbnRTcGF0aWFsRGF0YXNldDogU3BhdGlhbERhdGFzZXQgfCBudWxsID0gbnVsbDtcbiAgLyoqIERpc3BsYXllZCBzbGljZS4gT25seSBhIHZvbHVtZS1iYWNrZWQgc3BhdGlhbCBkYXRhc2V0IHJlYWRzIGl0LCB0byBrZWVwIGFcbiAgICogIHJlZ2lvbiBkcmF3biBvdmVyIG9uZSBzZWN0aW9uIGZyb20gc2VsZWN0aW5nIHRoZSB3aG9sZSBkZXB0aCBiZWhpbmQgaXQuICovXG4gIHByaXZhdGUgY3VycmVudFpJbmRleCA9IDA7XG4gIHByaXZhdGUgc3BhdGlhbERhdGFzZXRTdWI6IFN1YnNjcmlwdGlvbiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBMb2FkIHBpeGVsIGZyYW1lcyBmb3IgaW50ZW5zaXR5IHNhbXBsaW5nIHdoZW4gT3BlblNlYWRyYWdvbiBvd25zIHRoZSBpbWFnZVxuICAgKiAgKGl0IGRvZXNuJ3QgZmVlZCBQbG90bHkncyBmcmFtZSBjYWNoZSkuIE5vLW9wIG5lZWRlZCB3aGVuIFBsb3RseSByZW5kZXJzLiAqL1xuICBlbnN1cmVJbnRlbnNpdHlTYW1wbGluZyhpbWFnZUluZm86IElJbWFnZUluZm8sIHpJbmRleDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMucGxvdGx5LmVuc3VyZUludGVuc2l0eVNhbXBsaW5nKGltYWdlSW5mbywgekluZGV4KTtcbiAgfVxuXG4gIC8qKiBWaXNpYmxlLXJlZ2lvbiBjaGFuZ2VzIGZyb20gdGhlIE9wZW5TZWFkcmFnb24gdmlld2VyIChpbWFnZS1waXhlbCBjb29yZHMpLFxuICAgKiAgc28gdGhlIGludGVuc2l0eSBpbnNldCBjYW4gcmUtc2FtcGxlIGF0IHRoZSBjdXJyZW50IHpvb20gbGV2ZWwuIFBsb3RseSdzIG93blxuICAgKiAgaGlnaC1kZWYgem9vbSB1cGRhdGVzIHRoZSBzYW1wbGluZyBjYWNoZSBpbmxpbmUsIHNvIG9ubHkgT1NEIGZlZWRzIHRoaXMuICovXG4gIGdldFZpZXdwb3J0Q2hhbmdlJCgpOiBPYnNlcnZhYmxlPHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH0+IHtcbiAgICByZXR1cm4gdGhpcy5vc2QuZ2V0Vmlld3BvcnRDaGFuZ2UkKCk7XG4gIH1cblxuICAvKiogUmUtc2FtcGxlIHRoZSBpbnRlbnNpdHkgcHJvZmlsZXMgZnJvbSBhIGZyZXNoIGNyb3Agb2YgdGhlIGdpdmVuIGltYWdlLXBpeGVsXG4gICAqICBST0kgYXQgZGlzcGxheSByZXNvbHV0aW9uIChzYW1wbGluZyBhbHdheXMgbGl2ZXMgaW4gUGxvdGx5KS4gKi9cbiAgcmVmcmVzaEludGVuc2l0eVNhbXBsaW5nRm9yUm9pKHg6IG51bWJlciwgeTogbnVtYmVyLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgekluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnBsb3RseS5yZWZyZXNoSW50ZW5zaXR5U2FtcGxpbmdGb3JSb2koeCwgeSwgd2lkdGgsIGhlaWdodCwgekluZGV4KTtcbiAgfVxuXG4gIHVuc3Vic2NyaWJlKCk6IHZvaWQge1xuICAgIHRoaXMucGxvdGx5LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5vc2QudW5zdWJzY3JpYmUoKTtcbiAgfVxufVxuIl19
1207
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGluZy12aXN1YWxpemVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3JvdXRpbmctdmlzdWFsaXplci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFhLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4RSxPQUFPLEVBQUUsS0FBSyxFQUFjLE9BQU8sRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdkcsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXJDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFLNUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxNQUFNLHdEQUF3RCxDQUFDO0FBQ3hHLE9BQU8sRUFDTCxRQUFRLEVBRVIsVUFBVSxFQUNWLGVBQWUsRUFDZixjQUFjLEVBQ2QsZ0JBQWdCLEVBQ2hCLGtCQUFrQixFQUNsQixjQUFjLEdBQ2YsTUFBTSx1QkFBdUIsQ0FBQztBQWUvQixPQUFPLEVBQUUsaUJBQWlCLEVBQW1CLE1BQU0scUNBQXFDLENBQUM7QUFFekYsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDMUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSx1QkFBdUIsRUFBa0MsTUFBTSwrQkFBK0IsQ0FBQztBQUl4RyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUUvRSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUsxRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztB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QUUsVUFBVSxFQUFFLE1BQU0sRUFBRTs7MEJBbUU3QixNQUFNOzJCQUFDLFVBQVU7OzBCQU1qQixRQUFROzswQkFDUixNQUFNOzJCQUFDLGlCQUFpQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgT25EZXN0cm95LCBPcHRpb25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRU1QVFksIE9ic2VydmFibGUsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiwgY29tYmluZUxhdGVzdCwgbWVyZ2UsIEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSW1hZ2UgfSBmcm9tICdpbWFnZS1qcyc7XG5pbXBvcnQgeyByZXNvbHZlQ29sb3JtYXAgfSBmcm9tICduYXBhcmktanMnO1xuXG5pbXBvcnQgeyBJSW1hZ2VJbmZvLCBJSW1hZ2VNZXRhZGF0YSB9IGZyb20gJy4vY29udHJhY3RzL2ltYWdlLmNvbnRyYWN0JztcbmltcG9ydCB7IFBvbHlnb24sIFJlZ2lvbiB9IGZyb20gJy4vbW9kZWxzL3JlZ2lvbic7XG5pbXBvcnQgeyBDbGFzc1ByZXNldCwgUHJlc2V0U2V0IH0gZnJvbSAnLi9tb2RlbHMvY2xhc3MtcHJlc2V0JztcbmltcG9ydCB7IFBsb3RseVNlcnZpY2UgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9ucy9wbG90bHkvcGxvdGx5LnNlcnZpY2UnO1xuaW1wb3J0IHsgT3BlblNlYWRyYWdvblZpc3VhbGl6ZXJTZXJ2aWNlIH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbnMvb3NkL29wZW5zZWFkcmFnb24tdmlzdWFsaXplci5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIFBsb3RUeXBlLFxuICBQbG90VHlwZURlc2NyaXB0b3IsXG4gIGlzTmFwYXJpM2QsXG4gIGlzTmFwYXJpU2NhdHRlcixcbiAgaXNTcGF0aWFsT21pY3MsXG4gIGlzU3BhdGlhbE9taWNzM2QsXG4gIGlzTmFwYXJpSXNvc3VyZmFjZSxcbiAgaXNOYXBhcmlWb2x1bWUsXG59IGZyb20gJy4vY29udHJhY3RzL3Bsb3QtdHlwZSc7XG5pbXBvcnQge1xuICBJVmlld2VyQmFja2VuZCxcbiAgSVZpc3VhbGl6ZXIsXG4gIExvYWRlZEltYWdlLFxuICBQaXhlbERhdGEsXG4gIEludGVuc2l0eVByb2ZpbGUsXG4gIElJc29zdXJmYWNlQ29udHJvbHMsXG4gIElJbnRlbnNpdHlDb250cm9scyxcbiAgSVN1cmZhY2UzZENvbnRyb2xzLFxuICBJU3BhdGlhbENvbnRyb2xzLFxuICBJSW50ZW5zaXR5U2FtcGxpbmcsXG4gIElPc2RWaWV3T3B0aW9ucyxcbiAgSVZvbHVtZVJlc29sdXRpb24sXG59IGZyb20gJy4vY29udHJhY3RzL3Zpc3VhbGl6ZXIuY29udHJhY3QnO1xuaW1wb3J0IHsgU1BBVElBTF9EQVRBX1BPUlQsIFNwYXRpYWxEYXRhUG9ydCB9IGZyb20gJy4vY29udHJhY3RzL3BvcnRzL3NwYXRpYWwtZGF0YS5wb3J0JztcbmltcG9ydCB7IENhbnZhc1Rvb2xPcHRpb25zLCBDb2xvcm1hcE5vZGUsIElCcnVzaE9wdGlvbnMsIElXYW5kT3B0aW9ucyB9IGZyb20gJy4vY29udHJhY3RzL2Rpc3BsYXktdHlwZXMnO1xuaW1wb3J0IHsgU3BhdGlhbENvbnRyb2xzRmFjYWRlIH0gZnJvbSAnLi9zcGF0aWFsL3NwYXRpYWwtY29udHJvbHMuZmFjYWRlJztcbmltcG9ydCB7IFJlZ2lvblN0b3JlIH0gZnJvbSAnLi9zdG9yZS9yZWdpb24tc3RvcmUuc2VydmljZSc7XG5pbXBvcnQgeyBSRUdJT05fU09VUkNFX01JTl9DSEFSUywgUmVnaW9uU291cmNlLCBSZWdpb25Tb3VyY2VWaWV3IH0gZnJvbSAnLi9yZWdpb24tc291cmNlL3JlZ2lvbi1zb3VyY2UnO1xuaW1wb3J0IHR5cGUgeyBSZWdpb25JbmRleFBhZ2UsIFJlZ2lvbkluZGV4UXVlcnkgfSBmcm9tICcuL3JlZ2lvbi1zb3VyY2UvcmVnaW9uLXRpbGVzJztcbmltcG9ydCB0eXBlIHsgUmVnaW9uU3R5bGUgfSBmcm9tICcuL3JlZ2lvbi1vdmVybGF5L3JlZ2lvbi1zdHlsZSc7XG5pbXBvcnQgdHlwZSB7IE1lc2ggfSBmcm9tICduYXBhcmktanMvZ2VvbWV0cnknO1xuaW1wb3J0IHsgb3Blbkdlb0pzb25SZWdpb25Tb3VyY2UgfSBmcm9tICcuL3JlZ2lvbi1zb3VyY2Uvd29ya2VyLXJlZ2lvbi1zb3VyY2UnO1xuaW1wb3J0IHR5cGUgeyBSZWdpb25Tb3VyY2VPcGVuZXIsIFJlZ2lvblNvdXJjZVNsaWNlcyB9IGZyb20gJy4vc3RvcmUvcmVnaW9uLXNvdXJjZS1zY29wZSc7XG5pbXBvcnQgeyBTcGF0aWFsU2VsZWN0aW9uU3RvcmUgfSBmcm9tICcuL3N0b3JlL3NwYXRpYWwtc2VsZWN0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgVmlld2VyQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi9jb250cmFjdHMvY2FwYWJpbGl0aWVzLmNvbnRyYWN0JztcbmltcG9ydCB7IElSZWdpb25PdmVybGF5IH0gZnJvbSAnLi9jb250cmFjdHMvcmVnaW9uLW92ZXJsYXkuY29udHJhY3QnO1xuaW1wb3J0IHsgSVJlZ2lvbkVkaXRvckFwaSB9IGZyb20gJy4vY29udHJhY3RzL3JlZ2lvbi1lZGl0b3ItYXBpLmNvbnRyYWN0JztcbmltcG9ydCB7IElDaGFubmVsSGlzdG9ncmFtQXBpLCBJQ2hhbm5lbFN0YXRlLCBJSGlzdG9ncmFtIH0gZnJvbSAnLi9jb250cmFjdHMvY2hhbm5lbC1oaXN0b2dyYW0tYXBpLmNvbnRyYWN0JztcbmltcG9ydCB7IGF1dG9XaW5kb3dGcm9tSGlzdG9ncmFtIH0gZnJvbSAnLi9jb250cmFjdHMvaW50ZW5zaXR5JztcbmltcG9ydCB7IFZpc3VhbGl6ZXJTdG9yZSB9IGZyb20gJy4vc3RvcmUvdmlzdWFsaXplci1zdG9yZS5zZXJ2aWNlJztcbmltcG9ydCB7IE5hcGFyaVZpc3VhbGl6ZXJTZXJ2aWNlIH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbnMvbmFwYXJpLWpzL25hcGFyaS12aXN1YWxpemVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgY2hhbm5lbFRpbnRDb2xvcm1hcCwgdm9sdW1lQ29sb3JtYXAgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9ucy9uYXBhcmktanMvbmFwYXJpLWRpc3BsYXktc3RhdGUnO1xuaW1wb3J0IHsgVklaX0NPTkZJRywgVml6Q29uZmlnIH0gZnJvbSAnLi9jb250cmFjdHMvdml6LWNvbmZpZyc7XG5pbXBvcnQgeyBQbG90TW9kZVZpZXdwb3J0IH0gZnJvbSAnLi9jb250cmFjdHMvcGxvdC10eXBlLWNvbnRyaWJ1dGlvbi5jb250cmFjdCc7XG5pbXBvcnQgeyBJbnRlbnNpdHlQcm9maWxlU2VydmljZSB9IGZyb20gJy4vaW50ZW5zaXR5L2ludGVuc2l0eS1wcm9maWxlLnNlcnZpY2UnO1xuaW1wb3J0IHsgY2hhbmdlZENsYXNzZXMsIGNsYXNzU2lnbmF0dXJlcyB9IGZyb20gJy4vc3RvcmUvY2xhc3Mtc2lnbmF0dXJlcyc7XG5pbXBvcnQgeyBWb2x1bWVTZWN0aW9ucyB9IGZyb20gJy4vdmlzdWFsaXplci92b2x1bWUtc2VjdGlvbnMnO1xuaW1wb3J0IHR5cGUgeyBTZWN0aW9uQXhpcywgU2VjdGlvblZpZXdzIH0gZnJvbSAnLi9jb250cmFjdHMvc2VjdGlvbi12aWV3LmNvbnRyYWN0JztcblxuLyoqIEhvdyBsb25nIGFmdGVyIHRoZSBsYXN0IGVkaXQgdGhlIHN1cmZhY2VzIG9mIHRoZSBjbGFzc2VzIGl0IHRvdWNoZWQgYXJlIHJlYnVpbHQgKG1zKS4gKi9cbmV4cG9ydCBjb25zdCBSRUdJT05fU1VSRkFDRV9SRUJVSUxEX01TID0gNjAwO1xuXG4vKiogSW50ZW5zaXR5LXByb2ZpbGUgbGluZSBST0lzIGFyZSBvd25lZCBieSB0aGUgaW50ZW5zaXR5IHRvb2wsIG5vdCB0aGUgZWRpdG9yLlxuICogIFBhY2thZ2UtaW50ZXJuYWwgcHJlZGljYXRlIChwcm9wZXJ0eS1iYXNlZCBzbyBpdCBhbHNvIG1hdGNoZXMgcGxhaW4gb2JqZWN0c1xuICogIGFmdGVyIGEgZHJhZyByb3VuZC10cmlwKS4gKi9cbmZ1bmN0aW9uIGlzUHJvZmlsZVJlZ2lvbihyOiB7IGtpbmQ/OiBzdHJpbmcgfSB8IG51bGwgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgcmV0dXJuIHI/LmtpbmQgPT09ICdwcm9maWxlJztcbn1cblxuLyoqXG4gKiBUaGUgdmlzdWFsaXplciBjaGFpbidzIGZyb250IGRvb3I6IGltcGxlbWVudHMgYElWaXN1YWxpemVyYCwgYElSZWdpb25FZGl0b3JBcGlgXG4gKiBhbmQgYElDaGFubmVsSGlzdG9ncmFtQXBpYCAoYm91bmQgdG8gdGhlIGBWSVNVQUxJWkVSYCAvIGBSRUdJT05fRURJVE9SX0FQSWAgL1xuICogYENIQU5ORUxfSElTVE9HUkFNX0FQSWAgdG9rZW5zKSBvdmVyIHRocmVlIHJlbmRlcmluZyBiYWNrZW5kcywgY2hvc2VuIHBlciBwbG90IHR5cGU6XG4gKiAgLSAqKkltYWdlKiogcmVuZGVycyB0aHJvdWdoIE9wZW5TZWFkcmFnb24gKG5hdGl2ZWx5IHRpbGVkLCByZWdpb24gdG9vbHMsXG4gKiAgICBjbGllbnQtc2lkZSBjb2xvcm1hcCksIG9yIHRocm91Z2ggbmFwYXJpLWpzIHdoZW4gYFZpekNvbmZpZy51c2VOYXBhcmlSZW5kZXJlcmBcbiAqICAgIG9wdHMgaW47IHRoZSBuYXBhcmkgaW1hZ2UgdHlwZXMgYW5kIHRoZSAyRCBzcGF0aWFsLW9taWNzIG1vZGUgcmVuZGVyIHRocm91Z2hcbiAqICAgIG5hcGFyaS1qcy4gQSBmYWlsZWQgbG9hZCBmYWxscyBiYWNrIG5hcGFyaS1qcyDihpIgT1NEIOKGkiBQbG90bHkgZm9yIHRoYXQgaW1hZ2Ugb25seVxuICogICAgKHNlZSBgbmFwYXJpRmVsbEJhY2tgIC8gYG9zZEZlbGxCYWNrYCwgY2xlYXJlZCBieSBgcmVzZXQoKWApLlxuICogIC0gdGhlIG5hcGFyaSAzRCB0eXBlcyAodm9sdW1lLCBpc29zdXJmYWNlLCBzdXJmYWNlLCAzRCBzY2F0dGVyLCB0aGUgM0Qgc3BhdGlhbFxuICogICAgY2xvdWQpIHJlbmRlciB0aHJvdWdoIG5hcGFyaS1qcywgZmFsbGluZyBiYWNrIHRvIFBsb3RseS5cbiAqICAtIGV2ZXJ5IG90aGVyIHBsb3QgdHlwZSAoaGVhdG1hcCwgY29udG91ciwgc3VyZmFjZSwgc2NhdHRlciwgbGluZSwg4oCmKSByZW5kZXJzXG4gKiAgICB0aHJvdWdoIFBsb3RseS5cbiAqXG4gKiBPbmx5IHJlbmRlcmluZyBhbmQgdGhlIHZpZXdwb3J0IGFyZSByb3V0ZWQgdG8gdGhlIGJhY2tlbmQgb24gc2NyZWVuLiBSZWdpb24gc3RhdGVcbiAqIGxpdmVzIGluIHRoZSBzaGFyZWQgYFJlZ2lvblN0b3JlYCBhbmQgZGlzcGxheSBzdGF0ZSAoY29sb3JtYXAsIGNoYW5uZWxzLCBwcmVzZXRzLFxuICogc3BhdGlhbCB2aWV3KSBpbiB0aGUgc2hhcmVkIGBWaXN1YWxpemVyU3RvcmVgLCBzbyBldmVyeSBiYWNrZW5kIHNlZXMgdGhlIHNhbWVcbiAqIHZhbHVlczsgdGhlIGJhY2tlbmRzIHN1YnNjcmliZSB0byB0aGVtIHRvIHJlZHJhdy5cbiAqXG4gKiBQYWNrYWdlLWludGVybmFsOiBob3N0cyBkZXBlbmQgb24gdGhlIHRva2Vucywgbm90IG9uIHRoaXMgY2xhc3MuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgUm91dGluZ1Zpc3VhbGl6ZXJTZXJ2aWNlIGltcGxlbWVudHMgSVZpc3VhbGl6ZXIsIElSZWdpb25FZGl0b3JBcGksIElDaGFubmVsSGlzdG9ncmFtQXBpLCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIGN1cnJlbnRQbG90VHlwZTogUGxvdFR5cGUgPSBQbG90VHlwZS5JTUFHRTtcbiAgcHJpdmF0ZSBsYXN0UmVuZGVyZWQ6IElWaWV3ZXJCYWNrZW5kIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBPU0QgZmFpbGVkIGZvciB0aGUgKmN1cnJlbnQqIHJlbmRlciBjeWNsZSAoZS5nLiBhIGZyZXNoIGZpbGUgc3RpbGwgY2FjaGluZ1xuICAgKiAgcGFzdCB0aGUgZGVhZGxpbmUpIOKGkiBmYWxsIGJhY2sgdG8gUGxvdGx5IGZvciB0aGlzIGltYWdlIG9ubHkuIFJlc2V0IGJ5XG4gICAqICByZXNldCgpIGF0IHRoZSBzdGFydCBvZiBldmVyeSByZW5kZXIgY3ljbGUsIHNvIHRoZSBuZXh0IGZpbGUg4oCUIG9yIGFcbiAgICogIHJlLXNlbGVjdCBvbmNlIHRoZSBmaWxlIGlzIGNhY2hlZCDigJQgcmV0cmllcyBPU0QuIChXYXMgYSBwZXJtYW5lbnQgZmxhZyxcbiAgICogIHdoaWNoIGxlZnQgdGhlIHdob2xlIHNlc3Npb24gc3R1Y2sgb24gUGxvdGx5IGFmdGVyIG9uZSBzbG93IGxvYWQuKSAqL1xuICBwcml2YXRlIG9zZEZlbGxCYWNrID0gZmFsc2U7XG4gIC8qKiBuYXBhcmktanMgZmFpbGVkIGZvciB0aGUgY3VycmVudCByZW5kZXIgY3ljbGUg4oaSIGZhbGwgYmFjayB0byBPU0QgKHRoZW4gUGxvdGx5KS5cbiAgICogIFJlc2V0IGJ5IHJlc2V0KCkgYXQgdGhlIHN0YXJ0IG9mIGV2ZXJ5IGN5Y2xlLCBsaWtlIHtAbGluayBvc2RGZWxsQmFja30uICovXG4gIHByaXZhdGUgbmFwYXJpRmVsbEJhY2sgPSBmYWxzZTtcbiAgLyoqIFRoZSBmaWxlIG5hbWUgb2YgdGhlIGltYWdlIGxhc3QgcGxvdHRlZCAobmFtZXMgYSBHZW9KU09OIGV4cG9ydCkuICovXG4gIHByaXZhdGUgcGxvdHRlZEZpbGVOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIC8qKiBUaGUgZGl2IHRoZSBiYWNrZW5kcyByZW5kZXIgaW50byAoZXZlcnkgYmFja2VuZCBzaGFyZXMgaXQpOyAnJyBiZWZvcmUgdGhlIGZpcnN0IHBsb3QuICovXG4gIHByaXZhdGUgcGxvdERpdiA9ICcnO1xuICAvKiogV2hldGhlciBhIG5hcGFyaSB2b2x1bWUgdmlldyBpcyB0aGUgY3VycmVudCBwbG90IHR5cGUuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgdm9sdW1lVmlldyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIFdoZXRoZXIgdGhlIHZvbHVtZSB2aWV3J3Mgc2xpY2UgcGFuZSBpcyB3YW50ZWQgKHNlZSB7QGxpbmsgc2V0U2xpY2VFZGl0b3J9KS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBzbGljZUVkaXRvciQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIFdoZXRoZXIgdGhlIHZvbHVtZSB2aWV3IGRyYXdzIHRoZSByZWdpb24gcmVjb25zdHJ1Y3Rpb25zIHRocm91Z2ggdGhlIHZvbHVtZS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSByZWdpb25zVGhyb3VnaFZvbHVtZSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIFJlZ2lvbiByZWNvbnN0cnVjdGlvbnMgYnVpbHQgc28gZmFyLCBieSBpbWFnZSwgcmVzb2x1dGlvbiBhbmQgY2xhc3NlcyAod2l0aCB0aG9zZSBjbGFzc2VzKS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBtZXNoQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgeyBtZXNoOiBNZXNoOyBjbGFzc2VzOiByZWFkb25seSBzdHJpbmdbXSB9PigpO1xuICAvKiogQnVtcGVkIHBlciB7QGxpbmsgc2hvd1JlZ2lvbkNsYXNzZXMzZH0gKGFuZCBwZXIgbmV3IGltYWdlKSwgc28gb25seSB0aGUgbGF0ZXN0IG9uZSBzaG93cy4gKi9cbiAgcHJpdmF0ZSBtZXNoUmVxdWVzdCA9IDA7XG4gIC8qKiBUaGUgY2xhc3MgZ3JvdXBzIHNob3duIGluIDNELCBhbmQgdGhlIGltYWdlIHRoZXkgYmVsb25nIHRvLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGNsYXNzZXMzZCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFJlYWRvbmx5QXJyYXk8eyBrZXk6IHN0cmluZzsgY2xhc3NlczogcmVhZG9ubHkgc3RyaW5nW10gfT4+KFxuICAgIFtdLFxuICApO1xuICBwcml2YXRlIGNsYXNzZXMzZEltYWdlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIC8qKiBUaGUgZ3JvdXBzIGxhc3QgYXNrZWQgZm9yIGluIDNELCB3aXRoIHRoZWlyIGNvbG91cnM6IHdoYXQgYW4gZWRpdCdzIHJlYnVpbGQgc2hvd3MgYWdhaW4uICovXG4gIHByaXZhdGUgc2hvd24zZDogUmVhZG9ubHlBcnJheTx7IGtleTogc3RyaW5nOyBjbGFzc2VzOiByZWFkb25seSBzdHJpbmdbXTsgY29sb3I6IHN0cmluZzsgbGFiZWw/OiBzdHJpbmcgfT4gPSBbXTtcbiAgLyoqXG4gICAqIEVhY2ggY2xhc3MncyBmaW5nZXJwcmludCBvbiB0aGUgbGl2ZSBzbGljZSAoc2VlIGNsYXNzU2lnbmF0dXJlcyksIHdoaWNoIGltYWdlIGFuZCBzbGljZSwgYW5kXG4gICAqIHdoYXQgdGhlIHJlZ2lvbiBzb3VyY2VzIGhvbGQgKHNlZSBSZWdpb25TdG9yZS5nZXRTb3VyY2VTdGF0ZUtleSkuIE51bGwgd2hpbGUgbm90aGluZyBmb2xsb3dzXG4gICAqIHRoZSBlZGl0cyAobm8gc3VyZmFjZSBidWlsdCwgbm8gc2VjdGlvbnMpLlxuICAgKi9cbiAgcHJpdmF0ZSBsaXZlQ2xhc3NlczogeyBhdDogc3RyaW5nOyBzaWduYXR1cmVzOiBNYXA8c3RyaW5nLCBudW1iZXI+OyBzb3VyY2VzOiBzdHJpbmcgfSB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIHBlbmRpbmcgcmVidWlsZCBvZiB0aGUgc3VyZmFjZXMgYW4gZWRpdCB0b3VjaGVkLiAqL1xuICBwcml2YXRlIHJlYnVpbGRUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSByZWdpb25VcGRhdGVzOiBTdWJzY3JpcHRpb247XG5cbiAgLy8g4pSA4pSAIFRoZSBzbGljZSBwYW5lICh0aGUgdm9sdW1lIHZpZXcncyBzcGxpdCk6IE9TRCBlZGl0aW5nIG9uZSBzbGljZSBiZXNpZGUgdGhlIDNEIHZpZXcg4pSA4pSAXG4gIC8qKiBUaGUgZGl2IHRoZSBzbGljZSBwYW5lIHJlbmRlcnMgaW50byB3aGlsZSBpdCBpcyB3YW50ZWQgKG51bGw6IG5vIHNwbGl0KS4gKi9cbiAgcHJpdmF0ZSBzbGljZURpdjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBXaGV0aGVyIE9TRCBpcyBtb3VudGVkIGluIHRoZSBzbGljZSBwYW5lOiByZWdpb24sIHRvb2wgYW5kIG92ZXJsYXkgY2FsbHMgZ28gdG8gaXQuICovXG4gIHByaXZhdGUgc2xpY2VNb3VudGVkID0gZmFsc2U7XG4gIC8qKiBUaGUgaW1hZ2UgdGhlIHNsaWNlIHBhbmUgc2hvd3MuICovXG4gIHByaXZhdGUgc2xpY2VGaWxlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIC8qKiBCdW1wZWQgcGVyIHNsaWNlLXBhbmUgbW91bnQgb3IgdGVhcmRvd24sIHNvIG9ubHkgdGhlIGxhdGVzdCBvbmUgbGFuZHMuICovXG4gIHByaXZhdGUgc2xpY2VSZXF1ZXN0ID0gMDtcbiAgLyoqIFRoZSBzZWN0aW9ucyBiZXNpZGUgdGhlIHNwbGl0IHZvbHVtZSB2aWV3ICh0aGUgcGxhbmVzIHggYW5kIHkgdGhyb3VnaCB0aGUgc3RhY2spLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHNlY3Rpb25zOiBWb2x1bWVTZWN0aW9ucztcbiAgLyoqIFRoZSB6IHBsYW5lIGRyYWdnZWQgaW4gdGhlIHZvbHVtZTogdGhlIHNsaWNlIHRvIHNob3cgKHNlZSB7QGxpbmsgZ2V0U2xpY2VEcmFnJH0pLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHNsaWNlRHJhZyQgPSBuZXcgU3ViamVjdDxudW1iZXI+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2VjdGlvblN1YnMgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIC8qKiBUaGUgaW1hZ2UgaW5mbyBhbmQgc2NyZWVuIGhlaWdodCBvZiB0aGUgbGFzdCBwbG90ICh3aGF0IHRoZSBzbGljZSBwYW5lIG1vdW50cykuICovXG4gIHByaXZhdGUgcGxvdHRlZEluZm86IElJbWFnZUluZm8gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwbG90dGVkSGVpZ2h0ID0gMDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHBsb3RseTogUGxvdGx5U2VydmljZSxcbiAgICBwcml2YXRlIG9zZDogT3BlblNlYWRyYWdvblZpc3VhbGl6ZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgbmFwYXJpOiBOYXBhcmlWaXN1YWxpemVyU2VydmljZSxcbiAgICBwcml2YXRlIHN0b3JlOiBWaXN1YWxpemVyU3RvcmUsXG4gICAgQEluamVjdChWSVpfQ09ORklHKSBwcml2YXRlIGNvbmZpZzogVml6Q29uZmlnLFxuICAgIC8vIE9wdGlvbmFsOiBhIGhvc3QgdGhhdCBzZXJ2ZXMgbm8gc3BhdGlhbC1vbWljcyBkYXRhIGJpbmRzIG5vdGhpbmcsXG4gICAgLy8gYW5kIGBnZXRTcGF0aWFsQ29udHJvbHMoKWAgdGhlbiByZXR1cm5zIG51bGwuXG4gICAgcHJpdmF0ZSByZWdpb25TdG9yZTogUmVnaW9uU3RvcmUsXG4gICAgcHJpdmF0ZSBzZWxlY3Rpb25TdG9yZTogU3BhdGlhbFNlbGVjdGlvblN0b3JlLFxuICAgIHByaXZhdGUgaW50ZW5zaXR5OiBJbnRlbnNpdHlQcm9maWxlU2VydmljZSxcbiAgICBAT3B0aW9uYWwoKVxuICAgIEBJbmplY3QoU1BBVElBTF9EQVRBX1BPUlQpXG4gICAgcHJpdmF0ZSBzcGF0aWFsRGF0YTogU3BhdGlhbERhdGFQb3J0IHwgbnVsbCA9IG51bGwsXG4gICkge1xuICAgIHRoaXMucmVnaW9uVXBkYXRlcyA9IHRoaXMucmVnaW9uU3RvcmUuZ2V0UmVnaW9uVXBkYXRlRXZlbnQoKS5zdWJzY3JpYmUoKCkgPT4gdGhpcy5vblJlZ2lvbnNDaGFuZ2VkKCkpO1xuICAgIHRoaXMuc2VjdGlvbnMgPSBuZXcgVm9sdW1lU2VjdGlvbnMoe1xuICAgICAgdm9sdW1lOiAoKSA9PiB0aGlzLm5hcGFyaS52b2x1bWVWb3hlbHMoKSxcbiAgICAgIGltYWdlOiAoKSA9PiB0aGlzLnBsb3R0ZWRGaWxlTmFtZSxcbiAgICAgIHNob3dQbGFuZXM6IChwbGFuZXMpID0+IHRoaXMubmFwYXJpLnNldFNsaWNlUGxhbmVzKHBsYW5lcyksXG4gICAgICBvdXRsaW5lc0J5Q2xhc3M6IChsZXZlbCkgPT4gdGhpcy5yZWdpb25TdG9yZS5vdXRsaW5lc0J5Q2xhc3MobGV2ZWwpLFxuICAgICAgaXNDbGFzc0hpZGRlbjogKGxhYmVsKSA9PiB0aGlzLnJlZ2lvblN0b3JlLmlzQ2xhc3NIaWRkZW4obGFiZWwpLFxuICAgICAgY29sb3JPZjogKGxhYmVsKSA9PiB0aGlzLmNsYXNzQ29sb3IobGFiZWwpLFxuICAgICAgY2hhbm5lbFN0YXRlczogKCkgPT4gdGhpcy5zdG9yZS5jdXJyZW50Q2hhbm5lbFN0YXRlcygpLFxuICAgICAgY29sb3JtYXA6IChzdCwgbXVsdGljaGFubmVsKSA9PiB7XG4gICAgICAgIC8vIEFzIHRoZSB2b2x1bWUgc2NlbmUgY29sb3VycyB0aGUgY2hhbm5lbCAoaW52ZXJ0IGlzIGFwcGxpZWQgYmVmb3JlIHRoZSBjb2xvcm1hcCkuXG4gICAgICAgIGNvbnN0IGRpc3BsYXkgPSB7XG4gICAgICAgICAgY29sb3JtYXA6IHRoaXMuc3RvcmUuY3VycmVudENvbG9ybWFwKCksXG4gICAgICAgICAgcmV2ZXJzZTogdGhpcy5zdG9yZS5jdXJyZW50UmV2ZXJzZVNjYWxlKCksXG4gICAgICAgICAgaW52ZXJ0OiBmYWxzZSxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVDb2xvcm1hcChcbiAgICAgICAgICBtdWx0aWNoYW5uZWwgPyBjaGFubmVsVGludENvbG9ybWFwKHN0Py5jb2xvciA/PyAnI2ZmZmZmZicsIGRpc3BsYXkpIDogdm9sdW1lQ29sb3JtYXAoc3QsIGRpc3BsYXkpLFxuICAgICAgICApO1xuICAgICAgfSxcbiAgICAgIGludmVydDogKCkgPT4gdGhpcy5zdG9yZS5jdXJyZW50SW52ZXJ0KCksXG4gICAgICBzbGljZTogKCkgPT4gdGhpcy5jdXJyZW50WkluZGV4LFxuICAgIH0pO1xuICAgIC8vIEEgcGxhbmUgZHJhZ2dlZCBpbiB0aGUgdm9sdW1lOiB0aGUgeiBwbGFuZSBwaWNrcyB0aGUgc2xpY2UgKHRocm91Z2ggdGhlIGhvc3QncyBzbGlkZXIsIHNvXG4gICAgLy8gdGhlIHN0b3JlIGFuZCB0aGUgc2xpY2UgcGFuZSBmb2xsb3cpLCB0aGUgb3RoZXJzIG1vdmUgdGhlaXIgc2VjdGlvbi5cbiAgICB0aGlzLnNlY3Rpb25TdWJzLmFkZChcbiAgICAgIHRoaXMubmFwYXJpLmdldFNsaWNlUGxhbmVNb3ZlJCgpLnN1YnNjcmliZSgoeyBheGlzLCB2YWx1ZSB9KSA9PiB7XG4gICAgICAgIGlmIChheGlzID09PSAneicpIHRoaXMuc2xpY2VEcmFnJC5uZXh0KE1hdGgucm91bmQodmFsdWUpKTtcbiAgICAgICAgZWxzZSB0aGlzLnNlY3Rpb25zLnNldFBsYW5lKGF4aXMsIHZhbHVlKTtcbiAgICAgIH0pLFxuICAgICk7XG4gICAgdGhpcy5zZWN0aW9uU3Vicy5hZGQodGhpcy5zdG9yZS5nZXRDaGFubmVsU3RhdGVzKCkuc3Vic2NyaWJlKCgpID0+IHRoaXMuc2VjdGlvbnMuc2NoZWR1bGUoKSkpO1xuICAgIHRoaXMuc2VjdGlvblN1YnMuYWRkKHRoaXMuc3RvcmUuZ2V0SW52ZXJ0KCkuc3Vic2NyaWJlKCgpID0+IHRoaXMuc2VjdGlvbnMuc2NoZWR1bGUoKSkpO1xuICAgIHRoaXMuc2VjdGlvblN1YnMuYWRkKHRoaXMuc3RvcmUuZ2V0Q29sb3JtYXAoKS5zdWJzY3JpYmUoKCkgPT4gdGhpcy5zZWN0aW9ucy5zY2hlZHVsZSgpKSk7XG4gICAgdGhpcy5zZWN0aW9uU3Vicy5hZGQodGhpcy5zdG9yZS5nZXRSZXZlcnNlU2NhbGUoKS5zdWJzY3JpYmUoKCkgPT4gdGhpcy5zZWN0aW9ucy5zY2hlZHVsZSgpKSk7XG4gIH1cblxuICAvKiogQSBjbGFzcydzIGNvbG91cjogaXRzIGNsYXNzaWZpY2F0aW9uIGNvbG91ciwgZWxzZSBpdHMgcmVnaW9uIHNvdXJjZSdzLCBlbHNlIGEgZGVmYXVsdC4gKi9cbiAgcHJpdmF0ZSBjbGFzc0NvbG9yKGxhYmVsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLnN0b3JlLmdldENsYXNzaWZpY2F0aW9uQ29sb3JzKCkuZ2V0KGxhYmVsKSA/P1xuICAgICAgdGhpcy5yZWdpb25TdG9yZS5nZXRSZWdpb25Tb3VyY2VWaWV3KCk/LmNvbG9yT2YoeyBsYWJlbCwgY29sb3I6IG51bGwgfSkgPz9cbiAgICAgICcjZmZjYzAwJ1xuICAgICk7XG4gIH1cblxuICAvKiogVGhlIHNlY3Rpb25zIGJlc2lkZSB0aGUgc3BsaXQgdm9sdW1lIHZpZXcgKG51bGxzIHdoaWxlIGl0IGlzIG5vdCBzcGxpdCkuICovXG4gIGdldFNlY3Rpb25WaWV3cyQoKTogT2JzZXJ2YWJsZTxTZWN0aW9uVmlld3M+IHtcbiAgICByZXR1cm4gdGhpcy5zZWN0aW9ucy5nZXRWaWV3cyQoKTtcbiAgfVxuXG4gIC8qKiBNb3ZlIGEgc2VjdGlvbidzIHBsYW5lIHRvIGBhdGAgKGltYWdlIHB4KS4gKi9cbiAgc2V0U2VjdGlvblBsYW5lKGF4aXM6IFNlY3Rpb25BeGlzLCBhdDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5zZWN0aW9ucy5zZXRQbGFuZShheGlzLCBhdCk7XG4gIH1cblxuICAvKiogVGhlIHNsaWNlIHBpY2tlZCBieSBkcmFnZ2luZyB0aGUgeiBwbGFuZSBpbiB0aGUgdm9sdW1lOiB0aGUgaG9zdCBzaG93cyBpdCAoaXRzIHNsaWRlcikuICovXG4gIGdldFNsaWNlRHJhZyQoKTogT2JzZXJ2YWJsZTxudW1iZXI+IHtcbiAgICByZXR1cm4gdGhpcy5zbGljZURyYWckLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0ltYWdlVHlwZSh0OiBQbG90VHlwZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0ID09PSBQbG90VHlwZS5JTUFHRTtcbiAgfVxuXG4gIC8qKiBUaGUgMkQgbmFwYXJpIHR5cGVzIChpbWFnZSwgcmVnaW9uLWNlbnRyb2lkIHNjYXR0ZXIsIHNwYXRpYWwgb21pY3MpIOKAlCBhIDJEIGZhbGxiYWNrIGNoYWluXG4gICAqICAoT1NELCB0aGVuIFBsb3RseSkuXG4gICAqXG4gICAqICBOT1RFIGZvciBTUEFUSUFMX09NSUNTOiBvbmx5IG5hcGFyaS1qcyBkcmF3cyB0aGUgb2JzZXJ2YXRpb24gbWFya2Vycy4gSWYgaXQgZmFpbHMgKG5vIFdlYkdQVSxcbiAgICogIGRldmljZSBsb3NzKSB0aGUgZmFsbGJhY2sgcmVuZGVycyB0aGUgdGlzc3VlIGltYWdlIEFMT05FIOKAlCB0aGUgc3BhdGlhbCBsYXllciBpcyBhYnNlbnQsIG5vdFxuICAgKiAgZGVncmFkZWQuIFRoYXQgaXMgZGVsaWJlcmF0ZSBmb3Igbm93OiBzaG93aW5nIHRoZSBzbGlkZSBiZWF0cyBzaG93aW5nIG5vdGhpbmcsIGFuZCBhIFBsb3RseVxuICAgKiAgYHNjYXR0ZXJnbGAgc3BhdGlhbCBtb2RlIGlzIHRoZSBwbGFubmVkIHJlYWwgZmFsbGJhY2sgKHNlZSB0aGUgcGxvdC1tb2RlIGRlc2lnbiBkb2MpLiAqL1xuICBwcml2YXRlIGlzTmFwYXJpSW1hZ2VUeXBlKHQ6IFBsb3RUeXBlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHQgPT09IFBsb3RUeXBlLk5BUEFSSV9JTUFHRSB8fCBpc05hcGFyaVNjYXR0ZXIodCkgfHwgaXNTcGF0aWFsT21pY3ModCk7XG4gIH1cblxuICAvKiogVGhlIDNEIG5hcGFyaSB0eXBlcyAodm9sdW1lL2lzb3N1cmZhY2Uvc3VyZmFjZS9zY2F0dGVyLCBwbHVzIHRoZSAzRCBzcGF0aWFsIGNsb3VkKSDigJQgbm8gMkRcbiAgICogIGZhbGxiYWNrIGV4aXN0cyAoT1NEIGlzIGltYWdlLW9ubHkpLCBzbyB0aGV5IGZhbGwgc3RyYWlnaHQgdG8gUGxvdGx5LiAqL1xuICBwcml2YXRlIGlzTmFwYXJpM2RUeXBlKHQ6IFBsb3RUeXBlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzTmFwYXJpM2QodCkgfHwgaXNTcGF0aWFsT21pY3MzZCh0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCYWNrZW5kIHRvIGF0dGVtcHQgZm9yIHRoZSBjdXJyZW50IHBsb3QgdHlwZSB0aGlzIHJlbmRlci4gVGhlIGZhbGxiYWNrIGNoYWlucyBiZWxvdyBhcmVcbiAgICogbWlycm9yZWQgZXhhY3RseSBieSB7QGxpbmsgbG9hZH0gc28gdGhlIGhhbmRsZSBgcGxvdCgpYCByZWNlaXZlcyBhbHdheXMgY29tZXMgZnJvbSB0aGVcbiAgICogYmFja2VuZCBgcGxvdCgpYCBzZWxlY3RzIChubyBsb2FkL3Bsb3QgYmFja2VuZCBtaXNtYXRjaCk6XG4gICAqICAtIDJEIGltYWdlIChleHBsaWNpdCBgTkFQQVJJX0lNQUdFYCwgb3IgYElNQUdFYCB3aXRoIHRoZSBXZWJHUFUgb3B0LWluKTogbmFwYXJpLWpzIOKGkiBPU0Qg4oaSIFBsb3RseS5cbiAgICogIC0gcGxhaW4gYElNQUdFYCAobm8gb3B0LWluKTogT1NEIOKGkiBQbG90bHkuXG4gICAqICAtIDNEIG5hcGFyaSAoYE5BUEFSSV9WT0xVTUVgL2BOQVBBUklfSVNPU1VSRkFDRWApOiBuYXBhcmktanMg4oaSIFBsb3RseSAoT1NEIGNhbid0IHJlbmRlciAzRCkuXG4gICAqL1xuICBwcml2YXRlIGltYWdlQmFja2VuZCgpOiBJVmlld2VyQmFja2VuZCB7XG4gICAgY29uc3QgdCA9IHRoaXMuY3VycmVudFBsb3RUeXBlO1xuICAgIC8vIDJEIGltYWdlIHdpdGggYSBuYXBhcmktanMgYXR0ZW1wdCAoZXhwbGljaXQgbmFwYXJpIGltYWdlLCBvciBvcHQtaW4gb24gdGhlIEltYWdlIHR5cGUpLlxuICAgIGlmICh0aGlzLmlzTmFwYXJpSW1hZ2VUeXBlKHQpIHx8ICh0aGlzLmlzSW1hZ2VUeXBlKHQpICYmIHRoaXMuY29uZmlnLnVzZU5hcGFyaVJlbmRlcmVyKSkge1xuICAgICAgaWYgKCF0aGlzLm5hcGFyaUZlbGxCYWNrKSByZXR1cm4gdGhpcy5uYXBhcmk7XG4gICAgICBpZiAoIXRoaXMub3NkRmVsbEJhY2spIHJldHVybiB0aGlzLm9zZDtcbiAgICAgIHJldHVybiB0aGlzLnBsb3RseTtcbiAgICB9XG4gICAgLy8gUGxhaW4gSW1hZ2UgdHlwZSAobm8gbmFwYXJpIG9wdC1pbik6IE9TRCwgdGhlbiBQbG90bHkuXG4gICAgaWYgKHRoaXMuaXNJbWFnZVR5cGUodCkpIHtcbiAgICAgIHJldHVybiB0aGlzLm9zZEZlbGxCYWNrID8gdGhpcy5wbG90bHkgOiB0aGlzLm9zZDtcbiAgICB9XG4gICAgLy8gM0QgbmFwYXJpIHR5cGVzOiBuYXBhcmktanMsIHdpdGggUGxvdGx5IGFzIHRoZSBvbmx5IHZpYWJsZSBmYWxsYmFjay5cbiAgICBpZiAodGhpcy5pc05hcGFyaTNkVHlwZSh0KSkge1xuICAgICAgcmV0dXJuIHRoaXMubmFwYXJpRmVsbEJhY2sgPyB0aGlzLnBsb3RseSA6IHRoaXMubmFwYXJpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wbG90bHk7XG4gIH1cblxuICAvKiogQmFja2VuZCBjdXJyZW50bHkgb24gc2NyZWVuIOKAlCB3aGF0IG9uZ29pbmcgem9vbS90b29sL3JlZ2lvbiBvcHMgYWN0IG9uLiAqL1xuICBwcml2YXRlIHJlbmRlcmVyKCk6IElWaWV3ZXJCYWNrZW5kIHtcbiAgICByZXR1cm4gdGhpcy5sYXN0UmVuZGVyZWQgPz8gdGhpcy5wbG90bHk7XG4gIH1cblxuICAvKipcbiAgICogQmFja2VuZCByZWdpb24sIHRvb2wgYW5kIG92ZXJsYXkgY2FsbHMgYWN0IG9uOiB0aGUgc2xpY2UgcGFuZSdzIE9TRCB3aGlsZSB0aGUgdm9sdW1lIHZpZXcgaXNcbiAgICogc3BsaXQgKHJlZ2lvbnMgYXJlIGVkaXRlZCB0aGVyZSksIGVsc2UgdGhlIGJhY2tlbmQgb24gc2NyZWVuLiBWaWV3IGNhbGxzICh6b29tLCBmaXQsIGNvbG91cixcbiAgICogZXhwb3J0KSBzdGF5IHdpdGgge0BsaW5rIHJlbmRlcmVyfS5cbiAgICovXG4gIHByaXZhdGUgcmVnaW9uQmFja2VuZCgpOiBJVmlld2VyQmFja2VuZCB7XG4gICAgcmV0dXJuIHRoaXMuc2xpY2VNb3VudGVkID8gdGhpcy5vc2QgOiB0aGlzLnJlbmRlcmVyKCk7XG4gIH1cblxuICAvLyBTeXN0ZW0gY2FwYWJpbGl0aWVzIGFyZSBQbG90bHkncyAodGhlIGZ1bGwtZmVhdHVyZWQgYmFja2VuZCkgc28gdGhlIFVJXG4gIC8vIGtlZXBzIG9mZmVyaW5nIGV2ZXJ5IHBsb3QgdHlwZSByZWdhcmRsZXNzIG9mIHdoaWNoIG9uZSBpcyBvbiBzY3JlZW4uXG4gIGdldCBjYXBhYmlsaXRpZXMoKTogVmlld2VyQ2FwYWJpbGl0aWVzIHtcbiAgICByZXR1cm4gdGhpcy5wbG90bHkuY2FwYWJpbGl0aWVzO1xuICB9XG5cbiAgLy8g4pSA4pSAIHJlbmRlciAvIHZpZXdwb3J0IOKGkiBhY3RpdmUgcmVuZGVyZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIGFzeW5jIGxvYWQoaW1hZ2VJbmZvOiBJSW1hZ2VJbmZvLCB6SW5kZXg6IG51bWJlciwgc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPExvYWRlZEltYWdlPiB7XG4gICAgLy8gQSBzdGFjayBjYW4gb3BlbiBhd2F5IGZyb20gc2xpY2UgMCAoYGluaXRpYWxaSW5kZXhgIOKAlCBhIHZvbHVtZSBvcGVuc1xuICAgIC8vIG1pZC1zcGVjaW1lbiksIGFuZCB0aGF0IGFycml2ZXMgaGVyZSByYXRoZXIgdGhhbiB0aHJvdWdoIHNldFpJbmRleC5cbiAgICB0aGlzLmN1cnJlbnRaSW5kZXggPSB6SW5kZXg7XG4gICAgY29uc3QgYmFja2VuZCA9IHRoaXMuaW1hZ2VCYWNrZW5kKCk7XG4gICAgaWYgKGJhY2tlbmQgPT09IHRoaXMubmFwYXJpKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5uYXBhcmkubG9hZChpbWFnZUluZm8sIHpJbmRleCwgc2lnbmFsKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBBYm9ydGVkOiBub2JvZHkgd2FudHMgdGhpcyBpbWFnZSBhbnkgbW9yZSwgc28gZG9uJ3QgZ28gb24gdG8gbG9hZCBpdCBlbHNld2hlcmUuXG4gICAgICAgIGlmIChzaWduYWw/LmFib3J0ZWQpIHRocm93IGVycjtcbiAgICAgICAgdGhpcy5uYXBhcmlGZWxsQmFjayA9IHRydWU7XG4gICAgICAgIC8vIE1pcnJvciBpbWFnZUJhY2tlbmQoKSdzIGZhbGxiYWNrIHNvIGxvYWQgKyBwbG90IHBpY2sgdGhlIHNhbWUgYmFja2VuZDpcbiAgICAgICAgLy8gIC0gM0QgbmFwYXJpIHR5cGVzIGhhdmUgbm8gMkQgZmFsbGJhY2sg4oaSIHN0cmFpZ2h0IHRvIFBsb3RseS5cbiAgICAgICAgLy8gIC0gMkQgaW1hZ2Ug4oaSIE9TRCwgdGhlbiBQbG90bHkuXG4gICAgICAgIGlmICh0aGlzLmlzTmFwYXJpM2RUeXBlKHRoaXMuY3VycmVudFBsb3RUeXBlKSkge1xuICAgICAgICAgIGNvbnNvbGUud2FybignW3Zpc3VhbGl6ZXJdIG5hcGFyaS1qcyBsb2FkIGZhaWxlZCDigJQgZmFsbGluZyBiYWNrIHRvIFBsb3RseS4nLCBlcnIpO1xuICAgICAgICAgIHJldHVybiB0aGlzLnBsb3RseS5sb2FkKGltYWdlSW5mbywgekluZGV4LCBzaWduYWwpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUud2FybignW3Zpc3VhbGl6ZXJdIG5hcGFyaS1qcyBsb2FkIGZhaWxlZCDigJQgZmFsbGluZyBiYWNrIHRvIE9wZW5TZWFkcmFnb24uJywgZXJyKTtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9hZFZpYU9zZFRoZW5QbG90bHkoaW1hZ2VJbmZvLCB6SW5kZXgsIHNpZ25hbCk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChiYWNrZW5kID09PSB0aGlzLm9zZCkge1xuICAgICAgcmV0dXJuIHRoaXMubG9hZFZpYU9zZFRoZW5QbG90bHkoaW1hZ2VJbmZvLCB6SW5kZXgsIHNpZ25hbCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnBsb3RseS5sb2FkKGltYWdlSW5mbywgekluZGV4LCBzaWduYWwpO1xuICB9XG5cbiAgLyoqIFRyeSBPU0Q7IG9uIGZhaWx1cmUgZmFsbCBiYWNrIHRvIFBsb3RseSBmb3IgdGhpcyBpbWFnZSAobm90IHBlcm1hbmVudCDigJQgc2VlIHJlc2V0KCkpLiAqL1xuICBwcml2YXRlIGFzeW5jIGxvYWRWaWFPc2RUaGVuUGxvdGx5KFxuICAgIGltYWdlSW5mbzogSUltYWdlSW5mbyxcbiAgICB6SW5kZXg6IG51bWJlcixcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTxMb2FkZWRJbWFnZT4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5vc2QubG9hZChpbWFnZUluZm8sIHpJbmRleCwgc2lnbmFsKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChzaWduYWw/LmFib3J0ZWQpIHRocm93IGVycjtcbiAgICAgIGNvbnNvbGUud2FybignW3Zpc3VhbGl6ZXJdIE9wZW5TZWFkcmFnb24gbG9hZCBmYWlsZWQg4oCUIGZhbGxpbmcgYmFjayB0byBQbG90bHkgZm9yIHRoaXMgaW1hZ2UuJywgZXJyKTtcbiAgICAgIHRoaXMub3NkRmVsbEJhY2sgPSB0cnVlO1xuICAgICAgcmV0dXJuIHRoaXMucGxvdGx5LmxvYWQoaW1hZ2VJbmZvLCB6SW5kZXgsIHNpZ25hbCk7XG4gICAgfVxuICB9XG4gIHBsb3QoXG4gICAgcGxvdERpdjogc3RyaW5nLFxuICAgIGltYWdlTG9hZGVkOiB1bmtub3duLFxuICAgIGltYWdlSW5mbzogSUltYWdlSW5mbyxcbiAgICBzY3JlZW5IZWlnaHQ6IG51bWJlcixcbiAgICBwbG90VHlwZTogUGxvdFR5cGUsXG4gICAgaW5QbGFjZT86IGJvb2xlYW4sXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHRoaXMuY3VycmVudFBsb3RUeXBlID0gcGxvdFR5cGU7XG4gICAgdGhpcy52b2x1bWVWaWV3JC5uZXh0KGlzTmFwYXJpVm9sdW1lKHBsb3RUeXBlKSB8fCBpc05hcGFyaUlzb3N1cmZhY2UocGxvdFR5cGUpKTtcbiAgICB0aGlzLnBsb3R0ZWRGaWxlTmFtZSA9IGltYWdlSW5mbz8uZmlsZU5hbWU7XG4gICAgdGhpcy5wbG90dGVkSW5mbyA9IGltYWdlSW5mbyA/PyBudWxsO1xuICAgIHRoaXMucGxvdHRlZEhlaWdodCA9IHNjcmVlbkhlaWdodDtcbiAgICAvLyBUaGUgc2xpY2UgcGFuZSBiZWxvbmdzIHRvIHRoZSB2b2x1bWUgdmlldzogYW5vdGhlciBwbG90IHR5cGUgdGFrZXMgaXQgZG93biAoT1NEIG1heSBiZVxuICAgIC8vIGFib3V0IHRvIGRyYXcgdGhlIG1haW4gdmlldywgd2hpY2ggbXVzdCBub3QgZmluZCB0aGUgcGFuZSdzIHZpZXdlciBzdGlsbCBtb3VudGVkKS5cbiAgICBpZiAoIXRoaXMudm9sdW1lVmlldyQudmFsdWUpIHRoaXMudW5tb3VudFNsaWNlKCk7XG4gICAgLy8gUmVnaW9uIHN1cmZhY2VzIGJlbG9uZyB0byB0aGUgaW1hZ2UgdGhleSB3ZXJlIGJ1aWx0IGZyb206IGFub3RoZXIgaW1hZ2UgZHJvcHMgdGhlbS5cbiAgICBpZiAodGhpcy5jbGFzc2VzM2QkLnZhbHVlLmxlbmd0aCAmJiB0aGlzLnBsb3R0ZWRGaWxlTmFtZSAhPT0gdGhpcy5jbGFzc2VzM2RJbWFnZSkgdGhpcy5jbGVhclJlZ2lvbkNsYXNzZXMzZCgpO1xuICAgIHRoaXMucGxvdERpdiA9IHBsb3REaXY7XG4gICAgLy8gQXBwbHkgdGhlIHBlci1pbWFnZSByZWdpb24gY2FjaGUgKHNuYXBzaG90IG9sZCByZWdpb25zLCByZXN0b3JlIHRoZSBuZXdcbiAgICAvLyBpbWFnZSdzLCBjbGVhciBzZWxlY3Rpb24pIGZvciB3aGljaGV2ZXIgYmFja2VuZCByZW5kZXJzIOKAlCBQbG90bHkgZG9lc1xuICAgIC8vIHRoaXMgaW5zaWRlIGl0cyBvd24gcGxvdCgpLCBidXQgT1NEIGRvZXNuJ3QsIHNvIGRyaXZlIGl0IGhlcmUuIElkZW1wb3RlbnRcbiAgICAvLyBmb3IgdGhlIHNhbWUgaW1hZ2UsIHNvIGl0J3Mgc2FmZSB0byBjYWxsIG9uIGV2ZXJ5IChyZSlwbG90LlxuICAgIHRoaXMucGxvdGx5LnNldEFjdGl2ZUltYWdlKGltYWdlSW5mbyk7XG4gICAgY29uc3QgbmV4dCA9IHRoaXMuaW1hZ2VCYWNrZW5kKCk7XG4gICAgLy8gQm90aCBiYWNrZW5kcyBzaGFyZSB0aGUgc2FtZSBkaXYg4oCUIHRlYXIgZG93biB0aGUgb3V0Z29pbmcgb25lIG9uIHN3aXRjaC5cbiAgICAvLyBQbG90bHkgbXVzdCBiZSAqcHVyZ2VkKiAobm90IHJlc2V0LCB3aGljaCByZS1kcmF3cyBlbXB0eSBheGVzKSBiZWZvcmUgT1NEXG4gICAgLy8gdGFrZXMgdGhlIGRpdi5cbiAgICBpZiAodGhpcy5sYXN0UmVuZGVyZWQgJiYgdGhpcy5sYXN0UmVuZGVyZWQgIT09IG5leHQpIHtcbiAgICAgIGlmICh0aGlzLmxhc3RSZW5kZXJlZCA9PT0gdGhpcy5wbG90bHkpIHRoaXMucGxvdGx5LnB1cmdlUGxvdCgpO1xuICAgICAgZWxzZSB0aGlzLmxhc3RSZW5kZXJlZC5yZXNldCgpO1xuICAgIH1cbiAgICB0aGlzLmxhc3RSZW5kZXJlZCA9IG5leHQ7XG4gICAgY29uc3QgcGxvdHRlZCA9IG5leHQucGxvdChwbG90RGl2LCBpbWFnZUxvYWRlZCwgaW1hZ2VJbmZvLCBzY3JlZW5IZWlnaHQsIHBsb3RUeXBlLCBpblBsYWNlKTtcbiAgICBpZiAoIXRoaXMuc2xpY2VEaXYgfHwgIXRoaXMudm9sdW1lVmlldyQudmFsdWUpIHJldHVybiBwbG90dGVkO1xuICAgIC8vIFRoZSBzcGxpdCB2b2x1bWUgdmlldzogdGhlIHNsaWNlIHBhbmUgZm9sbG93cyB0aGUgaW1hZ2UgKGEgbmV3IG9uZSwgb3IgaXRzIHNoYXJwZXIgcGFzcykuXG4gICAgcmV0dXJuIHBsb3R0ZWQudGhlbigob2spID0+IHtcbiAgICAgIGlmIChvayAmJiAoIXRoaXMuc2xpY2VNb3VudGVkIHx8IHRoaXMuc2xpY2VGaWxlICE9PSBpbWFnZUluZm8/LmZpbGVOYW1lIHx8IGluUGxhY2UpKSB7XG4gICAgICAgIHZvaWQgdGhpcy5tb3VudFNsaWNlKCEhaW5QbGFjZSAmJiB0aGlzLnNsaWNlTW91bnRlZCAmJiB0aGlzLnNsaWNlRmlsZSA9PT0gaW1hZ2VJbmZvPy5maWxlTmFtZSk7XG4gICAgICB9XG4gICAgICAvLyBUaGUgdm9sdW1lIHdhcyBhc3NlbWJsZWQgYWdhaW4gKGFub3RoZXIgaW1hZ2UsIG9yIHJlc29sdXRpb24pOiBjdXQgdGhlIHNlY3Rpb25zIGZyb20gaXQuXG4gICAgICBpZiAob2spIHRoaXMuc2VjdGlvbnMuc2NoZWR1bGUoKTtcbiAgICAgIHJldHVybiBvaztcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdCB0aGUgdm9sdW1lIHZpZXc6IHNob3cgdGhlIHNsaWNlIGJlaW5nIGVkaXRlZCBpbiBgZGl2YCAoT3BlblNlYWRyYWdvbiwgd2l0aCBldmVyeSByZWdpb25cbiAgICogdG9vbCkgYmVzaWRlIHRoZSAzRCB2aWV3LCBvciBzdG9wIChudWxsKS4gS2VwdCBhY3Jvc3MgcmUtcGxvdHMgb2YgYSB2b2x1bWUgdmlldzsgYW5vdGhlciBwbG90XG4gICAqIHR5cGUgdGFrZXMgdGhlIHBhbmUgZG93biBhbmQgYSB2b2x1bWUgdmlldyBicmluZ3MgaXQgYmFjay4gUmVzb2x2ZXMgd2hldGhlciB0aGUgcGFuZSBzaG93cy5cbiAgICovXG4gIGFzeW5jIHNldFNsaWNlRWRpdG9yKGRpdjogc3RyaW5nIHwgbnVsbCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHRoaXMuc2xpY2VEaXYgPSBkaXY7XG4gICAgaWYgKHRoaXMuc2xpY2VFZGl0b3IkLnZhbHVlICE9PSAhIWRpdikgdGhpcy5zbGljZUVkaXRvciQubmV4dCghIWRpdik7XG4gICAgaWYgKCFkaXYpIHtcbiAgICAgIHRoaXMudW5tb3VudFNsaWNlKCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm1vdW50U2xpY2UoZmFsc2UpO1xuICB9XG5cbiAgLyoqIE1vdW50IChvciByZWZyZXNoIGluIHBsYWNlKSBPU0QgaW4gdGhlIHNsaWNlIHBhbmUgb24gdGhlIGRpc3BsYXllZCBzbGljZS4gKi9cbiAgcHJpdmF0ZSBhc3luYyBtb3VudFNsaWNlKGluUGxhY2U6IGJvb2xlYW4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBkaXYgPSB0aGlzLnNsaWNlRGl2O1xuICAgIGNvbnN0IGluZm8gPSB0aGlzLnBsb3R0ZWRJbmZvO1xuICAgIGlmICghZGl2IHx8ICFpbmZvPy51cmxzPy5sZW5ndGggfHwgIXRoaXMudm9sdW1lVmlldyQudmFsdWUpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCByZXF1ZXN0ID0gKyt0aGlzLnNsaWNlUmVxdWVzdDtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbG9hZGVkID0gYXdhaXQgdGhpcy5vc2QubG9hZChpbmZvLCB0aGlzLmN1cnJlbnRaSW5kZXgpO1xuICAgICAgaWYgKHJlcXVlc3QgIT09IHRoaXMuc2xpY2VSZXF1ZXN0KSByZXR1cm4gZmFsc2U7XG4gICAgICBjb25zdCBvayA9IGF3YWl0IHRoaXMub3NkLnBsb3QoZGl2LCBsb2FkZWQsIGluZm8sIHRoaXMucGxvdHRlZEhlaWdodCwgUGxvdFR5cGUuSU1BR0UsIGluUGxhY2UpO1xuICAgICAgaWYgKHJlcXVlc3QgIT09IHRoaXMuc2xpY2VSZXF1ZXN0KSByZXR1cm4gZmFsc2U7XG4gICAgICB0aGlzLnNsaWNlTW91bnRlZCA9IG9rO1xuICAgICAgdGhpcy5zbGljZUZpbGUgPSBpbmZvLmZpbGVOYW1lO1xuICAgICAgaWYgKG9rKSB7XG4gICAgICAgIC8vIFRoZSBzbGljZSBtYXkgaGF2ZSBtb3ZlZCB3aGlsZSB0aGUgcGFuZSBsb2FkZWQuXG4gICAgICAgIHRoaXMub3NkLnNldFpJbmRleCh0aGlzLmN1cnJlbnRaSW5kZXgpO1xuICAgICAgICB0aGlzLnRyYWNrTGl2ZUNsYXNzZXMoKTtcbiAgICAgICAgdGhpcy5zZWN0aW9ucy5zdGFydCgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9rO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKHJlcXVlc3QgPT09IHRoaXMuc2xpY2VSZXF1ZXN0KVxuICAgICAgICBjb25zb2xlLndhcm4oJ1t2aXN1YWxpemVyXSBUaGUgc2xpY2UgcGFuZSBjb3VsZCBub3Qgc2hvdyB0aGUgaW1hZ2UuJywgZXJyKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKiogVGFrZSB0aGUgc2xpY2UgcGFuZSdzIHZpZXdlciBkb3duICh0aGUgc3BsaXQgc3RheXMgd2FudGVkIHdoaWxlIHtAbGluayBzbGljZURpdn0gaXMgc2V0KS4gKi9cbiAgcHJpdmF0ZSB1bm1vdW50U2xpY2UoKTogdm9pZCB7XG4gICAgdGhpcy5zbGljZVJlcXVlc3QrKztcbiAgICBpZiAodGhpcy5zbGljZU1vdW50ZWQpIHtcbiAgICAgIHRoaXMub3NkLnJlc2V0KCk7XG4gICAgICB0aGlzLnNlY3Rpb25zLnN0b3AoKTtcbiAgICB9XG4gICAgdGhpcy5zbGljZU1vdW50ZWQgPSBmYWxzZTtcbiAgICB0aGlzLnNsaWNlRmlsZSA9IHVuZGVmaW5lZDtcbiAgfVxuICByZWxvYWRBbmRQbG90KCk6IHZvaWQge1xuICAgIHRoaXMucGxvdGx5LnJlbG9hZEFuZFBsb3QoKTtcbiAgfVxuICByZXNldCgpOiB2b2lkIHtcbiAgICAvLyBTdGFydCBvZiBhIHJlbmRlciBjeWNsZTogcmUtZW5hYmxlIG5hcGFyaS1qcy9PU0QgYXR0ZW1wdHMgKGNsZWFyIGFueSBwcmlvclxuICAgIC8vIHBlci1pbWFnZSBmYWxsYmFjaykgYW5kIHRlYXIgZG93biB3aGF0ZXZlcidzIG9uIHNjcmVlbi5cbiAgICB0aGlzLm9zZEZlbGxCYWNrID0gZmFsc2U7XG4gICAgdGhpcy5uYXBhcmlGZWxsQmFjayA9IGZhbHNlO1xuICAgIHRoaXMucmVuZGVyZXIoKS5yZXNldCgpO1xuICB9XG4gIHJlbGF5b3V0KHRydWVJbWFnZVNpemU/OiBudW1iZXJbXSk6IHZvaWQge1xuICAgIHRoaXMucmVuZGVyZXIoKS5yZWxheW91dCh0cnVlSW1hZ2VTaXplKTtcbiAgfVxuICByZXNldEF4ZXMoKTogdm9pZCB7XG4gICAgdGhpcy5yZW5kZXJlcigpLnJlc2V0QXhlcygpO1xuICB9XG4gIGZpdFRvVmlldygpOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlcmVyKCkuZml0VG9WaWV3KCk7XG4gIH1cbiAgLyoqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgZml0VG9WaWV3fS4gKi9cbiAgYXV0b3NjYWxlKCk6IHZvaWQge1xuICAgIHRoaXMuZml0VG9WaWV3KCk7XG4gIH1cbiAgem9vbUluKCk6IHZvaWQge1xuICAgIHRoaXMucmVuZGVyZXIoKS56b29tSW4oKTtcbiAgfVxuICB6b29tT3V0KCk6IHZvaWQge1xuICAgIHRoaXMucmVuZGVyZXIoKS56b29tT3V0KCk7XG4gIH1cbiAgc2V0RHJhZ01vZGUobW9kZTogc3RyaW5nIHwgZmFsc2UpOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlcmVyKCkuc2V0RHJhZ01vZGUobW9kZSk7XG4gICAgaWYgKHRoaXMuc2xpY2VNb3VudGVkKSB0aGlzLm9zZC5zZXREcmFnTW9kZShtb2RlKTtcbiAgfVxuICAvKiogRXZlcnkgYmFja2VuZCwgb24gc2NyZWVuIG9yIG5vdC4gKi9cbiAgcHJpdmF0ZSBiYWNrZW5kcygpOiBJVmlld2VyQmFja2VuZFtdIHtcbiAgICByZXR1cm4gW3RoaXMucGxvdGx5LCB0aGlzLm9zZCwgdGhpcy5uYXBhcmldO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBuYXZpZ2F0b3IgLyBzbW9vdGhpbmcgb3B0aW9ucywgYXBwbGllZCB0byBFVkVSWSBiYWNrZW5kIHRoYXQgaGFzIHRoZW0gKG5vdFxuICAgKiBqdXN0IHRoZSBhY3RpdmUgcmVuZGVyZXIpOiBjb25zdW1lcnMgc2V0IHRoZW0gYmVmb3JlIHRoZSBmaXJzdCByZW5kZXIsIHdoZW5cbiAgICogYHJlbmRlcmVyKClgIGlzIHN0aWxsIHRoZSBQbG90bHkgZGVmYXVsdCwgYW5kIE9TRC9uYXBhcmktanMgbXVzdCByZWNlaXZlIHRoZW1cbiAgICogdG8gaG9ub3VyIHRoZW0gYXQgdmlld2VyIGNyZWF0aW9uLlxuICAgKi9cbiAgZ2V0T3NkVmlld09wdGlvbnMoKTogSU9zZFZpZXdPcHRpb25zIHtcbiAgICByZXR1cm4gdGhpcy52aWV3T3B0aW9ucztcbiAgfVxuICBwcml2YXRlIHJlYWRvbmx5IHZpZXdPcHRpb25zOiBJT3NkVmlld09wdGlvbnMgPSB7XG4gICAgc2V0TmF2aWdhdG9yVmlzaWJsZTogKHZpc2libGUpID0+IHtcbiAgICAgIGZvciAoY29uc3QgYiBvZiB0aGlzLmJhY2tlbmRzKCkpIGIuZ2V0T3NkVmlld09wdGlvbnMoKT8uc2V0TmF2aWdhdG9yVmlzaWJsZSh2aXNpYmxlKTtcbiAgICB9LFxuICAgIHNldEltYWdlU21vb3RoaW5nRW5hYmxlZDogKGVuYWJsZWQpID0+IHtcbiAgICAgIGZvciAoY29uc3QgYiBvZiB0aGlzLmJhY2tlbmRzKCkpIGIuZ2V0T3NkVmlld09wdGlvbnMoKT8uc2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKGVuYWJsZWQpO1xuICAgIH0sXG4gIH07XG4gIC8qKiBAZGVwcmVjYXRlZCBVc2UgYGdldE9zZFZpZXdPcHRpb25zKCkuc2V0TmF2aWdhdG9yVmlzaWJsZSgpYC4gKi9cbiAgc2V0TmF2aWdhdG9yVmlzaWJsZSh2aXNpYmxlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy52aWV3T3B0aW9ucy5zZXROYXZpZ2F0b3JWaXNpYmxlKHZpc2libGUpO1xuICB9XG4gIC8qKiBAZGVwcmVjYXRlZCBVc2UgYGdldE9zZFZpZXdPcHRpb25zKCkuc2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKClgLiAqL1xuICBzZXRJbWFnZVNtb290aGluZ0VuYWJsZWQoZW5hYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMudmlld09wdGlvbnMuc2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKGVuYWJsZWQpO1xuICB9XG4gIHNldFNob3dTdGFjayhzaG93c3RhY2s6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlcmVyKCkuc2V0U2hvd1N0YWNrKHNob3dzdGFjayk7XG4gIH1cbiAgc2V0WkluZGV4KHpJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50WkluZGV4ID0gekluZGV4O1xuICAgIHRoaXMucmVuZGVyZXIoKS5zZXRaSW5kZXgoekluZGV4KTtcbiAgICBpZiAodGhpcy5zbGljZU1vdW50ZWQpIHtcbiAgICAgIHRoaXMub3NkLnNldFpJbmRleCh6SW5kZXgpO1xuICAgICAgdGhpcy5zZWN0aW9ucy5zY2hlZHVsZSgpO1xuICAgIH1cbiAgfVxuICBnZXRUcnVlSW1hZ2VTaXplKCk6IHsgd2lkdGg6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfSB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0VHJ1ZUltYWdlU2l6ZSgpO1xuICB9XG4gIGdldEN1cnJlbnRJbWFnZSgpOiBQcm9taXNlPEltYWdlIHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0Q3VycmVudEltYWdlKCk7XG4gIH1cbiAgZ2V0RGlzcGxheWVkUGl4ZWxEYXRhKCk6IFBpeGVsRGF0YSB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0RGlzcGxheWVkUGl4ZWxEYXRhKCk7XG4gIH1cbiAgZ2V0RGlzcGxheWVkU291cmNlUmVjdCgpOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyOyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXREaXNwbGF5ZWRTb3VyY2VSZWN0KCk7XG4gIH1cbiAgZG93bmxvYWRJbWFnZSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlcmVyKCkuZG93bmxvYWRJbWFnZSgpO1xuICB9XG4gIGV4cG9ydENvbXBvc2l0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlcmVyKCkuZXhwb3J0Q29tcG9zaXRlKCk7XG4gIH1cblxuICBzZXRQbG90VHlwZShwbG90VHlwZTogUGxvdFR5cGUpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRQbG90VHlwZSA9IHBsb3RUeXBlO1xuICAgIHRoaXMudm9sdW1lVmlldyQubmV4dChpc05hcGFyaVZvbHVtZShwbG90VHlwZSkgfHwgaXNOYXBhcmlJc29zdXJmYWNlKHBsb3RUeXBlKSk7XG4gICAgdGhpcy5wbG90bHkuc2V0UGxvdFR5cGUocGxvdFR5cGUpO1xuICB9XG4gIC8qKiBAZGVwcmVjYXRlZCBVc2UgYGdldFN1cmZhY2UzZENvbnRyb2xzKClgLiAqL1xuICBzZXRTdXJmYWNlRHJhZ01vZGUobW9kZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5nZXRTdXJmYWNlM2RDb250cm9scygpPy5zZXRTdXJmYWNlRHJhZ01vZGUobW9kZSk7XG4gIH1cbiAgLyoqIEBkZXByZWNhdGVkIFVzZSBgZ2V0U3VyZmFjZTNkQ29udHJvbHMoKWAuICovXG4gIHJlc2V0U3VyZmFjZUNhbWVyYSgpOiB2b2lkIHtcbiAgICB0aGlzLmdldFN1cmZhY2UzZENvbnRyb2xzKCk/LnJlc2V0U3VyZmFjZUNhbWVyYSgpO1xuICB9XG4gIC8qKiBUaGUgM0QgZGVjaW1hdGUgZmFjdG9yIG9mIHRoZSBiYWNrZW5kIG9uIHNjcmVlbiAobmFwYXJpLWpzKSwgZWxzZSBudWxsLiAqL1xuICBnZXRWb2x1bWVSZXNvbHV0aW9uKCk6IElWb2x1bWVSZXNvbHV0aW9uIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXRWb2x1bWVSZXNvbHV0aW9uKCk7XG4gIH1cbiAgLyoqIEBkZXByZWNhdGVkIFVzZSBgZ2V0Vm9sdW1lUmVzb2x1dGlvbigpPy5zZXQoKWAuICovXG4gIHNldFJlc29sdXRpb25TY2FsZShzY2FsZTogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5nZXRWb2x1bWVSZXNvbHV0aW9uKCk/LnNldChzY2FsZSk7XG4gIH1cbiAgLyoqIEBkZXByZWNhdGVkIFVzZSBgZ2V0Vm9sdW1lUmVzb2x1dGlvbigpPy5nZXQoKWAuICovXG4gIGdldFJlc29sdXRpb25TY2FsZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmdldFZvbHVtZVJlc29sdXRpb24oKT8uZ2V0KCkgPz8gMTtcbiAgfVxuICAvKiogVGhlIHZpZXdwb3J0IG9mIHRoZSBiYWNrZW5kIG9uIHNjcmVlbiwgZm9yIGEgY29udHJpYnV0ZWQgcGxvdCBtb2RlLiBOdWxsXG4gICAqICB3aGVuIHRoYXQgYmFja2VuZCBjYW5ub3QgcHJvdmlkZSBvbmUgKGUuZy4gT1NEIGZlbGwgYmFjayB0byBQbG90bHkpLiAqL1xuICBnZXRQbG90TW9kZVZpZXdwb3J0KCk6IFBsb3RNb2RlVmlld3BvcnQgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldFBsb3RNb2RlVmlld3BvcnQ/LigpID8/IG51bGw7XG4gIH1cbiAgZ2V0UGxvdFR5cGVEZXNjcmlwdG9ycygpOiBQbG90VHlwZURlc2NyaXB0b3JbXSB7XG4gICAgLy8gUGxvdGx5IGVudW1lcmF0ZXMgdGhlIGZ1bGwgUExPVF9UWVBFX0RFU0NSSVBUT1JTIG1hcCwgd2hpY2ggYWxyZWFkeSBpbmNsdWRlcyB0aGVcbiAgICAvLyBuYXBhcmktanMgV2ViR1BVIHR5cGVzIChqaXQtdWkjMTAyKSDigJQgc28gdGhpcyBzaW5nbGUgc291cmNlIGNvdmVycyB0aGVtIChubyBkdXBsaWNhdGVzKS5cbiAgICByZXR1cm4gdGhpcy5wbG90bHkuZ2V0UGxvdFR5cGVEZXNjcmlwdG9ycygpO1xuICB9XG5cbiAgLy8g4pSA4pSAIGxvbmctbGl2ZWQgb2JzZXJ2YWJsZXMgKyBzdGFjayBmbGFncyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgc2V0U3RhY2tMb2FkaW5nKGI6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnBsb3RseS5zZXRTdGFja0xvYWRpbmcoYik7XG4gIH1cbiAgLy8gQ2FuY2VsIGluLWZsaWdodCBsb2FkaW5nIG9uIGV2ZXJ5IGJhY2tlbmQg4oCUIHRoZSB1c2VyJ3MgQ2FuY2VsIHNob3VsZG4ndCBkZXBlbmQgb24gd2hpY2ggb25lIGlzXG4gIC8vIGFjdGl2ZS4gT25seSBiYWNrZW5kcyB0aGF0IHN0cmVhbSBmcmFtZXMgKG5hcGFyaS1qcykgZG8gcmVhbCB3b3JrOyB0aGUgcmVzdCBuby1vcC4gVGhlIGNvbmNyZXRlXG4gIC8vIGJhY2tlbmQgY2xhc3NlcyBkb24ndCBhbGwgZGVjbGFyZSB0aGUgb3B0aW9uYWwgY29udHJhY3QgbWV0aG9kLCBzbyBjYWxsIGl0IHZpYSBJVmlld2VyQmFja2VuZC5cbiAgY2FuY2VsTG9hZGluZygpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGJhY2tlbmQgb2YgW3RoaXMucGxvdGx5LCB0aGlzLm9zZCwgdGhpcy5uYXBhcmldIGFzIElWaWV3ZXJCYWNrZW5kW10pIHtcbiAgICAgIGJhY2tlbmQuY2FuY2VsTG9hZGluZz8uKCk7XG4gICAgfVxuICB9XG4gIC8vIExvYWRpbmcgc3RhdGUgaXMgc3VyZmFjZWQgZnJvbSB3aGljaGV2ZXIgYmFja2VuZCBpcyBkb2luZyB0aGUgd29yazogT1NEIGFuZCBuYXBhcmktanMgKHZvbHVtZVxuICAvLyBhc3NlbWJseSkgZHJpdmUgdGhlaXIgb3duIHN1YmplY3RzLCBzbyBtZXJnZSBhbGwgdGhyZWUgaW50byBvbmUgc3RhYmxlIHN0cmVhbSB0aGUgaG9zdFxuICAvLyBzdWJzY3JpYmVzIHRvIG9uY2UuIChQcmV2aW91c2x5IGhhcmRjb2RlZCB0byBQbG90bHksIHNvIG5hcGFyaS9PU0QgcHJvZ3Jlc3MgbmV2ZXIgc2hvd2VkLilcbiAgaXNTdGFja0xvYWRpbmcoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIGNvbWJpbmVMYXRlc3QoW1xuICAgICAgdGhpcy5wbG90bHkuaXNTdGFja0xvYWRpbmcoKSxcbiAgICAgIHRoaXMub3NkLmlzU3RhY2tMb2FkaW5nKCksXG4gICAgICB0aGlzLm5hcGFyaS5pc1N0YWNrTG9hZGluZygpLFxuICAgIF0pLnBpcGUobWFwKChmbGFncykgPT4gZmxhZ3Muc29tZShCb29sZWFuKSkpO1xuICB9XG4gIGdldFN0YWNrTG9hZGluZ1Byb2dyZXNzKCk6IE9ic2VydmFibGU8bnVtYmVyPiB7XG4gICAgLy8gUmVwb3J0IHRoZSBwcm9ncmVzcyBvZiB3aGljaGV2ZXIgYmFja2VuZCBpcyBBQ1RJVkVMWSBsb2FkaW5nIChtYXggYWNyb3NzIGFjdGl2ZSBvbmVzKS4gQSBwbGFpblxuICAgIC8vIG1lcmdlIGxldCBhbiBpZGxlIGJhY2tlbmQncyBzdGFsZSB2YWx1ZSB3aW4gdGhlIHN0cmVhbSBvbiBhIHJlLWxvYWQg4oCUIGxlYXZpbmcgdGhlIGJhciBiZWxvdyB0aGVcbiAgICAvLyBhY3RpdmUgYmFja2VuZCdzIHJlYWwgcHJvZ3Jlc3MgKGUuZy4gc3R1Y2sgfuKFkyB3aGlsZSB0aGUgJSByZWFkIDEwMCkuIEdhdGluZyBieSB0aGUgbG9hZGluZyBmbGFnXG4gICAgLy8gaWdub3JlcyBpZGxlIGJhY2tlbmRzLCBzbyB0aGUgYmFyIHRyYWNrcyB0aGUgb25lIGRvaW5nIHRoZSB3b3JrIGFuZCByZWFjaGVzIDEwMCUuXG4gICAgY29uc3QgdHJhY2sgPSAodjogSVZpZXdlckJhY2tlbmQpOiBPYnNlcnZhYmxlPFtudW1iZXIsIGJvb2xlYW5dPiA9PlxuICAgICAgY29tYmluZUxhdGVzdChbdi5nZXRTdGFja0xvYWRpbmdQcm9ncmVzcygpLCB2LmlzU3RhY2tMb2FkaW5nKCldKTtcbiAgICByZXR1cm4gY29tYmluZUxhdGVzdChbdHJhY2sodGhpcy5wbG90bHkpLCB0cmFjayh0aGlzLm9zZCksIHRyYWNrKHRoaXMubmFwYXJpKV0pLnBpcGUoXG4gICAgICBtYXAoKHBhaXJzKSA9PiB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZSA9IHBhaXJzLmZpbHRlcigoWywgbG9hZGluZ10pID0+IGxvYWRpbmcpLm1hcCgoW3BdKSA9PiBwKTtcbiAgICAgICAgcmV0dXJuIGFjdGl2ZS5sZW5ndGggPyBNYXRoLm1heCguLi5hY3RpdmUpIDogMDtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cbiAgLy8gRXZlcnkgYmFja2VuZCBmaXRzIHRvIHZpZXcgb24gaXRzIG93biAoUGxvdGx5J3MgYXV0b3NjYWxlLCBPU0QncyBnb0hvbWUsIG5hcGFyaSdzIGNhbWVyYVxuICAvLyBmaXQpIGFuZCBlYWNoIGVtaXRzIGZyb20gaXRzIG93biBzdWJqZWN0LCBzbyBtZXJnZSBhbGwgdGhyZWU6IGxpc3RlbmluZyB0byBQbG90bHkgYWxvbmVcbiAgLy8gbWlzc2VkIHRoZSBjb250ZXh0LW1lbnUgQXV0b3NjYWxlIG9uIHRoZSBJbWFnZSBhbmQgbmFwYXJpIHZpZXdzLlxuICBnZXRBdXRvc2NhbGVFdmVudCgpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gbWVyZ2UoXG4gICAgICB0aGlzLnBsb3RseS5nZXRBdXRvc2NhbGVFdmVudCgpLFxuICAgICAgdGhpcy5vc2QuZ2V0QXV0b3NjYWxlRXZlbnQoKSxcbiAgICAgIHRoaXMubmFwYXJpLmdldEF1dG9zY2FsZUV2ZW50KCksXG4gICAgKS5waXBlKG1hcCgoKSA9PiB1bmRlZmluZWQpKTtcbiAgfVxuICAvKiogVGhlIGxpbmUtUk9JIHByb2ZpbGVzOiBzYW1wbGVkIGJ5IHRoZSBiYWNrZW5kLW5ldXRyYWwgSW50ZW5zaXR5UHJvZmlsZVNlcnZpY2UuICovXG4gIGdldEludGVuc2l0eVByb2ZpbGUkKCk6IE9ic2VydmFibGU8SW50ZW5zaXR5UHJvZmlsZVtdPiB7XG4gICAgcmV0dXJuIHRoaXMuaW50ZW5zaXR5LmdldEludGVuc2l0eVByb2ZpbGUkKCk7XG4gIH1cbiAgLy8gVGhlIGludGVuc2l0eSBpbnNldCBpcyBhIFBsb3RseSBMSU5FIGNoYXJ0IOKAlCByZW5kZXIgaXQgdGhyb3VnaCBQbG90bHkgd2hpY2hldmVyXG4gIC8vIGJhY2tlbmQgZHJhd3MgdGhlIG1haW4gaW1hZ2UuXG4gIHJlbmRlckludGVuc2l0eUluc2V0KGRpdklkOiBzdHJpbmcsIHByb2ZpbGVzOiBJbnRlbnNpdHlQcm9maWxlW10pOiB2b2lkIHtcbiAgICB0aGlzLnBsb3RseS5yZW5kZXJJbnRlbnNpdHlJbnNldChkaXZJZCwgcHJvZmlsZXMpO1xuICB9XG5cbiAgLy8g4pSA4pSAIHJlZ2lvbnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIC8vIFJlZ2lvbiBzdGF0ZSBsaXZlcyBpbiB0aGUgc2hhcmVkIFJlZ2lvblN0b3JlLCBzbyBldmVyeSByZWFkIGFuZCB3cml0ZSBnb2VzXG4gIC8vIHN0cmFpZ2h0IHRvIGl0LiBFdmVyeSBiYWNrZW5kIGRyYXdzIGZyb20gdGhlIHN0b3JlJ3MgZXZlbnRzOiB0aGUgT1NEIGFuZFxuICAvLyBuYXBhcmktanMgb3ZlcmxheXMgYW5kIFBsb3RseSdzIHNoYXBlIHByb2plY3Rpb24gcmVkcmF3IG9uIGl0cyByZWdpb24tdXBkYXRlXG4gIC8vIGFuZCBzZWxlY3Rpb24gc3RyZWFtcywgYW5kIHRoZSBjYW52YXMgdG9vbHMgcmVzZXQgb24gZ2V0UmVnaW9uU2V0UmVwbGFjZWQkXG4gIC8vICh1bmRvLCByZWRvLCBhIHNsaWNlIHN3aXRjaCkuXG4gIHNldFJlZ2lvbnMoXG4gICAgcmVnaW9uczogUmVnaW9uW10sXG4gICAgc2hvd1JlZ2lvbkxhYmVsPzogYm9vbGVhbixcbiAgICBpc1JlZ2lvblNhdmVPbj86IGJvb2xlYW4sXG4gICAgZmlsbENvbG9yPzogc3RyaW5nLFxuICAgIGFwcGVuZD86IGJvb2xlYW4sXG4gICk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uU3RvcmUuc2V0UmVnaW9ucyhyZWdpb25zLCBzaG93UmVnaW9uTGFiZWwsIGlzUmVnaW9uU2F2ZU9uLCBmaWxsQ29sb3IsIGFwcGVuZCk7XG4gIH1cbiAgZ2V0UmVnaW9ucygpOiBSZWdpb25bXSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0UmVnaW9ucygpO1xuICB9XG4gIGdldFJlZ2lvblBvbHlnb25zKCk6IFBvbHlnb25bXSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0UmVnaW9uUG9seWdvbnMoKTtcbiAgfVxuICBnZXRSZWdpb25VcGRhdGVFdmVudCgpOiBPYnNlcnZhYmxlPFJlZ2lvbltdPiB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0UmVnaW9uVXBkYXRlRXZlbnQoKTtcbiAgfVxuICBzZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyhpbmRpY2VzOiBudW1iZXJbXSk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uU3RvcmUuc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoaW5kaWNlcyk7XG4gIH1cbiAgc2VsZWN0UmVnaW9uKHJlZ2lvbjogUmVnaW9uKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpb25TdG9yZS5zZWxlY3RSZWdpb24ocmVnaW9uKTtcbiAgfVxuICBnZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyQoKTogT2JzZXJ2YWJsZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0b3JlLmdldFNlbGVjdGVkU2hhcGVJbmRpY2VzJCgpO1xuICB9XG4gIGRlbGV0ZUFjdGl2ZVNoYXBlKCk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uU3RvcmUuZGVsZXRlQWN0aXZlU2hhcGUoKTtcbiAgfVxuICBnZXRTaG93U2hhcGVMYWJlbCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdG9yZS5nZXRTaG93U2hhcGVMYWJlbCgpO1xuICB9XG4gIGdldFNoYXBlQ29sb3IoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdG9yZS5nZXRTaGFwZUNvbG9yKCk7XG4gIH1cbiAgZ2V0RmlsbENvbG9yKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0RmlsbENvbG9yKCk7XG4gIH1cbiAgZ2V0Q2xhc3NpZmljYXRpb25Db2xvcnMoKTogTWFwPHN0cmluZywgc3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0Q2xhc3NpZmljYXRpb25Db2xvcnMoKTtcbiAgfVxuICBzZXRDbGFzc2lmaWNhdGlvbkNvbG9yKGxhYmVsOiBzdHJpbmcsIGNvbG9yOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JlLnNldENsYXNzaWZpY2F0aW9uQ29sb3IobGFiZWwsIGNvbG9yKTtcbiAgfVxuICAvLyBBbm5vdGF0aW9uLWNsYXNzIHByZXNldHMgbGl2ZSBpbiB0aGUgc2hhcmVkIFZpc3VhbGl6ZXJTdG9yZSAoYmFja2VuZC1uZXV0cmFsXG4gIC8vIHNlc3Npb24gc3RhdGUpLCBzbyByb3V0ZSBzdHJhaWdodCB0byBpdCByYXRoZXIgdGhhbiB0aHJvdWdoIHJlbmRlcmVyKCkuIChqaXQtdWkjNzApXG4gIGdldFByZXNldFNldCgpOiBQcmVzZXRTZXQge1xuICAgIHJldHVybiB0aGlzLnN0b3JlLmdldFByZXNldFNldCgpO1xuICB9XG4gIGdldFByZXNldFNldCQoKTogT2JzZXJ2YWJsZTxQcmVzZXRTZXQ+IHtcbiAgICByZXR1cm4gdGhpcy5zdG9yZS5nZXRQcmVzZXRTZXQkKCk7XG4gIH1cbiAgc2V0UHJlc2V0U2V0KHNldDogUHJlc2V0U2V0KTogdm9pZCB7XG4gICAgdGhpcy5zdG9yZS5zZXRQcmVzZXRTZXQoc2V0KTtcbiAgfVxuICB1cHNlcnRDbGFzcyhwcmVzZXQ6IENsYXNzUHJlc2V0KTogdm9pZCB7XG4gICAgdGhpcy5zdG9yZS51cHNlcnRDbGFzcyhwcmVzZXQpO1xuICB9XG4gIHJlbW92ZUNsYXNzKG5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuc3RvcmUucmVtb3ZlQ2xhc3MobmFtZSk7XG4gIH1cbiAgcmVzZXRQcmVzZXRzKCk6IHZvaWQge1xuICAgIHRoaXMuc3RvcmUucmVzZXRQcmVzZXRzKCk7XG4gIH1cbiAgdW5kbygpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvblN0b3JlLnVuZG8oKTtcbiAgfVxuICByZWRvKCk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uU3RvcmUucmVkbygpO1xuICB9XG4gIGNhblVuZG8oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuY2FuVW5kbygpO1xuICB9XG4gIGNhblJlZG8oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuY2FuUmVkbygpO1xuICB9XG4gIGdldENhblVuZG8kKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0b3JlLmdldENhblVuZG8kKCk7XG4gIH1cbiAgZ2V0Q2FuUmVkbyQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0Q2FuUmVkbyQoKTtcbiAgfVxuICByZXNldFVuZG9IaXN0b3J5KCk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uU3RvcmUucmVzZXRVbmRvSGlzdG9yeSgpO1xuICB9XG4gIGltcG9ydFJlZ2lvbnMoZ2VvSnNvblN0cjogc3RyaW5nKTogUmVnaW9uW10ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0b3JlLmltcG9ydFJlZ2lvbnMoZ2VvSnNvblN0cik7XG4gIH1cbiAgLyoqIERvd25sb2FkIGByZWdpb25zYCBhcyBHZW9KU09OLCBuYW1lZCBhZnRlciB0aGUgaW1hZ2UgbGFzdCBwbG90dGVkLiAqL1xuICBleHBvcnRSZWdpb25zKHJlZ2lvbnM6IFJlZ2lvbltdKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpb25TdG9yZS5leHBvcnRSZWdpb25zKHJlZ2lvbnMsIHRoaXMucGxvdHRlZEZpbGVOYW1lKTtcbiAgfVxuICBnZXRHZW9Kc29uU3RyaW5nKHJlZ2lvbnM6IFJlZ2lvbltdKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdG9yZS5nZXRHZW9Kc29uU3RyaW5nKHJlZ2lvbnMpO1xuICB9XG5cbiAgLyoqIEhvbGQgYSBsYXJnZSByZWdpb24gc2V0IGFzIGEgdGlsZWQgcmVnaW9uIHNvdXJjZSAoc2VlIFJlZ2lvblN0b3JlLmF0dGFjaFJlZ2lvblNvdXJjZSkuICovXG4gIGF0dGFjaFJlZ2lvblNvdXJjZShzb3VyY2U6IFJlZ2lvblNvdXJjZSB8IFJlZ2lvblNvdXJjZU9wZW5lciwgc2xpY2VzPzogUmVnaW9uU291cmNlU2xpY2VzKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpb25TdG9yZS5hdHRhY2hSZWdpb25Tb3VyY2Uoc291cmNlLCBzbGljZXMpO1xuICB9XG4gIGFzeW5jIGltcG9ydFJlZ2lvblNvdXJjZShnZW9Kc29uU3RyOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoZ2VvSnNvblN0ci5sZW5ndGggPCAodGhpcy5jb25maWc/LnJlZ2lvblNvdXJjZU1pbkNoYXJzID8/IFJFR0lPTl9TT1VSQ0VfTUlOX0NIQVJTKSkgcmV0dXJuIGZhbHNlO1xuICAgIGxldCBvcGVuZWQ6IFJlZ2lvblNvdXJjZSB8IG51bGwgPSBhd2FpdCBvcGVuR2VvSnNvblJlZ2lvblNvdXJjZShnZW9Kc29uU3RyKTtcbiAgICAvLyBUaGUgZmlyc3Qgb3BlbiBpcyB0aGUgb25lIGp1c3QgbWFkZTsgYSBzb3VyY2UgY2xvc2VkIHRvIHNhdmUgbWVtb3J5IHBhcnNlcyBhZ2Fpbi5cbiAgICB0aGlzLnJlZ2lvblN0b3JlLmF0dGFjaFJlZ2lvblNvdXJjZSgoKSA9PiB7XG4gICAgICBjb25zdCBzb3VyY2UgPSBvcGVuZWQ7XG4gICAgICBvcGVuZWQgPSBudWxsO1xuICAgICAgcmV0dXJuIHNvdXJjZSA/IFByb21pc2UucmVzb2x2ZShzb3VyY2UpIDogb3Blbkdlb0pzb25SZWdpb25Tb3VyY2UoZ2VvSnNvblN0cik7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgZHJvcFJlZ2lvblNvdXJjZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdG9yZS5kcm9wU2xpY2VSZWdpb25Tb3VyY2UoKTtcbiAgfVxuICBnZXRSZWdpb25Tb3VyY2VWaWV3JCgpOiBPYnNlcnZhYmxlPFJlZ2lvblNvdXJjZVZpZXcgfCBudWxsPiB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0UmVnaW9uU291cmNlVmlldyQoKTtcbiAgfVxuICBnZXRSZWdpb25Tb3VyY2VJbmRleChxdWVyeTogT21pdDxSZWdpb25JbmRleFF1ZXJ5LCAnZXhjbHVkZSc+KTogUHJvbWlzZTxSZWdpb25JbmRleFBhZ2U+IHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdG9yZS5nZXRSZWdpb25Tb3VyY2VJbmRleChxdWVyeSk7XG4gIH1cbiAgc2VsZWN0U291cmNlRmVhdHVyZXMoaWRzOiByZWFkb25seSBzdHJpbmdbXSwgYWRkaXRpdmU/OiBib29sZWFuKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0b3JlLnNlbGVjdFNvdXJjZUZlYXR1cmVzKGlkcywgYWRkaXRpdmUpO1xuICB9XG4gIGRlbGV0ZVNvdXJjZUZlYXR1cmVzKGlkczogcmVhZG9ubHkgc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvblN0b3JlLmRlbGV0ZVNvdXJjZUZlYXR1cmVzKGlkcyk7XG4gIH1cbiAgZ2V0UmVnaW9uU3R5bGUkKCk6IE9ic2VydmFibGU8UmVnaW9uU3R5bGU+IHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdG9yZS5nZXRSZWdpb25TdHlsZSQoKTtcbiAgfVxuICBzZXRSZWdpb25TdHlsZShwYXRjaDogUGFydGlhbDxSZWdpb25TdHlsZT4pOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvblN0b3JlLnNldFJlZ2lvblN0eWxlKHBhdGNoKTtcbiAgfVxuICAvLyDilIDilIAgUmVnaW9ucyBpbiAzRDogdGhlaXIgcmVjb25zdHJ1Y3Rpb25zIHNob3duIGluIHRoZSB2b2x1bWUgdmlldyDilIDilIDilIDilIDilIBcblxuICAvKiogV2hldGhlciBhIG5hcGFyaSB2b2x1bWUgKG9yIGlzb3N1cmZhY2UpIHZpZXcgaXMgb24gc2NyZWVuOiByZWdpb25zIGNhbiBiZSBzaG93biBpbiAzRC4gKi9cbiAgZ2V0Vm9sdW1lVmlldyQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMudm9sdW1lVmlldyQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgdm9sdW1lIHZpZXcncyBzbGljZSBwYW5lIGlzIHdhbnRlZCAoaXQgc2hvd3Mgd2hpbGUgYSB2b2x1bWUgdmlldyBpcyBvbiBzY3JlZW4pLiAqL1xuICBnZXRTbGljZUVkaXRvciQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuc2xpY2VFZGl0b3IkLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqIFdoZXRoZXIgdGhlIHZvbHVtZSB2aWV3IGRyYXdzIHRoZSByZWdpb24gcmVjb25zdHJ1Y3Rpb25zIHRocm91Z2ggdGhlIHZvbHVtZS4gKi9cbiAgZ2V0UmVnaW9uc1Rocm91Z2hWb2x1bWUkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvbnNUaHJvdWdoVm9sdW1lJC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEcmF3IHRoZSByZWdpb24gcmVjb25zdHJ1Y3Rpb25zIHRocm91Z2ggdGhlIHZvbHVtZSAoaXQgaGlkZXMgbm9uZSBvZiB0aGVtOiBzdXJmYWNlcyBpbnNpZGUgaXRzXG4gICAqIGJyaWdodCBzdHJ1Y3R1cmVzLCBhbiBPQ1QncyBsYXllciBib3VuZGFyaWVzKSBvciBoaWRkZW4gYmVoaW5kIHdoYXQgaXQgc2hvd3MgKHRoZSBkZWZhdWx0KS5cbiAgICovXG4gIHNldFJlZ2lvbnNUaHJvdWdoVm9sdW1lKHRocm91Z2g6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5yZWdpb25zVGhyb3VnaFZvbHVtZSQudmFsdWUgPT09IHRocm91Z2gpIHJldHVybjtcbiAgICB0aGlzLnJlZ2lvbnNUaHJvdWdoVm9sdW1lJC5uZXh0KHRocm91Z2gpO1xuICAgIHRoaXMubmFwYXJpLnNldFJlZ2lvbnNUaHJvdWdoVm9sdW1lKHRocm91Z2gpO1xuICB9XG5cbiAgLyoqIFRoZSBjbGFzcyBncm91cHMgc2hvd24gaW4gM0Qgb24gdGhpcyBpbWFnZSAoW10gYWZ0ZXIgYSBzd2l0Y2ggdG8gYW5vdGhlciBpbWFnZSkuICovXG4gIGdldFJlZ2lvbkNsYXNzZXMzZCQoKTogT2JzZXJ2YWJsZTxSZWFkb25seUFycmF5PHsga2V5OiBzdHJpbmc7IGNsYXNzZXM6IHJlYWRvbmx5IHN0cmluZ1tdIH0+PiB7XG4gICAgcmV0dXJuIHRoaXMuY2xhc3NlczNkJC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIC8qKiBIaWRlIGV2ZXJ5IHJlZ2lvbiBzdXJmYWNlIGFuZCBmb3JnZXQgdGhlbSAoYSBidWlsZCBzdGlsbCBydW5uaW5nIGlzIGRyb3BwZWQpLiAqL1xuICBwcml2YXRlIGNsZWFyUmVnaW9uQ2xhc3NlczNkKCk6IHZvaWQge1xuICAgIHRoaXMubWVzaFJlcXVlc3QrKztcbiAgICB0aGlzLnNob3duM2QgPSBbXTtcbiAgICB0aGlzLmNsYXNzZXMzZCQubmV4dChbXSk7XG4gICAgdGhpcy5jbGFzc2VzM2RJbWFnZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm5hcGFyaS5zZXRSZWdpb25NZXNoZXMoW10sIHVuZGVmaW5lZCk7XG4gICAgdGhpcy5uYXBhcmkuc2V0UmVnaW9uSGlnaGxpZ2h0KFtdKTtcbiAgfVxuXG4gIC8qKiBIaWdobGlnaHQgdGhlIHN1cmZhY2VzIG9mIHRoZXNlIGdyb3VwIGtleXMgaW4gdGhlIHZvbHVtZSB2aWV3IChub25lOiBhbGwgYXMgdXN1YWwpLiAqL1xuICBoaWdobGlnaHRSZWdpb25DbGFzc2VzM2Qoa2V5czogcmVhZG9ubHkgc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0aGlzLm5hcGFyaS5zZXRSZWdpb25IaWdobGlnaHQoa2V5cyk7XG4gIH1cblxuICAvKiogQSBzdXJmYWNlIGNsaWNrZWQgaW4gdGhlIHZvbHVtZSB2aWV3IHdpdGggdGhlIHNlbGVjdGlvbiB0b29sIChpdHMgZ3JvdXAga2V5KSwgb3Igbm9uZSAobnVsbCkuICovXG4gIGdldFJlZ2lvblBpY2tlZDNkJCgpOiBPYnNlcnZhYmxlPHsga2V5OiBzdHJpbmcgfCBudWxsOyBhZGRpdGl2ZTogYm9vbGVhbiB9PiB7XG4gICAgcmV0dXJuIHRoaXMubmFwYXJpLmdldFJlZ2lvbk1lc2hQaWNrJCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNob3cgdGhlc2UgZ3JvdXBzIG9mIGNsYXNzZXMgaW4gdGhlIHZvbHVtZSB2aWV3IGFzIDNEIHJlY29uc3RydWN0aW9ucyAoZWFjaCBncm91cCBvbmUgc3VyZmFjZVxuICAgKiBpbiBpdHMgY29sb3VyOiBhbiBhdGxhcyBzdHJ1Y3R1cmUgd2l0aCBpdHMgc3Vic3RydWN0dXJlcyksIGFuZCBvbmx5IHRoZXNlOyBbXSBoaWRlcyB0aGVtLlxuICAgKiBSZWNvbnN0cnVjdGVkIGZyb20gZXZlcnkgc2xpY2UncyBvdXRsaW5lcyBhdCB0aGUgdm9sdW1lJ3MgcmVzb2x1dGlvbiwgY2FjaGVkIHBlciBpbWFnZS5cbiAgICovXG4gIGFzeW5jIHNob3dSZWdpb25DbGFzc2VzM2QoXG4gICAgZ3JvdXBzOiBSZWFkb25seUFycmF5PHsga2V5OiBzdHJpbmc7IGNsYXNzZXM6IHJlYWRvbmx5IHN0cmluZ1tdOyBjb2xvcjogc3RyaW5nOyBsYWJlbD86IHN0cmluZyB9PixcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVxdWVzdCA9ICsrdGhpcy5tZXNoUmVxdWVzdDtcbiAgICB0aGlzLmNsYXNzZXMzZEltYWdlID0gdGhpcy5wbG90dGVkRmlsZU5hbWU7XG4gICAgdGhpcy5zaG93bjNkID0gZ3JvdXBzO1xuICAgIC8vIFdoYXQgYW4gZWRpdCBmcm9tIG5vdyBvbiBpcyBjb21wYXJlZCB3aXRoICh0aGUgbGl2ZSBzbGljZSBtYXkgbm90IGhhdmUgY2hhbmdlZCB5ZXQpLlxuICAgIHRoaXMubGl2ZUNsYXNzZXMgPSBudWxsO1xuICAgIHRoaXMudHJhY2tMaXZlQ2xhc3NlcygpO1xuICAgIHRoaXMuY2xhc3NlczNkJC5uZXh0KGdyb3Vwcy5tYXAoKGcpID0+ICh7IGtleTogZy5rZXksIGNsYXNzZXM6IGcuY2xhc3NlcyB9KSkpO1xuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5nZXRUcnVlSW1hZ2VTaXplKCk/LndpZHRoID8/IDEwMjQ7XG4gICAgY29uc3Qgc3RlcCA9IHRoaXMubmFwYXJpLnJlZ2lvblZveGVsU3RlcCgpID8/IE1hdGgubWF4KDEsIHdpZHRoIC8gMjU2KTtcbiAgICBjb25zdCBpbWFnZSA9IHRoaXMucGxvdHRlZEZpbGVOYW1lID8/ICcnO1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gKGc6IHsgY2xhc3NlczogcmVhZG9ubHkgc3RyaW5nW10gfSkgPT4gYCR7aW1hZ2V9fCR7c3RlcC50b0ZpeGVkKDMpfXwke2cuY2xhc3Nlcy5qb2luKCcsJyl9YDtcbiAgICBjb25zdCBtaXNzaW5nID0gZ3JvdXBzLmZpbHRlcigoZykgPT4gIXRoaXMubWVzaENhY2hlLmhhcyhjYWNoZUtleShnKSkpO1xuICAgIGlmIChtaXNzaW5nLmxlbmd0aCkge1xuICAgICAgY29uc3QgbmFtZXMgPSBtaXNzaW5nLm1hcCgoZykgPT4gZy5rZXkpO1xuICAgICAgY29uc3Qgd2hhdCA9IG5hbWVzLmxlbmd0aCA+IDMgPyBgJHtuYW1lcy5sZW5ndGh9IHJlZ2lvbnNgIDogbmFtZXMuam9pbignLCAnKTtcbiAgICAgIGNvbnN0IGRvbmUgPSB0aGlzLm5hcGFyaS5iZWdpblRhc2soYEJ1aWxkaW5nICR7d2hhdH0gaW4gM0TigKZgKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGJ1aWx0ID0gYXdhaXQgdGhpcy5yZWdpb25TdG9yZS5yZWNvbnN0cnVjdENsYXNzZXMoXG4gICAgICAgICAgbWlzc2luZy5tYXAoKGcpID0+ICh7IGtleTogY2FjaGVLZXkoZyksIGNsYXNzZXM6IGcuY2xhc3NlcyB9KSksXG4gICAgICAgICAgc3RlcCxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgY2xhc3Nlc09mID0gbmV3IE1hcChtaXNzaW5nLm1hcCgoZykgPT4gW2NhY2hlS2V5KGcpLCBnLmNsYXNzZXNdKSk7XG4gICAgICAgIGZvciAoY29uc3QgYiBvZiBidWlsdCkgdGhpcy5tZXNoQ2FjaGUuc2V0KGIua2V5LCB7IG1lc2g6IGIubWVzaCwgY2xhc3NlczogY2xhc3Nlc09mLmdldChiLmtleSkgPz8gW10gfSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBkb25lKCk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChyZXF1ZXN0ICE9PSB0aGlzLm1lc2hSZXF1ZXN0KSByZXR1cm47XG4gICAgdGhpcy5uYXBhcmkuc2V0UmVnaW9uTWVzaGVzKFxuICAgICAgZ3JvdXBzLm1hcCgoZykgPT4ge1xuICAgICAgICBjb25zdCBtZXNoID0gdGhpcy5tZXNoQ2FjaGUuZ2V0KGNhY2hlS2V5KGcpKSEubWVzaDtcbiAgICAgICAgcmV0dXJuIHsga2V5OiBnLmtleSwgY29sb3I6IGcuY29sb3IsIGxhYmVsOiBnLmxhYmVsLCB2ZXJ0aWNlczogbWVzaC52ZXJ0aWNlcywgZmFjZXM6IG1lc2guZmFjZXMgfTtcbiAgICAgIH0pLFxuICAgICAgdGhpcy5wbG90dGVkRmlsZU5hbWUsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcmVnaW9ucyBjaGFuZ2VkOiB3aGVuIHRoZSBsaXZlIHNsaWNlJ3MgcmVnaW9ucyBvZiBzb21lIGNsYXNzZXMgZGlkIChhbiBlZGl0LCBhbiB1bmRvLCBub3RcbiAgICogYSBzbGljZSBvciBpbWFnZSBzd2l0Y2gpLCB0aGVpciByZWNvbnN0cnVjdGlvbnMgYXJlIHN0YWxlLiBUaGV5IGFyZSBkcm9wcGVkLCBhbmQgdGhvc2Ugc2hvd25cbiAgICogaW4gM0QgYXJlIHJlYnVpbHQgb25jZSB0aGUgZWRpdHMgcGF1c2UuXG4gICAqL1xuICBwcml2YXRlIG9uUmVnaW9uc0NoYW5nZWQoKTogdm9pZCB7XG4gICAgLy8gTm90aGluZyBmb2xsb3dzIHRoZSBlZGl0cyAobm8gc3VyZmFjZSBidWlsdCBvciBzaG93biwgbm8gc2VjdGlvbnMpOiBza2lwIHRoZSBmaW5nZXJwcmludHMuXG4gICAgaWYgKCF0aGlzLnNsaWNlTW91bnRlZCAmJiAhdGhpcy5zaG93bjNkLmxlbmd0aCAmJiAhdGhpcy5tZXNoQ2FjaGUuc2l6ZSkge1xuICAgICAgdGhpcy5saXZlQ2xhc3NlcyA9IG51bGw7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGJlZm9yZSA9IHRoaXMubGl2ZUNsYXNzZXM7XG4gICAgdGhpcy5saXZlQ2xhc3NlcyA9IG51bGw7XG4gICAgY29uc3Qgbm93ID0gdGhpcy50cmFja0xpdmVDbGFzc2VzKCk7XG4gICAgLy8gQW5vdGhlciBzbGljZSBvciBpbWFnZSBjYW1lIHVwOiBubyByZWdpb24gY2hhbmdlZCAodGhlIHNlY3Rpb25zIHJlY3V0IGZvciB0aGUgc2xpY2UpLlxuICAgIGlmICghYmVmb3JlIHx8IGJlZm9yZS5hdCAhPT0gbm93LmF0KSByZXR1cm47XG4gICAgY29uc3QgY2hhbmdlZCA9IGNoYW5nZWRDbGFzc2VzKGJlZm9yZS5zaWduYXR1cmVzLCBub3cuc2lnbmF0dXJlcyk7XG4gICAgLy8gU291cmNlIGZlYXR1cmVzIGRlbGV0ZWQgKG9yIHRoYXQgdW5kb25lKSBjaGFuZ2Ugbm8gbGl2ZSByZWdpb24sIGFuZCB3aGljaCBjbGFzc2VzIHRoZXkgd2VyZVxuICAgIC8vIGlzIG5vdCBrbm93biBoZXJlOiBldmVyeSBjbGFzcyBpcyBzdGFsZS4gQSBmZWF0dXJlIHRha2VuIHNob3dzIGFzIGl0cyBjbGFzcydzIGNoYW5nZS5cbiAgICBjb25zdCBldmVyeUNsYXNzID0gIWNoYW5nZWQuc2l6ZSAmJiBiZWZvcmUuc291cmNlcyAhPT0gbm93LnNvdXJjZXM7XG4gICAgaWYgKCFjaGFuZ2VkLnNpemUgJiYgIWV2ZXJ5Q2xhc3MpIHJldHVybjtcbiAgICBjb25zdCB0b3VjaGVkID0gKGM6IHN0cmluZykgPT4gZXZlcnlDbGFzcyB8fCBjaGFuZ2VkLmhhcyhjKTtcbiAgICBpZiAodGhpcy5zbGljZU1vdW50ZWQpIHRoaXMuc2VjdGlvbnMucmVnaW9uc0NoYW5nZWQoKTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIGVudHJ5XSBvZiBbLi4udGhpcy5tZXNoQ2FjaGVdKSB7XG4gICAgICBpZiAoZW50cnkuY2xhc3Nlcy5zb21lKHRvdWNoZWQpKSB0aGlzLm1lc2hDYWNoZS5kZWxldGUoa2V5KTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnNob3duM2Quc29tZSgoZykgPT4gZy5jbGFzc2VzLnNvbWUodG91Y2hlZCkpKSByZXR1cm47XG4gICAgaWYgKHRoaXMucmVidWlsZFRpbWVyKSBjbGVhclRpbWVvdXQodGhpcy5yZWJ1aWxkVGltZXIpO1xuICAgIHRoaXMucmVidWlsZFRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnJlYnVpbGRUaW1lciA9IG51bGw7XG4gICAgICBpZiAodGhpcy5zaG93bjNkLmxlbmd0aCAmJiB0aGlzLmNsYXNzZXMzZEltYWdlID09PSB0aGlzLnBsb3R0ZWRGaWxlTmFtZSkge1xuICAgICAgICB2b2lkIHRoaXMuc2hvd1JlZ2lvbkNsYXNzZXMzZCh0aGlzLnNob3duM2QpO1xuICAgICAgfVxuICAgIH0sIFJFR0lPTl9TVVJGQUNFX1JFQlVJTERfTVMpO1xuICB9XG5cbiAgLyoqIEZpbmdlcnByaW50IHRoZSBsaXZlIHNsaWNlJ3MgY2xhc3NlcywgdW5sZXNzIGFscmVhZHk6IHdoYXQgdGhlIG5leHQgZWRpdCBpcyBjb21wYXJlZCB3aXRoLiAqL1xuICBwcml2YXRlIHRyYWNrTGl2ZUNsYXNzZXMoKTogeyBhdDogc3RyaW5nOyBzaWduYXR1cmVzOiBNYXA8c3RyaW5nLCBudW1iZXI+OyBzb3VyY2VzOiBzdHJpbmcgfSB7XG4gICAgdGhpcy5saXZlQ2xhc3NlcyA/Pz0ge1xuICAgICAgYXQ6IHRoaXMubGl2ZVNsaWNlS2V5KCksXG4gICAgICBzaWduYXR1cmVzOiBjbGFzc1NpZ25hdHVyZXModGhpcy5yZWdpb25TdG9yZS5nZXRSZWdpb25zKCkpLFxuICAgICAgc291cmNlczogdGhpcy5yZWdpb25TdG9yZS5nZXRTb3VyY2VTdGF0ZUtleSgpLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMubGl2ZUNsYXNzZXM7XG4gIH1cblxuICAvKiogV2hpY2ggc2xpY2Ugb2Ygd2hpY2ggaW1hZ2UgdGhlIGxpdmUgcmVnaW9ucyBhcmUuICovXG4gIHByaXZhdGUgbGl2ZVNsaWNlS2V5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMucmVnaW9uU3RvcmUuZ2V0RGlzcGxheVNsaWNlKCl9XFxuJHt0aGlzLnBsb3R0ZWRGaWxlTmFtZSA/PyAnJ31gO1xuICB9XG5cbiAgLyoqIEVhY2ggY2xhc3MncyB2b2x1bWUgb3ZlciB0aGUgd2hvbGUgc3RhY2ssIGluIHB4wrIgw5cgc2xpY2VzIChzZWUgUmVnaW9uU3RvcmUuY2xhc3NWb2x1bWVzKS4gKi9cbiAgYXN5bmMgZ2V0Q2xhc3NWb2x1bWVzKGNsYXNzZXM6IHJlYWRvbmx5IHN0cmluZ1tdKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBudW1iZXI+PiB7XG4gICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhhd2FpdCB0aGlzLnJlZ2lvblN0b3JlLmNsYXNzVm9sdW1lcyhjbGFzc2VzKSk7XG4gIH1cblxuICBnZXRSZWdpb25Tb3VyY2VDbGFzc0NvdW50cyhzdGFjaz86IGJvb2xlYW4pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIG51bWJlcj4+IHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdG9yZS5nZXRSZWdpb25Tb3VyY2VDbGFzc0NvdW50cyhzdGFjayk7XG4gIH1cbiAgZ2V0SGlkZGVuQ2xhc3NlcyQoKTogT2JzZXJ2YWJsZTxSZWFkb25seVNldDxzdHJpbmc+PiB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0SGlkZGVuQ2xhc3NlcyQoKTtcbiAgfVxuICBzZXRDbGFzc2VzSGlkZGVuKGNsYXNzZXM6IHJlYWRvbmx5IHN0cmluZ1tdLCBoaWRkZW46IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvblN0b3JlLnNldENsYXNzZXNIaWRkZW4oY2xhc3NlcywgaGlkZGVuKTtcbiAgICAvLyBBIHN1cmZhY2UgaXMgaXRzIGNsYXNzJ3MgKGl0cyBncm91cCBrZXkgaXMgdGhlIGNsYXNzIG5hbWUpLlxuICAgIHRoaXMubmFwYXJpLnNldFJlZ2lvbkhpZGRlbihbLi4udGhpcy5yZWdpb25TdG9yZS5nZXRIaWRkZW5DbGFzc2VzKCldKTtcbiAgICB0aGlzLnNlY3Rpb25zLnNjaGVkdWxlKCk7XG4gIH1cbiAgYXN5bmMgc2VsZWN0UmVnaW9uQ2xhc3NlcyhjbGFzc2VzOiByZWFkb25seSBzdHJpbmdbXSwgYWRkaXRpdmU/OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5yZWdpb25TdG9yZS5zZWxlY3RDbGFzc2VzKGNsYXNzZXMsIGFkZGl0aXZlKTtcbiAgfVxuICBnZXRHZW9Kc29uU3RyaW5nV2l0aFNvdXJjZShyZWdpb25zOiBSZWdpb25bXSwgc2xpY2U/OiBudW1iZXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0b3JlLmdldEdlb0pzb25XaXRoU291cmNlKHJlZ2lvbnMsIHNsaWNlKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBQZXItc2xpY2Ugei1zdGFjayByZWdpb25zIChqaXQtdWkjOTMpLCBmcm9tIHRoZSBzaGFyZWQgUmVnaW9uU3RvcmUuIOKUgOKUgFxuICBlbnRlclN0YWNrTW9kZShcbiAgICBzbGljZXM6IE1hcDxudW1iZXIsIFJlZ2lvbltdPixcbiAgICBpbml0aWFsWj86IG51bWJlcixcbiAgICBzYXZlTGF5b3V0PzogJ2NvbWJpbmVkJyB8ICdwZXItc2xpY2UtZmlsZScsXG4gICk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uU3RvcmUuZW50ZXJTdGFja01vZGUoc2xpY2VzLCBpbml0aWFsWiwgc2F2ZUxheW91dCk7XG4gIH1cbiAgZXhpdFN0YWNrTW9kZSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvblN0b3JlLmV4aXRTdGFja01vZGUoKTtcbiAgfVxuICBpc1N0YWNrTW9kZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpb25TdG9yZS5pc1N0YWNrTW9kZSgpO1xuICB9XG4gIC8qKiBUaGUgc2xpY2UgdGhlIHJlZ2lvbnMgYXJlIHNob3duIGZvciAocmVjb3JkZWQgb3V0c2lkZSBzdGFjayBtb2RlIHRvbykuICovXG4gIGdldERpc3BsYXlTbGljZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0b3JlLmdldERpc3BsYXlTbGljZSgpO1xuICB9XG4gIGdldFN0YWNrU2F2ZUxheW91dCgpOiAnY29tYmluZWQnIHwgJ3Blci1zbGljZS1maWxlJyB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0U3RhY2tTYXZlTGF5b3V0KCk7XG4gIH1cbiAgc2V0RGlzcGxheVNsaWNlKHo6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uU3RvcmUuc2V0RGlzcGxheVNsaWNlKHopO1xuICB9XG4gIGdldFNsaWNlUmVnaW9ucygpOiBSZWdpb25bXSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0U2xpY2VSZWdpb25zKCk7XG4gIH1cbiAgZ2V0U3RhY2tTYXZlU2xpY2VzKCk6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uU3RvcmUuZ2V0U3RhY2tTYXZlU2xpY2VzKCk7XG4gIH1cbiAgLyoqIEFsbCBzbGljZXMnIEFOTk9UQVRJT04gcmVnaW9ucyBmb3IgYSB6LXN0YWNrIHNhdmUgKGppdC11aSM5MyksIGVhY2ggdGFnZ2VkXG4gICAqICB3aXRoIGl0cyB6ZXJvLWJhc2VkIFJlZ2lvbi56OyBwcm9maWxlIGxpbmVzIGV4Y2x1ZGVkLiBGbGF0IGFubm90YXRpb24gc2V0XG4gICAqICBvdXRzaWRlIHN0YWNrIG1vZGUuICovXG4gIGdldFNsaWNlQW5ub3RhdGlvblJlZ2lvbnMoKTogUmVnaW9uW10ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0b3JlLmdldFNsaWNlUmVnaW9ucygpLmZpbHRlcigocikgPT4gIWlzUHJvZmlsZVJlZ2lvbihyKSk7XG4gIH1cbiAgLyoqIFBlci1zbGljZSBhbm5vdGF0aW9uIHJlZ2lvbnMgdG8gd3JpdGUgb24gYSBmb2xkZXItc3RhY2sgc2F2ZSAoaml0LXVpIzkzKTpcbiAgICogIHNsaWNlIGluZGV4IOKGkiB0aGF0IHNsaWNlJ3MgYW5ub3RhdGlvbiByZWdpb25zIChwcm9maWxlIGxpbmVzIGV4Y2x1ZGVkKSxcbiAgICogIGluY2x1ZGluZyBub3ctZW1wdHkgc2xpY2VzIHRoYXQgd2VyZSBsb2FkZWQgbm9uLWVtcHR5IChzbyB0aGV5IG92ZXJ3cml0ZSkuICovXG4gIGdldFN0YWNrU2F2ZUFubm90YXRpb25TbGljZXMoKTogTWFwPG51bWJlciwgUmVnaW9uW10+IHtcbiAgICBjb25zdCBvdXQgPSBuZXcgTWFwPG51bWJlciwgUmVnaW9uW10+KCk7XG4gICAgZm9yIChjb25zdCBbeiwgcmVnc10gb2YgdGhpcy5yZWdpb25TdG9yZS5nZXRTdGFja1NhdmVTbGljZXMoKSkge1xuICAgICAgb3V0LnNldChcbiAgICAgICAgeixcbiAgICAgICAgcmVncy5maWx0ZXIoKHIpID0+ICFpc1Byb2ZpbGVSZWdpb24ocikpLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIC8qKiBBdXRob3JpdGF0aXZlIGZ1bGwtcmVzb2x1dGlvbiBpbWFnZSBzaXplIGZvciBtYXNrIGV4cG9ydC4gUHJlZmVycyB0aGVcbiAgICogIGFjdGl2ZSByZW5kZXJlcidzIHJlcG9ydGVkIHNpemUsIGZhbGxpbmcgYmFjayB0byB0aGUgaW1hZ2UgbWV0YWRhdGEgKHgveVxuICAgKiAgYXJlIHRoZSBmdWxsLXJlcyBwaXhlbCBkaW1lbnNpb25zIHVzZWQgYWNyb3NzIHRoZSBhcHApLiBSZWplY3RzIG5vbi1maW5pdGVcbiAgICogIG9yIG5vbi1wb3NpdGl2ZSBzaXplcyDigJQgdGhlIFBsb3RseSBib3VuZHMgY2FuIHlpZWxkIE5hTiBiZWZvcmUgYSBwbG90IGlzXG4gICAqICBmdWxseSBsYWlkIG91dCwgd2hpY2ggd291bGQgb3RoZXJ3aXNlIGNyYXNoIG1hc2sgY3JlYXRpb24uICovXG4gIGdldE1hc2tJbWFnZVNpemUoKTogeyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHwgbnVsbCB7XG4gICAgY29uc3QgdmFsaWQgPSAoczogeyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHwgbnVsbCB8IHVuZGVmaW5lZCkgPT5cbiAgICAgIHMgJiYgTnVtYmVyLmlzRmluaXRlKHMud2lkdGgpICYmIE51bWJlci5pc0Zpbml0ZShzLmhlaWdodCkgJiYgcy53aWR0aCA+PSAxICYmIHMuaGVpZ2h0ID49IDFcbiAgICAgICAgPyB7IHdpZHRoOiBNYXRoLnJvdW5kKHMud2lkdGgpLCBoZWlnaHQ6IE1hdGgucm91bmQocy5oZWlnaHQpIH1cbiAgICAgICAgOiBudWxsO1xuXG4gICAgY29uc3QgZnJvbVJlbmRlcmVyID0gdmFsaWQodGhpcy5nZXRUcnVlSW1hZ2VTaXplKCkpO1xuICAgIGlmIChmcm9tUmVuZGVyZXIpIHJldHVybiBmcm9tUmVuZGVyZXI7XG5cbiAgICBsZXQgbWV0YTogSUltYWdlTWV0YWRhdGFbXSA9IFtdO1xuICAgIHRoaXMuZ2V0SW1hZ2VNZXRhKClcbiAgICAgIC5zdWJzY3JpYmUoKG0pID0+IChtZXRhID0gbSkpXG4gICAgICAudW5zdWJzY3JpYmUoKTtcbiAgICBjb25zdCBtMCA9IG1ldGE/LlswXTtcbiAgICByZXR1cm4gbTAgPyB2YWxpZCh7IHdpZHRoOiBtMC54LCBoZWlnaHQ6IG0wLnkgfSkgOiBudWxsO1xuICB9XG5cbiAgLy8g4pSA4pSAIElSZWdpb25FZGl0b3JBcGk6IGFubm90YXRpb24tb25seSBzdXJmYWNlIGZvciB0aGUgUmVnaW9uIEVkaXRvciDilIDilIDilIBcbiAgLy8gSW50ZW5zaXR5LXByb2ZpbGUgbGluZXMgKGtpbmQ9J3Byb2ZpbGUnKSBiZWxvbmcgdG8gdGhlIGludGVuc2l0eSB0b29sLCBub3RcbiAgLy8gdGhlIGVkaXRvci4gVGhlc2UgbWV0aG9kcyBnaXZlIGV4dGVybmFsIGNvbnN1bWVycyBhbiBhbm5vdGF0aW9uLW9ubHkgdmlld1xuICAvLyBhbmQgZ3VhcmFudGVlIHByb2ZpbGUgbGluZXMgYXJlIHByZXNlcnZlZC4gVGhlIHdyaXRlcyBsYW5kIGluIHRoZSBzdG9yZSBsaWtlXG4gIC8vIGFueSBvdGhlciwgYW5kIGV2ZXJ5IGJhY2tlbmQgcmVkcmF3cyBmcm9tIGl0cyBldmVudHMuXG5cbiAgZ2V0QW5ub3RhdGlvblJlZ2lvbnMoKTogUmVnaW9uW10ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvblN0b3JlLmdldFJlZ2lvbnMoKS5maWx0ZXIoKHIpID0+ICFpc1Byb2ZpbGVSZWdpb24ocikpO1xuICB9XG4gIHNldEFubm90YXRpb25SZWdpb25zKFxuICAgIHJlZ2lvbnM6IFJlZ2lvbltdLFxuICAgIHNob3dSZWdpb25MYWJlbD86IGJvb2xlYW4sXG4gICAgaXNSZWdpb25TYXZlT24/OiBib29sZWFuLFxuICAgIGZpbGxDb2xvcj86IHN0cmluZyxcbiAgKTogdm9pZCB7XG4gICAgLy8gUmUtYXBwZW5kIHRoZSBzdG9yZSdzIHByb2ZpbGUgbGluZXMgc28gYW4gZWRpdG9yIHNhdmUvZGVsZXRlIGNhbid0IGRyb3AgdGhlbS5cbiAgICBjb25zdCBwcm9maWxlcyA9IHRoaXMucmVnaW9uU3RvcmUuZ2V0UmVnaW9ucygpLmZpbHRlcigocikgPT4gaXNQcm9maWxlUmVnaW9uKHIpKTtcbiAgICBjb25zdCBhbm5vdGF0aW9ucyA9IChyZWdpb25zIHx8IFtdKS5maWx0ZXIoKHIpID0+ICFpc1Byb2ZpbGVSZWdpb24ocikpO1xuICAgIHRoaXMuc2V0UmVnaW9ucyhbLi4uYW5ub3RhdGlvbnMsIC4uLnByb2ZpbGVzXSwgc2hvd1JlZ2lvbkxhYmVsLCBpc1JlZ2lvblNhdmVPbiwgZmlsbENvbG9yLCBmYWxzZSk7XG4gIH1cbiAgZ2V0U2VsZWN0ZWRSZWdpb25zJCgpOiBPYnNlcnZhYmxlPFJlZ2lvbltdPiB7XG4gICAgLy8gTWFwIHRoZSBpbnRlcm5hbCBpbmRleC1iYXNlZCBzZWxlY3Rpb24gdG8gdGhlIHNlbGVjdGVkIGFubm90YXRpb24gcmVnaW9ucy5cbiAgICByZXR1cm4gdGhpcy5nZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyQoKS5waXBlKFxuICAgICAgbWFwKChpZHhzKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlZ3MgPSB0aGlzLnJlZ2lvblN0b3JlLmdldFJlZ2lvbnMoKTtcbiAgICAgICAgcmV0dXJuIGlkeHMubWFwKChpKSA9PiByZWdzW2ldKS5maWx0ZXIoKHIpOiByIGlzIFJlZ2lvbiA9PiAhIXIgJiYgIWlzUHJvZmlsZVJlZ2lvbihyKSk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG4gIHNldFNlbGVjdGVkUmVnaW9ucyhyZWdpb25zOiBSZWdpb25bXSk6IHZvaWQge1xuICAgIGNvbnN0IHJlZ3MgPSB0aGlzLnJlZ2lvblN0b3JlLmdldFJlZ2lvbnMoKTtcbiAgICBjb25zdCBpbmRpY2VzID0gKHJlZ2lvbnMgfHwgW10pLm1hcCgocikgPT4gcmVncy5maW5kSW5kZXgoKHgpID0+IHguaWQgPT09IHIuaWQpKS5maWx0ZXIoKGkpID0+IGkgPj0gMCk7XG4gICAgdGhpcy5zZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyhpbmRpY2VzKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCB0b29scyDihpIgYWN0aXZlIHJlbmRlcmVyIChydW4gb24gZWl0aGVyIGJhY2tlbmQpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICAvLyBUaGUgd2FuZCwgdmVydGV4IGVyYXNlciBhbmQgem9vbS10by1ib3ggYXJlIGltcGxlbWVudGVkIG9uIGJvdGggYmFja2VuZHNcbiAgLy8gdmlhIElDb29yZGluYXRlVHJhbnNmb3JtICgrIGEgdmlld3BvcnQgcGl4ZWwgcmVhZGJhY2sgZm9yIHRoZSB3YW5kKSwgc28gdGhleVxuICAvLyBmb2xsb3cgdGhlIGFjdGl2ZSByZW5kZXJlciDigJQgdGhlIHNsaWNlIHBhbmUncyB3aGlsZSB0aGUgdm9sdW1lIHZpZXcgaXMgc3BsaXQuXG4gIHNldEFjdGl2ZVRvb2woaWQ6IHN0cmluZyB8IG51bGwsIG9wdGlvbnM/OiBDYW52YXNUb29sT3B0aW9ucyk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uQmFja2VuZCgpLnNldEFjdGl2ZVRvb2woaWQsIG9wdGlvbnMpO1xuICB9XG4gIC8qKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rIHNldEFjdGl2ZVRvb2x9LiAqL1xuICBzZXRXYW5kTW9kZShhY3RpdmU6IGJvb2xlYW4sIG9wdGlvbnM/OiBJV2FuZE9wdGlvbnMpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvbkJhY2tlbmQoKS5zZXRXYW5kTW9kZShhY3RpdmUsIG9wdGlvbnMpO1xuICB9XG4gIHNldFdhbmRPcHRpb25zKG9wdGlvbnM6IElXYW5kT3B0aW9ucyk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uQmFja2VuZCgpLnNldFdhbmRPcHRpb25zKG9wdGlvbnMpO1xuICB9XG4gIGNsZWFyQWN0aXZlV2FuZFJlZ2lvbigpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvbkJhY2tlbmQoKS5jbGVhckFjdGl2ZVdhbmRSZWdpb24oKTtcbiAgfVxuICAvKiogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBzZXRBY3RpdmVUb29sfS4gKi9cbiAgc2V0QnJ1c2hNb2RlKGFjdGl2ZTogYm9vbGVhbiwgb3B0aW9ucz86IElCcnVzaE9wdGlvbnMpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvbkJhY2tlbmQoKS5zZXRCcnVzaE1vZGUoYWN0aXZlLCBvcHRpb25zKTtcbiAgfVxuICBzZXRCcnVzaE9wdGlvbnMob3B0aW9uczogSUJydXNoT3B0aW9ucyk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uQmFja2VuZCgpLnNldEJydXNoT3B0aW9ucyhvcHRpb25zKTtcbiAgfVxuICAvKiogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBzZXRBY3RpdmVUb29sfS4gKi9cbiAgc2V0VmVydGV4RXJhc2VyTW9kZShhY3RpdmU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvbkJhY2tlbmQoKS5zZXRWZXJ0ZXhFcmFzZXJNb2RlKGFjdGl2ZSk7XG4gIH1cbiAgc2V0VmVydGV4RXJhc2VyUmFkaXVzKHJhZGl1czogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpb25CYWNrZW5kKCkuc2V0VmVydGV4RXJhc2VyUmFkaXVzKHJhZGl1cyk7XG4gIH1cbiAgLyoqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgc2V0QWN0aXZlVG9vbH0uICovXG4gIHNldFpvb21Ub0JveE1vZGUoYWN0aXZlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5yZWdpb25CYWNrZW5kKCkuc2V0Wm9vbVRvQm94TW9kZShhY3RpdmUpO1xuICB9XG4gIHNlZ21lbnRSZWN0YW5nbGVzKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgcmV0dXJuIHRoaXMucmVnaW9uQmFja2VuZCgpLnNlZ21lbnRSZWN0YW5nbGVzKCk7XG4gIH1cbiAgc2VnbWVudFJlY3RhbmdsZXNDZWxscG9zZSgpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIHJldHVybiB0aGlzLnJlZ2lvbkJhY2tlbmQoKS5zZWdtZW50UmVjdGFuZ2xlc0NlbGxwb3NlKCk7XG4gIH1cbiAgc2V0U2FtTW9kZWwoaWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uQmFja2VuZCgpLnNldFNhbU1vZGVsKGlkKTtcbiAgfVxuICAvKiogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBzZXRBY3RpdmVUb29sfS4gKi9cbiAgc2V0U2FtUG9pbnRNb2RlKGFjdGl2ZTogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uQmFja2VuZCgpLnNldFNhbVBvaW50TW9kZShhY3RpdmUpO1xuICB9XG4gIGNvbW1pdFNhbVBvaW50cygpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvbkJhY2tlbmQoKS5jb21taXRTYW1Qb2ludHMoKTtcbiAgfVxuICBjbGVhclNhbVBvaW50cygpOiB2b2lkIHtcbiAgICB0aGlzLnJlZ2lvbkJhY2tlbmQoKS5jbGVhclNhbVBvaW50cygpO1xuICB9XG5cbiAgLy8g4pSA4pSAIGRpc3BsYXkgb3B0aW9ucyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gU3RhdGUgbGl2ZXMgaW4gdGhlIHNoYXJlZCBWaXN1YWxpemVyU3RvcmUg4oCUIHJlYWRzIGdvIHN0cmFpZ2h0IHRvIGl0LlxuICAvLyBUaGUgdHdvIFNFVFRFUlMgc3RpbGwgcm91dGUgdGhyb3VnaCBQbG90bHkgYmVjYXVzZSBpdHMgaW1wbGVtZW50YXRpb25zXG4gIC8vIGNhcnJ5IHJlbmRlciBnbHVlIGJleW9uZCB0aGUgc3RvcmUgd3JpdGUgKGEgbGl2ZSBQbG90bHkucmVzdHlsZSBvZlxuICAvLyBjb2xvcnNjYWxlL3JldmVyc2VzY2FsZSBvbiB0aGUgbW91bnRlZCBoZWF0bWFwKTsgT1NEIHJlY29sb3JzIHZpYSBpdHMgb3duXG4gIC8vIHN0b3JlIHN1YnNjcmlwdGlvbiBlaXRoZXIgd2F5LlxuICBnZXRDb2xvcm1hcCgpOiBPYnNlcnZhYmxlPENvbG9ybWFwTm9kZSB8IG51bGw+IHtcbiAgICByZXR1cm4gdGhpcy5zdG9yZS5nZXRDb2xvcm1hcCgpO1xuICB9XG4gIHNldENvbG9ybWFwKGNvbG9ybWFwOiBDb2xvcm1hcE5vZGUpOiB2b2lkIHtcbiAgICB0aGlzLnBsb3RseS5zZXRDb2xvcm1hcChjb2xvcm1hcCk7XG4gIH1cbiAgZ2V0Q29sb3JtYXBPcHRpb25zKCk6IENvbG9ybWFwTm9kZVtdIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yZS5nZXRDb2xvcm1hcE9wdGlvbnMoKTtcbiAgfVxuICBnZXRSZXZlcnNlU2NhbGUoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0UmV2ZXJzZVNjYWxlKCk7XG4gIH1cbiAgc2V0UmV2ZXJzZVNjYWxlKHJldmVyc2U6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnBsb3RseS5zZXRSZXZlcnNlU2NhbGUocmV2ZXJzZSk7XG4gIH1cbiAgc2V0SW1hZ2VNZXRhKGltYWdlTWV0YTogSUltYWdlTWV0YWRhdGFbXSwgaW1hZ2VLZXk/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JlLnNldEltYWdlTWV0YShpbWFnZU1ldGEsIGltYWdlS2V5KTtcbiAgfVxuICBnZXRJbWFnZU1ldGEoKTogT2JzZXJ2YWJsZTxJSW1hZ2VNZXRhZGF0YVtdPiB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0SW1hZ2VNZXRhKCk7XG4gIH1cblxuICAvLyDilIDilIAgSUNoYW5uZWxIaXN0b2dyYW1BcGk6IENoYW5uZWxzICYgSGlzdG9ncmFtIHBhbmUgc3VyZmFjZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gQ2hhbm5lbC9ncmF5c2NhbGUvaW52ZXJ0IHN0YXRlIGxpdmVzIGluIHRoZSBzaGFyZWQgVmlzdWFsaXplclN0b3JlOyBib3RoXG4gIC8vIGJhY2tlbmRzIHN1YnNjcmliZSBhbmQgcmVjb2xvciBsaXZlLCBzbyBzZXR0ZXJzIGp1c3Qgd3JpdGUgdGhlIHN0b3JlLiBUaGVcbiAgLy8gaGlzdG9ncmFtIGNvbWVzIGZyb20gd2hpY2hldmVyIGJhY2tlbmQgaXMgb24gc2NyZWVuIChpdHMgbmF0aXZlIHBpeGVscykuXG4gIGdldEhpc3RvZ3JhbShjaGFubmVsSW5kZXg6IG51bWJlciwgYmluczogbnVtYmVyKTogSUhpc3RvZ3JhbSB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0SGlzdG9ncmFtKGNoYW5uZWxJbmRleCwgYmlucyk7XG4gIH1cbiAgZ2V0SGlzdG9ncmFtJChjaGFubmVsSW5kZXg6IG51bWJlciwgYmluczogbnVtYmVyKTogT2JzZXJ2YWJsZTxJSGlzdG9ncmFtIHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyKCkuZ2V0SGlzdG9ncmFtJChjaGFubmVsSW5kZXgsIGJpbnMpO1xuICB9XG4gIC8qKiBFeHBvcnQgdGhlIHVuZGVybHlpbmcgZGF0YSAoMTYtYml0IG11bHRpLWJhbmQgVElGRikgdmlhIHRoZSBhY3RpdmUgYmFja2VuZC4gKi9cbiAgZXhwb3J0RGF0YSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlcmVyKCkuZXhwb3J0RGF0YSgpO1xuICB9XG4gIGdldENoYW5uZWxzJCgpOiBPYnNlcnZhYmxlPElDaGFubmVsU3RhdGVbXT4ge1xuICAgIHJldHVybiB0aGlzLnN0b3JlLmdldENoYW5uZWxTdGF0ZXMoKTtcbiAgfVxuICBzZXRTZWxlY3RlZENoYW5uZWwoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuc3RvcmUuc2V0U2VsZWN0ZWRDaGFubmVsKGluZGV4KTtcbiAgfVxuICBzZXRDaGFubmVsU3RhdGUoaW5kZXg6IG51bWJlciwgcGFydGlhbDogUGFydGlhbDxJQ2hhbm5lbFN0YXRlPik6IHZvaWQge1xuICAgIHRoaXMuc3RvcmUuc2V0Q2hhbm5lbFN0YXRlKGluZGV4LCBwYXJ0aWFsKTtcbiAgfVxuICByZXNldENvbnRyYXN0KGluZGljZXM6IG51bWJlcltdKTogdm9pZCB7XG4gICAgLy8gRnVsbCByZXNldDogd2luZG93ICgwLi4yNTUpLCBnYW1tYSAoMSkgQU5EIHRoZSBjaGFubmVsJ3MgZGVmYXVsdCB0aW50LlxuICAgIGZvciAoY29uc3QgaSBvZiBpbmRpY2VzKSB0aGlzLnN0b3JlLnJlc2V0Q2hhbm5lbFN0YXRlKGkpO1xuICB9XG4gIC8qKiBBdXRvLXdpbmRvdyBlYWNoIGNoYW5uZWwgYnkgc2F0dXJhdGluZyBgc2F0dXJhdGlvbmAgKDAuLjEpIG9mIHBpeGVscyBhdCBlYWNoXG4gICAqICBlbmQgb2YgaXRzIGhpc3RvZ3JhbSAoc2tpcHBpbmcgb3V0bGllciBmaXJzdC9sYXN0IGJpbnMpLiAqL1xuICBhdXRvQ29udHJhc3QoaW5kaWNlczogbnVtYmVyW10sIHNhdHVyYXRpb246IG51bWJlcik6IHZvaWQge1xuICAgIGZvciAoY29uc3QgaSBvZiBpbmRpY2VzKSB7XG4gICAgICBjb25zdCBoID0gdGhpcy5yZW5kZXJlcigpLmdldEhpc3RvZ3JhbShpLCAyNTYpO1xuICAgICAgaWYgKCFoKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IFttaW4sIG1heF0gPSBhdXRvV2luZG93RnJvbUhpc3RvZ3JhbShoLCBzYXR1cmF0aW9uLCBbMCwgMjU1XSk7XG4gICAgICBpZiAobWF4ID4gbWluKSB0aGlzLnN0b3JlLnNldENoYW5uZWxTdGF0ZShpLCB7IG1pbiwgbWF4IH0pO1xuICAgIH1cbiAgfVxuICBnZXRHcmF5c2NhbGUkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLnN0b3JlLmdldEdyYXlzY2FsZSgpO1xuICB9XG4gIHNldEdyYXlzY2FsZShvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuc3RvcmUuc2V0R3JheXNjYWxlKG9uKTtcbiAgfVxuICBnZXRJbnZlcnQkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLnN0b3JlLmdldEludmVydCgpO1xuICB9XG4gIHNldEludmVydChvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuc3RvcmUuc2V0SW52ZXJ0KG9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYWN0aXZlIGJhY2tlbmQncyByZWdpb24gb3ZlcmxheSAodGhlIHNsaWNlIHBhbmUncyB3aGlsZSB0aGUgdm9sdW1lIHZpZXcgaXMgc3BsaXQpLiBGYWxsc1xuICAgKiBiYWNrIHRvIFBsb3RseSdzIHdoZW4gdGhlIGFjdGl2ZSBiYWNrZW5kXG4gICAqIChPU0Qgb3IgbmFwYXJpLWpzKSBpcyBzZWxlY3RlZCBidXQgYSBwbG90IGlzbid0IG1vdW50ZWQgeWV0LCBzbyBjYWxsZXJzIGFsd2F5cyBnZXQgYVxuICAgKiB1c2FibGUgb3ZlcmxheS5cbiAgICovXG4gIGdldFJlZ2lvbk92ZXJsYXkoKTogSVJlZ2lvbk92ZXJsYXkge1xuICAgIGNvbnN0IHIgPSB0aGlzLnJlZ2lvbkJhY2tlbmQoKTtcbiAgICBpZiAociA9PT0gdGhpcy5vc2QpIHtcbiAgICAgIHJldHVybiB0aGlzLm9zZC5nZXRSZWdpb25PdmVybGF5KCkgPz8gdGhpcy5wbG90bHkuZ2V0UmVnaW9uT3ZlcmxheSgpO1xuICAgIH1cbiAgICBpZiAociA9PT0gdGhpcy5uYXBhcmkpIHtcbiAgICAgIHJldHVybiB0aGlzLm5hcGFyaS5nZXRSZWdpb25PdmVybGF5KCkgPz8gdGhpcy5wbG90bHkuZ2V0UmVnaW9uT3ZlcmxheSgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wbG90bHkuZ2V0UmVnaW9uT3ZlcmxheSgpO1xuICB9XG5cbiAgLyoqIElzb3N1cmZhY2UgY29udHJvbHMgb2YgdGhlIGJhY2tlbmQgb24gc2NyZWVuLCB3aGVuIGl0IHJlbmRlcnMgaXNvc3VyZmFjZXMuICovXG4gIGdldElzb3N1cmZhY2VDb250cm9scygpOiBJSXNvc3VyZmFjZUNvbnRyb2xzIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyZXIoKS5nZXRJc29zdXJmYWNlQ29udHJvbHMoKTtcbiAgfVxuXG4gIC8qKiAzRCBzY2VuZSBjb250cm9scyBvZiB0aGUgYmFja2VuZCBvbiBzY3JlZW4gKFBsb3RseSBvciBuYXBhcmktanMpLCBvciBudWxsIG9uIGFcbiAgICogIDJELW9ubHkgb25lLiAqL1xuICBnZXRTdXJmYWNlM2RDb250cm9scygpOiBJU3VyZmFjZTNkQ29udHJvbHMgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJlcigpLmdldFN1cmZhY2UzZENvbnRyb2xzKCk7XG4gIH1cblxuICAvKiogSW50ZW5zaXR5IChsaW5lLVJPSSkgY29udHJvbHMsIHdoaWNoZXZlciBiYWNrZW5kIGRyYXdzIHRoZSBpbWFnZTogdGhlXG4gICAqICBJbnRlbnNpdHlQcm9maWxlU2VydmljZSBhZGRzIHRoZSBsaW5lIHRvIHRoZSBzdG9yZSwgYW5kIGV2ZXJ5IGJhY2tlbmRcbiAgICogIChQbG90bHkgaW5jbHVkZWQpIGRyYXdzIGl0IGZyb20gdGhlIHN0b3JlJ3MgdXBkYXRlIGV2ZW50LiAqL1xuICBnZXRJbnRlbnNpdHlDb250cm9scygpOiBJSW50ZW5zaXR5Q29udHJvbHMgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5pbnRlbnNpdHk7XG4gIH1cblxuICAvKipcbiAgICogU3BhdGlhbC1vbWljcyBjb250cm9scywgb3IgbnVsbCB3aGVuIG5vIGBTUEFUSUFMX0RBVEFfUE9SVGAgaXMgYm91bmQuIFNlcnZlZCBieSBhXG4gICAqIGJhY2tlbmQtbmV1dHJhbCB7QGxpbmsgU3BhdGlhbENvbnRyb2xzRmFjYWRlfSAoc3RhdGUgaW4gdGhlIHNoYXJlZCBzdG9yZXMpLCBzbyB0aGVcbiAgICogY29udHJvbHMgd29yayBhY3Jvc3MgYSBwbG90LXR5cGUgc3dpdGNoIGFuZCBiZWZvcmUgYW55IGJhY2tlbmQgaGFzIG1vdW50ZWQuXG4gICAqL1xuICBnZXRTcGF0aWFsQ29udHJvbHMoKTogSVNwYXRpYWxDb250cm9scyB8IG51bGwge1xuICAgIGlmICghdGhpcy5zcGF0aWFsRGF0YSkgcmV0dXJuIG51bGw7XG4gICAgdGhpcy5zcGF0aWFsRmFjYWRlID8/PSBuZXcgU3BhdGlhbENvbnRyb2xzRmFjYWRlKHRoaXMuc3BhdGlhbERhdGEsIHtcbiAgICAgIHN0b3JlOiB0aGlzLnN0b3JlLFxuICAgICAgcmVnaW9uU3RvcmU6IHRoaXMucmVnaW9uU3RvcmUsXG4gICAgICBzZWxlY3Rpb25TdG9yZTogdGhpcy5zZWxlY3Rpb25TdG9yZSxcbiAgICAgIG5hcGFyaTogdGhpcy5uYXBhcmksXG4gICAgICBwbG90VHlwZTogKCkgPT4gdGhpcy5jdXJyZW50UGxvdFR5cGUsXG4gICAgICB6SW5kZXg6ICgpID0+IHRoaXMuY3VycmVudFpJbmRleCxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5zcGF0aWFsRmFjYWRlLmNvbnRyb2xzO1xuICB9XG5cbiAgLyoqIENyZWF0ZWQgb24gZmlyc3QgdXNlOyBvd25zIHRoZSBkYXRhc2V0IHN1YnNjcmlwdGlvbi4gKi9cbiAgcHJpdmF0ZSBzcGF0aWFsRmFjYWRlOiBTcGF0aWFsQ29udHJvbHNGYWNhZGUgfCBudWxsID0gbnVsbDtcbiAgLyoqIERpc3BsYXllZCBzbGljZS4gT25seSBhIHZvbHVtZS1iYWNrZWQgc3BhdGlhbCBkYXRhc2V0IHJlYWRzIGl0LCB0byBrZWVwIGFcbiAgICogIHJlZ2lvbiBkcmF3biBvdmVyIG9uZSBzZWN0aW9uIGZyb20gc2VsZWN0aW5nIHRoZSB3aG9sZSBkZXB0aCBiZWhpbmQgaXQuICovXG4gIHByaXZhdGUgY3VycmVudFpJbmRleCA9IDA7XG5cbiAgLyoqIEFuZ3VsYXIgY2FsbHMgdGhpcyB3aGVuIHRoZSBpbmplY3RvciBwcm92aWRpbmcgdGhlIHJvdXRlciBpcyBkZXN0cm95ZWQg4oCUIHRoZSBob3N0XG4gICAqICBjb21wb25lbnQgZm9yIGEgYHByb3ZpZGVWaXN1YWxpemF0aW9uKClgIGNoYWluLiBUaGUgZGF0YXNldCBzdWJzY3JpcHRpb24gd291bGRcbiAgICogIG90aGVyd2lzZSBrZWVwIHRoZSB3aG9sZSBpc29sYXRlZCBjaGFpbiByZWFjaGFibGUgZnJvbSB0aGUgcm9vdCBkYXRhIHBvcnQuICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3BhdGlhbEZhY2FkZT8uZGlzcG9zZSgpO1xuICAgIHRoaXMuc3BhdGlhbEZhY2FkZSA9IG51bGw7XG4gICAgdGhpcy5yZWdpb25VcGRhdGVzLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5zZWN0aW9uU3Vicy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuc2VjdGlvbnMuc3RvcCgpO1xuICAgIGlmICh0aGlzLnJlYnVpbGRUaW1lcikgY2xlYXJUaW1lb3V0KHRoaXMucmVidWlsZFRpbWVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnRlbnNpdHktcHJvZmlsZSBzYW1wbGluZywgd2hpY2hldmVyIGJhY2tlbmQgaXMgb24gc2NyZWVuOiB0aGUgc2FtcGxpbmcgaXMgdGhlXG4gICAqIGJhY2tlbmQtbmV1dHJhbCBJbnRlbnNpdHlQcm9maWxlU2VydmljZSdzOyB0aGUgdmlld3BvcnQgY2hhbmdlcyBjb21lIGZyb20gZXZlcnlcbiAgICogYmFja2VuZCB0aGF0IHJlcG9ydHMgdGhlbSAoT3BlblNlYWRyYWdvbiwgbmFwYXJpLWpzKSwgbWVyZ2VkIGludG8gb25lIHN0YWJsZVxuICAgKiBzdHJlYW0gdGhlIGluc2V0IHN1YnNjcmliZXMgdG8gb25jZS5cbiAgICovXG4gIGdldEludGVuc2l0eVNhbXBsaW5nKCk6IElJbnRlbnNpdHlTYW1wbGluZyB7XG4gICAgcmV0dXJuIHRoaXMuaW50ZW5zaXR5U2FtcGxpbmc7XG4gIH1cbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlbnNpdHlTYW1wbGluZzogSUludGVuc2l0eVNhbXBsaW5nID0ge1xuICAgIC8vIExvYWQgdGhlIGRpc3BsYXllZCBzbGljZSdzIHBpeGVscyBmb3IgYSBiYWNrZW5kIHRoYXQgaGFzIG5vIGZyYW1lcyBvZiBpdHMgb3duXG4gICAgLy8gKE9wZW5TZWFkcmFnb24sIG5hcGFyaS1qczsgUGxvdGx5IGZlZWRzIGl0cyBmcmFtZXMgdG8gdGhlIHNlcnZpY2Ugd2hlbiBpdCBwbG90cykuXG4gICAgZW5zdXJlSW50ZW5zaXR5U2FtcGxpbmc6IChpbWFnZUluZm8sIHpJbmRleCkgPT4ge1xuICAgICAgdGhpcy5wb2ludFNhbXBsaW5nQXRQbG90KCk7XG4gICAgICByZXR1cm4gdGhpcy5pbnRlbnNpdHkuZW5zdXJlSW50ZW5zaXR5U2FtcGxpbmcoaW1hZ2VJbmZvLCB6SW5kZXgpO1xuICAgIH0sXG4gICAgLy8gUmUtc2FtcGxlIGZyb20gYSBmcmVzaCBjcm9wIG9mIHRoZSBpbWFnZS1waXhlbCBST0kgYXQgZGlzcGxheSByZXNvbHV0aW9uLlxuICAgIHJlZnJlc2hJbnRlbnNpdHlTYW1wbGluZ0ZvclJvaTogKHgsIHksIHdpZHRoLCBoZWlnaHQsIHpJbmRleCkgPT4ge1xuICAgICAgdGhpcy5wb2ludFNhbXBsaW5nQXRQbG90KCk7XG4gICAgICB0aGlzLmludGVuc2l0eS5yZWZyZXNoSW50ZW5zaXR5U2FtcGxpbmdGb3JSb2koeCwgeSwgd2lkdGgsIGhlaWdodCwgekluZGV4KTtcbiAgICB9LFxuICAgIGdldFZpZXdwb3J0Q2hhbmdlJDogKCkgPT5cbiAgICAgIG1lcmdlKC4uLnRoaXMuYmFja2VuZHMoKS5tYXAoKGIpID0+IGIuZ2V0SW50ZW5zaXR5U2FtcGxpbmcoKT8uZ2V0Vmlld3BvcnRDaGFuZ2UkKCkgPz8gRU1QVFkpKSxcbiAgfTtcbiAgLyoqIEBkZXByZWNhdGVkIFVzZSBgZ2V0SW50ZW5zaXR5U2FtcGxpbmcoKS5lbnN1cmVJbnRlbnNpdHlTYW1wbGluZygpYC4gKi9cbiAgZW5zdXJlSW50ZW5zaXR5U2FtcGxpbmcoaW1hZ2VJbmZvOiBJSW1hZ2VJbmZvLCB6SW5kZXg6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmludGVuc2l0eVNhbXBsaW5nLmVuc3VyZUludGVuc2l0eVNhbXBsaW5nKGltYWdlSW5mbywgekluZGV4KTtcbiAgfVxuXG4gIC8qKiBDcm9wcyBmb3Igc2FtcGxpbmcgYXJlIHNpemVkIGZyb20gdGhlIHBsb3QgZGl2ICh3aGljaGV2ZXIgYmFja2VuZCByZW5kZXJzIGludG8gaXQpLiAqL1xuICBwcml2YXRlIHBvaW50U2FtcGxpbmdBdFBsb3QoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucGxvdERpdikgdGhpcy5pbnRlbnNpdHkuc2V0U2FtcGxpbmdFbGVtZW50KHRoaXMucGxvdERpdik7XG4gIH1cblxuICAvKiogQGRlcHJlY2F0ZWQgVXNlIGBnZXRJbnRlbnNpdHlTYW1wbGluZygpLmdldFZpZXdwb3J0Q2hhbmdlJCgpYC4gKi9cbiAgZ2V0Vmlld3BvcnRDaGFuZ2UkKCk6IE9ic2VydmFibGU8eyB4OiBudW1iZXI7IHk6IG51bWJlcjsgd2lkdGg6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfT4ge1xuICAgIHJldHVybiB0aGlzLmludGVuc2l0eVNhbXBsaW5nLmdldFZpZXdwb3J0Q2hhbmdlJCgpO1xuICB9XG5cbiAgLyoqIEBkZXByZWNhdGVkIFVzZSBgZ2V0SW50ZW5zaXR5U2FtcGxpbmcoKS5yZWZyZXNoSW50ZW5zaXR5U2FtcGxpbmdGb3JSb2koKWAuICovXG4gIHJlZnJlc2hJbnRlbnNpdHlTYW1wbGluZ0ZvclJvaSh4OiBudW1iZXIsIHk6IG51bWJlciwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIHpJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5pbnRlbnNpdHlTYW1wbGluZy5yZWZyZXNoSW50ZW5zaXR5U2FtcGxpbmdGb3JSb2koeCwgeSwgd2lkdGgsIGhlaWdodCwgekluZGV4KTtcbiAgfVxuXG4gIC8qKiBUaGUgdmlzdWFsaXplciB2aWV3IGlzIGdvaW5nIGF3YXk6IGRldGFjaCBldmVyeSBiYWNrZW5kIOKAlCBkcm9wcGluZyB0aGVpciB2aWV3LWJvdW5kXG4gICAqICBzdWJzY3JpcHRpb25zIGFuZCBkaXNwb3NpbmcgdGhlIG5hcGFyaS1qcyB2aWV3ZXIsIHdob3NlIGNhbnZhcywgcmVuZGVyIGxvb3AgYW5kIEdQVVxuICAgKiAgYnVmZmVycyB3b3VsZCBvdGhlcndpc2Ugb3V0bGl2ZSB0aGUgdmlldyAoZm9yIGEgY29tcG9uZW50LXNjb3BlZCBjaGFpbiwgZm9yZXZlcikuXG4gICAqICBOb3RoaW5nIGlzIG9uIHNjcmVlbiBhZnRlcndhcmRzLCBzbyB0aGUgbmV4dCBwbG90IHN0YXJ0cyBmcm9tIHRoZSBkZWZhdWx0IGJhY2tlbmQuICovXG4gIGRldGFjaCgpOiB2b2lkIHtcbiAgICB0aGlzLnNsaWNlUmVxdWVzdCsrO1xuICAgIHRoaXMuc2VjdGlvbnMuc3RvcCgpO1xuICAgIHRoaXMuc2xpY2VNb3VudGVkID0gZmFsc2U7XG4gICAgdGhpcy5zbGljZURpdiA9IG51bGw7XG4gICAgdGhpcy5wbG90bHkuZGV0YWNoKCk7XG4gICAgdGhpcy5vc2QuZGV0YWNoKCk7XG4gICAgdGhpcy5uYXBhcmkuZGV0YWNoKCk7XG4gICAgdGhpcy5sYXN0UmVuZGVyZWQgPSBudWxsO1xuICB9XG5cbiAgLyoqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgZGV0YWNofS4gKi9cbiAgdW5zdWJzY3JpYmUoKTogdm9pZCB7XG4gICAgdGhpcy5kZXRhY2goKTtcbiAgfVxufVxuIl19