@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.
- package/README.md +201 -460
- package/esm2022/index.mjs +34 -15
- package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
- package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
- package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
- package/esm2022/lib/contracts/color.mjs +60 -0
- package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
- package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
- package/esm2022/lib/contracts/display-types.mjs +11 -1
- package/esm2022/lib/contracts/image.contract.mjs +1 -1
- package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/intensity.mjs +48 -5
- package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
- package/esm2022/lib/contracts/plot-type.mjs +134 -17
- package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
- package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
- package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
- package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
- package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
- package/esm2022/lib/contracts/sam.contract.mjs +1 -1
- package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
- package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
- package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/contracts/viz-config.mjs +2 -1
- package/esm2022/lib/geometry/contour.mjs +63 -0
- package/esm2022/lib/geometry/loft.mjs +128 -0
- package/esm2022/lib/geometry/polylabel.mjs +156 -0
- package/esm2022/lib/geometry/raster.mjs +98 -0
- package/esm2022/lib/geometry/reconstruct.mjs +315 -0
- package/esm2022/lib/geometry/reslice-image.mjs +57 -0
- package/esm2022/lib/geometry/ring.mjs +201 -0
- package/esm2022/lib/geometry/section.mjs +215 -0
- package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
- package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
- package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
- package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
- package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
- package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
- package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +12 -9
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +83 -0
- package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +180 -591
- package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +270 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
- package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
- package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
- package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
- package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +347 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +427 -4207
- package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +550 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
- package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +194 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
- package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
- package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
- package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
- package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
- package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
- package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
- package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
- package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
- package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +164 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +213 -716
- package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
- package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
- package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
- package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
- package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
- package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
- package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
- package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
- package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
- package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
- package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
- package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
- package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
- package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
- package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
- package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
- package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
- package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
- package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
- package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
- package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
- package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
- package/esm2022/lib/implementations/region-centroids.mjs +47 -0
- package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
- package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
- package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
- package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
- package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
- package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
- package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
- package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
- package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
- package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
- package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
- package/esm2022/lib/models/bezier.mjs +1 -11
- package/esm2022/lib/models/class-preset.mjs +41 -3
- package/esm2022/lib/models/geometry.mjs +27 -164
- package/esm2022/lib/models/polygon-edit.mjs +254 -0
- package/esm2022/lib/models/polygon-factory.mjs +134 -0
- package/esm2022/lib/models/region-clone.mjs +68 -0
- package/esm2022/lib/models/region-geojson.mjs +411 -0
- package/esm2022/lib/models/region.mjs +34 -33
- package/esm2022/lib/models/shape.mjs +18 -16
- package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
- package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
- package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
- package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
- package/esm2022/lib/plot.utilities.mjs +296 -473
- package/esm2022/lib/processing/image-crop.mjs +1 -1
- package/esm2022/lib/processing/processing-image.mjs +28 -15
- package/esm2022/lib/provide-visualization.mjs +40 -14
- package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
- package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +163 -0
- package/esm2022/lib/region-editor/file-stem.mjs +13 -0
- package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
- package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
- package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
- package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
- package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
- package/esm2022/lib/region-editor/region-editor.component.mjs +896 -660
- package/esm2022/lib/region-editor/region-metrics.mjs +86 -0
- package/esm2022/lib/region-editor/region-persistence.service.mjs +160 -0
- package/esm2022/lib/region-editor/region-table/region-table.component.mjs +169 -0
- package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
- package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
- package/esm2022/lib/region-ops.service.mjs +28 -70
- package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
- package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
- package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
- package/esm2022/lib/region-overlay/region-style.mjs +97 -0
- package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
- package/esm2022/lib/region-source/http-region-source.mjs +104 -0
- package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
- package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
- package/esm2022/lib/region-source/region-source.mjs +67 -0
- package/esm2022/lib/region-source/region-tiles.mjs +708 -0
- package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
- package/esm2022/lib/render-orchestrator.mjs +14 -11
- package/esm2022/lib/render-session.mjs +207 -0
- package/esm2022/lib/routing-visualizer.service.mjs +858 -414
- package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
- package/esm2022/lib/spatial/density-raster.mjs +14 -0
- package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
- package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
- package/esm2022/lib/spatial/gene-search.mjs +1 -1
- package/esm2022/lib/spatial/glyphs.mjs +97 -0
- package/esm2022/lib/spatial/lod.mjs +187 -0
- package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
- package/esm2022/lib/spatial/spatial-density.mjs +25 -16
- package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
- package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
- package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
- package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
- package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
- package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
- package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
- package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
- package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
- package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
- package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
- package/esm2022/lib/spatial/stats.mjs +71 -0
- package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
- package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
- package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
- package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
- package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
- package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
- package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
- package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
- package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
- package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
- package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
- package/esm2022/lib/store/class-color.util.mjs +53 -5
- package/esm2022/lib/store/class-signatures.mjs +63 -0
- package/esm2022/lib/store/region-history.mjs +146 -0
- package/esm2022/lib/store/region-scope-cache.mjs +144 -0
- package/esm2022/lib/store/region-selection.mjs +82 -0
- package/esm2022/lib/store/region-source-scope.mjs +171 -0
- package/esm2022/lib/store/region-store.service.mjs +986 -670
- package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
- package/esm2022/lib/store/visualizer-store.service.mjs +81 -76
- package/esm2022/lib/toast-outlets.mjs +5 -4
- package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
- package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
- package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
- package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
- package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
- package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +120 -0
- package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
- package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
- package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
- package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
- package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
- package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
- package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
- package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
- package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
- package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
- package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
- package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
- package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
- package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +121 -0
- package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
- package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
- package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
- package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
- package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
- package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
- package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
- package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
- package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
- package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
- package/esm2022/lib/toolbar/toolbar.component.mjs +84 -119
- package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
- package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
- package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
- package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
- package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
- package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
- package/esm2022/lib/util/mark-for-check.mjs +17 -0
- package/esm2022/lib/util/supersede.mjs +56 -0
- package/esm2022/lib/visualization.module.mjs +39 -141
- package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
- package/esm2022/lib/visualizer/region-actions.mjs +149 -0
- package/esm2022/lib/visualizer/region-load.mjs +123 -0
- package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
- package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
- package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
- package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
- package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
- package/esm2022/lib/visualizer.component.mjs +602 -1902
- package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
- package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
- package/esm2022/lib/workers/spatial-math.mjs +190 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs +47169 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs +238 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
- package/fesm2022/mask.worker.js +36 -917
- package/fesm2022/onnx-sam.worker.js +52 -16
- package/fesm2022/region-source.worker.js +1067 -0
- package/fesm2022/spatial-math.worker.js +471 -0
- package/fesm2022/tsne.worker.js +32 -15
- package/index.d.ts +19 -10
- package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
- package/lib/contracts/capabilities.contract.d.ts +4 -2
- package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
- package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
- package/lib/contracts/color.d.ts +27 -0
- package/lib/contracts/colormap-lut.d.ts +19 -4
- package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
- package/lib/contracts/display-types.d.ts +21 -0
- package/lib/contracts/image.contract.d.ts +4 -0
- package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
- package/lib/contracts/intensity.d.ts +13 -2
- package/lib/contracts/plot-type.d.ts +3 -1
- package/lib/contracts/ports/image-state.port.d.ts +6 -2
- package/lib/contracts/ports/preferences.port.d.ts +4 -0
- package/lib/contracts/ports/region-io.port.d.ts +1 -0
- package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
- package/lib/contracts/ports/tile-access.port.d.ts +1 -0
- package/lib/contracts/region-editor-api.contract.d.ts +85 -1
- package/lib/contracts/region-overlay.contract.d.ts +5 -0
- package/lib/contracts/region-store.contract.d.ts +22 -0
- package/lib/contracts/sam.contract.d.ts +7 -0
- package/lib/contracts/section-view.contract.d.ts +44 -0
- package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
- package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
- package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
- package/lib/contracts/visualizer.contract.d.ts +231 -54
- package/lib/contracts/viz-config.d.ts +9 -0
- package/lib/geometry/contour.d.ts +24 -0
- package/lib/geometry/loft.d.ts +22 -0
- package/lib/geometry/polylabel.d.ts +23 -0
- package/lib/geometry/raster.d.ts +42 -0
- package/lib/geometry/reconstruct.d.ts +54 -0
- package/lib/geometry/reslice-image.d.ts +33 -0
- package/lib/geometry/ring.d.ts +67 -0
- package/lib/geometry/section.d.ts +52 -0
- package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
- package/lib/implementations/base-store-visualizer.d.ts +61 -15
- package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
- package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
- package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
- package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
- package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -3
- package/lib/implementations/napari-js/napari-loading-state.d.ts +37 -0
- package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +68 -71
- package/lib/implementations/napari-js/napari-scene.d.ts +126 -0
- package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
- package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
- package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
- package/lib/implementations/napari-js/napari-spatial-hover.d.ts +91 -0
- package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
- package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
- package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
- package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
- package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
- package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +169 -883
- package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +148 -0
- package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
- package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
- package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
- package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
- package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
- package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
- package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
- package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
- package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
- package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
- package/lib/implementations/osd/display-pipeline.d.ts +38 -9
- package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
- package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
- package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
- package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
- package/lib/implementations/osd/osd-coords.d.ts +6 -4
- package/lib/implementations/osd/osd-export.d.ts +36 -0
- package/lib/implementations/osd/osd-lib.d.ts +7 -0
- package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
- package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
- package/lib/implementations/osd/osd-region-overlay-draw.d.ts +38 -0
- package/lib/implementations/osd/osd-region-overlay.d.ts +46 -51
- package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
- package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
- package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
- package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
- package/lib/implementations/osd/osd-viewport.d.ts +77 -0
- package/lib/implementations/osd/osd-zoom.d.ts +6 -0
- package/lib/implementations/osd/simple-source.d.ts +161 -0
- package/lib/implementations/osd/slice-cache.d.ts +12 -3
- package/lib/implementations/osd/tile-client.d.ts +11 -14
- package/lib/implementations/osd/tile-recolor.d.ts +141 -0
- package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
- package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
- package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
- package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
- package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
- package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
- package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
- package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
- package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
- package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
- package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
- package/lib/implementations/plotly/plotly.service.d.ts +136 -401
- package/lib/implementations/region-centroids.d.ts +14 -0
- package/lib/implementations/simple-slice-access.service.d.ts +7 -4
- package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
- package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
- package/lib/implementations/tile-server/index.d.ts +5 -0
- package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
- package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
- package/lib/implementations/tile-server/tile-protocol.d.ts +83 -0
- package/lib/implementations/tile-server/transport.d.ts +62 -0
- package/lib/intensity/intensity-profile.d.ts +66 -0
- package/lib/intensity/intensity-profile.service.d.ts +108 -0
- package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
- package/lib/models/bezier.d.ts +0 -5
- package/lib/models/class-preset.d.ts +25 -0
- package/lib/models/geometry.d.ts +14 -48
- package/lib/models/polygon-edit.d.ts +72 -0
- package/lib/models/polygon-factory.d.ts +45 -0
- package/lib/models/region-clone.d.ts +20 -0
- package/lib/models/region-geojson.d.ts +57 -0
- package/lib/models/region.d.ts +59 -4
- package/lib/models/shape.d.ts +8 -0
- package/lib/plot-mode/contribution-host.d.ts +125 -0
- package/lib/plot-mode/plot-type-menu.d.ts +60 -0
- package/lib/plot-mode/tool-params-model.d.ts +49 -0
- package/lib/plot.utilities.d.ts +19 -30
- package/lib/processing/processing-image.d.ts +5 -2
- package/lib/provide-visualization.d.ts +19 -2
- package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
- package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +86 -0
- package/lib/region-editor/file-stem.d.ts +7 -0
- package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
- package/lib/region-editor/mask-export.service.d.ts +54 -0
- package/lib/region-editor/mask-raster.d.ts +2 -8
- package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
- package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
- package/lib/region-editor/region-editor.component.d.ts +283 -200
- package/lib/region-editor/region-metrics.d.ts +34 -0
- package/lib/region-editor/region-persistence.service.d.ts +77 -0
- package/lib/region-editor/region-table/region-table.component.d.ts +89 -0
- package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
- package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
- package/lib/region-ops.service.d.ts +1 -7
- package/lib/region-overlay/region-geometry.d.ts +158 -0
- package/lib/region-overlay/region-hit-test.d.ts +38 -0
- package/lib/region-overlay/region-source-layer.d.ts +96 -0
- package/lib/region-overlay/region-style.d.ts +52 -0
- package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
- package/lib/region-source/http-region-source.d.ts +45 -0
- package/lib/region-source/region-source-ops.d.ts +89 -0
- package/lib/region-source/region-source-worker.d.ts +7 -0
- package/lib/region-source/region-source.d.ts +82 -0
- package/lib/region-source/region-tiles.d.ts +289 -0
- package/lib/region-source/worker-region-source.d.ts +65 -0
- package/lib/render-orchestrator.d.ts +6 -2
- package/lib/render-session.d.ts +75 -0
- package/lib/routing-visualizer.service.d.ts +248 -59
- package/lib/section-pane/section-pane.component.d.ts +47 -0
- package/lib/spatial/density-raster.d.ts +6 -0
- package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
- package/lib/spatial/embedding-compute.d.ts +21 -2
- package/lib/spatial/glyphs.d.ts +16 -0
- package/lib/spatial/lod.d.ts +94 -0
- package/lib/spatial/spatial-controls.facade.d.ts +64 -0
- package/lib/spatial/spatial-density.d.ts +15 -5
- package/lib/spatial/spatial-encoding.d.ts +11 -44
- package/lib/spatial/spatial-expression.d.ts +40 -22
- package/lib/spatial/spatial-framing.d.ts +1 -0
- package/lib/spatial/spatial-heatmap.d.ts +2 -0
- package/lib/spatial/spatial-hover.d.ts +4 -16
- package/lib/spatial/spatial-panel-model.d.ts +135 -0
- package/lib/spatial/spatial-selection.d.ts +21 -26
- package/lib/spatial/spatial-tile-merge.d.ts +41 -0
- package/lib/spatial/spatial-tiles.d.ts +9 -256
- package/lib/spatial/stats.d.ts +38 -0
- package/lib/spatial/transcript-grouping.d.ts +119 -0
- package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
- package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
- package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
- package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
- package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
- package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
- package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
- package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
- package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
- package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
- package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
- package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
- package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
- package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
- package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
- package/lib/store/class-color.util.d.ts +39 -2
- package/lib/store/class-signatures.d.ts +11 -0
- package/lib/store/region-history.d.ts +66 -0
- package/lib/store/region-scope-cache.d.ts +65 -0
- package/lib/store/region-selection.d.ts +36 -0
- package/lib/store/region-source-scope.d.ts +68 -0
- package/lib/store/region-store.service.d.ts +312 -116
- package/lib/store/visualizer-store.service.d.ts +32 -33
- package/lib/toast-outlets.d.ts +4 -3
- package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
- package/lib/toolbar/canvas-tools.d.ts +20 -0
- package/lib/toolbar/crop/slide-crop.d.ts +10 -4
- package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
- package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
- package/lib/toolbar/region-tools/region-tools.component.d.ts +62 -0
- package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
- package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
- package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
- package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
- package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
- package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
- package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
- package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
- package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
- package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
- package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
- package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
- package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
- package/lib/toolbar/stack-controls/stack-controls.component.d.ts +51 -0
- package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
- package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
- package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
- package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
- package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
- package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
- package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
- package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
- package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
- package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
- package/lib/toolbar/toolbar.component.d.ts +55 -84
- package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
- package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
- package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
- package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
- package/lib/toolbar/wand/wand.service.d.ts +22 -116
- package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
- package/lib/util/mark-for-check.d.ts +11 -0
- package/lib/util/supersede.d.ts +53 -0
- package/lib/visualization.module.d.ts +18 -39
- package/lib/visualizer/floating-drag.directive.d.ts +30 -0
- package/lib/visualizer/region-actions.d.ts +54 -0
- package/lib/visualizer/region-load.d.ts +46 -0
- package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
- package/lib/visualizer/tool-modes.d.ts +49 -0
- package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
- package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
- package/lib/visualizer/volume-sections.d.ts +64 -0
- package/lib/visualizer.component.d.ts +232 -447
- package/lib/workers/spatial-math-ops.d.ts +65 -0
- package/lib/workers/spatial-math-worker.d.ts +7 -0
- package/lib/workers/spatial-math.d.ts +74 -0
- package/package.json +12 -3
- package/src/lib/assets/slice.svg +23 -0
- package/src/lib/styles/_viz-icons-rules.scss +73 -0
- package/src/lib/styles/viz-icons.scss +14 -0
- package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
- package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
- package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
- package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
- package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
- package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
- package/src/lib/assets/cell-detection.svg +0 -37
- package/src/lib/assets/click.svg +0 -1
- package/src/lib/assets/colormap-luts.json +0 -1
- package/src/lib/assets/edit-selection-white.svg +0 -47
- package/src/lib/assets/icons/colormap-earth.png +0 -0
- package/src/lib/assets/icons/colormap-placeholder.png +0 -0
- package/src/lib/assets/icons/colormap-pubu.png +0 -0
- package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
- package/src/lib/assets/picture-segmentation.svg +0 -43
- package/src/lib/assets/test/download-379.svg +0 -1
- package/src/lib/assets/test/download-98.svg +0 -1
- package/src/lib/assets/test/json-1.svg +0 -1
- package/src/lib/assets/test/load-53.svg +0 -1
- package/src/lib/assets/test/mask-44.svg +0 -1
- package/src/lib/assets/test/mask-download-44.svg +0 -15
- package/src/lib/assets/test/mask-save-44.svg +0 -11
- package/src/lib/assets/test/overlay-1.svg +0 -1
- package/src/lib/assets/test/overlay-4.svg +0 -1
- package/src/lib/assets/test/region-26.svg +0 -1
- package/src/lib/assets/test/save-56.svg +0 -1
- 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,
|
|
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 {
|
|
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
|
-
|
|
27
|
-
|
|
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
|
-
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
/**
|
|
111
|
-
this.
|
|
112
|
-
/**
|
|
113
|
-
|
|
114
|
-
|
|
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.
|
|
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() {
|
|
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
|
-
|
|
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) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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.
|
|
251
|
-
this.plotly.setNavigatorVisible(visible);
|
|
252
|
-
this.napari.setNavigatorVisible(visible);
|
|
457
|
+
this.viewOptions.setNavigatorVisible(visible);
|
|
253
458
|
}
|
|
254
|
-
|
|
255
|
-
// the first render, when the active renderer is still Plotly.
|
|
459
|
+
/** @deprecated Use `getOsdViewOptions().setImageSmoothingEnabled()`. */
|
|
256
460
|
setImageSmoothingEnabled(enabled) {
|
|
257
|
-
this.
|
|
258
|
-
|
|
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() {
|
|
272
|
-
|
|
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
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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) {
|
|
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
|
|
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
|
-
|
|
323
|
-
|
|
324
|
-
//
|
|
325
|
-
|
|
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
|
|
330
|
-
// Region
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
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.
|
|
337
|
-
}
|
|
338
|
-
getRegions() {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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.
|
|
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() {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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.
|
|
379
|
-
}
|
|
380
|
-
exitStackMode() {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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.
|
|
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.
|
|
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()
|
|
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.
|
|
424
|
-
//
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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() {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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() {
|
|
495
|
-
|
|
496
|
-
|
|
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$() {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
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
|
|
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.
|
|
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
|
-
*
|
|
538
|
-
*
|
|
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
|
-
|
|
557
|
-
if (!port)
|
|
1124
|
+
if (!this.spatialData)
|
|
558
1125
|
return null;
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
this.
|
|
564
|
-
|
|
565
|
-
|
|
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.
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
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
|
-
*
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
* the
|
|
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
|
-
|
|
721
|
-
|
|
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
|
-
/**
|
|
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.
|
|
1159
|
+
return this.intensitySampling.ensureIntensitySampling(imageInfo, zIndex);
|
|
732
1160
|
}
|
|
733
|
-
/**
|
|
734
|
-
|
|
735
|
-
|
|
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.
|
|
1168
|
+
return this.intensitySampling.getViewportChange$();
|
|
738
1169
|
}
|
|
739
|
-
/**
|
|
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.
|
|
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.
|
|
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
|