@igo2/common 1.15.4 → 1.15.5
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/esm2020/igo2-common.mjs +4 -4
- package/esm2020/lib/action/action.module.mjs +27 -27
- package/esm2020/lib/action/actionbar/actionbar-item.component.mjs +252 -252
- package/esm2020/lib/action/actionbar/actionbar.component.mjs +370 -370
- package/esm2020/lib/action/actionbar/actionbar.module.mjs +57 -57
- package/esm2020/lib/action/index.mjs +3 -3
- package/esm2020/lib/action/shared/action.enums.mjs +7 -7
- package/esm2020/lib/action/shared/action.interfaces.mjs +2 -2
- package/esm2020/lib/action/shared/index.mjs +4 -4
- package/esm2020/lib/action/shared/store.mjs +8 -8
- package/esm2020/lib/backdrop/backdrop.component.mjs +26 -26
- package/esm2020/lib/backdrop/backdrop.module.mjs +25 -25
- package/esm2020/lib/backdrop/index.mjs +2 -2
- package/esm2020/lib/badge-icon/badge-icon.directive.mjs +141 -141
- package/esm2020/lib/badge-icon/badge-icon.module.mjs +26 -26
- package/esm2020/lib/badge-icon/index.mjs +2 -2
- package/esm2020/lib/clickout/clickout.directive.mjs +32 -32
- package/esm2020/lib/clickout/clickout.module.mjs +24 -24
- package/esm2020/lib/clickout/index.mjs +2 -2
- package/esm2020/lib/clone/clone.module.mjs +24 -24
- package/esm2020/lib/clone/clone.pipe.mjs +24 -24
- package/esm2020/lib/clone/index.mjs +2 -2
- package/esm2020/lib/collapsible/collapse.directive.mjs +55 -55
- package/esm2020/lib/collapsible/collapsible.component.mjs +57 -57
- package/esm2020/lib/collapsible/collapsible.module.mjs +27 -27
- package/esm2020/lib/collapsible/index.mjs +3 -3
- package/esm2020/lib/confirm-dialog/confirm-dialog.component.mjs +44 -44
- package/esm2020/lib/confirm-dialog/confirm-dialog.module.mjs +29 -29
- package/esm2020/lib/confirm-dialog/confirm-dialog.service.mjs +24 -24
- package/esm2020/lib/confirm-dialog/index.mjs +3 -3
- package/esm2020/lib/context-menu/context-menu.directive.mjs +103 -103
- package/esm2020/lib/context-menu/context-menu.module.mjs +25 -25
- package/esm2020/lib/context-menu/index.mjs +3 -3
- package/esm2020/lib/context-menu/long-press.directive.mjs +67 -67
- package/esm2020/lib/custom-html/custom-html.component.mjs +28 -28
- package/esm2020/lib/custom-html/custom-html.module.mjs +47 -47
- package/esm2020/lib/custom-html/custom-html.pipe.mjs +18 -18
- package/esm2020/lib/custom-html/index.mjs +3 -3
- package/esm2020/lib/dom/dom.interfaces.mjs +2 -2
- package/esm2020/lib/dom/dom.module.mjs +23 -23
- package/esm2020/lib/dom/dom.service.mjs +30 -30
- package/esm2020/lib/dom/index.mjs +3 -3
- package/esm2020/lib/drag-drop/drag-drop.directive.mjs +87 -87
- package/esm2020/lib/drag-drop/drag-drop.module.mjs +24 -24
- package/esm2020/lib/drag-drop/index.mjs +2 -2
- package/esm2020/lib/dynamic-component/dynamic-component.module.mjs +31 -31
- package/esm2020/lib/dynamic-component/dynamic-outlet/dynamic-outlet.component.mjs +122 -122
- package/esm2020/lib/dynamic-component/dynamic-outlet/dynamic-outlet.module.mjs +28 -28
- package/esm2020/lib/dynamic-component/index.mjs +3 -3
- package/esm2020/lib/dynamic-component/shared/dynamic-component.interfaces.mjs +2 -2
- package/esm2020/lib/dynamic-component/shared/dynamic-component.mjs +174 -174
- package/esm2020/lib/dynamic-component/shared/dynamic-component.service.mjs +29 -29
- package/esm2020/lib/dynamic-component/shared/index.mjs +4 -4
- package/esm2020/lib/entity/entity-selector/entity-selector.component.mjs +194 -194
- package/esm2020/lib/entity/entity-selector/entity-selector.module.mjs +32 -32
- package/esm2020/lib/entity/entity-table/entity-table-row.directive.mjs +137 -137
- package/esm2020/lib/entity/entity-table/entity-table.component.mjs +1376 -1376
- package/esm2020/lib/entity/entity-table/entity-table.module.mjs +102 -102
- package/esm2020/lib/entity/entity-table-paginator/entity-table-paginator.component.mjs +132 -132
- package/esm2020/lib/entity/entity-table-paginator/entity-table-paginator.interface.mjs +2 -2
- package/esm2020/lib/entity/entity-table-paginator/entity-table-paginator.module.mjs +28 -28
- package/esm2020/lib/entity/entity.module.mjs +31 -31
- package/esm2020/lib/entity/index.mjs +6 -6
- package/esm2020/lib/entity/shared/entity.enums.mjs +28 -28
- package/esm2020/lib/entity/shared/entity.interfaces.mjs +2 -2
- package/esm2020/lib/entity/shared/entity.utils.mjs +67 -67
- package/esm2020/lib/entity/shared/index.mjs +10 -10
- package/esm2020/lib/entity/shared/state.mjs +191 -191
- package/esm2020/lib/entity/shared/store.mjs +288 -288
- package/esm2020/lib/entity/shared/strategies/filter-custom-function.mjs +79 -79
- package/esm2020/lib/entity/shared/strategies/filter-selection.mjs +84 -84
- package/esm2020/lib/entity/shared/strategies/index.mjs +4 -4
- package/esm2020/lib/entity/shared/strategies/strategy.mjs +75 -75
- package/esm2020/lib/entity/shared/transaction.mjs +316 -316
- package/esm2020/lib/entity/shared/view.mjs +315 -315
- package/esm2020/lib/entity/shared/watcher.mjs +120 -120
- package/esm2020/lib/flexible/flexible.component.mjs +148 -148
- package/esm2020/lib/flexible/flexible.module.mjs +24 -24
- package/esm2020/lib/flexible/flexible.type.mjs +2 -2
- package/esm2020/lib/flexible/index.mjs +3 -3
- package/esm2020/lib/form/form/form.component.mjs +117 -117
- package/esm2020/lib/form/form/form.module.mjs +40 -40
- package/esm2020/lib/form/form-field/form-field-select.component.mjs +127 -127
- package/esm2020/lib/form/form-field/form-field-text.component.mjs +104 -104
- package/esm2020/lib/form/form-field/form-field-textarea.component.mjs +105 -105
- package/esm2020/lib/form/form-field/form-field.component.mjs +72 -72
- package/esm2020/lib/form/form-field/form-field.module.mjs +74 -74
- package/esm2020/lib/form/form-field/index.mjs +5 -5
- package/esm2020/lib/form/form-group/form-group.component.mjs +105 -105
- package/esm2020/lib/form/form-group/form-group.module.mjs +40 -40
- package/esm2020/lib/form/form.module.mjs +49 -49
- package/esm2020/lib/form/index.mjs +5 -5
- package/esm2020/lib/form/shared/form-field-component.mjs +7 -7
- package/esm2020/lib/form/shared/form-field.service.mjs +29 -29
- package/esm2020/lib/form/shared/form.interfaces.mjs +2 -2
- package/esm2020/lib/form/shared/form.service.mjs +81 -81
- package/esm2020/lib/form/shared/form.utils.mjs +40 -40
- package/esm2020/lib/form/shared/index.mjs +6 -6
- package/esm2020/lib/home-button/home-button.component.mjs +31 -31
- package/esm2020/lib/home-button/home-button.module.mjs +41 -41
- package/esm2020/lib/home-button/index.mjs +2 -2
- package/esm2020/lib/image/image-error.directive.mjs +35 -35
- package/esm2020/lib/image/image.module.mjs +25 -25
- package/esm2020/lib/image/index.mjs +3 -3
- package/esm2020/lib/image/secure-image.pipe.mjs +59 -59
- package/esm2020/lib/interactive-tour/index.mjs +5 -5
- package/esm2020/lib/interactive-tour/interactive-tour.component.mjs +135 -135
- package/esm2020/lib/interactive-tour/interactive-tour.interface.mjs +2 -2
- package/esm2020/lib/interactive-tour/interactive-tour.loader.mjs +44 -44
- package/esm2020/lib/interactive-tour/interactive-tour.module.mjs +40 -40
- package/esm2020/lib/interactive-tour/interactive-tour.service.mjs +285 -285
- package/esm2020/lib/json-dialog/index.mjs +3 -3
- package/esm2020/lib/json-dialog/json-dialog.component.mjs +109 -109
- package/esm2020/lib/json-dialog/json-dialog.module.mjs +29 -29
- package/esm2020/lib/json-dialog/json-dialog.service.mjs +24 -24
- package/esm2020/lib/keyvalue/index.mjs +2 -2
- package/esm2020/lib/keyvalue/keyvalue.module.mjs +24 -24
- package/esm2020/lib/keyvalue/keyvalue.pipe.mjs +18 -18
- package/esm2020/lib/list/index.mjs +3 -3
- package/esm2020/lib/list/list-item.directive.mjs +165 -165
- package/esm2020/lib/list/list.component.mjs +262 -262
- package/esm2020/lib/list/list.module.mjs +29 -29
- package/esm2020/lib/panel/index.mjs +2 -2
- package/esm2020/lib/panel/panel.component.mjs +59 -59
- package/esm2020/lib/panel/panel.module.mjs +19 -19
- package/esm2020/lib/sidenav/index.mjs +2 -2
- package/esm2020/lib/sidenav/sidenav-shim.directive.mjs +55 -55
- package/esm2020/lib/sidenav/sidenav.module.mjs +24 -24
- package/esm2020/lib/spinner/index.mjs +3 -3
- package/esm2020/lib/spinner/spinner-activity.directive.mjs +47 -47
- package/esm2020/lib/spinner/spinner.component.mjs +35 -35
- package/esm2020/lib/spinner/spinner.module.mjs +21 -21
- package/esm2020/lib/stop-propagation/index.mjs +3 -3
- package/esm2020/lib/stop-propagation/stop-drop-propagation.directive.mjs +22 -22
- package/esm2020/lib/stop-propagation/stop-propagation.directive.mjs +21 -21
- package/esm2020/lib/stop-propagation/stop-propagation.module.mjs +25 -25
- package/esm2020/lib/table/index.mjs +6 -6
- package/esm2020/lib/table/table-action-color.enum.mjs +7 -7
- package/esm2020/lib/table/table-database.mjs +28 -28
- package/esm2020/lib/table/table-datasource.mjs +61 -61
- package/esm2020/lib/table/table-model.interface.mjs +2 -2
- package/esm2020/lib/table/table.component.mjs +297 -297
- package/esm2020/lib/table/table.module.mjs +67 -67
- package/esm2020/lib/tool/index.mjs +3 -3
- package/esm2020/lib/tool/shared/index.mjs +6 -6
- package/esm2020/lib/tool/shared/tool-component.mjs +9 -9
- package/esm2020/lib/tool/shared/tool.interface.mjs +2 -2
- package/esm2020/lib/tool/shared/tool.service.mjs +43 -43
- package/esm2020/lib/tool/shared/toolbox.enums.mjs +7 -7
- package/esm2020/lib/tool/shared/toolbox.mjs +179 -179
- package/esm2020/lib/tool/tool.module.mjs +32 -32
- package/esm2020/lib/tool/toolbox/toolbox.animation.mjs +10 -10
- package/esm2020/lib/tool/toolbox/toolbox.component.mjs +255 -255
- package/esm2020/lib/tool/toolbox/toolbox.module.mjs +36 -36
- package/esm2020/lib/widget/index.mjs +3 -3
- package/esm2020/lib/widget/shared/index.mjs +4 -4
- package/esm2020/lib/widget/shared/widget.interfaces.mjs +2 -2
- package/esm2020/lib/widget/shared/widget.mjs +4 -4
- package/esm2020/lib/widget/shared/widget.service.mjs +20 -20
- package/esm2020/lib/widget/widget-outlet/widget-outlet.component.mjs +116 -116
- package/esm2020/lib/widget/widget-outlet/widget-outlet.module.mjs +32 -32
- package/esm2020/lib/widget/widget.module.mjs +32 -32
- package/esm2020/lib/workspace/index.mjs +4 -4
- package/esm2020/lib/workspace/shared/index.mjs +4 -4
- package/esm2020/lib/workspace/shared/store.mjs +40 -40
- package/esm2020/lib/workspace/shared/workspace.interfaces.mjs +2 -2
- package/esm2020/lib/workspace/shared/workspace.mjs +117 -117
- package/esm2020/lib/workspace/workspace-selector/workspace-selector.component.mjs +51 -51
- package/esm2020/lib/workspace/workspace-selector/workspace-selector.module.mjs +32 -32
- package/esm2020/lib/workspace/workspace-widget-outlet/workspace-widget-outlet.component.mjs +88 -88
- package/esm2020/lib/workspace/workspace-widget-outlet/workspace-widget-outlet.module.mjs +32 -32
- package/esm2020/lib/workspace/workspace.module.mjs +27 -27
- package/esm2020/public_api.mjs +74 -74
- package/fesm2015/igo2-common.mjs +10016 -10016
- package/fesm2015/igo2-common.mjs.map +1 -1
- package/fesm2020/igo2-common.mjs +9319 -9319
- package/fesm2020/igo2-common.mjs.map +1 -1
- package/index.d.ts +5 -5
- package/lib/action/action.module.d.ts +8 -8
- package/lib/action/actionbar/actionbar-item.component.d.ts +78 -78
- package/lib/action/actionbar/actionbar.component.d.ts +146 -146
- package/lib/action/actionbar/actionbar.module.d.ts +20 -20
- package/lib/action/index.d.ts +2 -2
- package/lib/action/shared/action.enums.d.ts +5 -5
- package/lib/action/shared/action.interfaces.d.ts +17 -17
- package/lib/action/shared/index.d.ts +3 -3
- package/lib/action/shared/store.d.ts +8 -8
- package/lib/backdrop/backdrop.component.d.ts +9 -9
- package/lib/backdrop/backdrop.module.d.ts +10 -10
- package/lib/backdrop/index.d.ts +1 -1
- package/lib/badge-icon/badge-icon.directive.d.ts +36 -36
- package/lib/badge-icon/badge-icon.module.d.ts +11 -11
- package/lib/badge-icon/index.d.ts +1 -1
- package/lib/clickout/clickout.directive.d.ts +10 -10
- package/lib/clickout/clickout.module.d.ts +9 -9
- package/lib/clickout/index.d.ts +1 -1
- package/lib/clone/clone.module.d.ts +9 -9
- package/lib/clone/clone.pipe.d.ts +7 -7
- package/lib/clone/index.d.ts +1 -1
- package/lib/collapsible/collapse.directive.d.ts +19 -19
- package/lib/collapsible/collapsible.component.d.ts +13 -13
- package/lib/collapsible/collapsible.module.d.ts +12 -12
- package/lib/collapsible/index.d.ts +2 -2
- package/lib/confirm-dialog/confirm-dialog.component.d.ts +9 -9
- package/lib/confirm-dialog/confirm-dialog.module.d.ts +12 -12
- package/lib/confirm-dialog/confirm-dialog.service.d.ts +12 -12
- package/lib/confirm-dialog/index.d.ts +2 -2
- package/lib/context-menu/context-menu.directive.d.ts +21 -21
- package/lib/context-menu/context-menu.module.d.ts +10 -10
- package/lib/context-menu/index.d.ts +2 -2
- package/lib/context-menu/long-press.directive.d.ts +20 -20
- package/lib/custom-html/custom-html.component.d.ts +9 -9
- package/lib/custom-html/custom-html.module.d.ts +16 -16
- package/lib/custom-html/custom-html.pipe.d.ts +10 -10
- package/lib/custom-html/index.d.ts +2 -2
- package/lib/dom/dom.interfaces.d.ts +10 -10
- package/lib/dom/dom.module.d.ts +8 -8
- package/lib/dom/dom.service.d.ts +10 -10
- package/lib/dom/index.d.ts +2 -2
- package/lib/drag-drop/drag-drop.directive.d.ts +14 -14
- package/lib/drag-drop/drag-drop.module.d.ts +9 -9
- package/lib/drag-drop/index.d.ts +1 -1
- package/lib/dynamic-component/dynamic-component.module.d.ts +8 -8
- package/lib/dynamic-component/dynamic-outlet/dynamic-outlet.component.d.ts +70 -70
- package/lib/dynamic-component/dynamic-outlet/dynamic-outlet.module.d.ts +11 -11
- package/lib/dynamic-component/index.d.ts +2 -2
- package/lib/dynamic-component/shared/dynamic-component.d.ts +88 -88
- package/lib/dynamic-component/shared/dynamic-component.interfaces.d.ts +3 -3
- package/lib/dynamic-component/shared/dynamic-component.service.d.ts +18 -18
- package/lib/dynamic-component/shared/index.d.ts +3 -3
- package/lib/entity/entity-selector/entity-selector.component.d.ts +92 -92
- package/lib/entity/entity-selector/entity-selector.module.d.ts +13 -13
- package/lib/entity/entity-table/entity-table-row.directive.d.ts +69 -69
- package/lib/entity/entity-table/entity-table.component.d.ts +333 -333
- package/lib/entity/entity-table/entity-table.module.d.ts +29 -29
- package/lib/entity/entity-table-paginator/entity-table-paginator.component.d.ts +49 -49
- package/lib/entity/entity-table-paginator/entity-table-paginator.interface.d.ts +8 -8
- package/lib/entity/entity-table-paginator/entity-table-paginator.module.d.ts +11 -11
- package/lib/entity/entity.module.d.ts +10 -10
- package/lib/entity/index.d.ts +5 -5
- package/lib/entity/shared/entity.enums.d.ts +23 -23
- package/lib/entity/shared/entity.interfaces.d.ts +114 -114
- package/lib/entity/shared/entity.utils.d.ts +49 -49
- package/lib/entity/shared/index.d.ts +9 -9
- package/lib/entity/shared/state.d.ts +103 -103
- package/lib/entity/shared/store.d.ts +176 -176
- package/lib/entity/shared/strategies/filter-custom-function.d.ts +51 -51
- package/lib/entity/shared/strategies/filter-selection.d.ts +48 -48
- package/lib/entity/shared/strategies/index.d.ts +3 -3
- package/lib/entity/shared/strategies/strategy.d.ts +56 -56
- package/lib/entity/shared/transaction.d.ts +168 -168
- package/lib/entity/shared/view.d.ts +193 -193
- package/lib/entity/shared/watcher.d.ts +72 -72
- package/lib/flexible/flexible.component.d.ts +41 -41
- package/lib/flexible/flexible.module.d.ts +9 -9
- package/lib/flexible/flexible.type.d.ts +2 -2
- package/lib/flexible/index.d.ts +2 -2
- package/lib/form/form/form.component.d.ts +53 -53
- package/lib/form/form/form.module.d.ts +12 -12
- package/lib/form/form-field/form-field-select.component.d.ts +48 -48
- package/lib/form/form-field/form-field-text.component.d.ts +41 -41
- package/lib/form/form-field/form-field-textarea.component.d.ts +41 -41
- package/lib/form/form-field/form-field.component.d.ts +34 -34
- package/lib/form/form-field/form-field.module.d.ts +21 -21
- package/lib/form/form-field/index.d.ts +4 -4
- package/lib/form/form-group/form-group.component.d.ts +49 -49
- package/lib/form/form-group/form-group.module.d.ts +14 -14
- package/lib/form/form.module.d.ts +13 -13
- package/lib/form/index.d.ts +4 -4
- package/lib/form/shared/form-field-component.d.ts +1 -1
- package/lib/form/shared/form-field.service.d.ts +19 -19
- package/lib/form/shared/form.interfaces.d.ts +57 -57
- package/lib/form/shared/form.service.d.ts +15 -15
- package/lib/form/shared/form.utils.d.ts +11 -11
- package/lib/form/shared/index.d.ts +5 -5
- package/lib/home-button/home-button.component.d.ts +9 -9
- package/lib/home-button/home-button.module.d.ts +15 -15
- package/lib/home-button/index.d.ts +1 -1
- package/lib/image/image-error.directive.d.ts +11 -11
- package/lib/image/image.module.d.ts +10 -10
- package/lib/image/index.d.ts +2 -2
- package/lib/image/secure-image.pipe.d.ts +13 -13
- package/lib/interactive-tour/index.d.ts +4 -4
- package/lib/interactive-tour/interactive-tour.component.d.ts +30 -30
- package/lib/interactive-tour/interactive-tour.interface.d.ts +32 -32
- package/lib/interactive-tour/interactive-tour.loader.d.ts +18 -18
- package/lib/interactive-tour/interactive-tour.module.d.ts +12 -12
- package/lib/interactive-tour/interactive-tour.service.d.ts +29 -29
- package/lib/json-dialog/index.d.ts +2 -2
- package/lib/json-dialog/json-dialog.component.d.ts +13 -13
- package/lib/json-dialog/json-dialog.module.d.ts +13 -13
- package/lib/json-dialog/json-dialog.service.d.ts +10 -10
- package/lib/keyvalue/index.d.ts +1 -1
- package/lib/keyvalue/keyvalue.module.d.ts +9 -9
- package/lib/keyvalue/keyvalue.pipe.d.ts +7 -7
- package/lib/list/index.d.ts +2 -2
- package/lib/list/list-item.directive.d.ts +43 -43
- package/lib/list/list.component.d.ts +51 -51
- package/lib/list/list.module.d.ts +14 -14
- package/lib/panel/index.d.ts +1 -1
- package/lib/panel/panel.component.d.ts +10 -10
- package/lib/panel/panel.module.d.ts +8 -8
- package/lib/sidenav/index.d.ts +1 -1
- package/lib/sidenav/sidenav-shim.directive.d.ts +20 -20
- package/lib/sidenav/sidenav.module.d.ts +9 -9
- package/lib/spinner/index.d.ts +2 -2
- package/lib/spinner/spinner-activity.directive.d.ts +32 -32
- package/lib/spinner/spinner.component.d.ts +12 -12
- package/lib/spinner/spinner.module.d.ts +10 -10
- package/lib/stop-propagation/index.d.ts +2 -2
- package/lib/stop-propagation/stop-drop-propagation.directive.d.ts +6 -6
- package/lib/stop-propagation/stop-propagation.directive.d.ts +6 -6
- package/lib/stop-propagation/stop-propagation.module.d.ts +10 -10
- package/lib/table/index.d.ts +5 -5
- package/lib/table/table-action-color.enum.d.ts +5 -5
- package/lib/table/table-database.d.ts +10 -10
- package/lib/table/table-datasource.d.ts +17 -17
- package/lib/table/table-model.interface.d.ts +28 -28
- package/lib/table/table.component.d.ts +40 -40
- package/lib/table/table.module.d.ts +20 -20
- package/lib/tool/index.d.ts +2 -2
- package/lib/tool/shared/index.d.ts +5 -5
- package/lib/tool/shared/tool-component.d.ts +2 -2
- package/lib/tool/shared/tool.interface.d.ts +18 -18
- package/lib/tool/shared/tool.service.d.ts +30 -30
- package/lib/tool/shared/toolbox.d.ts +95 -95
- package/lib/tool/shared/toolbox.enums.d.ts +5 -5
- package/lib/tool/tool.module.d.ts +10 -10
- package/lib/tool/toolbox/toolbox.animation.d.ts +2 -2
- package/lib/tool/toolbox/toolbox.component.d.ts +127 -127
- package/lib/tool/toolbox/toolbox.module.d.ts +13 -13
- package/lib/widget/index.d.ts +2 -2
- package/lib/widget/shared/index.d.ts +3 -3
- package/lib/widget/shared/widget.d.ts +4 -4
- package/lib/widget/shared/widget.interfaces.d.ts +12 -12
- package/lib/widget/shared/widget.service.d.ts +10 -10
- package/lib/widget/widget-outlet/widget-outlet.component.d.ts +71 -71
- package/lib/widget/widget-outlet/widget-outlet.module.d.ts +12 -12
- package/lib/widget/widget.module.d.ts +8 -8
- package/lib/workspace/index.d.ts +3 -3
- package/lib/workspace/shared/index.d.ts +3 -3
- package/lib/workspace/shared/store.d.ts +20 -20
- package/lib/workspace/shared/workspace.d.ts +108 -108
- package/lib/workspace/shared/workspace.interfaces.d.ts +11 -11
- package/lib/workspace/workspace-selector/workspace-selector.component.d.ts +39 -39
- package/lib/workspace/workspace-selector/workspace-selector.module.d.ts +12 -12
- package/lib/workspace/workspace-widget-outlet/workspace-widget-outlet.component.d.ts +57 -57
- package/lib/workspace/workspace-widget-outlet/workspace-widget-outlet.module.d.ts +12 -12
- package/lib/workspace/workspace.module.d.ts +9 -9
- package/package.json +3 -3
- package/public_api.d.ts +70 -70
- package/style/common.theming.scss +12 -12
- package/style/partial/action.scss +18 -18
- package/style/partial/common.variables.scss +8 -8
|
@@ -1,316 +1,316 @@
|
|
|
1
|
-
import { of } from 'rxjs';
|
|
2
|
-
import { catchError, tap } from 'rxjs/operators';
|
|
3
|
-
import { BehaviorSubject } from 'rxjs';
|
|
4
|
-
import { EntityStore } from './store';
|
|
5
|
-
import { EntityOperationType } from './entity.enums';
|
|
6
|
-
import { getEntityId } from './entity.utils';
|
|
7
|
-
/**
|
|
8
|
-
* This class holds a reference to the insert, update and delete
|
|
9
|
-
* operations performed on a store. This is useful to commit
|
|
10
|
-
* these operations in a single pass or to cancel them.
|
|
11
|
-
*/
|
|
12
|
-
export class EntityTransaction {
|
|
13
|
-
constructor(options = {}) {
|
|
14
|
-
this.inCommitPhase$ = new BehaviorSubject(false);
|
|
15
|
-
this.getKey = options.getKey ? options.getKey : getEntityId;
|
|
16
|
-
this.operations = new EntityStore([], {
|
|
17
|
-
getKey: (operation) => operation.key
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Whether there are pending operations
|
|
22
|
-
*/
|
|
23
|
-
get empty$() { return this.operations.empty$; }
|
|
24
|
-
/**
|
|
25
|
-
* Whether there are pending operations
|
|
26
|
-
*/
|
|
27
|
-
get empty() { return this.empty$.value; }
|
|
28
|
-
/**
|
|
29
|
-
* Whether thise store is in commit phase
|
|
30
|
-
*/
|
|
31
|
-
get inCommitPhase() { return this.inCommitPhase$.value; }
|
|
32
|
-
destroy() {
|
|
33
|
-
this.operations.destroy();
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Insert an entity into a store. If no store is specified, an insert
|
|
37
|
-
* operation is still created but the transaction won't add the new
|
|
38
|
-
* entity to the store.
|
|
39
|
-
* @param current The entity to insert
|
|
40
|
-
* @param store Optional: The store to insert the entity into
|
|
41
|
-
* @param meta Optional: Any metadata on the operation
|
|
42
|
-
*/
|
|
43
|
-
insert(current, store, meta) {
|
|
44
|
-
const existingOperation = this.getOperationByEntity(current);
|
|
45
|
-
if (existingOperation !== undefined) {
|
|
46
|
-
this.removeOperation(existingOperation);
|
|
47
|
-
}
|
|
48
|
-
this.doInsert(current, store, meta);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Update an entity in a store. If no store is specified, an update
|
|
52
|
-
* operation is still created but the transaction won't update the
|
|
53
|
-
* entity into the store.
|
|
54
|
-
* @param previous The entity before update
|
|
55
|
-
* @param current The entity after update
|
|
56
|
-
* @param store Optional: The store to update the entity into
|
|
57
|
-
* @param meta Optional: Any metadata on the operation
|
|
58
|
-
*/
|
|
59
|
-
update(previous, current, store, meta) {
|
|
60
|
-
const existingOperation = this.getOperationByEntity(current);
|
|
61
|
-
if (existingOperation !== undefined) {
|
|
62
|
-
this.removeOperation(existingOperation);
|
|
63
|
-
if (existingOperation.type === EntityOperationType.Insert) {
|
|
64
|
-
this.doInsert(current, store, meta);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
else if (existingOperation.type === EntityOperationType.Update) {
|
|
68
|
-
previous = existingOperation.previous;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
this.doUpdate(previous, current, store, meta);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Delete an entity from a store. If no store is specified, a delete
|
|
75
|
-
* operation is still created but the transaction won't remove the
|
|
76
|
-
* entity from the store.
|
|
77
|
-
* @param previous The entity before delete
|
|
78
|
-
* @param store Optional: The store to delete the entity from
|
|
79
|
-
* @param meta Optional: Any metadata on the operation
|
|
80
|
-
*/
|
|
81
|
-
delete(previous, store, meta) {
|
|
82
|
-
const existingOperation = this.getOperationByEntity(previous);
|
|
83
|
-
if (existingOperation !== undefined) {
|
|
84
|
-
this.removeOperation(existingOperation);
|
|
85
|
-
if (existingOperation.type === EntityOperationType.Insert) {
|
|
86
|
-
if (store !== undefined) {
|
|
87
|
-
store.delete(previous);
|
|
88
|
-
}
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
this.doDelete(previous, store, meta);
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Commit operations the transaction. This method doesn't do much
|
|
96
|
-
* in itself. The handler it receives does the hard work and it's
|
|
97
|
-
* implementation is left to the caller. This method simply wraps
|
|
98
|
-
* the handler into an error catching mechanism to update
|
|
99
|
-
* the transaction afterward. The caller needs to subscribe to this
|
|
100
|
-
* method's output (observable) for the commit to be performed.
|
|
101
|
-
* @param operations Operations to commit
|
|
102
|
-
* @param handler Function that handles the commit operation
|
|
103
|
-
* @returns The handler output (observable)
|
|
104
|
-
*/
|
|
105
|
-
commit(operations, handler) {
|
|
106
|
-
this.inCommitPhase$.next(true);
|
|
107
|
-
return handler(this, operations)
|
|
108
|
-
.pipe(catchError(() => of(new Error())), tap((result) => {
|
|
109
|
-
if (result instanceof Error) {
|
|
110
|
-
this.onCommitError(operations);
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
this.onCommitSuccess(operations);
|
|
114
|
-
}
|
|
115
|
-
}));
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Commit all the operations of the transaction.
|
|
119
|
-
* @param handler Function that handles the commit operation
|
|
120
|
-
* @returns The handler output (observable)
|
|
121
|
-
*/
|
|
122
|
-
commitAll(handler) {
|
|
123
|
-
const operations = this.getOperationsInCommit();
|
|
124
|
-
return this.commit(operations, handler);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Rollback this transaction
|
|
128
|
-
*/
|
|
129
|
-
rollback() {
|
|
130
|
-
this.rollbackOperations(this.operations.all());
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Rollback specific operations
|
|
134
|
-
*/
|
|
135
|
-
rollbackOperations(operations) {
|
|
136
|
-
this.checkInCommitPhase();
|
|
137
|
-
const operationsFactory = () => new Map([
|
|
138
|
-
[EntityOperationType.Delete, []],
|
|
139
|
-
[EntityOperationType.Update, []],
|
|
140
|
-
[EntityOperationType.Insert, []]
|
|
141
|
-
]);
|
|
142
|
-
const storesOperations = new Map();
|
|
143
|
-
// Group operations by store and by operation type.
|
|
144
|
-
// Grouping operations allows us to revert them in bacth, thus, triggering
|
|
145
|
-
// observables only one per operation type.
|
|
146
|
-
for (const operation of operations) {
|
|
147
|
-
const store = operation.store;
|
|
148
|
-
if (operation.store === undefined) {
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
let storeOperations = storesOperations.get(store);
|
|
152
|
-
if (storeOperations === undefined) {
|
|
153
|
-
storeOperations = operationsFactory();
|
|
154
|
-
storesOperations.set(store, storeOperations);
|
|
155
|
-
}
|
|
156
|
-
storeOperations.get(operation.type).push(operation);
|
|
157
|
-
}
|
|
158
|
-
Array.from(storesOperations.keys()).forEach((store) => {
|
|
159
|
-
const storeOperations = storesOperations.get(store);
|
|
160
|
-
const deletes = storeOperations.get(EntityOperationType.Delete);
|
|
161
|
-
store.insertMany(deletes.map((_delete) => _delete.previous));
|
|
162
|
-
const updates = storeOperations.get(EntityOperationType.Update);
|
|
163
|
-
store.updateMany(updates.map((_update) => _update.previous));
|
|
164
|
-
const inserts = storeOperations.get(EntityOperationType.Insert);
|
|
165
|
-
store.deleteMany(inserts.map((_insert) => _insert.current));
|
|
166
|
-
});
|
|
167
|
-
this.operations.deleteMany(operations);
|
|
168
|
-
this.inCommitPhase$.next(false);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Clear this transaction
|
|
172
|
-
* @todo Raise event and synchronize stores?
|
|
173
|
-
*/
|
|
174
|
-
clear() {
|
|
175
|
-
this.operations.clear();
|
|
176
|
-
this.inCommitPhase$.next(false);
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Get any existing operation on an entity
|
|
180
|
-
* @param entity Entity
|
|
181
|
-
* @returns Either an insert, update or delete operation
|
|
182
|
-
*/
|
|
183
|
-
getOperationByEntity(entity) {
|
|
184
|
-
return this.operations.get(this.getKey(entity));
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Merge another transaction in this one
|
|
188
|
-
* @param transaction Another transaction
|
|
189
|
-
*/
|
|
190
|
-
mergeTransaction(transaction) {
|
|
191
|
-
this.checkInCommitPhase();
|
|
192
|
-
const operations = transaction.operations.all();
|
|
193
|
-
operations.forEach((operation) => {
|
|
194
|
-
this.addOperation(operation);
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Create an insert operation and add an entity to the store
|
|
199
|
-
* @param current The entity to insert
|
|
200
|
-
* @param store Optional: The store to insert the entity into
|
|
201
|
-
* @param meta Optional: Any metadata on the operation
|
|
202
|
-
*/
|
|
203
|
-
doInsert(current, store, meta) {
|
|
204
|
-
this.addOperation({
|
|
205
|
-
key: this.getKey(current),
|
|
206
|
-
type: EntityOperationType.Insert,
|
|
207
|
-
previous: undefined,
|
|
208
|
-
current,
|
|
209
|
-
store,
|
|
210
|
-
meta
|
|
211
|
-
});
|
|
212
|
-
if (store !== undefined) {
|
|
213
|
-
store.insert(current);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Create an update operation and update an entity into the store
|
|
218
|
-
* @param previous The entity before update
|
|
219
|
-
* @param current The entity after update
|
|
220
|
-
* @param store Optional: The store to update the entity into
|
|
221
|
-
* @param meta Optional: Any metadata on the operation
|
|
222
|
-
*/
|
|
223
|
-
doUpdate(previous, current, store, meta) {
|
|
224
|
-
this.addOperation({
|
|
225
|
-
key: this.getKey(current),
|
|
226
|
-
type: EntityOperationType.Update,
|
|
227
|
-
previous,
|
|
228
|
-
current,
|
|
229
|
-
store,
|
|
230
|
-
meta
|
|
231
|
-
});
|
|
232
|
-
if (store !== undefined) {
|
|
233
|
-
store.update(current);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Create a delete operation and delete an entity from the store
|
|
238
|
-
* @param previous The entity before delete
|
|
239
|
-
* @param store Optional: The store to delete the entity from
|
|
240
|
-
* @param meta Optional: Any metadata on the operation
|
|
241
|
-
*/
|
|
242
|
-
doDelete(previous, store, meta) {
|
|
243
|
-
this.addOperation({
|
|
244
|
-
key: this.getKey(previous),
|
|
245
|
-
type: EntityOperationType.Delete,
|
|
246
|
-
previous,
|
|
247
|
-
current: undefined,
|
|
248
|
-
store,
|
|
249
|
-
meta
|
|
250
|
-
});
|
|
251
|
-
if (store !== undefined) {
|
|
252
|
-
store.delete(previous);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Remove committed operations from store
|
|
257
|
-
* @param operations Commited operations
|
|
258
|
-
* @todo Raise event and synchronize stores?
|
|
259
|
-
*/
|
|
260
|
-
resolveOperations(operations) {
|
|
261
|
-
this.operations.deleteMany(operations);
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* On commit success, resolve commited operations and exit commit phase
|
|
265
|
-
* @param operations Commited operations
|
|
266
|
-
*/
|
|
267
|
-
onCommitSuccess(operations) {
|
|
268
|
-
this.resolveOperations(operations);
|
|
269
|
-
this.inCommitPhase$.next(false);
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* On commit error, abort transaction
|
|
273
|
-
* @param operations Commited operations
|
|
274
|
-
*/
|
|
275
|
-
onCommitError(operations) {
|
|
276
|
-
this.inCommitPhase$.next(false);
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Add an operation to the operations store
|
|
280
|
-
* @param operation Operation to add
|
|
281
|
-
*/
|
|
282
|
-
addOperation(operation) {
|
|
283
|
-
this.checkInCommitPhase();
|
|
284
|
-
this.operations.insert(operation);
|
|
285
|
-
this.operations.state.update(operation, { added: true });
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Remove an operation from the operations store
|
|
289
|
-
* @param operation Operation to remove
|
|
290
|
-
*/
|
|
291
|
-
removeOperation(operation) {
|
|
292
|
-
this.checkInCommitPhase();
|
|
293
|
-
this.operations.delete(operation);
|
|
294
|
-
this.operations.state.update(operation, { added: false });
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Get all the operations to commit
|
|
298
|
-
* @returns Operations to commit
|
|
299
|
-
*/
|
|
300
|
-
getOperationsInCommit() {
|
|
301
|
-
return this.operations.stateView
|
|
302
|
-
.manyBy((value) => {
|
|
303
|
-
return value.state.added === true;
|
|
304
|
-
})
|
|
305
|
-
.map((value) => value.entity);
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Check if the transaction is in the commit phase and throw an error if it is
|
|
309
|
-
*/
|
|
310
|
-
checkInCommitPhase() {
|
|
311
|
-
if (this.inCommitPhase === true) {
|
|
312
|
-
throw new Error('This transaction is in the commit phase. Cannot complete this operation.');
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21tb24vc3JjL2xpYi9lbnRpdHkvc2hhcmVkL3RyYW5zYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBUXZDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDdEMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBTzdDOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8saUJBQWlCO0lBNEI1QixZQUFZLFVBQW9DLEVBQUU7UUFGekMsbUJBQWMsR0FBNkIsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7UUFHN0UsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUM7UUFDNUQsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLFdBQVcsQ0FBd0MsRUFBRSxFQUFFO1lBQzNFLE1BQU0sRUFBRSxDQUFDLFNBQTBCLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxHQUFHO1NBQ3RELENBQUMsQ0FBQztJQUNMLENBQUM7SUFyQkQ7O09BRUc7SUFDSCxJQUFJLE1BQU0sS0FBK0IsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFFekU7O09BRUc7SUFDSCxJQUFJLEtBQUssS0FBYyxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUVsRDs7T0FFRztJQUNILElBQUksYUFBYSxLQUFjLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBVWxFLE9BQU87UUFDTCxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsTUFBTSxDQUFDLE9BQWUsRUFBRSxLQUEyQixFQUFFLElBQTJCO1FBQzlFLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdELElBQUksaUJBQWlCLEtBQUssU0FBUyxFQUFFO1lBQ25DLElBQUksQ0FBQyxlQUFlLENBQUMsaUJBQWlCLENBQUMsQ0FBQztTQUN6QztRQUVELElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxNQUFNLENBQUMsUUFBZ0IsRUFBRSxPQUFlLEVBQUUsS0FBMkIsRUFBRSxJQUEyQjtRQUNoRyxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM3RCxJQUFJLGlCQUFpQixLQUFLLFNBQVMsRUFBRTtZQUNuQyxJQUFJLENBQUMsZUFBZSxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDeEMsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLEtBQUssbUJBQW1CLENBQUMsTUFBTSxFQUFFO2dCQUN6RCxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3BDLE9BQU87YUFDUjtpQkFBTSxJQUFJLGlCQUFpQixDQUFDLElBQUksS0FBSyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7Z0JBQ2hFLFFBQVEsR0FBRyxpQkFBaUIsQ0FBQyxRQUFRLENBQUM7YUFDdkM7U0FDRjtRQUVELElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxNQUFNLENBQUMsUUFBZ0IsRUFBRSxLQUEyQixFQUFFLElBQTJCO1FBQy9FLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzlELElBQUksaUJBQWlCLEtBQUssU0FBUyxFQUFFO1lBQ25DLElBQUksQ0FBQyxlQUFlLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUN4QyxJQUFJLGlCQUFpQixDQUFDLElBQUksS0FBSyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7Z0JBQ3pELElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRTtvQkFDdkIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztpQkFDeEI7Z0JBQ0QsT0FBTzthQUNSO1NBQ0Y7UUFFRCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSCxNQUFNLENBQUMsVUFBNkIsRUFBRSxPQUF1QztRQUMzRSxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUvQixPQUFPLE9BQU8sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDO2FBQzdCLElBQUksQ0FDSCxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQyxFQUNqQyxHQUFHLENBQUMsQ0FBQyxNQUFXLEVBQUUsRUFBRTtZQUNsQixJQUFJLE1BQU0sWUFBWSxLQUFLLEVBQUU7Z0JBQzNCLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDaEM7aUJBQU07Z0JBQ0wsSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUNsQztRQUNILENBQUMsQ0FBQyxDQUNILENBQUM7SUFDTixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFNBQVMsQ0FBQyxPQUF1QztRQUMvQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNoRCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRDs7T0FFRztJQUNILFFBQVE7UUFDTixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRDs7T0FFRztJQUNILGtCQUFrQixDQUFDLFVBQTZCO1FBQzlDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBRTFCLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxHQUFHLENBQUM7WUFDdEMsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ2hDLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUNoQyxDQUFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7U0FDakMsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBRW5DLG1EQUFtRDtRQUNuRCwwRUFBMEU7UUFDMUUsMkNBQTJDO1FBQzNDLEtBQUssTUFBTSxTQUFTLElBQUksVUFBVSxFQUFFO1lBQ2xDLE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUM7WUFDOUIsSUFBSSxTQUFTLENBQUMsS0FBSyxLQUFLLFNBQVMsRUFBRTtnQkFBRSxTQUFTO2FBQUU7WUFFaEQsSUFBSSxlQUFlLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xELElBQUksZUFBZSxLQUFLLFNBQVMsRUFBRTtnQkFDakMsZUFBZSxHQUFHLGlCQUFpQixFQUFFLENBQUM7Z0JBQ3RDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLENBQUM7YUFDOUM7WUFDRCxlQUFlLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDckQ7UUFFRCxLQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBMEIsRUFBRSxFQUFFO1lBQ3pFLE1BQU0sZUFBZSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVwRCxNQUFNLE9BQU8sR0FBRyxlQUFlLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2hFLEtBQUssQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQXdCLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBRTlFLE1BQU0sT0FBTyxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDaEUsS0FBSyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBd0IsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFFOUUsTUFBTSxPQUFPLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNoRSxLQUFLLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUF3QixFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUMvRSxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILG9CQUFvQixDQUFDLE1BQWM7UUFDakMsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVEOzs7T0FHRztJQUNILGdCQUFnQixDQUFDLFdBQThCO1FBQzdDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBRTFCLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDaEQsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQTBCLEVBQUUsRUFBRTtZQUNoRCxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssUUFBUSxDQUFDLE9BQWUsRUFBRSxLQUEyQixFQUFFLElBQTJCO1FBQ3hGLElBQUksQ0FBQyxZQUFZLENBQUM7WUFDaEIsR0FBRyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQ3pCLElBQUksRUFBRSxtQkFBbUIsQ0FBQyxNQUFNO1lBQ2hDLFFBQVEsRUFBRSxTQUFTO1lBQ25CLE9BQU87WUFDUCxLQUFLO1lBQ0wsSUFBSTtTQUNMLENBQUMsQ0FBQztRQUVILElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRTtZQUN2QixLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQ3ZCO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNLLFFBQVEsQ0FBQyxRQUFnQixFQUFFLE9BQWUsRUFBRSxLQUEyQixFQUFFLElBQTJCO1FBQzFHLElBQUksQ0FBQyxZQUFZLENBQUM7WUFDaEIsR0FBRyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQ3pCLElBQUksRUFBRSxtQkFBbUIsQ0FBQyxNQUFNO1lBQ2hDLFFBQVE7WUFDUixPQUFPO1lBQ1AsS0FBSztZQUNMLElBQUk7U0FDTCxDQUFDLENBQUM7UUFFSCxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUU7WUFDdkIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUN2QjtJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLFFBQVEsQ0FBQyxRQUFnQixFQUFFLEtBQTJCLEVBQUUsSUFBMkI7UUFDekYsSUFBSSxDQUFDLFlBQVksQ0FBQztZQUNoQixHQUFHLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7WUFDMUIsSUFBSSxFQUFFLG1CQUFtQixDQUFDLE1BQU07WUFDaEMsUUFBUTtZQUNSLE9BQU8sRUFBRSxTQUFTO1lBQ2xCLEtBQUs7WUFDTCxJQUFJO1NBQ0wsQ0FBQyxDQUFDO1FBRUgsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFO1lBQ3ZCLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDeEI7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGlCQUFpQixDQUFDLFVBQTZCO1FBQ3JELElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxlQUFlLENBQUMsVUFBNkI7UUFDbkQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ25DLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxhQUFhLENBQUMsVUFBNkI7UUFDakQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVEOzs7T0FHRztJQUNLLFlBQVksQ0FBQyxTQUEwQjtRQUM3QyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUUxQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLEVBQUMsS0FBSyxFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVEOzs7T0FHRztJQUNLLGVBQWUsQ0FBQyxTQUEwQjtRQUNoRCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUUxQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLEVBQUMsS0FBSyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVEOzs7T0FHRztJQUNLLHFCQUFxQjtRQUMzQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUzthQUM3QixNQUFNLENBQUMsQ0FBQyxLQUE2RCxFQUFFLEVBQUU7WUFDeEUsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUM7UUFDcEMsQ0FBQyxDQUFDO2FBQ0QsR0FBRyxDQUFDLENBQUMsS0FBNkQsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFFRDs7T0FFRztJQUNLLGtCQUFrQjtRQUN4QixJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssSUFBSSxFQUFFO1lBQy9CLE1BQU0sSUFBSSxLQUFLLENBQUMsMEVBQTBFLENBQUMsQ0FBQztTQUM3RjtJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9ic2VydmFibGUsIG9mIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IGNhdGNoRXJyb3IsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuXHJcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xyXG5cclxuaW1wb3J0IHtcclxuICBFbnRpdHlLZXksXHJcbiAgRW50aXR5VHJhbnNhY3Rpb25PcHRpb25zLFxyXG4gIEVudGl0eU9wZXJhdGlvbixcclxuICBFbnRpdHlPcGVyYXRpb25TdGF0ZVxyXG59IGZyb20gJy4vZW50aXR5LmludGVyZmFjZXMnO1xyXG5pbXBvcnQgeyBFbnRpdHlTdG9yZSB9IGZyb20gJy4vc3RvcmUnO1xyXG5pbXBvcnQgeyBFbnRpdHlPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi9lbnRpdHkuZW51bXMnO1xyXG5pbXBvcnQgeyBnZXRFbnRpdHlJZCB9IGZyb20gJy4vZW50aXR5LnV0aWxzJztcclxuXHJcbmV4cG9ydCB0eXBlIEVudGl0eVRyYW5zYWN0aW9uQ29tbWl0SGFuZGxlciA9IChcclxuICB0cmFuc2FjdGlvbjogRW50aXR5VHJhbnNhY3Rpb24sXHJcbiAgb3BlcmF0aW9uczogRW50aXR5T3BlcmF0aW9uW11cclxuKSA9PiBPYnNlcnZhYmxlPGFueT47XHJcblxyXG4vKipcclxuICogVGhpcyBjbGFzcyBob2xkcyBhIHJlZmVyZW5jZSB0byB0aGUgaW5zZXJ0LCB1cGRhdGUgYW5kIGRlbGV0ZVxyXG4gKiBvcGVyYXRpb25zIHBlcmZvcm1lZCBvbiBhIHN0b3JlLiBUaGlzIGlzIHVzZWZ1bCB0byBjb21taXRcclxuICogdGhlc2Ugb3BlcmF0aW9ucyBpbiBhIHNpbmdsZSBwYXNzIG9yIHRvIGNhbmNlbCB0aGVtLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEVudGl0eVRyYW5zYWN0aW9uIHtcclxuXHJcbiAgLyoqXHJcbiAgICogU3RvcmUgaG9sZGluZyB0aGUgb3BlcmF0aW9ucyBvbiBhbm90aGVyIHN0b3JlXHJcbiAgICovXHJcbiAgcmVhZG9ubHkgb3BlcmF0aW9uczogRW50aXR5U3RvcmU8RW50aXR5T3BlcmF0aW9uLCBFbnRpdHlPcGVyYXRpb25TdGF0ZT47XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ldGhvZCB0byBnZXQgYW4gZW50aXR5J3MgaWRcclxuICAgKi9cclxuICByZWFkb25seSBnZXRLZXk6IChFKSA9PiBFbnRpdHlLZXk7XHJcblxyXG4gIC8qKlxyXG4gICAqIFdoZXRoZXIgdGhlcmUgYXJlIHBlbmRpbmcgb3BlcmF0aW9uc1xyXG4gICAqL1xyXG4gIGdldCBlbXB0eSQoKTogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+IHsgcmV0dXJuIHRoaXMub3BlcmF0aW9ucy5lbXB0eSQ7IH1cclxuXHJcbiAgLyoqXHJcbiAgICogV2hldGhlciB0aGVyZSBhcmUgcGVuZGluZyBvcGVyYXRpb25zXHJcbiAgICovXHJcbiAgZ2V0IGVtcHR5KCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5lbXB0eSQudmFsdWU7IH1cclxuXHJcbiAgLyoqXHJcbiAgICogV2hldGhlciB0aGlzZSBzdG9yZSBpcyBpbiBjb21taXQgcGhhc2VcclxuICAgKi9cclxuICBnZXQgaW5Db21taXRQaGFzZSgpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMuaW5Db21taXRQaGFzZSQudmFsdWU7IH1cclxuICByZWFkb25seSBpbkNvbW1pdFBoYXNlJDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdChmYWxzZSk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IEVudGl0eVRyYW5zYWN0aW9uT3B0aW9ucyA9IHt9KSB7XHJcbiAgICB0aGlzLmdldEtleSA9IG9wdGlvbnMuZ2V0S2V5ID8gb3B0aW9ucy5nZXRLZXkgOiBnZXRFbnRpdHlJZDtcclxuICAgIHRoaXMub3BlcmF0aW9ucyA9IG5ldyBFbnRpdHlTdG9yZTxFbnRpdHlPcGVyYXRpb24sIEVudGl0eU9wZXJhdGlvblN0YXRlPihbXSwge1xyXG4gICAgICBnZXRLZXk6IChvcGVyYXRpb246IEVudGl0eU9wZXJhdGlvbikgPT4gb3BlcmF0aW9uLmtleVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBkZXN0cm95KCkge1xyXG4gICAgdGhpcy5vcGVyYXRpb25zLmRlc3Ryb3koKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluc2VydCBhbiBlbnRpdHkgaW50byBhIHN0b3JlLiBJZiBubyBzdG9yZSBpcyBzcGVjaWZpZWQsIGFuIGluc2VydFxyXG4gICAqIG9wZXJhdGlvbiBpcyBzdGlsbCBjcmVhdGVkIGJ1dCB0aGUgdHJhbnNhY3Rpb24gd29uJ3QgYWRkIHRoZSBuZXdcclxuICAgKiBlbnRpdHkgdG8gdGhlIHN0b3JlLlxyXG4gICAqIEBwYXJhbSBjdXJyZW50IFRoZSBlbnRpdHkgdG8gaW5zZXJ0XHJcbiAgICogQHBhcmFtIHN0b3JlIE9wdGlvbmFsOiBUaGUgc3RvcmUgdG8gaW5zZXJ0IHRoZSBlbnRpdHkgaW50b1xyXG4gICAqIEBwYXJhbSBtZXRhIE9wdGlvbmFsOiBBbnkgbWV0YWRhdGEgb24gdGhlIG9wZXJhdGlvblxyXG4gICAqL1xyXG4gIGluc2VydChjdXJyZW50OiBvYmplY3QsIHN0b3JlPzogRW50aXR5U3RvcmU8b2JqZWN0PiwgbWV0YT86IHtba2V5OiBzdHJpbmddOiBhbnl9KSB7XHJcbiAgICBjb25zdCBleGlzdGluZ09wZXJhdGlvbiA9IHRoaXMuZ2V0T3BlcmF0aW9uQnlFbnRpdHkoY3VycmVudCk7XHJcbiAgICBpZiAoZXhpc3RpbmdPcGVyYXRpb24gIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aGlzLnJlbW92ZU9wZXJhdGlvbihleGlzdGluZ09wZXJhdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5kb0luc2VydChjdXJyZW50LCBzdG9yZSwgbWV0YSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGUgYW4gZW50aXR5IGluIGEgc3RvcmUuIElmIG5vIHN0b3JlIGlzIHNwZWNpZmllZCwgYW4gdXBkYXRlXHJcbiAgICogb3BlcmF0aW9uIGlzIHN0aWxsIGNyZWF0ZWQgYnV0IHRoZSB0cmFuc2FjdGlvbiB3b24ndCB1cGRhdGUgdGhlXHJcbiAgICogZW50aXR5IGludG8gdGhlIHN0b3JlLlxyXG4gICAqIEBwYXJhbSBwcmV2aW91cyBUaGUgZW50aXR5IGJlZm9yZSB1cGRhdGVcclxuICAgKiBAcGFyYW0gY3VycmVudCBUaGUgZW50aXR5IGFmdGVyIHVwZGF0ZVxyXG4gICAqIEBwYXJhbSBzdG9yZSBPcHRpb25hbDogVGhlIHN0b3JlIHRvIHVwZGF0ZSB0aGUgZW50aXR5IGludG9cclxuICAgKiBAcGFyYW0gbWV0YSBPcHRpb25hbDogQW55IG1ldGFkYXRhIG9uIHRoZSBvcGVyYXRpb25cclxuICAgKi9cclxuICB1cGRhdGUocHJldmlvdXM6IG9iamVjdCwgY3VycmVudDogb2JqZWN0LCBzdG9yZT86IEVudGl0eVN0b3JlPG9iamVjdD4sIG1ldGE/OiB7W2tleTogc3RyaW5nXTogYW55fSkge1xyXG4gICAgY29uc3QgZXhpc3RpbmdPcGVyYXRpb24gPSB0aGlzLmdldE9wZXJhdGlvbkJ5RW50aXR5KGN1cnJlbnQpO1xyXG4gICAgaWYgKGV4aXN0aW5nT3BlcmF0aW9uICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgdGhpcy5yZW1vdmVPcGVyYXRpb24oZXhpc3RpbmdPcGVyYXRpb24pO1xyXG4gICAgICBpZiAoZXhpc3RpbmdPcGVyYXRpb24udHlwZSA9PT0gRW50aXR5T3BlcmF0aW9uVHlwZS5JbnNlcnQpIHtcclxuICAgICAgICB0aGlzLmRvSW5zZXJ0KGN1cnJlbnQsIHN0b3JlLCBtZXRhKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH0gZWxzZSBpZiAoZXhpc3RpbmdPcGVyYXRpb24udHlwZSA9PT0gRW50aXR5T3BlcmF0aW9uVHlwZS5VcGRhdGUpIHtcclxuICAgICAgICBwcmV2aW91cyA9IGV4aXN0aW5nT3BlcmF0aW9uLnByZXZpb3VzO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5kb1VwZGF0ZShwcmV2aW91cywgY3VycmVudCwgc3RvcmUsIG1ldGEpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGVsZXRlIGFuIGVudGl0eSBmcm9tIGEgc3RvcmUuIElmIG5vIHN0b3JlIGlzIHNwZWNpZmllZCwgYSBkZWxldGVcclxuICAgKiBvcGVyYXRpb24gaXMgc3RpbGwgY3JlYXRlZCBidXQgdGhlIHRyYW5zYWN0aW9uIHdvbid0IHJlbW92ZSB0aGVcclxuICAgKiBlbnRpdHkgZnJvbSB0aGUgc3RvcmUuXHJcbiAgICogQHBhcmFtIHByZXZpb3VzIFRoZSBlbnRpdHkgYmVmb3JlIGRlbGV0ZVxyXG4gICAqIEBwYXJhbSBzdG9yZSBPcHRpb25hbDogVGhlIHN0b3JlIHRvIGRlbGV0ZSB0aGUgZW50aXR5IGZyb21cclxuICAgKiBAcGFyYW0gbWV0YSBPcHRpb25hbDogQW55IG1ldGFkYXRhIG9uIHRoZSBvcGVyYXRpb25cclxuICAgKi9cclxuICBkZWxldGUocHJldmlvdXM6IG9iamVjdCwgc3RvcmU/OiBFbnRpdHlTdG9yZTxvYmplY3Q+LCBtZXRhPzoge1trZXk6IHN0cmluZ106IGFueX0pIHtcclxuICAgIGNvbnN0IGV4aXN0aW5nT3BlcmF0aW9uID0gdGhpcy5nZXRPcGVyYXRpb25CeUVudGl0eShwcmV2aW91cyk7XHJcbiAgICBpZiAoZXhpc3RpbmdPcGVyYXRpb24gIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aGlzLnJlbW92ZU9wZXJhdGlvbihleGlzdGluZ09wZXJhdGlvbik7XHJcbiAgICAgIGlmIChleGlzdGluZ09wZXJhdGlvbi50eXBlID09PSBFbnRpdHlPcGVyYXRpb25UeXBlLkluc2VydCkge1xyXG4gICAgICAgIGlmIChzdG9yZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICBzdG9yZS5kZWxldGUocHJldmlvdXMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmRvRGVsZXRlKHByZXZpb3VzLCBzdG9yZSwgbWV0YSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb21taXQgb3BlcmF0aW9ucyB0aGUgdHJhbnNhY3Rpb24uIFRoaXMgbWV0aG9kIGRvZXNuJ3QgZG8gbXVjaFxyXG4gICAqIGluIGl0c2VsZi4gVGhlIGhhbmRsZXIgaXQgcmVjZWl2ZXMgZG9lcyB0aGUgaGFyZCB3b3JrIGFuZCBpdCdzXHJcbiAgICogaW1wbGVtZW50YXRpb24gaXMgbGVmdCB0byB0aGUgY2FsbGVyLiBUaGlzIG1ldGhvZCBzaW1wbHkgd3JhcHNcclxuICAgKiB0aGUgaGFuZGxlciBpbnRvIGFuIGVycm9yIGNhdGNoaW5nIG1lY2hhbmlzbSB0byB1cGRhdGVcclxuICAgKiB0aGUgdHJhbnNhY3Rpb24gYWZ0ZXJ3YXJkLiBUaGUgY2FsbGVyIG5lZWRzIHRvIHN1YnNjcmliZSB0byB0aGlzXHJcbiAgICogbWV0aG9kJ3Mgb3V0cHV0IChvYnNlcnZhYmxlKSBmb3IgdGhlIGNvbW1pdCB0byBiZSBwZXJmb3JtZWQuXHJcbiAgICogQHBhcmFtIG9wZXJhdGlvbnMgT3BlcmF0aW9ucyB0byBjb21taXRcclxuICAgKiBAcGFyYW0gaGFuZGxlciBGdW5jdGlvbiB0aGF0IGhhbmRsZXMgdGhlIGNvbW1pdCBvcGVyYXRpb25cclxuICAgKiBAcmV0dXJucyBUaGUgaGFuZGxlciBvdXRwdXQgKG9ic2VydmFibGUpXHJcbiAgICovXHJcbiAgY29tbWl0KG9wZXJhdGlvbnM6IEVudGl0eU9wZXJhdGlvbltdLCBoYW5kbGVyOiBFbnRpdHlUcmFuc2FjdGlvbkNvbW1pdEhhbmRsZXIpOiBPYnNlcnZhYmxlPGFueT4ge1xyXG4gICAgdGhpcy5pbkNvbW1pdFBoYXNlJC5uZXh0KHRydWUpO1xyXG5cclxuICAgIHJldHVybiBoYW5kbGVyKHRoaXMsIG9wZXJhdGlvbnMpXHJcbiAgICAgIC5waXBlKFxyXG4gICAgICAgIGNhdGNoRXJyb3IoKCkgPT4gb2YobmV3IEVycm9yKCkpKSxcclxuICAgICAgICB0YXAoKHJlc3VsdDogYW55KSA9PiB7XHJcbiAgICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcclxuICAgICAgICAgICAgdGhpcy5vbkNvbW1pdEVycm9yKG9wZXJhdGlvbnMpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5vbkNvbW1pdFN1Y2Nlc3Mob3BlcmF0aW9ucyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbW1pdCBhbGwgdGhlIG9wZXJhdGlvbnMgb2YgdGhlIHRyYW5zYWN0aW9uLlxyXG4gICAqIEBwYXJhbSBoYW5kbGVyIEZ1bmN0aW9uIHRoYXQgaGFuZGxlcyB0aGUgY29tbWl0IG9wZXJhdGlvblxyXG4gICAqIEByZXR1cm5zIFRoZSBoYW5kbGVyIG91dHB1dCAob2JzZXJ2YWJsZSlcclxuICAgKi9cclxuICBjb21taXRBbGwoaGFuZGxlcjogRW50aXR5VHJhbnNhY3Rpb25Db21taXRIYW5kbGVyKTogT2JzZXJ2YWJsZTxhbnk+IHtcclxuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSB0aGlzLmdldE9wZXJhdGlvbnNJbkNvbW1pdCgpO1xyXG4gICAgcmV0dXJuIHRoaXMuY29tbWl0KG9wZXJhdGlvbnMsIGhhbmRsZXIpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUm9sbGJhY2sgdGhpcyB0cmFuc2FjdGlvblxyXG4gICAqL1xyXG4gIHJvbGxiYWNrKCkge1xyXG4gICAgdGhpcy5yb2xsYmFja09wZXJhdGlvbnModGhpcy5vcGVyYXRpb25zLmFsbCgpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJvbGxiYWNrIHNwZWNpZmljIG9wZXJhdGlvbnNcclxuICAgKi9cclxuICByb2xsYmFja09wZXJhdGlvbnMob3BlcmF0aW9uczogRW50aXR5T3BlcmF0aW9uW10pIHtcclxuICAgIHRoaXMuY2hlY2tJbkNvbW1pdFBoYXNlKCk7XHJcblxyXG4gICAgY29uc3Qgb3BlcmF0aW9uc0ZhY3RvcnkgPSAoKSA9PiBuZXcgTWFwKFtcclxuICAgICAgW0VudGl0eU9wZXJhdGlvblR5cGUuRGVsZXRlLCBbXV0sXHJcbiAgICAgIFtFbnRpdHlPcGVyYXRpb25UeXBlLlVwZGF0ZSwgW11dLFxyXG4gICAgICBbRW50aXR5T3BlcmF0aW9uVHlwZS5JbnNlcnQsIFtdXVxyXG4gICAgXSk7XHJcbiAgICBjb25zdCBzdG9yZXNPcGVyYXRpb25zID0gbmV3IE1hcCgpO1xyXG5cclxuICAgIC8vIEdyb3VwIG9wZXJhdGlvbnMgYnkgc3RvcmUgYW5kIGJ5IG9wZXJhdGlvbiB0eXBlLlxyXG4gICAgLy8gR3JvdXBpbmcgb3BlcmF0aW9ucyBhbGxvd3MgdXMgdG8gcmV2ZXJ0IHRoZW0gaW4gYmFjdGgsIHRodXMsIHRyaWdnZXJpbmdcclxuICAgIC8vIG9ic2VydmFibGVzIG9ubHkgb25lIHBlciBvcGVyYXRpb24gdHlwZS5cclxuICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIG9wZXJhdGlvbnMpIHtcclxuICAgICAgY29uc3Qgc3RvcmUgPSBvcGVyYXRpb24uc3RvcmU7XHJcbiAgICAgIGlmIChvcGVyYXRpb24uc3RvcmUgPT09IHVuZGVmaW5lZCkgeyBjb250aW51ZTsgfVxyXG5cclxuICAgICAgbGV0IHN0b3JlT3BlcmF0aW9ucyA9IHN0b3Jlc09wZXJhdGlvbnMuZ2V0KHN0b3JlKTtcclxuICAgICAgaWYgKHN0b3JlT3BlcmF0aW9ucyA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgc3RvcmVPcGVyYXRpb25zID0gb3BlcmF0aW9uc0ZhY3RvcnkoKTtcclxuICAgICAgICBzdG9yZXNPcGVyYXRpb25zLnNldChzdG9yZSwgc3RvcmVPcGVyYXRpb25zKTtcclxuICAgICAgfVxyXG4gICAgICBzdG9yZU9wZXJhdGlvbnMuZ2V0KG9wZXJhdGlvbi50eXBlKS5wdXNoKG9wZXJhdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgQXJyYXkuZnJvbShzdG9yZXNPcGVyYXRpb25zLmtleXMoKSkuZm9yRWFjaCgoc3RvcmU6IEVudGl0eVN0b3JlPG9iamVjdD4pID0+IHtcclxuICAgICAgY29uc3Qgc3RvcmVPcGVyYXRpb25zID0gc3RvcmVzT3BlcmF0aW9ucy5nZXQoc3RvcmUpO1xyXG5cclxuICAgICAgY29uc3QgZGVsZXRlcyA9IHN0b3JlT3BlcmF0aW9ucy5nZXQoRW50aXR5T3BlcmF0aW9uVHlwZS5EZWxldGUpO1xyXG4gICAgICBzdG9yZS5pbnNlcnRNYW55KGRlbGV0ZXMubWFwKChfZGVsZXRlOiBFbnRpdHlPcGVyYXRpb24pID0+IF9kZWxldGUucHJldmlvdXMpKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZXMgPSBzdG9yZU9wZXJhdGlvbnMuZ2V0KEVudGl0eU9wZXJhdGlvblR5cGUuVXBkYXRlKTtcclxuICAgICAgc3RvcmUudXBkYXRlTWFueSh1cGRhdGVzLm1hcCgoX3VwZGF0ZTogRW50aXR5T3BlcmF0aW9uKSA9PiBfdXBkYXRlLnByZXZpb3VzKSk7XHJcblxyXG4gICAgICBjb25zdCBpbnNlcnRzID0gc3RvcmVPcGVyYXRpb25zLmdldChFbnRpdHlPcGVyYXRpb25UeXBlLkluc2VydCk7XHJcbiAgICAgIHN0b3JlLmRlbGV0ZU1hbnkoaW5zZXJ0cy5tYXAoKF9pbnNlcnQ6IEVudGl0eU9wZXJhdGlvbikgPT4gX2luc2VydC5jdXJyZW50KSk7XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLm9wZXJhdGlvbnMuZGVsZXRlTWFueShvcGVyYXRpb25zKTtcclxuICAgIHRoaXMuaW5Db21taXRQaGFzZSQubmV4dChmYWxzZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhciB0aGlzIHRyYW5zYWN0aW9uXHJcbiAgICogQHRvZG8gUmFpc2UgZXZlbnQgYW5kIHN5bmNocm9uaXplIHN0b3Jlcz9cclxuICAgKi9cclxuICBjbGVhcigpIHtcclxuICAgIHRoaXMub3BlcmF0aW9ucy5jbGVhcigpO1xyXG4gICAgdGhpcy5pbkNvbW1pdFBoYXNlJC5uZXh0KGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCBhbnkgZXhpc3Rpbmcgb3BlcmF0aW9uIG9uIGFuIGVudGl0eVxyXG4gICAqIEBwYXJhbSBlbnRpdHkgRW50aXR5XHJcbiAgICogQHJldHVybnMgRWl0aGVyIGFuIGluc2VydCwgdXBkYXRlIG9yIGRlbGV0ZSBvcGVyYXRpb25cclxuICAgKi9cclxuICBnZXRPcGVyYXRpb25CeUVudGl0eShlbnRpdHk6IG9iamVjdCk6IEVudGl0eU9wZXJhdGlvbiB7XHJcbiAgICByZXR1cm4gdGhpcy5vcGVyYXRpb25zLmdldCh0aGlzLmdldEtleShlbnRpdHkpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1lcmdlIGFub3RoZXIgdHJhbnNhY3Rpb24gaW4gdGhpcyBvbmVcclxuICAgKiBAcGFyYW0gdHJhbnNhY3Rpb24gQW5vdGhlciB0cmFuc2FjdGlvblxyXG4gICAqL1xyXG4gIG1lcmdlVHJhbnNhY3Rpb24odHJhbnNhY3Rpb246IEVudGl0eVRyYW5zYWN0aW9uKSB7XHJcbiAgICB0aGlzLmNoZWNrSW5Db21taXRQaGFzZSgpO1xyXG5cclxuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSB0cmFuc2FjdGlvbi5vcGVyYXRpb25zLmFsbCgpO1xyXG4gICAgb3BlcmF0aW9ucy5mb3JFYWNoKChvcGVyYXRpb246IEVudGl0eU9wZXJhdGlvbikgPT4ge1xyXG4gICAgICB0aGlzLmFkZE9wZXJhdGlvbihvcGVyYXRpb24pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGUgYW4gaW5zZXJ0IG9wZXJhdGlvbiBhbmQgYWRkIGFuIGVudGl0eSB0byB0aGUgc3RvcmVcclxuICAgKiBAcGFyYW0gY3VycmVudCBUaGUgZW50aXR5IHRvIGluc2VydFxyXG4gICAqIEBwYXJhbSBzdG9yZSBPcHRpb25hbDogVGhlIHN0b3JlIHRvIGluc2VydCB0aGUgZW50aXR5IGludG9cclxuICAgKiBAcGFyYW0gbWV0YSBPcHRpb25hbDogQW55IG1ldGFkYXRhIG9uIHRoZSBvcGVyYXRpb25cclxuICAgKi9cclxuICBwcml2YXRlIGRvSW5zZXJ0KGN1cnJlbnQ6IG9iamVjdCwgc3RvcmU/OiBFbnRpdHlTdG9yZTxvYmplY3Q+LCBtZXRhPzoge1trZXk6IHN0cmluZ106IGFueX0pIHtcclxuICAgIHRoaXMuYWRkT3BlcmF0aW9uKHtcclxuICAgICAga2V5OiB0aGlzLmdldEtleShjdXJyZW50KSxcclxuICAgICAgdHlwZTogRW50aXR5T3BlcmF0aW9uVHlwZS5JbnNlcnQsXHJcbiAgICAgIHByZXZpb3VzOiB1bmRlZmluZWQsXHJcbiAgICAgIGN1cnJlbnQsXHJcbiAgICAgIHN0b3JlLFxyXG4gICAgICBtZXRhXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoc3RvcmUgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBzdG9yZS5pbnNlcnQoY3VycmVudCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGUgYW4gdXBkYXRlIG9wZXJhdGlvbiBhbmQgdXBkYXRlIGFuIGVudGl0eSBpbnRvIHRoZSBzdG9yZVxyXG4gICAqIEBwYXJhbSBwcmV2aW91cyBUaGUgZW50aXR5IGJlZm9yZSB1cGRhdGVcclxuICAgKiBAcGFyYW0gY3VycmVudCBUaGUgZW50aXR5IGFmdGVyIHVwZGF0ZVxyXG4gICAqIEBwYXJhbSBzdG9yZSBPcHRpb25hbDogVGhlIHN0b3JlIHRvIHVwZGF0ZSB0aGUgZW50aXR5IGludG9cclxuICAgKiBAcGFyYW0gbWV0YSBPcHRpb25hbDogQW55IG1ldGFkYXRhIG9uIHRoZSBvcGVyYXRpb25cclxuICAgKi9cclxuICBwcml2YXRlIGRvVXBkYXRlKHByZXZpb3VzOiBvYmplY3QsIGN1cnJlbnQ6IG9iamVjdCwgc3RvcmU/OiBFbnRpdHlTdG9yZTxvYmplY3Q+LCBtZXRhPzoge1trZXk6IHN0cmluZ106IGFueX0pIHtcclxuICAgIHRoaXMuYWRkT3BlcmF0aW9uKHtcclxuICAgICAga2V5OiB0aGlzLmdldEtleShjdXJyZW50KSxcclxuICAgICAgdHlwZTogRW50aXR5T3BlcmF0aW9uVHlwZS5VcGRhdGUsXHJcbiAgICAgIHByZXZpb3VzLFxyXG4gICAgICBjdXJyZW50LFxyXG4gICAgICBzdG9yZSxcclxuICAgICAgbWV0YVxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKHN0b3JlICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgc3RvcmUudXBkYXRlKGN1cnJlbnQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgZGVsZXRlIG9wZXJhdGlvbiBhbmQgZGVsZXRlIGFuIGVudGl0eSBmcm9tIHRoZSBzdG9yZVxyXG4gICAqIEBwYXJhbSBwcmV2aW91cyBUaGUgZW50aXR5IGJlZm9yZSBkZWxldGVcclxuICAgKiBAcGFyYW0gc3RvcmUgT3B0aW9uYWw6IFRoZSBzdG9yZSB0byBkZWxldGUgdGhlIGVudGl0eSBmcm9tXHJcbiAgICogQHBhcmFtIG1ldGEgT3B0aW9uYWw6IEFueSBtZXRhZGF0YSBvbiB0aGUgb3BlcmF0aW9uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBkb0RlbGV0ZShwcmV2aW91czogb2JqZWN0LCBzdG9yZT86IEVudGl0eVN0b3JlPG9iamVjdD4sIG1ldGE/OiB7W2tleTogc3RyaW5nXTogYW55fSkge1xyXG4gICAgdGhpcy5hZGRPcGVyYXRpb24oe1xyXG4gICAgICBrZXk6IHRoaXMuZ2V0S2V5KHByZXZpb3VzKSxcclxuICAgICAgdHlwZTogRW50aXR5T3BlcmF0aW9uVHlwZS5EZWxldGUsXHJcbiAgICAgIHByZXZpb3VzLFxyXG4gICAgICBjdXJyZW50OiB1bmRlZmluZWQsXHJcbiAgICAgIHN0b3JlLFxyXG4gICAgICBtZXRhXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoc3RvcmUgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBzdG9yZS5kZWxldGUocHJldmlvdXMpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIGNvbW1pdHRlZCBvcGVyYXRpb25zIGZyb20gc3RvcmVcclxuICAgKiBAcGFyYW0gb3BlcmF0aW9ucyBDb21taXRlZCBvcGVyYXRpb25zXHJcbiAgICogQHRvZG8gUmFpc2UgZXZlbnQgYW5kIHN5bmNocm9uaXplIHN0b3Jlcz9cclxuICAgKi9cclxuICBwcml2YXRlIHJlc29sdmVPcGVyYXRpb25zKG9wZXJhdGlvbnM6IEVudGl0eU9wZXJhdGlvbltdKSB7XHJcbiAgICB0aGlzLm9wZXJhdGlvbnMuZGVsZXRlTWFueShvcGVyYXRpb25zKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE9uIGNvbW1pdCBzdWNjZXNzLCByZXNvbHZlIGNvbW1pdGVkIG9wZXJhdGlvbnMgYW5kIGV4aXQgY29tbWl0IHBoYXNlXHJcbiAgICogQHBhcmFtIG9wZXJhdGlvbnMgQ29tbWl0ZWQgb3BlcmF0aW9uc1xyXG4gICAqL1xyXG4gIHByaXZhdGUgb25Db21taXRTdWNjZXNzKG9wZXJhdGlvbnM6IEVudGl0eU9wZXJhdGlvbltdKSB7XHJcbiAgICB0aGlzLnJlc29sdmVPcGVyYXRpb25zKG9wZXJhdGlvbnMpO1xyXG4gICAgdGhpcy5pbkNvbW1pdFBoYXNlJC5uZXh0KGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE9uIGNvbW1pdCBlcnJvciwgYWJvcnQgdHJhbnNhY3Rpb25cclxuICAgKiBAcGFyYW0gb3BlcmF0aW9ucyBDb21taXRlZCBvcGVyYXRpb25zXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBvbkNvbW1pdEVycm9yKG9wZXJhdGlvbnM6IEVudGl0eU9wZXJhdGlvbltdKSB7XHJcbiAgICB0aGlzLmluQ29tbWl0UGhhc2UkLm5leHQoZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQWRkIGFuIG9wZXJhdGlvbiB0byB0aGUgb3BlcmF0aW9ucyBzdG9yZVxyXG4gICAqIEBwYXJhbSBvcGVyYXRpb24gT3BlcmF0aW9uIHRvIGFkZFxyXG4gICAqL1xyXG4gIHByaXZhdGUgYWRkT3BlcmF0aW9uKG9wZXJhdGlvbjogRW50aXR5T3BlcmF0aW9uKSB7XHJcbiAgICB0aGlzLmNoZWNrSW5Db21taXRQaGFzZSgpO1xyXG5cclxuICAgIHRoaXMub3BlcmF0aW9ucy5pbnNlcnQob3BlcmF0aW9uKTtcclxuICAgIHRoaXMub3BlcmF0aW9ucy5zdGF0ZS51cGRhdGUob3BlcmF0aW9uLCB7YWRkZWQ6IHRydWV9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlbW92ZSBhbiBvcGVyYXRpb24gZnJvbSB0aGUgb3BlcmF0aW9ucyBzdG9yZVxyXG4gICAqIEBwYXJhbSBvcGVyYXRpb24gT3BlcmF0aW9uIHRvIHJlbW92ZVxyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVtb3ZlT3BlcmF0aW9uKG9wZXJhdGlvbjogRW50aXR5T3BlcmF0aW9uKSB7XHJcbiAgICB0aGlzLmNoZWNrSW5Db21taXRQaGFzZSgpO1xyXG5cclxuICAgIHRoaXMub3BlcmF0aW9ucy5kZWxldGUob3BlcmF0aW9uKTtcclxuICAgIHRoaXMub3BlcmF0aW9ucy5zdGF0ZS51cGRhdGUob3BlcmF0aW9uLCB7YWRkZWQ6IGZhbHNlfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgYWxsIHRoZSBvcGVyYXRpb25zIHRvIGNvbW1pdFxyXG4gICAqIEByZXR1cm5zIE9wZXJhdGlvbnMgdG8gY29tbWl0XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZXRPcGVyYXRpb25zSW5Db21taXQoKTogRW50aXR5T3BlcmF0aW9uW10ge1xyXG4gICAgcmV0dXJuIHRoaXMub3BlcmF0aW9ucy5zdGF0ZVZpZXdcclxuICAgICAgLm1hbnlCeSgodmFsdWU6IHtlbnRpdHk6IEVudGl0eU9wZXJhdGlvbiwgc3RhdGU6IEVudGl0eU9wZXJhdGlvblN0YXRlfSkgPT4ge1xyXG4gICAgICAgIHJldHVybiB2YWx1ZS5zdGF0ZS5hZGRlZCA9PT0gdHJ1ZTtcclxuICAgICAgfSlcclxuICAgICAgLm1hcCgodmFsdWU6IHtlbnRpdHk6IEVudGl0eU9wZXJhdGlvbiwgc3RhdGU6IEVudGl0eU9wZXJhdGlvblN0YXRlfSkgPT4gdmFsdWUuZW50aXR5KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrIGlmIHRoZSB0cmFuc2FjdGlvbiBpcyBpbiB0aGUgY29tbWl0IHBoYXNlIGFuZCB0aHJvdyBhbiBlcnJvciBpZiBpdCBpc1xyXG4gICAqL1xyXG4gIHByaXZhdGUgY2hlY2tJbkNvbW1pdFBoYXNlKCkge1xyXG4gICAgaWYgKHRoaXMuaW5Db21taXRQaGFzZSA9PT0gdHJ1ZSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgdHJhbnNhY3Rpb24gaXMgaW4gdGhlIGNvbW1pdCBwaGFzZS4gQ2Fubm90IGNvbXBsZXRlIHRoaXMgb3BlcmF0aW9uLicpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0=
|
|
1
|
+
import { of } from 'rxjs';
|
|
2
|
+
import { catchError, tap } from 'rxjs/operators';
|
|
3
|
+
import { BehaviorSubject } from 'rxjs';
|
|
4
|
+
import { EntityStore } from './store';
|
|
5
|
+
import { EntityOperationType } from './entity.enums';
|
|
6
|
+
import { getEntityId } from './entity.utils';
|
|
7
|
+
/**
|
|
8
|
+
* This class holds a reference to the insert, update and delete
|
|
9
|
+
* operations performed on a store. This is useful to commit
|
|
10
|
+
* these operations in a single pass or to cancel them.
|
|
11
|
+
*/
|
|
12
|
+
export class EntityTransaction {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.inCommitPhase$ = new BehaviorSubject(false);
|
|
15
|
+
this.getKey = options.getKey ? options.getKey : getEntityId;
|
|
16
|
+
this.operations = new EntityStore([], {
|
|
17
|
+
getKey: (operation) => operation.key
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Whether there are pending operations
|
|
22
|
+
*/
|
|
23
|
+
get empty$() { return this.operations.empty$; }
|
|
24
|
+
/**
|
|
25
|
+
* Whether there are pending operations
|
|
26
|
+
*/
|
|
27
|
+
get empty() { return this.empty$.value; }
|
|
28
|
+
/**
|
|
29
|
+
* Whether thise store is in commit phase
|
|
30
|
+
*/
|
|
31
|
+
get inCommitPhase() { return this.inCommitPhase$.value; }
|
|
32
|
+
destroy() {
|
|
33
|
+
this.operations.destroy();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Insert an entity into a store. If no store is specified, an insert
|
|
37
|
+
* operation is still created but the transaction won't add the new
|
|
38
|
+
* entity to the store.
|
|
39
|
+
* @param current The entity to insert
|
|
40
|
+
* @param store Optional: The store to insert the entity into
|
|
41
|
+
* @param meta Optional: Any metadata on the operation
|
|
42
|
+
*/
|
|
43
|
+
insert(current, store, meta) {
|
|
44
|
+
const existingOperation = this.getOperationByEntity(current);
|
|
45
|
+
if (existingOperation !== undefined) {
|
|
46
|
+
this.removeOperation(existingOperation);
|
|
47
|
+
}
|
|
48
|
+
this.doInsert(current, store, meta);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Update an entity in a store. If no store is specified, an update
|
|
52
|
+
* operation is still created but the transaction won't update the
|
|
53
|
+
* entity into the store.
|
|
54
|
+
* @param previous The entity before update
|
|
55
|
+
* @param current The entity after update
|
|
56
|
+
* @param store Optional: The store to update the entity into
|
|
57
|
+
* @param meta Optional: Any metadata on the operation
|
|
58
|
+
*/
|
|
59
|
+
update(previous, current, store, meta) {
|
|
60
|
+
const existingOperation = this.getOperationByEntity(current);
|
|
61
|
+
if (existingOperation !== undefined) {
|
|
62
|
+
this.removeOperation(existingOperation);
|
|
63
|
+
if (existingOperation.type === EntityOperationType.Insert) {
|
|
64
|
+
this.doInsert(current, store, meta);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
else if (existingOperation.type === EntityOperationType.Update) {
|
|
68
|
+
previous = existingOperation.previous;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
this.doUpdate(previous, current, store, meta);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Delete an entity from a store. If no store is specified, a delete
|
|
75
|
+
* operation is still created but the transaction won't remove the
|
|
76
|
+
* entity from the store.
|
|
77
|
+
* @param previous The entity before delete
|
|
78
|
+
* @param store Optional: The store to delete the entity from
|
|
79
|
+
* @param meta Optional: Any metadata on the operation
|
|
80
|
+
*/
|
|
81
|
+
delete(previous, store, meta) {
|
|
82
|
+
const existingOperation = this.getOperationByEntity(previous);
|
|
83
|
+
if (existingOperation !== undefined) {
|
|
84
|
+
this.removeOperation(existingOperation);
|
|
85
|
+
if (existingOperation.type === EntityOperationType.Insert) {
|
|
86
|
+
if (store !== undefined) {
|
|
87
|
+
store.delete(previous);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
this.doDelete(previous, store, meta);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Commit operations the transaction. This method doesn't do much
|
|
96
|
+
* in itself. The handler it receives does the hard work and it's
|
|
97
|
+
* implementation is left to the caller. This method simply wraps
|
|
98
|
+
* the handler into an error catching mechanism to update
|
|
99
|
+
* the transaction afterward. The caller needs to subscribe to this
|
|
100
|
+
* method's output (observable) for the commit to be performed.
|
|
101
|
+
* @param operations Operations to commit
|
|
102
|
+
* @param handler Function that handles the commit operation
|
|
103
|
+
* @returns The handler output (observable)
|
|
104
|
+
*/
|
|
105
|
+
commit(operations, handler) {
|
|
106
|
+
this.inCommitPhase$.next(true);
|
|
107
|
+
return handler(this, operations)
|
|
108
|
+
.pipe(catchError(() => of(new Error())), tap((result) => {
|
|
109
|
+
if (result instanceof Error) {
|
|
110
|
+
this.onCommitError(operations);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
this.onCommitSuccess(operations);
|
|
114
|
+
}
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Commit all the operations of the transaction.
|
|
119
|
+
* @param handler Function that handles the commit operation
|
|
120
|
+
* @returns The handler output (observable)
|
|
121
|
+
*/
|
|
122
|
+
commitAll(handler) {
|
|
123
|
+
const operations = this.getOperationsInCommit();
|
|
124
|
+
return this.commit(operations, handler);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Rollback this transaction
|
|
128
|
+
*/
|
|
129
|
+
rollback() {
|
|
130
|
+
this.rollbackOperations(this.operations.all());
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Rollback specific operations
|
|
134
|
+
*/
|
|
135
|
+
rollbackOperations(operations) {
|
|
136
|
+
this.checkInCommitPhase();
|
|
137
|
+
const operationsFactory = () => new Map([
|
|
138
|
+
[EntityOperationType.Delete, []],
|
|
139
|
+
[EntityOperationType.Update, []],
|
|
140
|
+
[EntityOperationType.Insert, []]
|
|
141
|
+
]);
|
|
142
|
+
const storesOperations = new Map();
|
|
143
|
+
// Group operations by store and by operation type.
|
|
144
|
+
// Grouping operations allows us to revert them in bacth, thus, triggering
|
|
145
|
+
// observables only one per operation type.
|
|
146
|
+
for (const operation of operations) {
|
|
147
|
+
const store = operation.store;
|
|
148
|
+
if (operation.store === undefined) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
let storeOperations = storesOperations.get(store);
|
|
152
|
+
if (storeOperations === undefined) {
|
|
153
|
+
storeOperations = operationsFactory();
|
|
154
|
+
storesOperations.set(store, storeOperations);
|
|
155
|
+
}
|
|
156
|
+
storeOperations.get(operation.type).push(operation);
|
|
157
|
+
}
|
|
158
|
+
Array.from(storesOperations.keys()).forEach((store) => {
|
|
159
|
+
const storeOperations = storesOperations.get(store);
|
|
160
|
+
const deletes = storeOperations.get(EntityOperationType.Delete);
|
|
161
|
+
store.insertMany(deletes.map((_delete) => _delete.previous));
|
|
162
|
+
const updates = storeOperations.get(EntityOperationType.Update);
|
|
163
|
+
store.updateMany(updates.map((_update) => _update.previous));
|
|
164
|
+
const inserts = storeOperations.get(EntityOperationType.Insert);
|
|
165
|
+
store.deleteMany(inserts.map((_insert) => _insert.current));
|
|
166
|
+
});
|
|
167
|
+
this.operations.deleteMany(operations);
|
|
168
|
+
this.inCommitPhase$.next(false);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Clear this transaction
|
|
172
|
+
* @todo Raise event and synchronize stores?
|
|
173
|
+
*/
|
|
174
|
+
clear() {
|
|
175
|
+
this.operations.clear();
|
|
176
|
+
this.inCommitPhase$.next(false);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get any existing operation on an entity
|
|
180
|
+
* @param entity Entity
|
|
181
|
+
* @returns Either an insert, update or delete operation
|
|
182
|
+
*/
|
|
183
|
+
getOperationByEntity(entity) {
|
|
184
|
+
return this.operations.get(this.getKey(entity));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Merge another transaction in this one
|
|
188
|
+
* @param transaction Another transaction
|
|
189
|
+
*/
|
|
190
|
+
mergeTransaction(transaction) {
|
|
191
|
+
this.checkInCommitPhase();
|
|
192
|
+
const operations = transaction.operations.all();
|
|
193
|
+
operations.forEach((operation) => {
|
|
194
|
+
this.addOperation(operation);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Create an insert operation and add an entity to the store
|
|
199
|
+
* @param current The entity to insert
|
|
200
|
+
* @param store Optional: The store to insert the entity into
|
|
201
|
+
* @param meta Optional: Any metadata on the operation
|
|
202
|
+
*/
|
|
203
|
+
doInsert(current, store, meta) {
|
|
204
|
+
this.addOperation({
|
|
205
|
+
key: this.getKey(current),
|
|
206
|
+
type: EntityOperationType.Insert,
|
|
207
|
+
previous: undefined,
|
|
208
|
+
current,
|
|
209
|
+
store,
|
|
210
|
+
meta
|
|
211
|
+
});
|
|
212
|
+
if (store !== undefined) {
|
|
213
|
+
store.insert(current);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Create an update operation and update an entity into the store
|
|
218
|
+
* @param previous The entity before update
|
|
219
|
+
* @param current The entity after update
|
|
220
|
+
* @param store Optional: The store to update the entity into
|
|
221
|
+
* @param meta Optional: Any metadata on the operation
|
|
222
|
+
*/
|
|
223
|
+
doUpdate(previous, current, store, meta) {
|
|
224
|
+
this.addOperation({
|
|
225
|
+
key: this.getKey(current),
|
|
226
|
+
type: EntityOperationType.Update,
|
|
227
|
+
previous,
|
|
228
|
+
current,
|
|
229
|
+
store,
|
|
230
|
+
meta
|
|
231
|
+
});
|
|
232
|
+
if (store !== undefined) {
|
|
233
|
+
store.update(current);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Create a delete operation and delete an entity from the store
|
|
238
|
+
* @param previous The entity before delete
|
|
239
|
+
* @param store Optional: The store to delete the entity from
|
|
240
|
+
* @param meta Optional: Any metadata on the operation
|
|
241
|
+
*/
|
|
242
|
+
doDelete(previous, store, meta) {
|
|
243
|
+
this.addOperation({
|
|
244
|
+
key: this.getKey(previous),
|
|
245
|
+
type: EntityOperationType.Delete,
|
|
246
|
+
previous,
|
|
247
|
+
current: undefined,
|
|
248
|
+
store,
|
|
249
|
+
meta
|
|
250
|
+
});
|
|
251
|
+
if (store !== undefined) {
|
|
252
|
+
store.delete(previous);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Remove committed operations from store
|
|
257
|
+
* @param operations Commited operations
|
|
258
|
+
* @todo Raise event and synchronize stores?
|
|
259
|
+
*/
|
|
260
|
+
resolveOperations(operations) {
|
|
261
|
+
this.operations.deleteMany(operations);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* On commit success, resolve commited operations and exit commit phase
|
|
265
|
+
* @param operations Commited operations
|
|
266
|
+
*/
|
|
267
|
+
onCommitSuccess(operations) {
|
|
268
|
+
this.resolveOperations(operations);
|
|
269
|
+
this.inCommitPhase$.next(false);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* On commit error, abort transaction
|
|
273
|
+
* @param operations Commited operations
|
|
274
|
+
*/
|
|
275
|
+
onCommitError(operations) {
|
|
276
|
+
this.inCommitPhase$.next(false);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Add an operation to the operations store
|
|
280
|
+
* @param operation Operation to add
|
|
281
|
+
*/
|
|
282
|
+
addOperation(operation) {
|
|
283
|
+
this.checkInCommitPhase();
|
|
284
|
+
this.operations.insert(operation);
|
|
285
|
+
this.operations.state.update(operation, { added: true });
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Remove an operation from the operations store
|
|
289
|
+
* @param operation Operation to remove
|
|
290
|
+
*/
|
|
291
|
+
removeOperation(operation) {
|
|
292
|
+
this.checkInCommitPhase();
|
|
293
|
+
this.operations.delete(operation);
|
|
294
|
+
this.operations.state.update(operation, { added: false });
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get all the operations to commit
|
|
298
|
+
* @returns Operations to commit
|
|
299
|
+
*/
|
|
300
|
+
getOperationsInCommit() {
|
|
301
|
+
return this.operations.stateView
|
|
302
|
+
.manyBy((value) => {
|
|
303
|
+
return value.state.added === true;
|
|
304
|
+
})
|
|
305
|
+
.map((value) => value.entity);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Check if the transaction is in the commit phase and throw an error if it is
|
|
309
|
+
*/
|
|
310
|
+
checkInCommitPhase() {
|
|
311
|
+
if (this.inCommitPhase === true) {
|
|
312
|
+
throw new Error('This transaction is in the commit phase. Cannot complete this operation.');
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21tb24vc3JjL2xpYi9lbnRpdHkvc2hhcmVkL3RyYW5zYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBUXZDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDdEMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBTzdDOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8saUJBQWlCO0lBNEI1QixZQUFZLFVBQW9DLEVBQUU7UUFGekMsbUJBQWMsR0FBNkIsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7UUFHN0UsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUM7UUFDNUQsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLFdBQVcsQ0FBd0MsRUFBRSxFQUFFO1lBQzNFLE1BQU0sRUFBRSxDQUFDLFNBQTBCLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxHQUFHO1NBQ3RELENBQUMsQ0FBQztJQUNMLENBQUM7SUFyQkQ7O09BRUc7SUFDSCxJQUFJLE1BQU0sS0FBK0IsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFFekU7O09BRUc7SUFDSCxJQUFJLEtBQUssS0FBYyxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsS0FB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a0JBQWtCLEVBQUUsQ0FBQztRQUUxQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLEVBQUMsS0FBSyxFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVEOzs7T0FHRztJQUNLLGVBQWUsQ0FBQyxTQUEwQjtRQUNoRCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUUxQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLEVBQUMsS0FBSyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVEOzs7T0FHRztJQUNLLHFCQUFxQjtRQUMzQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUzthQUM3QixNQUFNLENBQUMsQ0FBQyxLQUE2RCxFQUFFLEVBQUU7WUFDeEUsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUM7UUFDcEMsQ0FBQyxDQUFDO2FBQ0QsR0FBRyxDQUFDLENBQUMsS0FBNkQsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFFRDs7T0FFRztJQUNLLGtCQUFrQjtRQUN4QixJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssSUFBSSxFQUFFO1lBQy9CLE1BQU0sSUFBSSxLQUFLLENBQUMsMEVBQTBFLENBQUMsQ0FBQztTQUM3RjtJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9ic2VydmFibGUsIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQge1xuICBFbnRpdHlLZXksXG4gIEVudGl0eVRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgRW50aXR5T3BlcmF0aW9uLFxuICBFbnRpdHlPcGVyYXRpb25TdGF0ZVxufSBmcm9tICcuL2VudGl0eS5pbnRlcmZhY2VzJztcbmltcG9ydCB7IEVudGl0eVN0b3JlIH0gZnJvbSAnLi9zdG9yZSc7XG5pbXBvcnQgeyBFbnRpdHlPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi9lbnRpdHkuZW51bXMnO1xuaW1wb3J0IHsgZ2V0RW50aXR5SWQgfSBmcm9tICcuL2VudGl0eS51dGlscyc7XG5cbmV4cG9ydCB0eXBlIEVudGl0eVRyYW5zYWN0aW9uQ29tbWl0SGFuZGxlciA9IChcbiAgdHJhbnNhY3Rpb246IEVudGl0eVRyYW5zYWN0aW9uLFxuICBvcGVyYXRpb25zOiBFbnRpdHlPcGVyYXRpb25bXVxuKSA9PiBPYnNlcnZhYmxlPGFueT47XG5cbi8qKlxuICogVGhpcyBjbGFzcyBob2xkcyBhIHJlZmVyZW5jZSB0byB0aGUgaW5zZXJ0LCB1cGRhdGUgYW5kIGRlbGV0ZVxuICogb3BlcmF0aW9ucyBwZXJmb3JtZWQgb24gYSBzdG9yZS4gVGhpcyBpcyB1c2VmdWwgdG8gY29tbWl0XG4gKiB0aGVzZSBvcGVyYXRpb25zIGluIGEgc2luZ2xlIHBhc3Mgb3IgdG8gY2FuY2VsIHRoZW0uXG4gKi9cbmV4cG9ydCBjbGFzcyBFbnRpdHlUcmFuc2FjdGlvbiB7XG5cbiAgLyoqXG4gICAqIFN0b3JlIGhvbGRpbmcgdGhlIG9wZXJhdGlvbnMgb24gYW5vdGhlciBzdG9yZVxuICAgKi9cbiAgcmVhZG9ubHkgb3BlcmF0aW9uczogRW50aXR5U3RvcmU8RW50aXR5T3BlcmF0aW9uLCBFbnRpdHlPcGVyYXRpb25TdGF0ZT47XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBnZXQgYW4gZW50aXR5J3MgaWRcbiAgICovXG4gIHJlYWRvbmx5IGdldEtleTogKEUpID0+IEVudGl0eUtleTtcblxuICAvKipcbiAgICogV2hldGhlciB0aGVyZSBhcmUgcGVuZGluZyBvcGVyYXRpb25zXG4gICAqL1xuICBnZXQgZW1wdHkkKCk6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPiB7IHJldHVybiB0aGlzLm9wZXJhdGlvbnMuZW1wdHkkOyB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlcmUgYXJlIHBlbmRpbmcgb3BlcmF0aW9uc1xuICAgKi9cbiAgZ2V0IGVtcHR5KCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5lbXB0eSQudmFsdWU7IH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzZSBzdG9yZSBpcyBpbiBjb21taXQgcGhhc2VcbiAgICovXG4gIGdldCBpbkNvbW1pdFBoYXNlKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5pbkNvbW1pdFBoYXNlJC52YWx1ZTsgfVxuICByZWFkb25seSBpbkNvbW1pdFBoYXNlJDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdChmYWxzZSk7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogRW50aXR5VHJhbnNhY3Rpb25PcHRpb25zID0ge30pIHtcbiAgICB0aGlzLmdldEtleSA9IG9wdGlvbnMuZ2V0S2V5ID8gb3B0aW9ucy5nZXRLZXkgOiBnZXRFbnRpdHlJZDtcbiAgICB0aGlzLm9wZXJhdGlvbnMgPSBuZXcgRW50aXR5U3RvcmU8RW50aXR5T3BlcmF0aW9uLCBFbnRpdHlPcGVyYXRpb25TdGF0ZT4oW10sIHtcbiAgICAgIGdldEtleTogKG9wZXJhdGlvbjogRW50aXR5T3BlcmF0aW9uKSA9PiBvcGVyYXRpb24ua2V5XG4gICAgfSk7XG4gIH1cblxuICBkZXN0cm95KCkge1xuICAgIHRoaXMub3BlcmF0aW9ucy5kZXN0cm95KCk7XG4gIH1cblxuICAvKipcbiAgICogSW5zZXJ0IGFuIGVudGl0eSBpbnRvIGEgc3RvcmUuIElmIG5vIHN0b3JlIGlzIHNwZWNpZmllZCwgYW4gaW5zZXJ0XG4gICAqIG9wZXJhdGlvbiBpcyBzdGlsbCBjcmVhdGVkIGJ1dCB0aGUgdHJhbnNhY3Rpb24gd29uJ3QgYWRkIHRoZSBuZXdcbiAgICogZW50aXR5IHRvIHRoZSBzdG9yZS5cbiAgICogQHBhcmFtIGN1cnJlbnQgVGhlIGVudGl0eSB0byBpbnNlcnRcbiAgICogQHBhcmFtIHN0b3JlIE9wdGlvbmFsOiBUaGUgc3RvcmUgdG8gaW5zZXJ0IHRoZSBlbnRpdHkgaW50b1xuICAgKiBAcGFyYW0gbWV0YSBPcHRpb25hbDogQW55IG1ldGFkYXRhIG9uIHRoZSBvcGVyYXRpb25cbiAgICovXG4gIGluc2VydChjdXJyZW50OiBvYmplY3QsIHN0b3JlPzogRW50aXR5U3RvcmU8b2JqZWN0PiwgbWV0YT86IHtba2V5OiBzdHJpbmddOiBhbnl9KSB7XG4gICAgY29uc3QgZXhpc3RpbmdPcGVyYXRpb24gPSB0aGlzLmdldE9wZXJhdGlvbkJ5RW50aXR5KGN1cnJlbnQpO1xuICAgIGlmIChleGlzdGluZ09wZXJhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnJlbW92ZU9wZXJhdGlvbihleGlzdGluZ09wZXJhdGlvbik7XG4gICAgfVxuXG4gICAgdGhpcy5kb0luc2VydChjdXJyZW50LCBzdG9yZSwgbWV0YSk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIGFuIGVudGl0eSBpbiBhIHN0b3JlLiBJZiBubyBzdG9yZSBpcyBzcGVjaWZpZWQsIGFuIHVwZGF0ZVxuICAgKiBvcGVyYXRpb24gaXMgc3RpbGwgY3JlYXRlZCBidXQgdGhlIHRyYW5zYWN0aW9uIHdvbid0IHVwZGF0ZSB0aGVcbiAgICogZW50aXR5IGludG8gdGhlIHN0b3JlLlxuICAgKiBAcGFyYW0gcHJldmlvdXMgVGhlIGVudGl0eSBiZWZvcmUgdXBkYXRlXG4gICAqIEBwYXJhbSBjdXJyZW50IFRoZSBlbnRpdHkgYWZ0ZXIgdXBkYXRlXG4gICAqIEBwYXJhbSBzdG9yZSBPcHRpb25hbDogVGhlIHN0b3JlIHRvIHVwZGF0ZSB0aGUgZW50aXR5IGludG9cbiAgICogQHBhcmFtIG1ldGEgT3B0aW9uYWw6IEFueSBtZXRhZGF0YSBvbiB0aGUgb3BlcmF0aW9uXG4gICAqL1xuICB1cGRhdGUocHJldmlvdXM6IG9iamVjdCwgY3VycmVudDogb2JqZWN0LCBzdG9yZT86IEVudGl0eVN0b3JlPG9iamVjdD4sIG1ldGE/OiB7W2tleTogc3RyaW5nXTogYW55fSkge1xuICAgIGNvbnN0IGV4aXN0aW5nT3BlcmF0aW9uID0gdGhpcy5nZXRPcGVyYXRpb25CeUVudGl0eShjdXJyZW50KTtcbiAgICBpZiAoZXhpc3RpbmdPcGVyYXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5yZW1vdmVPcGVyYXRpb24oZXhpc3RpbmdPcGVyYXRpb24pO1xuICAgICAgaWYgKGV4aXN0aW5nT3BlcmF0aW9uLnR5cGUgPT09IEVudGl0eU9wZXJhdGlvblR5cGUuSW5zZXJ0KSB7XG4gICAgICAgIHRoaXMuZG9JbnNlcnQoY3VycmVudCwgc3RvcmUsIG1ldGEpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2UgaWYgKGV4aXN0aW5nT3BlcmF0aW9uLnR5cGUgPT09IEVudGl0eU9wZXJhdGlvblR5cGUuVXBkYXRlKSB7XG4gICAgICAgIHByZXZpb3VzID0gZXhpc3RpbmdPcGVyYXRpb24ucHJldmlvdXM7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5kb1VwZGF0ZShwcmV2aW91cywgY3VycmVudCwgc3RvcmUsIG1ldGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZSBhbiBlbnRpdHkgZnJvbSBhIHN0b3JlLiBJZiBubyBzdG9yZSBpcyBzcGVjaWZpZWQsIGEgZGVsZXRlXG4gICAqIG9wZXJhdGlvbiBpcyBzdGlsbCBjcmVhdGVkIGJ1dCB0aGUgdHJhbnNhY3Rpb24gd29uJ3QgcmVtb3ZlIHRoZVxuICAgKiBlbnRpdHkgZnJvbSB0aGUgc3RvcmUuXG4gICAqIEBwYXJhbSBwcmV2aW91cyBUaGUgZW50aXR5IGJlZm9yZSBkZWxldGVcbiAgICogQHBhcmFtIHN0b3JlIE9wdGlvbmFsOiBUaGUgc3RvcmUgdG8gZGVsZXRlIHRoZSBlbnRpdHkgZnJvbVxuICAgKiBAcGFyYW0gbWV0YSBPcHRpb25hbDogQW55IG1ldGFkYXRhIG9uIHRoZSBvcGVyYXRpb25cbiAgICovXG4gIGRlbGV0ZShwcmV2aW91czogb2JqZWN0LCBzdG9yZT86IEVudGl0eVN0b3JlPG9iamVjdD4sIG1ldGE/OiB7W2tleTogc3RyaW5nXTogYW55fSkge1xuICAgIGNvbnN0IGV4aXN0aW5nT3BlcmF0aW9uID0gdGhpcy5nZXRPcGVyYXRpb25CeUVudGl0eShwcmV2aW91cyk7XG4gICAgaWYgKGV4aXN0aW5nT3BlcmF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMucmVtb3ZlT3BlcmF0aW9uKGV4aXN0aW5nT3BlcmF0aW9uKTtcbiAgICAgIGlmIChleGlzdGluZ09wZXJhdGlvbi50eXBlID09PSBFbnRpdHlPcGVyYXRpb25UeXBlLkluc2VydCkge1xuICAgICAgICBpZiAoc3RvcmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHN0b3JlLmRlbGV0ZShwcmV2aW91cyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZG9EZWxldGUocHJldmlvdXMsIHN0b3JlLCBtZXRhKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21taXQgb3BlcmF0aW9ucyB0aGUgdHJhbnNhY3Rpb24uIFRoaXMgbWV0aG9kIGRvZXNuJ3QgZG8gbXVjaFxuICAgKiBpbiBpdHNlbGYuIFRoZSBoYW5kbGVyIGl0IHJlY2VpdmVzIGRvZXMgdGhlIGhhcmQgd29yayBhbmQgaXQnc1xuICAgKiBpbXBsZW1lbnRhdGlvbiBpcyBsZWZ0IHRvIHRoZSBjYWxsZXIuIFRoaXMgbWV0aG9kIHNpbXBseSB3cmFwc1xuICAgKiB0aGUgaGFuZGxlciBpbnRvIGFuIGVycm9yIGNhdGNoaW5nIG1lY2hhbmlzbSB0byB1cGRhdGVcbiAgICogdGhlIHRyYW5zYWN0aW9uIGFmdGVyd2FyZC4gVGhlIGNhbGxlciBuZWVkcyB0byBzdWJzY3JpYmUgdG8gdGhpc1xuICAgKiBtZXRob2QncyBvdXRwdXQgKG9ic2VydmFibGUpIGZvciB0aGUgY29tbWl0IHRvIGJlIHBlcmZvcm1lZC5cbiAgICogQHBhcmFtIG9wZXJhdGlvbnMgT3BlcmF0aW9ucyB0byBjb21taXRcbiAgICogQHBhcmFtIGhhbmRsZXIgRnVuY3Rpb24gdGhhdCBoYW5kbGVzIHRoZSBjb21taXQgb3BlcmF0aW9uXG4gICAqIEByZXR1cm5zIFRoZSBoYW5kbGVyIG91dHB1dCAob2JzZXJ2YWJsZSlcbiAgICovXG4gIGNvbW1pdChvcGVyYXRpb25zOiBFbnRpdHlPcGVyYXRpb25bXSwgaGFuZGxlcjogRW50aXR5VHJhbnNhY3Rpb25Db21taXRIYW5kbGVyKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICB0aGlzLmluQ29tbWl0UGhhc2UkLm5leHQodHJ1ZSk7XG5cbiAgICByZXR1cm4gaGFuZGxlcih0aGlzLCBvcGVyYXRpb25zKVxuICAgICAgLnBpcGUoXG4gICAgICAgIGNhdGNoRXJyb3IoKCkgPT4gb2YobmV3IEVycm9yKCkpKSxcbiAgICAgICAgdGFwKChyZXN1bHQ6IGFueSkgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgdGhpcy5vbkNvbW1pdEVycm9yKG9wZXJhdGlvbnMpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm9uQ29tbWl0U3VjY2VzcyhvcGVyYXRpb25zKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbW1pdCBhbGwgdGhlIG9wZXJhdGlvbnMgb2YgdGhlIHRyYW5zYWN0aW9uLlxuICAgKiBAcGFyYW0gaGFuZGxlciBGdW5jdGlvbiB0aGF0IGhhbmRsZXMgdGhlIGNvbW1pdCBvcGVyYXRpb25cbiAgICogQHJldHVybnMgVGhlIGhhbmRsZXIgb3V0cHV0IChvYnNlcnZhYmxlKVxuICAgKi9cbiAgY29tbWl0QWxsKGhhbmRsZXI6IEVudGl0eVRyYW5zYWN0aW9uQ29tbWl0SGFuZGxlcik6IE9ic2VydmFibGU8YW55PiB7XG4gICAgY29uc3Qgb3BlcmF0aW9ucyA9IHRoaXMuZ2V0T3BlcmF0aW9uc0luQ29tbWl0KCk7XG4gICAgcmV0dXJuIHRoaXMuY29tbWl0KG9wZXJhdGlvbnMsIGhhbmRsZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJvbGxiYWNrIHRoaXMgdHJhbnNhY3Rpb25cbiAgICovXG4gIHJvbGxiYWNrKCkge1xuICAgIHRoaXMucm9sbGJhY2tPcGVyYXRpb25zKHRoaXMub3BlcmF0aW9ucy5hbGwoKSk7XG4gIH1cblxuICAvKipcbiAgICogUm9sbGJhY2sgc3BlY2lmaWMgb3BlcmF0aW9uc1xuICAgKi9cbiAgcm9sbGJhY2tPcGVyYXRpb25zKG9wZXJhdGlvbnM6IEVudGl0eU9wZXJhdGlvbltdKSB7XG4gICAgdGhpcy5jaGVja0luQ29tbWl0UGhhc2UoKTtcblxuICAgIGNvbnN0IG9wZXJhdGlvbnNGYWN0b3J5ID0gKCkgPT4gbmV3IE1hcChbXG4gICAgICBbRW50aXR5T3BlcmF0aW9uVHlwZS5EZWxldGUsIFtdXSxcbiAgICAgIFtFbnRpdHlPcGVyYXRpb25UeXBlLlVwZGF0ZSwgW11dLFxuICAgICAgW0VudGl0eU9wZXJhdGlvblR5cGUuSW5zZXJ0LCBbXV1cbiAgICBdKTtcbiAgICBjb25zdCBzdG9yZXNPcGVyYXRpb25zID0gbmV3IE1hcCgpO1xuXG4gICAgLy8gR3JvdXAgb3BlcmF0aW9ucyBieSBzdG9yZSBhbmQgYnkgb3BlcmF0aW9uIHR5cGUuXG4gICAgLy8gR3JvdXBpbmcgb3BlcmF0aW9ucyBhbGxvd3MgdXMgdG8gcmV2ZXJ0IHRoZW0gaW4gYmFjdGgsIHRodXMsIHRyaWdnZXJpbmdcbiAgICAvLyBvYnNlcnZhYmxlcyBvbmx5IG9uZSBwZXIgb3BlcmF0aW9uIHR5cGUuXG4gICAgZm9yIChjb25zdCBvcGVyYXRpb24gb2Ygb3BlcmF0aW9ucykge1xuICAgICAgY29uc3Qgc3RvcmUgPSBvcGVyYXRpb24uc3RvcmU7XG4gICAgICBpZiAob3BlcmF0aW9uLnN0b3JlID09PSB1bmRlZmluZWQpIHsgY29udGludWU7IH1cblxuICAgICAgbGV0IHN0b3JlT3BlcmF0aW9ucyA9IHN0b3Jlc09wZXJhdGlvbnMuZ2V0KHN0b3JlKTtcbiAgICAgIGlmIChzdG9yZU9wZXJhdGlvbnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzdG9yZU9wZXJhdGlvbnMgPSBvcGVyYXRpb25zRmFjdG9yeSgpO1xuICAgICAgICBzdG9yZXNPcGVyYXRpb25zLnNldChzdG9yZSwgc3RvcmVPcGVyYXRpb25zKTtcbiAgICAgIH1cbiAgICAgIHN0b3JlT3BlcmF0aW9ucy5nZXQob3BlcmF0aW9uLnR5cGUpLnB1c2gob3BlcmF0aW9uKTtcbiAgICB9XG5cbiAgICBBcnJheS5mcm9tKHN0b3Jlc09wZXJhdGlvbnMua2V5cygpKS5mb3JFYWNoKChzdG9yZTogRW50aXR5U3RvcmU8b2JqZWN0PikgPT4ge1xuICAgICAgY29uc3Qgc3RvcmVPcGVyYXRpb25zID0gc3RvcmVzT3BlcmF0aW9ucy5nZXQoc3RvcmUpO1xuXG4gICAgICBjb25zdCBkZWxldGVzID0gc3RvcmVPcGVyYXRpb25zLmdldChFbnRpdHlPcGVyYXRpb25UeXBlLkRlbGV0ZSk7XG4gICAgICBzdG9yZS5pbnNlcnRNYW55KGRlbGV0ZXMubWFwKChfZGVsZXRlOiBFbnRpdHlPcGVyYXRpb24pID0+IF9kZWxldGUucHJldmlvdXMpKTtcblxuICAgICAgY29uc3QgdXBkYXRlcyA9IHN0b3JlT3BlcmF0aW9ucy5nZXQoRW50aXR5T3BlcmF0aW9uVHlwZS5VcGRhdGUpO1xuICAgICAgc3RvcmUudXBkYXRlTWFueSh1cGRhdGVzLm1hcCgoX3VwZGF0ZTogRW50aXR5T3BlcmF0aW9uKSA9PiBfdXBkYXRlLnByZXZpb3VzKSk7XG5cbiAgICAgIGNvbnN0IGluc2VydHMgPSBzdG9yZU9wZXJhdGlvbnMuZ2V0KEVudGl0eU9wZXJhdGlvblR5cGUuSW5zZXJ0KTtcbiAgICAgIHN0b3JlLmRlbGV0ZU1hbnkoaW5zZXJ0cy5tYXAoKF9pbnNlcnQ6IEVudGl0eU9wZXJhdGlvbikgPT4gX2luc2VydC5jdXJyZW50KSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLm9wZXJhdGlvbnMuZGVsZXRlTWFueShvcGVyYXRpb25zKTtcbiAgICB0aGlzLmluQ29tbWl0UGhhc2UkLm5leHQoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFyIHRoaXMgdHJhbnNhY3Rpb25cbiAgICogQHRvZG8gUmFpc2UgZXZlbnQgYW5kIHN5bmNocm9uaXplIHN0b3Jlcz9cbiAgICovXG4gIGNsZWFyKCkge1xuICAgIHRoaXMub3BlcmF0aW9ucy5jbGVhcigpO1xuICAgIHRoaXMuaW5Db21taXRQaGFzZSQubmV4dChmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFueSBleGlzdGluZyBvcGVyYXRpb24gb24gYW4gZW50aXR5XG4gICAqIEBwYXJhbSBlbnRpdHkgRW50aXR5XG4gICAqIEByZXR1cm5zIEVpdGhlciBhbiBpbnNlcnQsIHVwZGF0ZSBvciBkZWxldGUgb3BlcmF0aW9uXG4gICAqL1xuICBnZXRPcGVyYXRpb25CeUVudGl0eShlbnRpdHk6IG9iamVjdCk6IEVudGl0eU9wZXJhdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMub3BlcmF0aW9ucy5nZXQodGhpcy5nZXRLZXkoZW50aXR5KSk7XG4gIH1cblxuICAvKipcbiAgICogTWVyZ2UgYW5vdGhlciB0cmFuc2FjdGlvbiBpbiB0aGlzIG9uZVxuICAgKiBAcGFyYW0gdHJhbnNhY3Rpb24gQW5vdGhlciB0cmFuc2FjdGlvblxuICAgKi9cbiAgbWVyZ2VUcmFuc2FjdGlvbih0cmFuc2FjdGlvbjogRW50aXR5VHJhbnNhY3Rpb24pIHtcbiAgICB0aGlzLmNoZWNrSW5Db21taXRQaGFzZSgpO1xuXG4gICAgY29uc3Qgb3BlcmF0aW9ucyA9IHRyYW5zYWN0aW9uLm9wZXJhdGlvbnMuYWxsKCk7XG4gICAgb3BlcmF0aW9ucy5mb3JFYWNoKChvcGVyYXRpb246IEVudGl0eU9wZXJhdGlvbikgPT4ge1xuICAgICAgdGhpcy5hZGRPcGVyYXRpb24ob3BlcmF0aW9uKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW4gaW5zZXJ0IG9wZXJhdGlvbiBhbmQgYWRkIGFuIGVudGl0eSB0byB0aGUgc3RvcmVcbiAgICogQHBhcmFtIGN1cnJlbnQgVGhlIGVudGl0eSB0byBpbnNlcnRcbiAgICogQHBhcmFtIHN0b3JlIE9wdGlvbmFsOiBUaGUgc3RvcmUgdG8gaW5zZXJ0IHRoZSBlbnRpdHkgaW50b1xuICAgKiBAcGFyYW0gbWV0YSBPcHRpb25hbDogQW55IG1ldGFkYXRhIG9uIHRoZSBvcGVyYXRpb25cbiAgICovXG4gIHByaXZhdGUgZG9JbnNlcnQoY3VycmVudDogb2JqZWN0LCBzdG9yZT86IEVudGl0eVN0b3JlPG9iamVjdD4sIG1ldGE/OiB7W2tleTogc3RyaW5nXTogYW55fSkge1xuICAgIHRoaXMuYWRkT3BlcmF0aW9uKHtcbiAgICAgIGtleTogdGhpcy5nZXRLZXkoY3VycmVudCksXG4gICAgICB0eXBlOiBFbnRpdHlPcGVyYXRpb25UeXBlLkluc2VydCxcbiAgICAgIHByZXZpb3VzOiB1bmRlZmluZWQsXG4gICAgICBjdXJyZW50LFxuICAgICAgc3RvcmUsXG4gICAgICBtZXRhXG4gICAgfSk7XG5cbiAgICBpZiAoc3RvcmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgc3RvcmUuaW5zZXJ0KGN1cnJlbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW4gdXBkYXRlIG9wZXJhdGlvbiBhbmQgdXBkYXRlIGFuIGVudGl0eSBpbnRvIHRoZSBzdG9yZVxuICAgKiBAcGFyYW0gcHJldmlvdXMgVGhlIGVudGl0eSBiZWZvcmUgdXBkYXRlXG4gICAqIEBwYXJhbSBjdXJyZW50IFRoZSBlbnRpdHkgYWZ0ZXIgdXBkYXRlXG4gICAqIEBwYXJhbSBzdG9yZSBPcHRpb25hbDogVGhlIHN0b3JlIHRvIHVwZGF0ZSB0aGUgZW50aXR5IGludG9cbiAgICogQHBhcmFtIG1ldGEgT3B0aW9uYWw6IEFueSBtZXRhZGF0YSBvbiB0aGUgb3BlcmF0aW9uXG4gICAqL1xuICBwcml2YXRlIGRvVXBkYXRlKHByZXZpb3VzOiBvYmplY3QsIGN1cnJlbnQ6IG9iamVjdCwgc3RvcmU/OiBFbnRpdHlTdG9yZTxvYmplY3Q+LCBtZXRhPzoge1trZXk6IHN0cmluZ106IGFueX0pIHtcbiAgICB0aGlzLmFkZE9wZXJhdGlvbih7XG4gICAgICBrZXk6IHRoaXMuZ2V0S2V5KGN1cnJlbnQpLFxuICAgICAgdHlwZTogRW50aXR5T3BlcmF0aW9uVHlwZS5VcGRhdGUsXG4gICAgICBwcmV2aW91cyxcbiAgICAgIGN1cnJlbnQsXG4gICAgICBzdG9yZSxcbiAgICAgIG1ldGFcbiAgICB9KTtcblxuICAgIGlmIChzdG9yZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBzdG9yZS51cGRhdGUoY3VycmVudCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIGRlbGV0ZSBvcGVyYXRpb24gYW5kIGRlbGV0ZSBhbiBlbnRpdHkgZnJvbSB0aGUgc3RvcmVcbiAgICogQHBhcmFtIHByZXZpb3VzIFRoZSBlbnRpdHkgYmVmb3JlIGRlbGV0ZVxuICAgKiBAcGFyYW0gc3RvcmUgT3B0aW9uYWw6IFRoZSBzdG9yZSB0byBkZWxldGUgdGhlIGVudGl0eSBmcm9tXG4gICAqIEBwYXJhbSBtZXRhIE9wdGlvbmFsOiBBbnkgbWV0YWRhdGEgb24gdGhlIG9wZXJhdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBkb0RlbGV0ZShwcmV2aW91czogb2JqZWN0LCBzdG9yZT86IEVudGl0eVN0b3JlPG9iamVjdD4sIG1ldGE/OiB7W2tleTogc3RyaW5nXTogYW55fSkge1xuICAgIHRoaXMuYWRkT3BlcmF0aW9uKHtcbiAgICAgIGtleTogdGhpcy5nZXRLZXkocHJldmlvdXMpLFxuICAgICAgdHlwZTogRW50aXR5T3BlcmF0aW9uVHlwZS5EZWxldGUsXG4gICAgICBwcmV2aW91cyxcbiAgICAgIGN1cnJlbnQ6IHVuZGVmaW5lZCxcbiAgICAgIHN0b3JlLFxuICAgICAgbWV0YVxuICAgIH0pO1xuXG4gICAgaWYgKHN0b3JlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHN0b3JlLmRlbGV0ZShwcmV2aW91cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBjb21taXR0ZWQgb3BlcmF0aW9ucyBmcm9tIHN0b3JlXG4gICAqIEBwYXJhbSBvcGVyYXRpb25zIENvbW1pdGVkIG9wZXJhdGlvbnNcbiAgICogQHRvZG8gUmFpc2UgZXZlbnQgYW5kIHN5bmNocm9uaXplIHN0b3Jlcz9cbiAgICovXG4gIHByaXZhdGUgcmVzb2x2ZU9wZXJhdGlvbnMob3BlcmF0aW9uczogRW50aXR5T3BlcmF0aW9uW10pIHtcbiAgICB0aGlzLm9wZXJhdGlvbnMuZGVsZXRlTWFueShvcGVyYXRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPbiBjb21taXQgc3VjY2VzcywgcmVzb2x2ZSBjb21taXRlZCBvcGVyYXRpb25zIGFuZCBleGl0IGNvbW1pdCBwaGFzZVxuICAgKiBAcGFyYW0gb3BlcmF0aW9ucyBDb21taXRlZCBvcGVyYXRpb25zXG4gICAqL1xuICBwcml2YXRlIG9uQ29tbWl0U3VjY2VzcyhvcGVyYXRpb25zOiBFbnRpdHlPcGVyYXRpb25bXSkge1xuICAgIHRoaXMucmVzb2x2ZU9wZXJhdGlvbnMob3BlcmF0aW9ucyk7XG4gICAgdGhpcy5pbkNvbW1pdFBoYXNlJC5uZXh0KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPbiBjb21taXQgZXJyb3IsIGFib3J0IHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBvcGVyYXRpb25zIENvbW1pdGVkIG9wZXJhdGlvbnNcbiAgICovXG4gIHByaXZhdGUgb25Db21taXRFcnJvcihvcGVyYXRpb25zOiBFbnRpdHlPcGVyYXRpb25bXSkge1xuICAgIHRoaXMuaW5Db21taXRQaGFzZSQubmV4dChmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGFuIG9wZXJhdGlvbiB0byB0aGUgb3BlcmF0aW9ucyBzdG9yZVxuICAgKiBAcGFyYW0gb3BlcmF0aW9uIE9wZXJhdGlvbiB0byBhZGRcbiAgICovXG4gIHByaXZhdGUgYWRkT3BlcmF0aW9uKG9wZXJhdGlvbjogRW50aXR5T3BlcmF0aW9uKSB7XG4gICAgdGhpcy5jaGVja0luQ29tbWl0UGhhc2UoKTtcblxuICAgIHRoaXMub3BlcmF0aW9ucy5pbnNlcnQob3BlcmF0aW9uKTtcbiAgICB0aGlzLm9wZXJhdGlvbnMuc3RhdGUudXBkYXRlKG9wZXJhdGlvbiwge2FkZGVkOiB0cnVlfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGFuIG9wZXJhdGlvbiBmcm9tIHRoZSBvcGVyYXRpb25zIHN0b3JlXG4gICAqIEBwYXJhbSBvcGVyYXRpb24gT3BlcmF0aW9uIHRvIHJlbW92ZVxuICAgKi9cbiAgcHJpdmF0ZSByZW1vdmVPcGVyYXRpb24ob3BlcmF0aW9uOiBFbnRpdHlPcGVyYXRpb24pIHtcbiAgICB0aGlzLmNoZWNrSW5Db21taXRQaGFzZSgpO1xuXG4gICAgdGhpcy5vcGVyYXRpb25zLmRlbGV0ZShvcGVyYXRpb24pO1xuICAgIHRoaXMub3BlcmF0aW9ucy5zdGF0ZS51cGRhdGUob3BlcmF0aW9uLCB7YWRkZWQ6IGZhbHNlfSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCB0aGUgb3BlcmF0aW9ucyB0byBjb21taXRcbiAgICogQHJldHVybnMgT3BlcmF0aW9ucyB0byBjb21taXRcbiAgICovXG4gIHByaXZhdGUgZ2V0T3BlcmF0aW9uc0luQ29tbWl0KCk6IEVudGl0eU9wZXJhdGlvbltdIHtcbiAgICByZXR1cm4gdGhpcy5vcGVyYXRpb25zLnN0YXRlVmlld1xuICAgICAgLm1hbnlCeSgodmFsdWU6IHtlbnRpdHk6IEVudGl0eU9wZXJhdGlvbiwgc3RhdGU6IEVudGl0eU9wZXJhdGlvblN0YXRlfSkgPT4ge1xuICAgICAgICByZXR1cm4gdmFsdWUuc3RhdGUuYWRkZWQgPT09IHRydWU7XG4gICAgICB9KVxuICAgICAgLm1hcCgodmFsdWU6IHtlbnRpdHk6IEVudGl0eU9wZXJhdGlvbiwgc3RhdGU6IEVudGl0eU9wZXJhdGlvblN0YXRlfSkgPT4gdmFsdWUuZW50aXR5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGUgdHJhbnNhY3Rpb24gaXMgaW4gdGhlIGNvbW1pdCBwaGFzZSBhbmQgdGhyb3cgYW4gZXJyb3IgaWYgaXQgaXNcbiAgICovXG4gIHByaXZhdGUgY2hlY2tJbkNvbW1pdFBoYXNlKCkge1xuICAgIGlmICh0aGlzLmluQ29tbWl0UGhhc2UgPT09IHRydWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhpcyB0cmFuc2FjdGlvbiBpcyBpbiB0aGUgY29tbWl0IHBoYXNlLiBDYW5ub3QgY29tcGxldGUgdGhpcyBvcGVyYXRpb24uJyk7XG4gICAgfVxuICB9XG59XG4iXX0=
|