@angular-generic-table/core 5.0.0-alpha.2 → 5.0.0-rc.11
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 +13 -134
- package/angular-generic-table-core.d.ts +2 -19
- package/esm2020/angular-generic-table-core.mjs +5 -0
- package/esm2020/lib/core.component.mjs +143 -0
- package/esm2020/lib/core.module.mjs +23 -0
- package/esm2020/lib/core.service.mjs +14 -0
- package/esm2020/lib/enums/order.enum.mjs +6 -0
- package/esm2020/lib/models/table-column.interface.mjs +2 -0
- package/esm2020/lib/models/table-config.interface.mjs +2 -0
- package/esm2020/lib/models/table-info.interface.mjs +2 -0
- package/esm2020/lib/models/table-meta.interface.mjs +2 -0
- package/esm2020/lib/models/table-row.interface.mjs +2 -0
- package/esm2020/lib/models/table-sort.interface.mjs +2 -0
- package/esm2020/lib/pagination/pagination.component.mjs +63 -0
- package/esm2020/lib/pagination/pagination.module.mjs +18 -0
- package/esm2020/lib/pipes/capital-case.pipe.mjs +17 -0
- package/esm2020/lib/pipes/dash-case.pipe.mjs +17 -0
- package/esm2020/lib/pipes/dynamic.pipe.mjs +25 -0
- package/esm2020/lib/pipes/highlight.pipe.mjs +48 -0
- package/esm2020/lib/pipes/sort-class.pipe.mjs +22 -0
- package/esm2020/lib/utilities/utilities.mjs +39 -0
- package/esm2020/public-api.mjs +15 -0
- package/fesm2015/angular-generic-table-core.mjs +412 -0
- package/fesm2015/angular-generic-table-core.mjs.map +1 -0
- package/fesm2020/angular-generic-table-core.mjs +408 -0
- package/fesm2020/angular-generic-table-core.mjs.map +1 -0
- package/lib/core.component.d.ts +34 -0
- package/lib/core.module.d.ts +12 -1
- package/lib/core.service.d.ts +6 -0
- package/lib/enums/order.enum.d.ts +4 -0
- package/lib/models/table-column.interface.d.ts +19 -0
- package/lib/models/table-config.interface.d.ts +15 -0
- package/lib/models/table-info.interface.d.ts +4 -0
- package/lib/models/table-meta.interface.d.ts +8 -0
- package/lib/models/table-row.interface.d.ts +4 -0
- package/lib/models/table-sort.interface.d.ts +5 -0
- package/lib/pagination/pagination.component.d.ts +14 -0
- package/lib/pagination/pagination.module.d.ts +8 -0
- package/lib/pipes/capital-case.pipe.d.ts +7 -0
- package/lib/pipes/dash-case.pipe.d.ts +4 -1
- package/lib/pipes/dynamic.pipe.d.ts +9 -0
- package/lib/pipes/highlight.pipe.d.ts +7 -0
- package/lib/pipes/sort-class.pipe.d.ts +11 -0
- package/lib/utilities/utilities.d.ts +6 -0
- package/package.json +26 -24
- package/public-api.d.ts +11 -0
- package/scss/index.scss +102 -0
- package/CHANGELOG.md +0 -461
- package/LICENSE.md +0 -201
- package/angular-generic-table-core.metadata.json +0 -1
- package/bundles/angular-generic-table-core.umd.js +0 -3679
- package/bundles/angular-generic-table-core.umd.js.map +0 -1
- package/bundles/angular-generic-table-core.umd.min.js +0 -2
- package/bundles/angular-generic-table-core.umd.min.js.map +0 -1
- package/css/generic-table.css +0 -168
- package/css/generic-table.css.map +0 -9
- package/css/generic-table.min.css +0 -2
- package/css/generic-table.min.css.map +0 -1
- package/esm2015/angular-generic-table-core.js +0 -28
- package/esm2015/angular-generic-table-core.metadata.json +0 -1
- package/esm2015/lib/components/generic-table/generic-table.component.js +0 -1738
- package/esm2015/lib/components/generic-table/generic-table.component.metadata.json +0 -1
- package/esm2015/lib/components/gt-checkbox/gt-checkbox.component.js +0 -88
- package/esm2015/lib/components/gt-checkbox/gt-checkbox.component.metadata.json +0 -1
- package/esm2015/lib/components/gt-custom-component-factory/gt-custom-component-factory.component.js +0 -112
- package/esm2015/lib/components/gt-custom-component-factory/gt-custom-component-factory.component.metadata.json +0 -1
- package/esm2015/lib/components/gt-drilldown/gt-drilldown.component.js +0 -53
- package/esm2015/lib/components/gt-drilldown/gt-drilldown.component.metadata.json +0 -1
- package/esm2015/lib/components/gt-dropdown/gt-dropdown.component.js +0 -176
- package/esm2015/lib/components/gt-dropdown/gt-dropdown.component.metadata.json +0 -1
- package/esm2015/lib/components/gt-expanding-row/gt-expanding-row.component.js +0 -147
- package/esm2015/lib/components/gt-expanding-row/gt-expanding-row.component.metadata.json +0 -1
- package/esm2015/lib/components/gt-pagination/gt-pagination.component.js +0 -141
- package/esm2015/lib/components/gt-pagination/gt-pagination.component.metadata.json +0 -1
- package/esm2015/lib/components/gt-table-info/gt-table-info.component.js +0 -103
- package/esm2015/lib/components/gt-table-info/gt-table-info.component.metadata.json +0 -1
- package/esm2015/lib/core.module.js +0 -100
- package/esm2015/lib/core.module.metadata.json +0 -1
- package/esm2015/lib/directives/component-anchor.directive.js +0 -65
- package/esm2015/lib/directives/component-anchor.directive.metadata.json +0 -1
- package/esm2015/lib/directives/gt-column-width.directive.js +0 -73
- package/esm2015/lib/directives/gt-column-width.directive.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-config-field.js +0 -96
- package/esm2015/lib/interfaces/gt-config-field.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-config-setting.js +0 -41
- package/esm2015/lib/interfaces/gt-config-setting.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-config-total.js +0 -20
- package/esm2015/lib/interfaces/gt-config-total.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-config.js +0 -24
- package/esm2015/lib/interfaces/gt-config.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-event.js +0 -16
- package/esm2015/lib/interfaces/gt-event.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-information.js +0 -38
- package/esm2015/lib/interfaces/gt-information.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-options.js +0 -55
- package/esm2015/lib/interfaces/gt-options.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-render-field.js +0 -29
- package/esm2015/lib/interfaces/gt-render-field.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-row-meta.js +0 -18
- package/esm2015/lib/interfaces/gt-row-meta.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-row.js +0 -20
- package/esm2015/lib/interfaces/gt-row.metadata.json +0 -1
- package/esm2015/lib/interfaces/gt-texts.js +0 -36
- package/esm2015/lib/interfaces/gt-texts.metadata.json +0 -1
- package/esm2015/lib/pipes/dash-case.pipe.js +0 -30
- package/esm2015/lib/pipes/dash-case.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-chunk.pipe.js +0 -52
- package/esm2015/lib/pipes/gt-chunk.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-column-class.pipe.js +0 -51
- package/esm2015/lib/pipes/gt-column-class.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-filter.pipe.js +0 -60
- package/esm2015/lib/pipes/gt-filter.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-highlight.pipe.js +0 -72
- package/esm2015/lib/pipes/gt-highlight.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-is-editable.pipe.js +0 -37
- package/esm2015/lib/pipes/gt-is-editable.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-is-observable.pipe.js +0 -31
- package/esm2015/lib/pipes/gt-is-observable.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-meta.pipe.js +0 -54
- package/esm2015/lib/pipes/gt-meta.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-order-by.pipe.js +0 -202
- package/esm2015/lib/pipes/gt-order-by.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-property.pipe.js +0 -52
- package/esm2015/lib/pipes/gt-property.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-render.pipe.js +0 -173
- package/esm2015/lib/pipes/gt-render.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-row-class.pipe.js +0 -66
- package/esm2015/lib/pipes/gt-row-class.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-search.pipe.js +0 -114
- package/esm2015/lib/pipes/gt-search.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-totals-position.pipe.js +0 -35
- package/esm2015/lib/pipes/gt-totals-position.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-totals.pipe.js +0 -46
- package/esm2015/lib/pipes/gt-totals.pipe.metadata.json +0 -1
- package/esm2015/lib/pipes/gt-visible.pipe.js +0 -71
- package/esm2015/lib/pipes/gt-visible.pipe.metadata.json +0 -1
- package/esm2015/public_api.js +0 -18
- package/esm2015/public_api.metadata.json +0 -1
- package/esm5/angular-generic-table-core.js +0 -28
- package/esm5/angular-generic-table-core.metadata.json +0 -1
- package/esm5/lib/components/generic-table/generic-table.component.js +0 -1813
- package/esm5/lib/components/generic-table/generic-table.component.metadata.json +0 -1
- package/esm5/lib/components/gt-checkbox/gt-checkbox.component.js +0 -100
- package/esm5/lib/components/gt-checkbox/gt-checkbox.component.metadata.json +0 -1
- package/esm5/lib/components/gt-custom-component-factory/gt-custom-component-factory.component.js +0 -136
- package/esm5/lib/components/gt-custom-component-factory/gt-custom-component-factory.component.metadata.json +0 -1
- package/esm5/lib/components/gt-drilldown/gt-drilldown.component.js +0 -41
- package/esm5/lib/components/gt-drilldown/gt-drilldown.component.metadata.json +0 -1
- package/esm5/lib/components/gt-dropdown/gt-dropdown.component.js +0 -179
- package/esm5/lib/components/gt-dropdown/gt-dropdown.component.metadata.json +0 -1
- package/esm5/lib/components/gt-expanding-row/gt-expanding-row.component.js +0 -173
- package/esm5/lib/components/gt-expanding-row/gt-expanding-row.component.metadata.json +0 -1
- package/esm5/lib/components/gt-pagination/gt-pagination.component.js +0 -149
- package/esm5/lib/components/gt-pagination/gt-pagination.component.metadata.json +0 -1
- package/esm5/lib/components/gt-table-info/gt-table-info.component.js +0 -111
- package/esm5/lib/components/gt-table-info/gt-table-info.component.metadata.json +0 -1
- package/esm5/lib/core.module.js +0 -104
- package/esm5/lib/core.module.metadata.json +0 -1
- package/esm5/lib/directives/component-anchor.directive.js +0 -66
- package/esm5/lib/directives/component-anchor.directive.metadata.json +0 -1
- package/esm5/lib/directives/gt-column-width.directive.js +0 -81
- package/esm5/lib/directives/gt-column-width.directive.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-config-field.js +0 -96
- package/esm5/lib/interfaces/gt-config-field.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-config-setting.js +0 -41
- package/esm5/lib/interfaces/gt-config-setting.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-config-total.js +0 -20
- package/esm5/lib/interfaces/gt-config-total.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-config.js +0 -24
- package/esm5/lib/interfaces/gt-config.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-event.js +0 -16
- package/esm5/lib/interfaces/gt-event.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-information.js +0 -38
- package/esm5/lib/interfaces/gt-information.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-options.js +0 -55
- package/esm5/lib/interfaces/gt-options.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-render-field.js +0 -29
- package/esm5/lib/interfaces/gt-render-field.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-row-meta.js +0 -18
- package/esm5/lib/interfaces/gt-row-meta.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-row.js +0 -20
- package/esm5/lib/interfaces/gt-row.metadata.json +0 -1
- package/esm5/lib/interfaces/gt-texts.js +0 -36
- package/esm5/lib/interfaces/gt-texts.metadata.json +0 -1
- package/esm5/lib/pipes/dash-case.pipe.js +0 -38
- package/esm5/lib/pipes/dash-case.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-chunk.pipe.js +0 -70
- package/esm5/lib/pipes/gt-chunk.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-column-class.pipe.js +0 -61
- package/esm5/lib/pipes/gt-column-class.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-filter.pipe.js +0 -73
- package/esm5/lib/pipes/gt-filter.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-highlight.pipe.js +0 -77
- package/esm5/lib/pipes/gt-highlight.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-is-editable.pipe.js +0 -47
- package/esm5/lib/pipes/gt-is-editable.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-is-observable.pipe.js +0 -39
- package/esm5/lib/pipes/gt-is-observable.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-meta.pipe.js +0 -65
- package/esm5/lib/pipes/gt-meta.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-order-by.pipe.js +0 -223
- package/esm5/lib/pipes/gt-order-by.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-property.pipe.js +0 -63
- package/esm5/lib/pipes/gt-property.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-render.pipe.js +0 -182
- package/esm5/lib/pipes/gt-render.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-row-class.pipe.js +0 -75
- package/esm5/lib/pipes/gt-row-class.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-search.pipe.js +0 -125
- package/esm5/lib/pipes/gt-search.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-totals-position.pipe.js +0 -45
- package/esm5/lib/pipes/gt-totals-position.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-totals.pipe.js +0 -57
- package/esm5/lib/pipes/gt-totals.pipe.metadata.json +0 -1
- package/esm5/lib/pipes/gt-visible.pipe.js +0 -79
- package/esm5/lib/pipes/gt-visible.pipe.metadata.json +0 -1
- package/esm5/public_api.js +0 -18
- package/esm5/public_api.metadata.json +0 -1
- package/fesm2015/angular-generic-table-core.js +0 -3289
- package/fesm2015/angular-generic-table-core.js.map +0 -1
- package/fesm5/angular-generic-table-core.js +0 -3578
- package/fesm5/angular-generic-table-core.js.map +0 -1
- package/lib/components/generic-table/generic-table.component.d.ts +0 -282
- package/lib/components/gt-checkbox/gt-checkbox.component.d.ts +0 -12
- package/lib/components/gt-custom-component-factory/gt-custom-component-factory.component.d.ts +0 -27
- package/lib/components/gt-drilldown/gt-drilldown.component.d.ts +0 -6
- package/lib/components/gt-dropdown/gt-dropdown.component.d.ts +0 -21
- package/lib/components/gt-expanding-row/gt-expanding-row.component.d.ts +0 -34
- package/lib/components/gt-pagination/gt-pagination.component.d.ts +0 -11
- package/lib/components/gt-table-info/gt-table-info.component.d.ts +0 -15
- package/lib/directives/component-anchor.directive.d.ts +0 -10
- package/lib/directives/gt-column-width.directive.d.ts +0 -11
- package/lib/interfaces/gt-config-field.d.ts +0 -87
- package/lib/interfaces/gt-config-setting.d.ts +0 -21
- package/lib/interfaces/gt-config-total.d.ts +0 -8
- package/lib/interfaces/gt-config.d.ts +0 -12
- package/lib/interfaces/gt-event.d.ts +0 -4
- package/lib/interfaces/gt-information.d.ts +0 -15
- package/lib/interfaces/gt-options.d.ts +0 -27
- package/lib/interfaces/gt-render-field.d.ts +0 -19
- package/lib/interfaces/gt-row-meta.d.ts +0 -5
- package/lib/interfaces/gt-row.d.ts +0 -6
- package/lib/interfaces/gt-texts.d.ts +0 -14
- package/lib/pipes/gt-chunk.pipe.d.ts +0 -8
- package/lib/pipes/gt-column-class.pipe.d.ts +0 -6
- package/lib/pipes/gt-filter.pipe.d.ts +0 -5
- package/lib/pipes/gt-highlight.pipe.d.ts +0 -7
- package/lib/pipes/gt-is-editable.pipe.d.ts +0 -4
- package/lib/pipes/gt-is-observable.pipe.d.ts +0 -4
- package/lib/pipes/gt-meta.pipe.d.ts +0 -5
- package/lib/pipes/gt-order-by.pipe.d.ts +0 -11
- package/lib/pipes/gt-property.pipe.d.ts +0 -7
- package/lib/pipes/gt-render.pipe.d.ts +0 -19
- package/lib/pipes/gt-row-class.pipe.d.ts +0 -5
- package/lib/pipes/gt-search.pipe.d.ts +0 -10
- package/lib/pipes/gt-totals-position.pipe.d.ts +0 -5
- package/lib/pipes/gt-totals.pipe.d.ts +0 -4
- package/lib/pipes/gt-visible.pipe.d.ts +0 -9
- package/public_api.d.ts +0 -18
- package/scss/generic-table.scss +0 -246
|
@@ -1,1738 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview added by tsickle
|
|
3
|
-
* @suppress {checkTypes} checked by tsc
|
|
4
|
-
*/
|
|
5
|
-
import { Component, EventEmitter, Input, Output, Renderer2, Type } from '@angular/core';
|
|
6
|
-
import { GtMetaPipe } from '../../pipes/gt-meta.pipe';
|
|
7
|
-
// unsupported: template constraints.
|
|
8
|
-
// unsupported: template constraints.
|
|
9
|
-
/**
|
|
10
|
-
* @template R, C
|
|
11
|
-
*/
|
|
12
|
-
export class GenericTableComponent {
|
|
13
|
-
/**
|
|
14
|
-
* @param {?} renderer
|
|
15
|
-
* @param {?} gtMetaPipe
|
|
16
|
-
*/
|
|
17
|
-
constructor(renderer, gtMetaPipe) {
|
|
18
|
-
this.renderer = renderer;
|
|
19
|
-
this.gtMetaPipe = gtMetaPipe;
|
|
20
|
-
this.columnWidth = {};
|
|
21
|
-
this.sortOrder = [];
|
|
22
|
-
this.metaInfo = {};
|
|
23
|
-
this.selectedRows = [];
|
|
24
|
-
this.openRows = [];
|
|
25
|
-
this._gtSettings = [];
|
|
26
|
-
this._gtFields = [];
|
|
27
|
-
this.gtDefaultTexts = {
|
|
28
|
-
loading: 'Loading...',
|
|
29
|
-
noData: 'No data',
|
|
30
|
-
noMatchingData: 'No data matching results found',
|
|
31
|
-
noVisibleColumnsHeading: 'No visible columns',
|
|
32
|
-
noVisibleColumns: 'Please select at least one column to be visible.',
|
|
33
|
-
tableInfo: 'Showing #recordFrom to #recordTo of #recordsAfterSearch entries.',
|
|
34
|
-
tableInfoAfterSearch: 'Showing #recordFrom to #recordTo of #recordsAfterSearch entries (filtered from a total of #recordsAll entries).',
|
|
35
|
-
csvDownload: 'download',
|
|
36
|
-
sortLabel: 'Sort:',
|
|
37
|
-
paginateNext: 'Next page',
|
|
38
|
-
paginatePrevious: 'Previous page',
|
|
39
|
-
inlineEditEdited: 'Press enter to save'
|
|
40
|
-
};
|
|
41
|
-
this.gtTexts = this.gtDefaultTexts;
|
|
42
|
-
this.gtEvent = new EventEmitter();
|
|
43
|
-
this.gtDefaultOptions = {
|
|
44
|
-
csvDelimiter: ';',
|
|
45
|
-
stack: false,
|
|
46
|
-
lazyLoad: false,
|
|
47
|
-
cache: false,
|
|
48
|
-
debounceTime: 200,
|
|
49
|
-
highlightSearch: false,
|
|
50
|
-
rowSelection: false,
|
|
51
|
-
rowSelectionAllowMultiple: true,
|
|
52
|
-
rowExpandAllowMultiple: true,
|
|
53
|
-
numberOfRows: 10,
|
|
54
|
-
reportColumnWidth: false,
|
|
55
|
-
allowUnsorted: true,
|
|
56
|
-
mutateData: true
|
|
57
|
-
};
|
|
58
|
-
this._gtOptions = this.gtDefaultOptions;
|
|
59
|
-
this.store = [];
|
|
60
|
-
this.loading = true;
|
|
61
|
-
this.debounceTimer = null;
|
|
62
|
-
this.lazyAllSelected = false;
|
|
63
|
-
this.gtInfo = {
|
|
64
|
-
pageCurrent: 1,
|
|
65
|
-
pageTotal: 0,
|
|
66
|
-
recordFrom: 0,
|
|
67
|
-
recordTo: 0,
|
|
68
|
-
recordLength: this.gtOptions.numberOfRows,
|
|
69
|
-
recordsAll: 0,
|
|
70
|
-
recordsAfterFilter: 0,
|
|
71
|
-
recordsAfterSearch: 0
|
|
72
|
-
};
|
|
73
|
-
this.refreshPipe = false;
|
|
74
|
-
this.refreshTotals = false;
|
|
75
|
-
this.refreshSorting = false;
|
|
76
|
-
this.refreshFilter = false;
|
|
77
|
-
this.refreshPageArray = false;
|
|
78
|
-
this.editedRows = {};
|
|
79
|
-
this.data = { exportData: [] };
|
|
80
|
-
/**
|
|
81
|
-
* Sort table by object key.
|
|
82
|
-
* @param objectKey - name of key to sort on.
|
|
83
|
-
* @param event - such as key press during sorting.
|
|
84
|
-
*/
|
|
85
|
-
this.gtSort = function (objectKey, event) {
|
|
86
|
-
this.inlineEditCancel(); // cancel inline editing
|
|
87
|
-
// loop through current settings
|
|
88
|
-
for (let /** @type {?} */ i = 0; i < this._gtSettings.length; i++) {
|
|
89
|
-
if (this._gtSettings[i].objectKey === objectKey) {
|
|
90
|
-
// check if sorting is disabled...
|
|
91
|
-
if (this._gtSettings[i].sort &&
|
|
92
|
-
this._gtSettings[i].sort.indexOf('disable') !== -1) {
|
|
93
|
-
// ...if so, exit function without applying any sorting
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
else if (/* check if sorting is undefined... */ typeof this._gtSettings[i]
|
|
97
|
-
.sort === 'undefined') {
|
|
98
|
-
// ...is so, set sorting property to enable
|
|
99
|
-
this._gtSettings[i].sort = 'enable';
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
// check length
|
|
104
|
-
const /** @type {?} */ ctrlKey = event.metaKey || event.ctrlKey;
|
|
105
|
-
const /** @type {?} */ sort = this.sortOrder.slice(0);
|
|
106
|
-
let /** @type {?} */ match = -1;
|
|
107
|
-
let /** @type {?} */ matchDesc = -1;
|
|
108
|
-
let /** @type {?} */ pos = -1;
|
|
109
|
-
// check if property already exits
|
|
110
|
-
for (let /** @type {?} */ i = 0; i < sort.length; i++) {
|
|
111
|
-
const /** @type {?} */ hit = sort[i].indexOf(objectKey);
|
|
112
|
-
if (hit !== -1) {
|
|
113
|
-
match = this.sortOrder.indexOf(objectKey);
|
|
114
|
-
matchDesc =
|
|
115
|
-
match === -1 ? this.sortOrder.indexOf('-' + objectKey) : match;
|
|
116
|
-
pos = Math.max(match, matchDesc);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// if ctrl key or meta key is press together with sort...
|
|
120
|
-
if (ctrlKey) {
|
|
121
|
-
if (this.sortOrder[this.sortOrder.length - 1] === '$$gtInitialRowIndex') {
|
|
122
|
-
this.sortOrder.pop();
|
|
123
|
-
}
|
|
124
|
-
switch (pos) {
|
|
125
|
-
// ...and property is not sorted before...
|
|
126
|
-
case -1:
|
|
127
|
-
// ...add property to sorting
|
|
128
|
-
this.sortOrder.push(objectKey);
|
|
129
|
-
break;
|
|
130
|
-
default:
|
|
131
|
-
// ...and property is sorted before...
|
|
132
|
-
if (match !== -1) {
|
|
133
|
-
// ...change from asc to desc if sorted asc
|
|
134
|
-
this.sortOrder[pos] = '-' + objectKey;
|
|
135
|
-
}
|
|
136
|
-
else if (this.sortOrder.length > 1) {
|
|
137
|
-
// ...remove sorting if sorted desc
|
|
138
|
-
if (ctrlKey) {
|
|
139
|
-
this.sortOrder[pos] = objectKey;
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
this.sortOrder.splice(pos, 1);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
else if (this.sortOrder.length === 1) {
|
|
146
|
-
// ...set sorting to asc if only sorted property
|
|
147
|
-
this.sortOrder[pos] = objectKey;
|
|
148
|
-
}
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
/* if ctrl key or meta key is not press together with sort... */
|
|
154
|
-
switch (pos) {
|
|
155
|
-
// ...and property is not sorted before...
|
|
156
|
-
case -1:
|
|
157
|
-
// ...sort by property
|
|
158
|
-
this.sortOrder = [objectKey];
|
|
159
|
-
break;
|
|
160
|
-
default:
|
|
161
|
-
// ...change from desc to asc and vise versa
|
|
162
|
-
this.sortOrder =
|
|
163
|
-
match !== -1
|
|
164
|
-
? ['-' + objectKey]
|
|
165
|
-
: ctrlKey || !this.gtOptions.allowUnsorted
|
|
166
|
-
? [objectKey]
|
|
167
|
-
: [];
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
// update settings object with new sorting information
|
|
172
|
-
for (let /** @type {?} */ i = 0; i < this._gtSettings.length; i++) {
|
|
173
|
-
if (this._gtSettings[i].objectKey === objectKey) {
|
|
174
|
-
switch (this._gtSettings[i].sort) {
|
|
175
|
-
// if sorted asc...
|
|
176
|
-
case 'asc':
|
|
177
|
-
// ...change to desc
|
|
178
|
-
this._gtSettings[i].sort = 'desc';
|
|
179
|
-
break;
|
|
180
|
-
// if sorted desc...
|
|
181
|
-
case 'desc':
|
|
182
|
-
// ...change to asc if it's the only sorted property otherwise remove sorting
|
|
183
|
-
this._gtSettings[i].sort =
|
|
184
|
-
(this.sortOrder.length === 1 && sort.length < 2) ||
|
|
185
|
-
ctrlKey ||
|
|
186
|
-
!this.gtOptions.allowUnsorted
|
|
187
|
-
? 'asc'
|
|
188
|
-
: 'enable';
|
|
189
|
-
break;
|
|
190
|
-
// if sorting enabled...
|
|
191
|
-
case 'enable':
|
|
192
|
-
// ...change to asc
|
|
193
|
-
this._gtSettings[i].sort = 'asc';
|
|
194
|
-
break;
|
|
195
|
-
}
|
|
196
|
-
this._gtSettings[i].sortOrder =
|
|
197
|
-
this._gtSettings[i].sort === 'enable'
|
|
198
|
-
? this._gtSettings.length - 1
|
|
199
|
-
: this.sortOrder.indexOf(objectKey) === -1
|
|
200
|
-
? this.sortOrder.indexOf('-' + objectKey)
|
|
201
|
-
: this.sortOrder.indexOf(objectKey);
|
|
202
|
-
}
|
|
203
|
-
else if (this._gtSettings[i].sort &&
|
|
204
|
-
this._gtSettings[i].sort.indexOf('disable') === -1 &&
|
|
205
|
-
this.sortOrder.indexOf(this._gtSettings[i].objectKey) === -1 &&
|
|
206
|
-
this.sortOrder.indexOf('-' + this._gtSettings[i].objectKey) === -1) {
|
|
207
|
-
this._gtSettings[i].sort = 'enable';
|
|
208
|
-
this._gtSettings[i].sortOrder = this._gtSettings.length - 1;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
// refresh sorting pipe
|
|
212
|
-
this.refreshSorting = !this.refreshSorting;
|
|
213
|
-
this.refreshPageArray = !this.refreshPageArray;
|
|
214
|
-
// sort by initial sort order as last resort
|
|
215
|
-
this.sortOrder.push('$$gtInitialRowIndex');
|
|
216
|
-
// emit sort event
|
|
217
|
-
this.gtEvent.emit({
|
|
218
|
-
name: 'gt-sorting-applied',
|
|
219
|
-
value: this.sortOrder
|
|
220
|
-
});
|
|
221
|
-
};
|
|
222
|
-
/**
|
|
223
|
-
* Change number of rows to be displayed.
|
|
224
|
-
* @param rowLength - total number of rows.
|
|
225
|
-
* @param reset - should page be reset to first page.
|
|
226
|
-
*/
|
|
227
|
-
this.changeRowLength = function (rowLength, reset) {
|
|
228
|
-
let /** @type {?} */ lengthValue = isNaN(parseInt(rowLength, 10))
|
|
229
|
-
? 0
|
|
230
|
-
: parseInt(rowLength, 10);
|
|
231
|
-
let /** @type {?} */ newPosition = 1;
|
|
232
|
-
if (!lengthValue && this.gtData) {
|
|
233
|
-
lengthValue = this.gtData.length;
|
|
234
|
-
}
|
|
235
|
-
// if reset is not true and we're not lazy loading data...
|
|
236
|
-
if (reset !== true && this._gtOptions.lazyLoad !== true) {
|
|
237
|
-
// ...get current position in record set
|
|
238
|
-
const /** @type {?} */ currentRecord = this.gtInfo.recordLength * (this.gtInfo.pageCurrent - 1);
|
|
239
|
-
const /** @type {?} */ currentPosition = this._gtData.indexOf(this._gtData[currentRecord]) + 1;
|
|
240
|
-
// ...get new position
|
|
241
|
-
newPosition = Math.ceil(currentPosition / lengthValue);
|
|
242
|
-
}
|
|
243
|
-
// change row length
|
|
244
|
-
this.gtInfo.recordLength = lengthValue;
|
|
245
|
-
// go to new position
|
|
246
|
-
this.gtInfo.pageCurrent = newPosition;
|
|
247
|
-
// if lazy loading data...
|
|
248
|
-
if (this._gtOptions.lazyLoad) {
|
|
249
|
-
// ...replace data with place holders for new data
|
|
250
|
-
this._gtData[0] = this.loadingContent(lengthValue);
|
|
251
|
-
// ...empty current store
|
|
252
|
-
this.store = [];
|
|
253
|
-
}
|
|
254
|
-
// this.updateRecordRange();
|
|
255
|
-
this.gtEvent.emit({
|
|
256
|
-
name: 'gt-row-length-changed',
|
|
257
|
-
value: lengthValue
|
|
258
|
-
});
|
|
259
|
-
};
|
|
260
|
-
/**
|
|
261
|
-
* Force a redraw of table rows.
|
|
262
|
-
* As the table uses pure pipes, we need to force a redraw if an object in the array is changed to see the changes.
|
|
263
|
-
*/
|
|
264
|
-
this.redraw = function ($event) {
|
|
265
|
-
this.refreshSorting = !this.refreshSorting;
|
|
266
|
-
this.refreshPageArray = !this.refreshPageArray;
|
|
267
|
-
this.refreshPipe = !this.refreshPipe;
|
|
268
|
-
};
|
|
269
|
-
/**
|
|
270
|
-
* Go to next page.
|
|
271
|
-
*/
|
|
272
|
-
this.nextPage = function () {
|
|
273
|
-
const /** @type {?} */ page = this.gtInfo.pageCurrent === this.gtInfo.pageTotal
|
|
274
|
-
? this.gtInfo.pageTotal
|
|
275
|
-
: this.gtInfo.pageCurrent + 1;
|
|
276
|
-
this.goToPage(page);
|
|
277
|
-
};
|
|
278
|
-
/**
|
|
279
|
-
* Go to previous page.
|
|
280
|
-
*/
|
|
281
|
-
this.previousPage = function () {
|
|
282
|
-
const /** @type {?} */ page = this.gtInfo.pageCurrent === 1 ? 1 : this.gtInfo.pageCurrent - 1;
|
|
283
|
-
this.goToPage(page);
|
|
284
|
-
};
|
|
285
|
-
/**
|
|
286
|
-
* Request more data (used when lazy loading)
|
|
287
|
-
*/
|
|
288
|
-
this.getData = function () {
|
|
289
|
-
// ...emit event requesting for more data
|
|
290
|
-
this.gtEvent.emit({
|
|
291
|
-
name: 'gt-page-changed-lazy',
|
|
292
|
-
value: {
|
|
293
|
-
pageCurrent: this.gtInfo.pageCurrent,
|
|
294
|
-
recordLength: this.gtInfo.recordLength
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
};
|
|
298
|
-
/**
|
|
299
|
-
* Go to specific page.
|
|
300
|
-
* @param page - page number.
|
|
301
|
-
*/
|
|
302
|
-
this.goToPage = function (page) {
|
|
303
|
-
const /** @type {?} */ previousPage = this.gtInfo.pageCurrent;
|
|
304
|
-
this.gtInfo.pageCurrent = page;
|
|
305
|
-
this.inlineEditCancel(); // cancel inline edit
|
|
306
|
-
// if lazy loading and if page contains no records...
|
|
307
|
-
if (this._gtOptions.lazyLoad) {
|
|
308
|
-
// ...if data for current page contains no entries...
|
|
309
|
-
if (this._gtOptions.cache === false ||
|
|
310
|
-
this._gtData[this.gtInfo.pageCurrent - 1].length === 0) {
|
|
311
|
-
// ...create temporary content while waiting for data
|
|
312
|
-
this._gtData[this.gtInfo.pageCurrent - 1] = this.loadingContent(this.gtInfo.recordLength);
|
|
313
|
-
this.loading = true; // loading true
|
|
314
|
-
}
|
|
315
|
-
// ...if first entry in current page equals our loading placeholder...
|
|
316
|
-
if (this._gtData[this.gtInfo.pageCurrent - 1][0][this.loadingProperty] ===
|
|
317
|
-
this.gtTexts.loading) {
|
|
318
|
-
// ...get data
|
|
319
|
-
clearTimeout(this.debounceTimer);
|
|
320
|
-
this.debounceTimer = setTimeout(() => {
|
|
321
|
-
this.getData();
|
|
322
|
-
}, this._gtOptions.debounceTime);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
// this.updateRecordRange();
|
|
326
|
-
// ...emit page change event
|
|
327
|
-
if (previousPage !== page) {
|
|
328
|
-
this.gtEvent.emit({
|
|
329
|
-
name: 'gt-page-changed',
|
|
330
|
-
value: {
|
|
331
|
-
pageCurrent: this.gtInfo.pageCurrent,
|
|
332
|
-
pagePrevious: previousPage,
|
|
333
|
-
recordLength: this.gtInfo.recordLength
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
};
|
|
338
|
-
/**
|
|
339
|
-
* Sort by sort order
|
|
340
|
-
*/
|
|
341
|
-
this.getSortOrder = function (a, b) {
|
|
342
|
-
if (a.sortOrder < b.sortOrder) {
|
|
343
|
-
return -1;
|
|
344
|
-
}
|
|
345
|
-
if (a.sortOrder > b.sortOrder || typeof a.sortOrder === 'undefined') {
|
|
346
|
-
return 1;
|
|
347
|
-
}
|
|
348
|
-
return 0;
|
|
349
|
-
};
|
|
350
|
-
/**
|
|
351
|
-
* Sort by column order
|
|
352
|
-
*/
|
|
353
|
-
this.getColumnOrder = function (a, b) {
|
|
354
|
-
if (a.columnOrder === undefined) {
|
|
355
|
-
return -1;
|
|
356
|
-
}
|
|
357
|
-
if (a.columnOrder < b.columnOrder) {
|
|
358
|
-
return -1;
|
|
359
|
-
}
|
|
360
|
-
if (a.columnOrder > b.columnOrder) {
|
|
361
|
-
return 1;
|
|
362
|
-
}
|
|
363
|
-
return 0;
|
|
364
|
-
};
|
|
365
|
-
/**
|
|
366
|
-
* Create a deep copy of data
|
|
367
|
-
*/
|
|
368
|
-
this.cloneDeep = function (o) {
|
|
369
|
-
return JSON.parse(JSON.stringify(o));
|
|
370
|
-
};
|
|
371
|
-
/**
|
|
372
|
-
* Return property
|
|
373
|
-
*/
|
|
374
|
-
this.getProperty = function (array, key) {
|
|
375
|
-
for (let /** @type {?} */ i = 0; i < array.length; i++) {
|
|
376
|
-
if (array[i].objectKey === key) {
|
|
377
|
-
return array[i];
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
};
|
|
381
|
-
this.restructureSorting = function () {
|
|
382
|
-
/**
|
|
383
|
-
* Check and store sort order upon initialization.
|
|
384
|
-
* This is done by checking sort properties in the settings array of the table, if no sorting is defined
|
|
385
|
-
* we'll sort the data by the first visible and enabled column in the table(ascending). Please note that actually
|
|
386
|
-
* sorting have to be done server side when lazy loading data for obvious reasons.
|
|
387
|
-
*/
|
|
388
|
-
const /** @type {?} */ sorting = [];
|
|
389
|
-
if (this._gtSettings) {
|
|
390
|
-
// ...sort settings by sort order
|
|
391
|
-
this._gtSettings.sort(this.getSortOrder);
|
|
392
|
-
// ...loop through settings
|
|
393
|
-
for (let /** @type {?} */ i = 0; i < this._gtSettings.length; i++) {
|
|
394
|
-
const /** @type {?} */ setting = this._gtSettings[i];
|
|
395
|
-
// ...if sorted ascending...
|
|
396
|
-
if (setting.sort === 'asc') {
|
|
397
|
-
// ... add to sorting
|
|
398
|
-
sorting.push(setting.objectKey);
|
|
399
|
-
}
|
|
400
|
-
else if (setting.sort === 'desc') {
|
|
401
|
-
/* ...else if sorted descending... */
|
|
402
|
-
// ... add to sorting
|
|
403
|
-
sorting.push('-' + setting.objectKey);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
// ...if no sorting applied...
|
|
407
|
-
if (sorting.length === 0) {
|
|
408
|
-
sorting.push('$$gtRowId');
|
|
409
|
-
/*// ...sort settings by column order
|
|
410
|
-
this._gtSettings.sort(this.getColumnOrder);
|
|
411
|
-
|
|
412
|
-
// ...loop through settings
|
|
413
|
-
for (let i = 0; i < this._gtSettings.length; i++) {
|
|
414
|
-
const setting = this._gtSettings[i];
|
|
415
|
-
|
|
416
|
-
// ...if column is enabled and visible...
|
|
417
|
-
if (setting.enabled !== false && setting.visible !== false) {
|
|
418
|
-
// ...add first match and exit function
|
|
419
|
-
this.sortOrder = [this._gtSettings[i].objectKey];
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
}*/
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
if (this.sortOrder.length === 0) {
|
|
426
|
-
this.sortOrder = sorting;
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
/**
|
|
430
|
-
* Extend object function.
|
|
431
|
-
*/
|
|
432
|
-
this.extend = function (a, b) {
|
|
433
|
-
for (const /** @type {?} */ key in b) {
|
|
434
|
-
if (b.hasOwnProperty(key)) {
|
|
435
|
-
a[key] = b[key];
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
return a;
|
|
439
|
-
};
|
|
440
|
-
this.gtEvent.subscribe(($event) => {
|
|
441
|
-
if ($event.name === 'gt-info') {
|
|
442
|
-
this.updateRecordRange();
|
|
443
|
-
}
|
|
444
|
-
if ($event.name === 'gt-row-updated') {
|
|
445
|
-
this.updateTotals();
|
|
446
|
-
}
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* @return {?}
|
|
451
|
-
*/
|
|
452
|
-
get gtRowComponent() {
|
|
453
|
-
return this._gtRowComponent;
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* @return {?}
|
|
457
|
-
*/
|
|
458
|
-
get hasEdits() {
|
|
459
|
-
return Object.keys(this.editedRows).length > 0;
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* @return {?}
|
|
463
|
-
*/
|
|
464
|
-
get gtOptions() {
|
|
465
|
-
return this._gtOptions;
|
|
466
|
-
}
|
|
467
|
-
/**
|
|
468
|
-
* @return {?}
|
|
469
|
-
*/
|
|
470
|
-
get gtTotals() {
|
|
471
|
-
return this._gtTotals;
|
|
472
|
-
}
|
|
473
|
-
/**
|
|
474
|
-
* @return {?}
|
|
475
|
-
*/
|
|
476
|
-
get gtFields() {
|
|
477
|
-
return this._gtFields;
|
|
478
|
-
}
|
|
479
|
-
/**
|
|
480
|
-
* @return {?}
|
|
481
|
-
*/
|
|
482
|
-
get gtSettings() {
|
|
483
|
-
return this._gtSettings;
|
|
484
|
-
}
|
|
485
|
-
/**
|
|
486
|
-
* @return {?}
|
|
487
|
-
*/
|
|
488
|
-
get gtData() {
|
|
489
|
-
return this._gtData;
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* @param {?} value
|
|
493
|
-
* @return {?}
|
|
494
|
-
*/
|
|
495
|
-
set gtOptions(value) {
|
|
496
|
-
this._gtOptions = value;
|
|
497
|
-
// if number of rows is passed and if number of rows differs from current record length...
|
|
498
|
-
if (this.gtOptions.numberOfRows &&
|
|
499
|
-
this.gtInfo.recordLength !== this.gtOptions.numberOfRows) {
|
|
500
|
-
// ...update record length and redraw table
|
|
501
|
-
this.gtInfo.recordLength = this.gtOptions.numberOfRows;
|
|
502
|
-
this.redraw();
|
|
503
|
-
}
|
|
504
|
-
// ...extend gtOptions default values with values passed into component
|
|
505
|
-
this._gtOptions = /** @type {?} */ (this.extend(this.gtDefaultOptions, this._gtOptions));
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* @param {?} value
|
|
509
|
-
* @return {?}
|
|
510
|
-
*/
|
|
511
|
-
set gtTotals(value) {
|
|
512
|
-
this._gtTotals = value;
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* @param {?} value
|
|
516
|
-
* @return {?}
|
|
517
|
-
*/
|
|
518
|
-
set gtFields(value) {
|
|
519
|
-
this._gtFields = value;
|
|
520
|
-
const /** @type {?} */ COLUMNS_WITH_CLASS_NAMES = this._gtFields
|
|
521
|
-
.map(column => column)
|
|
522
|
-
.filter(column => column.classNames);
|
|
523
|
-
// TODO: remove deprecated warning when setting has been removed
|
|
524
|
-
if (COLUMNS_WITH_CLASS_NAMES.length > 0) {
|
|
525
|
-
console.warn('Field setting "classNames" have been deprecated in favor for "columnClass" and will be removed in the future, please update field settings for column with object key: ' +
|
|
526
|
-
COLUMNS_WITH_CLASS_NAMES[0].objectKey);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* @param {?} value
|
|
531
|
-
* @return {?}
|
|
532
|
-
*/
|
|
533
|
-
set gtSettings(value) {
|
|
534
|
-
this._gtSettings = value;
|
|
535
|
-
// loop through current settings
|
|
536
|
-
for (let /** @type {?} */ i = 0; i < this._gtSettings.length; i++) {
|
|
537
|
-
// set sort enabled/disabled setting
|
|
538
|
-
this._gtSettings[i].sortEnabled =
|
|
539
|
-
this._gtSettings[i].sortEnabled !== false
|
|
540
|
-
? (this._gtSettings[i].sortEnabled = !(this._gtSettings[i].sort &&
|
|
541
|
-
this._gtSettings[i].sort.indexOf('disable') !== -1))
|
|
542
|
-
: false;
|
|
543
|
-
// check if sorting is undefined...
|
|
544
|
-
if (typeof this._gtSettings[i].sort === 'undefined') {
|
|
545
|
-
// ...is so, set sorting property to enable
|
|
546
|
-
this._gtSettings[i].sort = 'enable';
|
|
547
|
-
}
|
|
548
|
-
// check if column order is undefined...
|
|
549
|
-
if (typeof this._gtSettings[i].columnOrder === 'undefined' &&
|
|
550
|
-
this._gtSettings[i].enabled !== false) {
|
|
551
|
-
// ...is so, set sorting property to enable
|
|
552
|
-
this._gtSettings[i].columnOrder = this._gtSettings[i - 1]
|
|
553
|
-
? this._gtSettings[i - 1].columnOrder + 1
|
|
554
|
-
: 0;
|
|
555
|
-
}
|
|
556
|
-
// check if column lock settings are undefined...
|
|
557
|
-
if (typeof this._gtSettings[i].lockSettings === 'undefined') {
|
|
558
|
-
// ...if so, set lock settings to false unless field is disabled (enable === false)
|
|
559
|
-
this._gtSettings[i].lockSettings =
|
|
560
|
-
this._gtSettings[i].enabled === false || false;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
this.restructureSorting();
|
|
564
|
-
}
|
|
565
|
-
/**
|
|
566
|
-
* @param {?} initialData
|
|
567
|
-
* @return {?}
|
|
568
|
-
*/
|
|
569
|
-
set gtData(initialData) {
|
|
570
|
-
const /** @type {?} */ data = this._gtOptions.mutateData
|
|
571
|
-
? [...initialData]
|
|
572
|
-
: this.cloneDeep(initialData);
|
|
573
|
-
if (this.gtOptions.lazyLoad && this.gtInfo) {
|
|
574
|
-
this.gtMetaPipe.transform(data, this.gtOptions.rowIndex, this.gtInfo.pageCurrent - 1, this.gtInfo.recordLength);
|
|
575
|
-
if (this.lazyAllSelected) {
|
|
576
|
-
const /** @type {?} */ UNIQUE_ROWS = this.selectedRows.map(row => row.$$gtRowId);
|
|
577
|
-
data.map(row => {
|
|
578
|
-
if (UNIQUE_ROWS.indexOf(row.$$gtRowId) === -1) {
|
|
579
|
-
this.selectedRows.push(row);
|
|
580
|
-
}
|
|
581
|
-
});
|
|
582
|
-
this._updateMetaInfo(this.selectedRows, 'isSelected', true);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
this.gtMetaPipe.transform(data, this.gtOptions.rowIndex);
|
|
587
|
-
}
|
|
588
|
-
if (this.gtOptions.rowSelectionInitialState) {
|
|
589
|
-
data.map(row => {
|
|
590
|
-
const /** @type {?} */ selected = typeof this.gtOptions.rowSelectionInitialState === 'function'
|
|
591
|
-
? this.gtOptions.rowSelectionInitialState(row)
|
|
592
|
-
: this.gtOptions.rowSelectionInitialState;
|
|
593
|
-
if (selected) {
|
|
594
|
-
if (typeof this.metaInfo[row.$$gtRowId] === 'undefined') {
|
|
595
|
-
this.metaInfo[row.$$gtRowId] = { isSelected: true };
|
|
596
|
-
}
|
|
597
|
-
else {
|
|
598
|
-
this.metaInfo[row.$$gtRowId].isSelected = true;
|
|
599
|
-
}
|
|
600
|
-
this.selectedRows.push(row);
|
|
601
|
-
}
|
|
602
|
-
});
|
|
603
|
-
}
|
|
604
|
-
if (this.gtOptions.rowExpandInitialState &&
|
|
605
|
-
this.gtOptions.rowExpandInitialComponent) {
|
|
606
|
-
data.map(row => {
|
|
607
|
-
const /** @type {?} */ expanded = typeof this.gtOptions.rowExpandInitialState === 'function'
|
|
608
|
-
? this.gtOptions.rowExpandInitialState(row)
|
|
609
|
-
: this.gtOptions.rowExpandInitialState;
|
|
610
|
-
this.expandedRow = this.gtOptions.rowExpandInitialComponent;
|
|
611
|
-
if (expanded) {
|
|
612
|
-
if (typeof this.metaInfo[row.$$gtRowId] === 'undefined') {
|
|
613
|
-
this.metaInfo[row.$$gtRowId] = { isOpen: true };
|
|
614
|
-
}
|
|
615
|
-
else {
|
|
616
|
-
this.metaInfo[row.$$gtRowId].isOpen = true;
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
this._gtData = data;
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* @param {?} value
|
|
625
|
-
* @return {?}
|
|
626
|
-
*/
|
|
627
|
-
set gtRowComponent(value) {
|
|
628
|
-
console.warn('GtRowComponent has been deprecated and support will be removed in a future release, see https://github.com/hjalmers/angular-generic-table/issues/34');
|
|
629
|
-
this._gtRowComponent = value;
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Update record range.
|
|
633
|
-
* @return {?}
|
|
634
|
-
*/
|
|
635
|
-
updateRecordRange() {
|
|
636
|
-
this.gtInfo.recordFrom =
|
|
637
|
-
this.gtInfo.recordsAfterSearch === 0
|
|
638
|
-
? 0
|
|
639
|
-
: (this.gtInfo.pageCurrent - 1) * this.gtInfo.recordLength + 1;
|
|
640
|
-
this.gtInfo.recordTo =
|
|
641
|
-
this.gtInfo.recordsAfterSearch <
|
|
642
|
-
this.gtInfo.pageCurrent * this.gtInfo.recordLength
|
|
643
|
-
? this.gtInfo.recordsAfterSearch
|
|
644
|
-
: this.gtInfo.pageCurrent * this.gtInfo.recordLength;
|
|
645
|
-
}
|
|
646
|
-
/**
|
|
647
|
-
* Update totals.
|
|
648
|
-
* @return {?}
|
|
649
|
-
*/
|
|
650
|
-
updateTotals() {
|
|
651
|
-
this.refreshTotals = !this.refreshTotals;
|
|
652
|
-
}
|
|
653
|
-
/**
|
|
654
|
-
* Get meta data for row.
|
|
655
|
-
* @param {?} row
|
|
656
|
-
* @return {?}
|
|
657
|
-
*/
|
|
658
|
-
getRowState(row) {
|
|
659
|
-
return typeof this.metaInfo[row.$$gtRowId] === 'undefined'
|
|
660
|
-
? null
|
|
661
|
-
: this.metaInfo[row.$$gtRowId];
|
|
662
|
-
}
|
|
663
|
-
/**
|
|
664
|
-
* Expand all rows.
|
|
665
|
-
* @param {?} expandedRow - component to render when rows are expanded.
|
|
666
|
-
* @return {?}
|
|
667
|
-
*/
|
|
668
|
-
expandAllRows(expandedRow) {
|
|
669
|
-
this.expandedRow = expandedRow;
|
|
670
|
-
this._toggleAllRowProperty('isOpen', true);
|
|
671
|
-
}
|
|
672
|
-
/**
|
|
673
|
-
* Collapse all rows.
|
|
674
|
-
* @return {?}
|
|
675
|
-
*/
|
|
676
|
-
collapseAllRows() {
|
|
677
|
-
this._toggleAllRowProperty('isOpen', false);
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Select all rows.
|
|
681
|
-
* @return {?}
|
|
682
|
-
*/
|
|
683
|
-
selectAllRows() {
|
|
684
|
-
this._toggleAllRowProperty('isSelected', true);
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Deselect all rows.
|
|
688
|
-
* @return {?}
|
|
689
|
-
*/
|
|
690
|
-
deselectAllRows() {
|
|
691
|
-
this._toggleAllRowProperty('isSelected', false);
|
|
692
|
-
}
|
|
693
|
-
/**
|
|
694
|
-
* Toggle all rows.
|
|
695
|
-
* @return {?}
|
|
696
|
-
*/
|
|
697
|
-
toggleAllRows() {
|
|
698
|
-
if (this._gtOptions.lazyLoad) {
|
|
699
|
-
if (!this.lazyAllSelected || this.selectedRows.length === 0) {
|
|
700
|
-
this.selectAllRows();
|
|
701
|
-
this.lazyAllSelected = true;
|
|
702
|
-
}
|
|
703
|
-
else {
|
|
704
|
-
this.deselectAllRows();
|
|
705
|
-
this.lazyAllSelected = false;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
else {
|
|
709
|
-
if (this.selectedRows.length !== this.gtData.length) {
|
|
710
|
-
this.selectAllRows();
|
|
711
|
-
}
|
|
712
|
-
else {
|
|
713
|
-
this.deselectAllRows();
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
/**
|
|
718
|
-
* Toggle row collapsed state ie. expanded/open or collapsed/closed.
|
|
719
|
-
* @param {?} row - row object that should be expanded/collapsed.
|
|
720
|
-
* @param {?=} expandedRow - component to render when row is expanded.
|
|
721
|
-
* @return {?}
|
|
722
|
-
*/
|
|
723
|
-
toggleCollapse(row, expandedRow) {
|
|
724
|
-
if (expandedRow) {
|
|
725
|
-
this.expandedRow = expandedRow;
|
|
726
|
-
}
|
|
727
|
-
this._toggleRowProperty(row, 'isOpen');
|
|
728
|
-
}
|
|
729
|
-
/**
|
|
730
|
-
* Toggle row selected state ie. selected or not.
|
|
731
|
-
* @param {?} row - row object that should be selected/deselected.
|
|
732
|
-
* @return {?}
|
|
733
|
-
*/
|
|
734
|
-
toggleSelect(row) {
|
|
735
|
-
this._toggleRowProperty(row, 'isSelected');
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* @param {?} row
|
|
739
|
-
* @param {?} $event
|
|
740
|
-
* @return {?}
|
|
741
|
-
*/
|
|
742
|
-
rowClick(row, $event) {
|
|
743
|
-
this.gtEvent.emit({
|
|
744
|
-
name: 'gt-row-clicked',
|
|
745
|
-
value: { row: row, event: $event }
|
|
746
|
-
});
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* Update row data.
|
|
750
|
-
* @param {?} row - row object that has been edited.
|
|
751
|
-
* @param {?} oldValue - row object before edit.
|
|
752
|
-
* @return {?}
|
|
753
|
-
*/
|
|
754
|
-
updateRow(row, oldValue) {
|
|
755
|
-
this._toggleRowProperty(row, 'isUpdated', oldValue);
|
|
756
|
-
}
|
|
757
|
-
/**
|
|
758
|
-
* removes a row from the table
|
|
759
|
-
* @param {?} row - the row object to remove
|
|
760
|
-
* @return {?}
|
|
761
|
-
*/
|
|
762
|
-
removeRow(row) {
|
|
763
|
-
if (this.isRowSelected(row)) {
|
|
764
|
-
this.toggleSelect(row);
|
|
765
|
-
}
|
|
766
|
-
const /** @type {?} */ index = this._gtData.indexOf(row);
|
|
767
|
-
this._gtData.splice(index, 1);
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* check if a row is selected
|
|
771
|
-
* @param {?} row - row object
|
|
772
|
-
* @return {?}
|
|
773
|
-
*/
|
|
774
|
-
isRowSelected(row) {
|
|
775
|
-
return (this.metaInfo[row.$$gtRowId] && this.metaInfo[row.$$gtRowId].isSelected);
|
|
776
|
-
}
|
|
777
|
-
/**
|
|
778
|
-
* Update meta info for all rows, ie. isSelected, isOpen.
|
|
779
|
-
* @param {?} array - array that holds rows that need to be updated.
|
|
780
|
-
* @param {?} property - name of property that should be changed/toggled.
|
|
781
|
-
* @param {?} active - should rows be expanded/open, selected.
|
|
782
|
-
* @param {?=} exception - update all rows except this one.
|
|
783
|
-
* @return {?}
|
|
784
|
-
*/
|
|
785
|
-
_updateMetaInfo(array, property, active, exception) {
|
|
786
|
-
for (let /** @type {?} */ i = 0; i < array.length; i++) {
|
|
787
|
-
if (!this.metaInfo[array[i].$$gtRowId]) {
|
|
788
|
-
this.metaInfo[array[i].$$gtRowId] = {};
|
|
789
|
-
}
|
|
790
|
-
if (exception && array[i].$$gtRowId === exception.$$gtRowId) {
|
|
791
|
-
}
|
|
792
|
-
else {
|
|
793
|
-
this.metaInfo[array[i].$$gtRowId][property] = active;
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
/**
|
|
798
|
-
* Push selected/expanded lazy loaded rows to array with meta data.
|
|
799
|
-
* @param {?} target - array to which rows should be added.
|
|
800
|
-
* @param {?} source - array that holds rows that should be added.
|
|
801
|
-
* @return {?} array with added rows.
|
|
802
|
-
*/
|
|
803
|
-
_pushLazyRows(target, source) {
|
|
804
|
-
const /** @type {?} */ UNIQUE_ROWS = target.map(row => row.$$gtRowId);
|
|
805
|
-
for (let /** @type {?} */ i = 0; i < source.length; i++) {
|
|
806
|
-
// only add if not already in list
|
|
807
|
-
if (UNIQUE_ROWS.indexOf(source[i].$$gtRowId) === -1) {
|
|
808
|
-
target.push(source[i]);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
return target;
|
|
812
|
-
}
|
|
813
|
-
/**
|
|
814
|
-
* Toggle meta info for all rows, ie. isSelected, isOpen.
|
|
815
|
-
* @param {?} property - name of property that should be changed/toggled.
|
|
816
|
-
* @param {?} active - should rows be expanded/open, selected.
|
|
817
|
-
* @return {?}
|
|
818
|
-
*/
|
|
819
|
-
_toggleAllRowProperty(property, active) {
|
|
820
|
-
let /** @type {?} */ eventName;
|
|
821
|
-
let /** @type {?} */ eventValue;
|
|
822
|
-
switch (property) {
|
|
823
|
-
case 'isOpen':
|
|
824
|
-
// check if multiple expanded rows are allowed...
|
|
825
|
-
if (this._gtOptions.rowExpandAllowMultiple === false) {
|
|
826
|
-
// ...if not, exit function
|
|
827
|
-
console.log('feature disabled: enable by setting "rowExpandAllowMultiple = true"');
|
|
828
|
-
return;
|
|
829
|
-
}
|
|
830
|
-
if (active) {
|
|
831
|
-
eventName = 'expand-all';
|
|
832
|
-
this.openRows = this._gtOptions.lazyLoad
|
|
833
|
-
? this._pushLazyRows(this.openRows, this._gtData[this.gtInfo.pageCurrent - 1].slice())
|
|
834
|
-
: this._gtData.slice();
|
|
835
|
-
this._updateMetaInfo(this.openRows, property, active);
|
|
836
|
-
}
|
|
837
|
-
else {
|
|
838
|
-
eventName = 'collapse-all';
|
|
839
|
-
this._updateMetaInfo(this.openRows, property, active);
|
|
840
|
-
this.openRows = [];
|
|
841
|
-
}
|
|
842
|
-
eventValue = {
|
|
843
|
-
expandedRows: this.openRows,
|
|
844
|
-
changedRow: 'all'
|
|
845
|
-
};
|
|
846
|
-
break;
|
|
847
|
-
case 'isSelected':
|
|
848
|
-
// check if multi row selection is allowed...
|
|
849
|
-
if (this._gtOptions.rowSelectionAllowMultiple === false) {
|
|
850
|
-
// ...if not, exit function
|
|
851
|
-
console.log('feature disabled: enable by setting "rowSelectionAllowMultiple = true"');
|
|
852
|
-
return;
|
|
853
|
-
}
|
|
854
|
-
if (active) {
|
|
855
|
-
eventName = 'select-all';
|
|
856
|
-
this.selectedRows = this._gtOptions.lazyLoad
|
|
857
|
-
? this._pushLazyRows(this.selectedRows, this._gtData[this.gtInfo.pageCurrent - 1].slice())
|
|
858
|
-
: this._gtData.slice();
|
|
859
|
-
this._updateMetaInfo(this.selectedRows, property, active);
|
|
860
|
-
}
|
|
861
|
-
else {
|
|
862
|
-
eventName = 'deselect-all';
|
|
863
|
-
this._updateMetaInfo(this.selectedRows, property, active);
|
|
864
|
-
this.selectedRows = [];
|
|
865
|
-
}
|
|
866
|
-
eventValue = {
|
|
867
|
-
selectedRows: this.selectedRows,
|
|
868
|
-
changedRow: 'all'
|
|
869
|
-
};
|
|
870
|
-
break;
|
|
871
|
-
}
|
|
872
|
-
this.gtEvent.emit({
|
|
873
|
-
name: 'gt-row-' + eventName,
|
|
874
|
-
value: eventValue
|
|
875
|
-
});
|
|
876
|
-
}
|
|
877
|
-
/**
|
|
878
|
-
* Toggle meta info for row, ie. isSelected, isOpen.
|
|
879
|
-
* @param {?} row - row object.
|
|
880
|
-
* @param {?} property - name of property that should be changed/toggled.
|
|
881
|
-
* @param {?=} propertyValues - optional property values that can be passed.
|
|
882
|
-
* @return {?}
|
|
883
|
-
*/
|
|
884
|
-
_toggleRowProperty(row, property, propertyValues) {
|
|
885
|
-
let /** @type {?} */ eventName;
|
|
886
|
-
let /** @type {?} */ eventValue;
|
|
887
|
-
// make sure gtRowId exists on row object
|
|
888
|
-
if (typeof row.$$gtRowId !== 'undefined') {
|
|
889
|
-
// check if meta info exists for row
|
|
890
|
-
if (!this.metaInfo[row.$$gtRowId]) {
|
|
891
|
-
// if not, add object to store meta info
|
|
892
|
-
this.metaInfo[row.$$gtRowId] = {};
|
|
893
|
-
}
|
|
894
|
-
switch (property) {
|
|
895
|
-
case 'isOpen':
|
|
896
|
-
const /** @type {?} */ opened = this.metaInfo[row.$$gtRowId][property];
|
|
897
|
-
// check if multiple expanded rows are allowed...
|
|
898
|
-
if (this._gtOptions.rowExpandAllowMultiple === false) {
|
|
899
|
-
// ...if not, collapse all rows except current row
|
|
900
|
-
this._updateMetaInfo(this.openRows, property, false, row);
|
|
901
|
-
this.openRows = [];
|
|
902
|
-
}
|
|
903
|
-
// check if row is expanded
|
|
904
|
-
if (!opened) {
|
|
905
|
-
eventName = 'expand';
|
|
906
|
-
// add row to expanded rows
|
|
907
|
-
this.openRows.push(row);
|
|
908
|
-
}
|
|
909
|
-
else {
|
|
910
|
-
eventName = 'collapse';
|
|
911
|
-
// loop through expanded rows...
|
|
912
|
-
for (let /** @type {?} */ i = 0; i < this.openRows.length; i++) {
|
|
913
|
-
// if expanded row equals passed row...
|
|
914
|
-
if (this.openRows[i].$$gtRowId === row.$$gtRowId) {
|
|
915
|
-
// ...remove row from expanded rows...
|
|
916
|
-
this.openRows.splice(i, 1);
|
|
917
|
-
// ...and exit loop
|
|
918
|
-
break;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
eventValue = {
|
|
923
|
-
expandedRows: this.openRows,
|
|
924
|
-
changedRow: row
|
|
925
|
-
};
|
|
926
|
-
break;
|
|
927
|
-
case 'isSelected':
|
|
928
|
-
const /** @type {?} */ selected = this.metaInfo[row.$$gtRowId][property];
|
|
929
|
-
// check if multi row selection is allowed...
|
|
930
|
-
if (this._gtOptions.rowSelectionAllowMultiple === false) {
|
|
931
|
-
// ...if not, deselect all rows except current row
|
|
932
|
-
this._updateMetaInfo(this.selectedRows, property, false, row);
|
|
933
|
-
this.selectedRows = [];
|
|
934
|
-
}
|
|
935
|
-
// check if row is selected
|
|
936
|
-
if (!selected) {
|
|
937
|
-
eventName = 'select';
|
|
938
|
-
// add row to selected rows
|
|
939
|
-
this.selectedRows.push(row);
|
|
940
|
-
}
|
|
941
|
-
else {
|
|
942
|
-
if (this.gtOptions.lazyLoad && this.lazyAllSelected) {
|
|
943
|
-
this.lazyAllSelected = false;
|
|
944
|
-
}
|
|
945
|
-
eventName = 'deselect';
|
|
946
|
-
// loop through selected rows...
|
|
947
|
-
for (let /** @type {?} */ i = 0; i < this.selectedRows.length; i++) {
|
|
948
|
-
// if selected row equals passed row...
|
|
949
|
-
if (this.selectedRows[i].$$gtRowId === row.$$gtRowId) {
|
|
950
|
-
// ...remove row from selected rows...
|
|
951
|
-
this.selectedRows.splice(i, 1);
|
|
952
|
-
// ...and exit loop
|
|
953
|
-
break;
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
eventValue = {
|
|
958
|
-
selectedRows: this.selectedRows,
|
|
959
|
-
changedRow: row
|
|
960
|
-
};
|
|
961
|
-
break;
|
|
962
|
-
case 'isUpdated':
|
|
963
|
-
eventName = 'updated';
|
|
964
|
-
const /** @type {?} */ oldValue = propertyValues;
|
|
965
|
-
// check if edit object exists for row
|
|
966
|
-
if (typeof this.metaInfo[row.$$gtRowId][property] === 'undefined') {
|
|
967
|
-
this.metaInfo[row.$$gtRowId][property] = {
|
|
968
|
-
originalValue: oldValue,
|
|
969
|
-
oldValue: oldValue,
|
|
970
|
-
newValue: row
|
|
971
|
-
};
|
|
972
|
-
}
|
|
973
|
-
else {
|
|
974
|
-
this.metaInfo[row.$$gtRowId][property].oldValue = oldValue;
|
|
975
|
-
this.metaInfo[row.$$gtRowId][property].newValue = row;
|
|
976
|
-
}
|
|
977
|
-
eventValue = this.metaInfo[row.$$gtRowId][property];
|
|
978
|
-
this.redraw();
|
|
979
|
-
this.inlineEditCancel(row);
|
|
980
|
-
// this.gtData = [...this.gtData.map((r) => { return{...r}; })];
|
|
981
|
-
break;
|
|
982
|
-
}
|
|
983
|
-
this.gtEvent.emit({
|
|
984
|
-
name: 'gt-row-' + eventName,
|
|
985
|
-
value: eventValue
|
|
986
|
-
});
|
|
987
|
-
if (property !== 'isUpdated') {
|
|
988
|
-
this.metaInfo[row.$$gtRowId][property] = !this.metaInfo[row.$$gtRowId][property];
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
/**
|
|
993
|
-
* Update column.
|
|
994
|
-
* @param {?} $event - key up event.
|
|
995
|
-
* @param {?} row - row object.
|
|
996
|
-
* @param {?} column - column object.
|
|
997
|
-
* @return {?}
|
|
998
|
-
*/
|
|
999
|
-
gtUpdateColumn($event, row, column) {
|
|
1000
|
-
this._editRow(row, column);
|
|
1001
|
-
}
|
|
1002
|
-
/**
|
|
1003
|
-
* Dropdown select.
|
|
1004
|
-
* @param {?} row - row object.
|
|
1005
|
-
* @param {?} column - column object.
|
|
1006
|
-
* @return {?}
|
|
1007
|
-
*/
|
|
1008
|
-
gtDropdownSelect(row, column) {
|
|
1009
|
-
const /** @type {?} */ oldValue = Object.assign({}, row);
|
|
1010
|
-
row[column.objectKey] = column.renderValue;
|
|
1011
|
-
this.updateRow(row, oldValue);
|
|
1012
|
-
}
|
|
1013
|
-
/**
|
|
1014
|
-
* @param {?} row
|
|
1015
|
-
* @param {?} column
|
|
1016
|
-
* @return {?}
|
|
1017
|
-
*/
|
|
1018
|
-
_editRow(row, column) {
|
|
1019
|
-
const /** @type {?} */ OBJECT_KEY = column.objectKey; // declare object key which contains changes
|
|
1020
|
-
// check if cell has changed value
|
|
1021
|
-
column.edited = row[column.objectKey] !== column.renderValue;
|
|
1022
|
-
// check if row contains changes...
|
|
1023
|
-
if (!this.editedRows[row.$$gtRowId]) {
|
|
1024
|
-
// if not, create an object for the changed row
|
|
1025
|
-
this.editedRows[row.$$gtRowId] = {
|
|
1026
|
-
changes: {},
|
|
1027
|
-
// create placeholder for changes
|
|
1028
|
-
row: row // store reference to the row that should be updated
|
|
1029
|
-
};
|
|
1030
|
-
}
|
|
1031
|
-
// store changed column under changes if it has been edited
|
|
1032
|
-
if (column.edited) {
|
|
1033
|
-
this.editedRows[row.$$gtRowId].changes[OBJECT_KEY] = column;
|
|
1034
|
-
}
|
|
1035
|
-
else {
|
|
1036
|
-
// delete change object if column is unchanged
|
|
1037
|
-
delete this.editedRows[row.$$gtRowId].changes[OBJECT_KEY];
|
|
1038
|
-
// check how many columns have been changed
|
|
1039
|
-
const /** @type {?} */ CHANGED_COLUMNS = Object.keys(this.editedRows[row.$$gtRowId].changes).length;
|
|
1040
|
-
if (CHANGED_COLUMNS === 0) {
|
|
1041
|
-
// delete row from edited rows if no columns have been edited
|
|
1042
|
-
delete this.editedRows[row.$$gtRowId];
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
// if no listener is present...
|
|
1046
|
-
if (!this.globalInlineEditListener) {
|
|
1047
|
-
// ...listen for update event
|
|
1048
|
-
this._listenForKeydownEvent();
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
/**
|
|
1052
|
-
* Listen for key down event - listen for key down event during inline edit.
|
|
1053
|
-
* @return {?}
|
|
1054
|
-
*/
|
|
1055
|
-
_listenForKeydownEvent() {
|
|
1056
|
-
// add global listener for key down events
|
|
1057
|
-
this.globalInlineEditListener = this.renderer.listen('document', 'keydown', $event => {
|
|
1058
|
-
switch ($event.key) {
|
|
1059
|
-
case 'Enter': // update data object
|
|
1060
|
-
// update data object
|
|
1061
|
-
this.inlineEditUpdate();
|
|
1062
|
-
break;
|
|
1063
|
-
case 'Escape': // cancel
|
|
1064
|
-
// cancel
|
|
1065
|
-
this.inlineEditCancel();
|
|
1066
|
-
break;
|
|
1067
|
-
}
|
|
1068
|
-
});
|
|
1069
|
-
}
|
|
1070
|
-
/**
|
|
1071
|
-
* Inline edit update - accept changes and update row values.
|
|
1072
|
-
* @return {?}
|
|
1073
|
-
*/
|
|
1074
|
-
inlineEditUpdate() {
|
|
1075
|
-
// loop through rows that have been edited
|
|
1076
|
-
Object.keys(this.editedRows).map(key => {
|
|
1077
|
-
const /** @type {?} */ ROW = this.editedRows[key].row; // row to update
|
|
1078
|
-
const /** @type {?} */ CHANGES = this.editedRows[key].changes; // changes to the row
|
|
1079
|
-
// loop through changes in row
|
|
1080
|
-
Object.keys(CHANGES).map(objectKey => {
|
|
1081
|
-
const /** @type {?} */ oldValue = Object.assign({}, ROW);
|
|
1082
|
-
ROW[objectKey] = CHANGES[objectKey].renderValue; // update data value
|
|
1083
|
-
this.updateRow(ROW, oldValue); // update meta info for row and send event
|
|
1084
|
-
CHANGES[objectKey].edited = false; // disable edit mode
|
|
1085
|
-
});
|
|
1086
|
-
});
|
|
1087
|
-
// clear rows marked as edited as the rows have been updated
|
|
1088
|
-
this.editedRows = {};
|
|
1089
|
-
// remove listener
|
|
1090
|
-
this._stopListeningForKeydownEvent();
|
|
1091
|
-
}
|
|
1092
|
-
/**
|
|
1093
|
-
* Inline edit cancel - cancel and reset inline edits.
|
|
1094
|
-
* @param {?=} row
|
|
1095
|
-
* @return {?}
|
|
1096
|
-
*/
|
|
1097
|
-
inlineEditCancel(row) {
|
|
1098
|
-
if (row) {
|
|
1099
|
-
delete this.editedRows[row.$$gtRowId];
|
|
1100
|
-
// remove listener
|
|
1101
|
-
this._stopListeningForKeydownEvent();
|
|
1102
|
-
return;
|
|
1103
|
-
}
|
|
1104
|
-
// loop through rows that have been edited
|
|
1105
|
-
Object.keys(this.editedRows).map(key => {
|
|
1106
|
-
const /** @type {?} */ ROW = this.editedRows[key].row; // row to update
|
|
1107
|
-
const /** @type {?} */ CHANGES = this.editedRows[key].changes; // changes to the row
|
|
1108
|
-
// loop through changes in row
|
|
1109
|
-
Object.keys(CHANGES).map(objectKey => {
|
|
1110
|
-
CHANGES[objectKey].renderValue = ROW[objectKey]; // reset rendered value
|
|
1111
|
-
CHANGES[objectKey].edited = false; // disable edit mode
|
|
1112
|
-
});
|
|
1113
|
-
});
|
|
1114
|
-
// clear rows marked as edited as the rows have been updated
|
|
1115
|
-
this.editedRows = {};
|
|
1116
|
-
// remove listener
|
|
1117
|
-
this._stopListeningForKeydownEvent();
|
|
1118
|
-
}
|
|
1119
|
-
/**
|
|
1120
|
-
* Stop listening for key down event - stop listening for key down events passed during inline edit.
|
|
1121
|
-
* @return {?}
|
|
1122
|
-
*/
|
|
1123
|
-
_stopListeningForKeydownEvent() {
|
|
1124
|
-
if (this.globalInlineEditListener) {
|
|
1125
|
-
this.globalInlineEditListener();
|
|
1126
|
-
this.globalInlineEditListener = null;
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
/**
|
|
1130
|
-
* Apply filter(s).
|
|
1131
|
-
* @param {?} filter - object containing key value pairs, where value should be array of values.
|
|
1132
|
-
* @return {?}
|
|
1133
|
-
*/
|
|
1134
|
-
gtApplyFilter(filter) {
|
|
1135
|
-
this.gtInfo.filter = filter;
|
|
1136
|
-
// go to first page
|
|
1137
|
-
this.goToPage(1);
|
|
1138
|
-
this.updateTotals();
|
|
1139
|
-
}
|
|
1140
|
-
/**
|
|
1141
|
-
* Clear/remove applied filter(s).
|
|
1142
|
-
* @return {?}
|
|
1143
|
-
*/
|
|
1144
|
-
gtClearFilter() {
|
|
1145
|
-
this.gtInfo.filter = false;
|
|
1146
|
-
this.updateTotals();
|
|
1147
|
-
// this.updateRecordRange();
|
|
1148
|
-
}
|
|
1149
|
-
/**
|
|
1150
|
-
* Search
|
|
1151
|
-
* @param {?} value - string containing one or more words
|
|
1152
|
-
* @return {?}
|
|
1153
|
-
*/
|
|
1154
|
-
gtSearch(value) {
|
|
1155
|
-
this.gtInfo.searchTerms = value;
|
|
1156
|
-
// always go to first page when searching
|
|
1157
|
-
this.goToPage(1);
|
|
1158
|
-
this.updateTotals();
|
|
1159
|
-
}
|
|
1160
|
-
/**
|
|
1161
|
-
* Add rows
|
|
1162
|
-
* @param {?} rows - rows to add
|
|
1163
|
-
* @return {?} new data array.
|
|
1164
|
-
*/
|
|
1165
|
-
gtAdd(rows) {
|
|
1166
|
-
this.gtData = [...this.gtData, ...rows];
|
|
1167
|
-
return [...this.gtData];
|
|
1168
|
-
}
|
|
1169
|
-
/**
|
|
1170
|
-
* Delete row
|
|
1171
|
-
* @param {?} objectKey - object key you want to find match with
|
|
1172
|
-
* @param {?} value - the value that should be deleted
|
|
1173
|
-
* @param {?=} match - all: delete all matches, first: delete first match (default)
|
|
1174
|
-
* @return {?} new data array.
|
|
1175
|
-
*/
|
|
1176
|
-
gtDelete(objectKey, value, match = 'first') {
|
|
1177
|
-
if (match === 'first') {
|
|
1178
|
-
for (let /** @type {?} */ i = 0; i < this.gtData.length; i++) {
|
|
1179
|
-
if (this.gtData[i][objectKey] === value) {
|
|
1180
|
-
if (this.isRowSelected(this.gtData[i])) {
|
|
1181
|
-
this.toggleSelect(this.gtData[i]);
|
|
1182
|
-
}
|
|
1183
|
-
this.gtData.splice(i, 1);
|
|
1184
|
-
this.gtData = [...this.gtData];
|
|
1185
|
-
if (match === 'first') {
|
|
1186
|
-
break;
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
else {
|
|
1192
|
-
for (let /** @type {?} */ i = this.gtData.length; i > 0; i--) {
|
|
1193
|
-
if (this.gtData[i - 1][objectKey] === value) {
|
|
1194
|
-
if (this.isRowSelected(this.gtData[i - 1])) {
|
|
1195
|
-
this.toggleSelect(this.gtData[i - 1]);
|
|
1196
|
-
}
|
|
1197
|
-
this.gtData.splice(i - 1, 1);
|
|
1198
|
-
this.gtData = [...this.gtData];
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
return [...this.gtData];
|
|
1203
|
-
}
|
|
1204
|
-
/**
|
|
1205
|
-
* Create store to hold previously loaded records.
|
|
1206
|
-
* @param {?} records - total number of records in store.
|
|
1207
|
-
* @param {?} perPage - how many records to show per page.
|
|
1208
|
-
* @return {?} a nested array to hold records per page.
|
|
1209
|
-
*/
|
|
1210
|
-
createStore(records, perPage) {
|
|
1211
|
-
const /** @type {?} */ stores = Math.ceil(records / perPage);
|
|
1212
|
-
const /** @type {?} */ store = [];
|
|
1213
|
-
for (let /** @type {?} */ i = 0; i < stores; i++) {
|
|
1214
|
-
store[i] = [];
|
|
1215
|
-
}
|
|
1216
|
-
return store;
|
|
1217
|
-
}
|
|
1218
|
-
/**
|
|
1219
|
-
* Create placeholders for rows while loading data from back-end.
|
|
1220
|
-
* @param {?} perPage - how many records to show per page.
|
|
1221
|
-
* @return {?} an array containing empty records to be presented while fetching real data.
|
|
1222
|
-
*/
|
|
1223
|
-
loadingContent(perPage) {
|
|
1224
|
-
// create row object
|
|
1225
|
-
const /** @type {?} */ rowObject = {
|
|
1226
|
-
$$loading: true
|
|
1227
|
-
};
|
|
1228
|
-
let /** @type {?} */ order = 0;
|
|
1229
|
-
// sort settings by column order
|
|
1230
|
-
this._gtSettings.sort(this.getColumnOrder);
|
|
1231
|
-
// loop through all settings objects...
|
|
1232
|
-
for (let /** @type {?} */ i = 0; i < this._gtSettings.length; i++) {
|
|
1233
|
-
const /** @type {?} */ setting = this._gtSettings[i];
|
|
1234
|
-
// ...if column is visible and enabled...
|
|
1235
|
-
if (setting.visible !== false && setting.enabled !== false) {
|
|
1236
|
-
// ...if first column, set value to loading text otherwise leave it empty
|
|
1237
|
-
if (order === 0) {
|
|
1238
|
-
rowObject[setting.objectKey] = this.gtTexts.loading;
|
|
1239
|
-
this.loadingProperty = setting.objectKey;
|
|
1240
|
-
}
|
|
1241
|
-
else {
|
|
1242
|
-
rowObject[setting.objectKey] = '';
|
|
1243
|
-
}
|
|
1244
|
-
order++;
|
|
1245
|
-
}
|
|
1246
|
-
else {
|
|
1247
|
-
rowObject[setting.objectKey] = '';
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
// create content placeholder
|
|
1251
|
-
const /** @type {?} */ contentPlaceholder = [];
|
|
1252
|
-
// create equal number of rows as rows per page
|
|
1253
|
-
for (let /** @type {?} */ i = 0; i < perPage; i++) {
|
|
1254
|
-
// ...add temporary row object
|
|
1255
|
-
contentPlaceholder.push(rowObject);
|
|
1256
|
-
}
|
|
1257
|
-
return contentPlaceholder;
|
|
1258
|
-
}
|
|
1259
|
-
/**
|
|
1260
|
-
* Export data as CSV
|
|
1261
|
-
* @param {?=} fileName - optional file name (overrides default file name).
|
|
1262
|
-
* @param {?=} useBOM - use BOM (byte order marker).
|
|
1263
|
-
* @return {?}
|
|
1264
|
-
*/
|
|
1265
|
-
exportCSV(fileName, useBOM = false) {
|
|
1266
|
-
const /** @type {?} */ data = this.data.exportData;
|
|
1267
|
-
let /** @type {?} */ csv = '';
|
|
1268
|
-
const /** @type {?} */ BOM = '\uFEFF';
|
|
1269
|
-
// csv export headers
|
|
1270
|
-
for (let /** @type {?} */ i = 0; i < this._gtSettings.length; i++) {
|
|
1271
|
-
if (this._gtSettings[i].export !== false) {
|
|
1272
|
-
csv += this.getProperty(this._gtFields, this._gtSettings[i].objectKey)
|
|
1273
|
-
.name;
|
|
1274
|
-
if (i < this._gtSettings.length - 1) {
|
|
1275
|
-
csv += this._gtOptions.csvDelimiter;
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
// csv export body
|
|
1280
|
-
data.forEach(row => {
|
|
1281
|
-
csv += '\n';
|
|
1282
|
-
for (let /** @type {?} */ i = 0; i < this._gtSettings.length; i++) {
|
|
1283
|
-
if (this._gtSettings[i].export !== false) {
|
|
1284
|
-
// get field settings
|
|
1285
|
-
const /** @type {?} */ fieldSetting = this.getProperty(this._gtFields, this._gtSettings[i].objectKey);
|
|
1286
|
-
// get export value, if export function is defined use it otherwise check for value function and as a last resort export raw data
|
|
1287
|
-
let /** @type {?} */ exportValue = fieldSetting.export && typeof fieldSetting.export === 'function'
|
|
1288
|
-
? fieldSetting.export(row)
|
|
1289
|
-
: fieldSetting.value && typeof fieldSetting.value === 'function'
|
|
1290
|
-
? fieldSetting.value(row)
|
|
1291
|
-
: row[this._gtSettings[i].objectKey];
|
|
1292
|
-
// escape export value using double quotes (") if export value contains delimiter
|
|
1293
|
-
exportValue =
|
|
1294
|
-
typeof exportValue === 'string' &&
|
|
1295
|
-
exportValue.indexOf(this._gtOptions.csvDelimiter) !== -1
|
|
1296
|
-
? '"' + exportValue + '"'
|
|
1297
|
-
: exportValue;
|
|
1298
|
-
csv += exportValue;
|
|
1299
|
-
if (i < this._gtSettings.length - 1) {
|
|
1300
|
-
csv += this._gtOptions.csvDelimiter;
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
});
|
|
1305
|
-
const /** @type {?} */ blob = new Blob([(useBOM ? BOM : '') + csv], {
|
|
1306
|
-
type: 'text/csv;charset=utf-8'
|
|
1307
|
-
});
|
|
1308
|
-
if (window.navigator.msSaveOrOpenBlob) {
|
|
1309
|
-
navigator.msSaveOrOpenBlob(blob, fileName ? fileName + '.csv' : this.gtTexts.csvDownload + '.csv');
|
|
1310
|
-
}
|
|
1311
|
-
else {
|
|
1312
|
-
const /** @type {?} */ link = document.createElement('a');
|
|
1313
|
-
link.style.display = 'none';
|
|
1314
|
-
document.body.appendChild(link);
|
|
1315
|
-
if (link.download !== undefined) {
|
|
1316
|
-
link.setAttribute('href', 'data:text/csv;charset=utf-8,' +
|
|
1317
|
-
encodeURIComponent((useBOM ? BOM : '') + csv)); // URL.createObjectURL(blob));
|
|
1318
|
-
link.setAttribute('download', fileName ? fileName + '.csv' : this.gtTexts.csvDownload + '.csv');
|
|
1319
|
-
document.body.appendChild(link);
|
|
1320
|
-
link.click();
|
|
1321
|
-
}
|
|
1322
|
-
else {
|
|
1323
|
-
csv = 'data:text/csv;charset=utf-8,' + (useBOM ? BOM : '') + csv;
|
|
1324
|
-
window.open(encodeURIComponent(csv));
|
|
1325
|
-
}
|
|
1326
|
-
document.body.removeChild(link);
|
|
1327
|
-
}
|
|
1328
|
-
// emit export event
|
|
1329
|
-
this.gtEvent.emit({
|
|
1330
|
-
name: 'gt-exported-csv',
|
|
1331
|
-
value: fileName ? fileName : this.gtTexts.csvDownload + '.csv'
|
|
1332
|
-
});
|
|
1333
|
-
}
|
|
1334
|
-
/**
|
|
1335
|
-
* @return {?}
|
|
1336
|
-
*/
|
|
1337
|
-
ngOnInit() {
|
|
1338
|
-
// if number of row to display from start is set to null or 0...
|
|
1339
|
-
if (!this.gtOptions.numberOfRows) {
|
|
1340
|
-
// ...change row length
|
|
1341
|
-
this.changeRowLength(this.gtOptions.numberOfRows);
|
|
1342
|
-
}
|
|
1343
|
-
this.restructureSorting();
|
|
1344
|
-
}
|
|
1345
|
-
/**
|
|
1346
|
-
* @param {?} changes
|
|
1347
|
-
* @return {?}
|
|
1348
|
-
*/
|
|
1349
|
-
ngOnChanges(changes) {
|
|
1350
|
-
// if gt texts have changed...
|
|
1351
|
-
if (changes['gtTexts']) {
|
|
1352
|
-
// ...extend gtOptions default values with values passed into component
|
|
1353
|
-
this.gtTexts = /** @type {?} */ (this.extend(this.gtDefaultTexts, this.gtTexts));
|
|
1354
|
-
}
|
|
1355
|
-
// if lazy loading data and paging information is available...
|
|
1356
|
-
if (this.gtOptions.lazyLoad && this.gtInfo) {
|
|
1357
|
-
// ...calculate total number of pages
|
|
1358
|
-
this.gtInfo.pageTotal = Math.ceil(this.gtInfo.recordsAfterSearch / this.gtInfo.recordLength);
|
|
1359
|
-
// ...declare store position
|
|
1360
|
-
const /** @type {?} */ storePosition = this.gtInfo.pageCurrent - 1;
|
|
1361
|
-
// ...and if store is empty or page length has changed...
|
|
1362
|
-
if (this.store.length === 0 ||
|
|
1363
|
-
this.store[0].length !== this.gtInfo.recordLength) {
|
|
1364
|
-
// ...create store
|
|
1365
|
-
this.store = this.createStore(this.gtInfo.recordsAfterSearch, this.gtInfo.recordLength);
|
|
1366
|
-
}
|
|
1367
|
-
// ...store retrieved data in store at store position
|
|
1368
|
-
this.store[storePosition] = this.gtData;
|
|
1369
|
-
this.gtInfo.visibleRecords = [...this.gtData]; // add visible rows
|
|
1370
|
-
// replace data with store
|
|
1371
|
-
this._gtData = this.store;
|
|
1372
|
-
this.loading = false;
|
|
1373
|
-
this.updateRecordRange();
|
|
1374
|
-
this.gtEvent.emit({
|
|
1375
|
-
name: 'gt-info',
|
|
1376
|
-
value: this.gtInfo
|
|
1377
|
-
});
|
|
1378
|
-
}
|
|
1379
|
-
else if (this._gtData &&
|
|
1380
|
-
this._gtData.length >= 0 &&
|
|
1381
|
-
changes['gtData'] &&
|
|
1382
|
-
changes['gtData'].previousValue) {
|
|
1383
|
-
this.loading = false;
|
|
1384
|
-
}
|
|
1385
|
-
else if (changes['gtData'] &&
|
|
1386
|
-
changes['gtData'].firstChange &&
|
|
1387
|
-
this._gtData &&
|
|
1388
|
-
this._gtData.length > 0) {
|
|
1389
|
-
this.loading = false;
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
/**
|
|
1393
|
-
* @param {?} index
|
|
1394
|
-
* @param {?} item
|
|
1395
|
-
* @return {?}
|
|
1396
|
-
*/
|
|
1397
|
-
trackByFn(index, item) {
|
|
1398
|
-
return item.$$gtRowId;
|
|
1399
|
-
}
|
|
1400
|
-
/**
|
|
1401
|
-
* @param {?} index
|
|
1402
|
-
* @param {?} item
|
|
1403
|
-
* @return {?}
|
|
1404
|
-
*/
|
|
1405
|
-
trackByColumnFn(index, item) {
|
|
1406
|
-
return item.objectKey;
|
|
1407
|
-
}
|
|
1408
|
-
/**
|
|
1409
|
-
* @return {?}
|
|
1410
|
-
*/
|
|
1411
|
-
ngOnDestroy() {
|
|
1412
|
-
// remove listener
|
|
1413
|
-
this._stopListeningForKeydownEvent();
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
GenericTableComponent.decorators = [
|
|
1417
|
-
{ type: Component, args: [{
|
|
1418
|
-
selector: 'generic-table',
|
|
1419
|
-
template: `<table class="table" ngClass="{{gtClasses}} {{gtOptions.stack ? 'table-stacked':''}}"
|
|
1420
|
-
*ngIf="gtFields && gtSettings && (gtFields | gtVisible:gtSettings:refreshPipe).length > 0">
|
|
1421
|
-
<thead>
|
|
1422
|
-
<tr>
|
|
1423
|
-
<th class="gt-sort-label" *ngIf="gtOptions.stack">{{gtTexts.sortLabel}}</th>
|
|
1424
|
-
<th *ngFor="let column of gtSettings | gtVisible:gtSettings:refreshPipe"
|
|
1425
|
-
ngClass="{{column.objectKey +'-column' | dashCase}} {{gtFields | gtProperty:column.objectKey:'classNames'}} {{column.sortEnabled ? 'sort-'+column.sort:''}} {{column.sortEnabled && column.sortOrder >= 0 ? 'sort-order-'+column.sortOrder:''}} {{ gtFields | gtColumnClass:column }}"
|
|
1426
|
-
(click)="column.sortEnabled ? gtSort(column.objectKey,$event):'';">
|
|
1427
|
-
<span *ngIf="!(gtFields | gtProperty:column.objectKey:'header')">{{gtFields | gtProperty:column.objectKey:'name'}}</span>
|
|
1428
|
-
<gt-custom-component-factory *ngIf="(gtFields | gtProperty:column.objectKey:'header')"
|
|
1429
|
-
[type]="(gtFields | gtProperty:column.objectKey:'header')?.type"
|
|
1430
|
-
[injector]="(gtFields | gtProperty:column.objectKey:'header')?.injector"
|
|
1431
|
-
[column]="gtFields | gtProperty:column.objectKey:'name'"></gt-custom-component-factory>
|
|
1432
|
-
<gt-checkbox *ngIf="(gtFields | gtProperty:column.objectKey:'columnComponent')?.type === 'checkbox'" [checked]="(gtOptions.lazyLoad ? lazyAllSelected:selectedRows.length === gtData.length)" (changed)="toggleAllRows()"></gt-checkbox>
|
|
1433
|
-
</th>
|
|
1434
|
-
</tr>
|
|
1435
|
-
</thead>
|
|
1436
|
-
<ng-template
|
|
1437
|
-
[ngIf]="gtTotals && (gtOptions.lazyLoad === false ? (gtData | gtFilter:gtInfo.filter:gtInfo:refreshFilter:gtData.length | gtSearch:gtInfo.searchTerms:gtInfo:gtSettings:gtFields:gtData.length).length > 0 : gtData.length > 0)">
|
|
1438
|
-
<thead class="gt-totals">
|
|
1439
|
-
<tr *ngFor="let total of gtTotals | gtTotalsPosition">
|
|
1440
|
-
<td *ngFor="let column of gtSettings | gtVisible:gtSettings:refreshPipe;let i = index;"
|
|
1441
|
-
ngClass="{{column.objectKey +'-totals-column' | dashCase}} {{gtFields | gtProperty:column.objectKey:'classNames'}} {{ gtFields | gtColumnClass:column }}">
|
|
1442
|
-
<span *ngIf="i === 0" class="float-left">{{total.name}}</span><span
|
|
1443
|
-
[innerHTML]="total.fields[column.objectKey] | gtTotals:(total.update === false || gtOptions.lazyLoad === true) ? gtData:(gtData | gtFilter:gtInfo.filter:gtInfo:refreshFilter:gtData.length | gtSearch:gtInfo.searchTerms:gtInfo:gtSettings:gtFields:gtData.length):column.objectKey:refreshTotals"></span>
|
|
1444
|
-
</td>
|
|
1445
|
-
</tr>
|
|
1446
|
-
</thead>
|
|
1447
|
-
<tfoot class="gt-totals">
|
|
1448
|
-
<tr *ngFor="let total of gtTotals | gtTotalsPosition:'footer'">
|
|
1449
|
-
<td *ngFor="let column of gtSettings | gtVisible:gtSettings:refreshPipe;let i = index;"
|
|
1450
|
-
ngClass="{{column.objectKey +'-totals-column' | dashCase}} {{gtFields | gtProperty:column.objectKey:'classNames'}} {{ gtFields | gtColumnClass:column }}">
|
|
1451
|
-
<span *ngIf="i === 0" class="float-left">{{total.name}}</span><span
|
|
1452
|
-
[innerHTML]="total.fields[column.objectKey] | gtTotals:(total.update === false || gtOptions.lazyLoad === true) ? gtData:(gtData | gtFilter:gtInfo.filter:gtInfo:refreshFilter:gtData.length | gtSearch:gtInfo.searchTerms:gtInfo:gtSettings:gtFields:gtData.length):column.objectKey:refreshTotals"></span>
|
|
1453
|
-
</td>
|
|
1454
|
-
</tr>
|
|
1455
|
-
</tfoot>
|
|
1456
|
-
</ng-template>
|
|
1457
|
-
<tbody *ngIf="gtData && gtInfo">
|
|
1458
|
-
<ng-template class="table-rows" ngFor let-row let-last="last" [ngForTrackBy]="trackByFn"
|
|
1459
|
-
[ngForOf]="gtOptions.lazyLoad && gtInfo ? (gtData[gtInfo.pageCurrent-1]) : (gtData | gtFilter:gtInfo.filter:gtInfo:refreshFilter:gtData.length | gtSearch:gtInfo.searchTerms:gtInfo:gtSettings:gtFields:gtData.length | gtOrderBy:sortOrder:gtFields:refreshSorting:gtData.length | gtChunk:gtInfo:gtInfo.recordLength:gtInfo.pageCurrent:refreshPageArray:gtData.length:gtEvent:data | gtRowClass:gtFields)">
|
|
1460
|
-
<tr [ngClass]="{'row-selected':metaInfo[row.$$gtRowId]?.isSelected, 'row-open':metaInfo[row.$$gtRowId]?.isOpen, 'row-loading':loading, 'row-expandable':gtRowComponent}"
|
|
1461
|
-
class="{{row.$$gtRowClass}}"
|
|
1462
|
-
(click)="gtOptions.rowSelection ? toggleSelect(row):rowClick(row, $event)">
|
|
1463
|
-
<td *ngFor="let column of row | gtRender:gtSettings:gtFields:refreshPipe:loading:gtOptions.highlightSearch:gtInfo.searchTerms;trackBy:trackByColumnFn"
|
|
1464
|
-
ngClass="{{column.objectKey +'-column' | dashCase}} {{gtFields | gtProperty:column.objectKey:'classNames'}} {{(gtFields | gtProperty:column.objectKey:'inlineEdit') ? 'gt-inline-edit':''}} {{column.edited ? 'gt-edited':''}} {{ gtFields | gtColumnClass:column:row }}">
|
|
1465
|
-
<span class="gt-row-label"
|
|
1466
|
-
*ngIf="gtOptions.stack">{{(gtFields | gtProperty:column.objectKey:'stackedHeading') ? (gtFields | gtProperty:column.objectKey:'stackedHeading') : (gtFields | gtProperty:column.objectKey:'name')}}</span>
|
|
1467
|
-
<gt-custom-component-factory *ngIf="column.columnComponent && column.columnComponent.type !== 'checkbox'" class="gt-row-content"
|
|
1468
|
-
[type]="column.columnComponent.type"
|
|
1469
|
-
[injector]="column.columnComponent.injector" [row]="row"
|
|
1470
|
-
[column]="column" (redrawEvent)="redraw($event)"
|
|
1471
|
-
[searchTerms]="gtInfo.searchTerms" (searchEvent)="redraw($event)"
|
|
1472
|
-
(click)="column.click ? column.click(row,column,$event):'';column.expand ? toggleCollapse(row, column.expand):''"></gt-custom-component-factory>
|
|
1473
|
-
<span *ngIf="!column.columnComponent && (!(gtFields | gtProperty:column.objectKey:'inlineEdit') || ((gtFields | gtProperty:column.objectKey:'inlineEdit')?.active | gtIsObservable) && !((gtFields | gtProperty:column.objectKey:'inlineEdit')?.active | async) || (!((gtFields | gtProperty:column.objectKey:'inlineEdit')?.active | gtIsObservable) && !((gtFields | gtProperty:column.objectKey:'inlineEdit')?.active | gtIsEditable:row:refreshPipe)))"
|
|
1474
|
-
class="gt-row-content" [innerHTML]="column.renderValue"
|
|
1475
|
-
(click)="column.click ? column.click(row,column,$event):'';column.expand ? toggleCollapse(row, column.expand):''"></span>
|
|
1476
|
-
<ng-template
|
|
1477
|
-
[ngIf]="!column.columnComponent && (((gtFields | gtProperty:column.objectKey:'inlineEdit')?.active | gtIsObservable) && ((gtFields | gtProperty:column.objectKey:'inlineEdit')?.active | async) || ((gtFields | gtProperty:column.objectKey:'inlineEdit')?.active | gtIsEditable:row:refreshPipe))">
|
|
1478
|
-
<ng-template [ngIf]="([true,'email','number','password', 'text'].indexOf((gtFields | gtProperty:column.objectKey:'inlineEdit').type) !== -1) || !(gtFields | gtProperty:column.objectKey:'inlineEdit').type">
|
|
1479
|
-
<input class="inline-edit" [attr.type]="!(gtFields | gtProperty:column.objectKey:'inlineEdit').type ? 'text' : !((gtFields | gtProperty:column.objectKey:'inlineEdit').type | gtIsObservable) ? (gtFields | gtProperty:column.objectKey:'inlineEdit').type:(gtFields | gtProperty:column.objectKey:'inlineEdit').type | async" [(ngModel)]="column.renderValue"
|
|
1480
|
-
(input)="gtUpdateColumn($event,row, column)">
|
|
1481
|
-
<span class="gt-inline-edit-notice">{{gtTexts.inlineEditEdited}}</span>
|
|
1482
|
-
</ng-template>
|
|
1483
|
-
<gt-dropdown
|
|
1484
|
-
*ngIf="(((gtFields | gtProperty:column.objectKey:'inlineEdit').type) && ((gtFields | gtProperty:column.objectKey:'inlineEdit').type).length > 0) || ((gtFields | gtProperty:column.objectKey:'inlineEdit').type | gtIsObservable)"
|
|
1485
|
-
[options]="!((gtFields | gtProperty:column.objectKey:'inlineEdit').type | gtIsObservable) ? (gtFields | gtProperty:column.objectKey:'inlineEdit').type : (gtFields | gtProperty:column.objectKey:'inlineEdit').type | async"
|
|
1486
|
-
[id]="'_' + row.$$gtRowId + '_' + column.objectKey"
|
|
1487
|
-
[(selected)]="column.renderValue" (selectedChange)="gtDropdownSelect(row, column)">Add
|
|
1488
|
-
inline editing module
|
|
1489
|
-
</gt-dropdown>
|
|
1490
|
-
</ng-template>
|
|
1491
|
-
<ng-template [ngIf]="!column.columnComponent && !((gtFields | gtProperty:column.objectKey:'inlineEdit')?.active) ">
|
|
1492
|
-
<ng-template
|
|
1493
|
-
[ngIf]="[true,'email','number','password'].indexOf(gtFields | gtProperty:column.objectKey:'inlineEdit') !== -1">
|
|
1494
|
-
<input class="inline-edit" [attr.type]="(gtFields | gtProperty:column.objectKey:'inlineEdit') === true ? 'text':(gtFields | gtProperty:column.objectKey:'inlineEdit')" [(ngModel)]="column.renderValue"
|
|
1495
|
-
(input)="gtUpdateColumn($event,row, column)">
|
|
1496
|
-
<span class="gt-inline-edit-notice">{{gtTexts.inlineEditEdited}}</span>
|
|
1497
|
-
</ng-template>
|
|
1498
|
-
<gt-dropdown
|
|
1499
|
-
*ngIf="(gtFields | gtProperty:column.objectKey:'inlineEdit') && [true,'email','number','password'].indexOf(gtFields | gtProperty:column.objectKey:'inlineEdit') === -1"
|
|
1500
|
-
[options]="gtFields | gtProperty:column.objectKey:'inlineEdit'"
|
|
1501
|
-
[id]="'_' + row.$$gtRowId + '_' + column.objectKey"
|
|
1502
|
-
[(selected)]="column.renderValue" (selectedChange)="gtDropdownSelect(row, column)">Add
|
|
1503
|
-
inline editing module
|
|
1504
|
-
</gt-dropdown>
|
|
1505
|
-
</ng-template>
|
|
1506
|
-
<gt-checkbox *ngIf="column.columnComponent && column.columnComponent.type === 'checkbox'" [checked]="metaInfo[row.$$gtRowId]?.isSelected" (changed)="toggleSelect(row)"></gt-checkbox>
|
|
1507
|
-
</td>
|
|
1508
|
-
</tr>
|
|
1509
|
-
<tr class="row-expanded" *ngIf="metaInfo[row.$$gtRowId]?.isOpen">
|
|
1510
|
-
<td [attr.colspan]="(gtFields | gtVisible:gtSettings:refreshPipe).length">
|
|
1511
|
-
<gt-expanding-row [row]="row"
|
|
1512
|
-
[type]="expandedRow.component ? expandedRow.component:gtRowComponent"
|
|
1513
|
-
[columnWidth]="columnWidth"
|
|
1514
|
-
[gtFields]="gtFields"
|
|
1515
|
-
[gtOptions]="gtOptions"
|
|
1516
|
-
[gtEvent]="gtEvent"
|
|
1517
|
-
[gtInfo]="gtInfo"
|
|
1518
|
-
[gtSettings]="gtSettings"
|
|
1519
|
-
[data]="expandedRow.data ? expandedRow.data:row"
|
|
1520
|
-
(redrawEvent)="redraw($event)"
|
|
1521
|
-
(toggleRowEvent)="toggleCollapse($event)"></gt-expanding-row>
|
|
1522
|
-
</td>
|
|
1523
|
-
</tr>
|
|
1524
|
-
<tr *ngIf="gtOptions.reportColumnWidth && last">
|
|
1525
|
-
<td style="padding: 0; border:none;"
|
|
1526
|
-
*ngFor="let column of gtSettings | gtVisible:gtSettings:refreshPipe" gtColumnWidth
|
|
1527
|
-
[objectKey]="column.objectKey" [widths]="columnWidth"></td>
|
|
1528
|
-
</tr>
|
|
1529
|
-
</ng-template>
|
|
1530
|
-
<tr *ngIf="gtInfo.pageTotal === 0 && (gtInfo.searchTerms || gtInfo.filter) && !loading">
|
|
1531
|
-
<td class="gt-no-matching-results" [attr.colspan]="(gtFields | gtVisible:gtSettings).length">
|
|
1532
|
-
{{gtTexts.noMatchingData}}
|
|
1533
|
-
</td>
|
|
1534
|
-
</tr>
|
|
1535
|
-
<tr *ngIf="gtInfo.pageTotal === 0 && !(gtInfo.searchTerms || gtInfo.filter) && !loading">
|
|
1536
|
-
<td class="gt-no-results" [attr.colspan]="(gtFields | gtVisible:gtSettings).length">{{gtTexts.noData}}
|
|
1537
|
-
</td>
|
|
1538
|
-
</tr>
|
|
1539
|
-
<tr *ngIf="gtInfo.pageTotal === 0 && loading">
|
|
1540
|
-
<td class="gt-loading-data" [attr.colspan]="(gtFields | gtVisible:gtSettings).length">{{gtTexts.loading}}</td>
|
|
1541
|
-
</tr>
|
|
1542
|
-
</tbody>
|
|
1543
|
-
</table>
|
|
1544
|
-
<table class="table" ngClass="{{gtClasses}} {{gtOptions.stack ? 'table-stacked':''}}"
|
|
1545
|
-
*ngIf="gtFields && gtSettings && (gtFields | gtVisible:gtSettings:refreshPipe).length === 0">
|
|
1546
|
-
<thead>
|
|
1547
|
-
<tr>
|
|
1548
|
-
<th class="gt-no-visible-columns">{{gtTexts.noVisibleColumnsHeading}}</th>
|
|
1549
|
-
</tr>
|
|
1550
|
-
</thead>
|
|
1551
|
-
<tbody>
|
|
1552
|
-
<tr>
|
|
1553
|
-
<td class="gt-no-visible-columns">{{gtTexts.noVisibleColumns}}</td>
|
|
1554
|
-
</tr>
|
|
1555
|
-
</tbody>
|
|
1556
|
-
</table>
|
|
1557
|
-
<table class="table" ngClass="{{gtClasses}} {{gtOptions.stack ? 'table-stacked':''}}"
|
|
1558
|
-
*ngIf="!gtFields || !gtSettings">
|
|
1559
|
-
<thead>
|
|
1560
|
-
<tr>
|
|
1561
|
-
<th class="gt-loading-config"> </th>
|
|
1562
|
-
</tr>
|
|
1563
|
-
</thead>
|
|
1564
|
-
<tbody>
|
|
1565
|
-
<tr>
|
|
1566
|
-
<td class="gt-loading-config"> </td>
|
|
1567
|
-
</tr>
|
|
1568
|
-
</tbody>
|
|
1569
|
-
</table>
|
|
1570
|
-
`
|
|
1571
|
-
}] }
|
|
1572
|
-
];
|
|
1573
|
-
/** @nocollapse */
|
|
1574
|
-
GenericTableComponent.ctorParameters = () => [
|
|
1575
|
-
{ type: Renderer2, },
|
|
1576
|
-
{ type: GtMetaPipe, },
|
|
1577
|
-
];
|
|
1578
|
-
GenericTableComponent.propDecorators = {
|
|
1579
|
-
"gtOptions": [{ type: Input },],
|
|
1580
|
-
"gtTotals": [{ type: Input },],
|
|
1581
|
-
"gtFields": [{ type: Input },],
|
|
1582
|
-
"gtSettings": [{ type: Input },],
|
|
1583
|
-
"gtData": [{ type: Input },],
|
|
1584
|
-
"gtRowComponent": [{ type: Input },],
|
|
1585
|
-
"gtTexts": [{ type: Input },],
|
|
1586
|
-
"gtClasses": [{ type: Input },],
|
|
1587
|
-
"gtEvent": [{ type: Output },],
|
|
1588
|
-
"gtInfo": [{ type: Input },],
|
|
1589
|
-
};
|
|
1590
|
-
function GenericTableComponent_tsickle_Closure_declarations() {
|
|
1591
|
-
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
|
|
1592
|
-
GenericTableComponent.decorators;
|
|
1593
|
-
/**
|
|
1594
|
-
* @nocollapse
|
|
1595
|
-
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
|
|
1596
|
-
*/
|
|
1597
|
-
GenericTableComponent.ctorParameters;
|
|
1598
|
-
/** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */
|
|
1599
|
-
GenericTableComponent.propDecorators;
|
|
1600
|
-
/** @type {?} */
|
|
1601
|
-
GenericTableComponent.prototype.columnWidth;
|
|
1602
|
-
/** @type {?} */
|
|
1603
|
-
GenericTableComponent.prototype.configObject;
|
|
1604
|
-
/** @type {?} */
|
|
1605
|
-
GenericTableComponent.prototype.sortOrder;
|
|
1606
|
-
/** @type {?} */
|
|
1607
|
-
GenericTableComponent.prototype.metaInfo;
|
|
1608
|
-
/** @type {?} */
|
|
1609
|
-
GenericTableComponent.prototype.selectedRows;
|
|
1610
|
-
/** @type {?} */
|
|
1611
|
-
GenericTableComponent.prototype.openRows;
|
|
1612
|
-
/** @type {?} */
|
|
1613
|
-
GenericTableComponent.prototype._gtSettings;
|
|
1614
|
-
/** @type {?} */
|
|
1615
|
-
GenericTableComponent.prototype._gtFields;
|
|
1616
|
-
/** @type {?} */
|
|
1617
|
-
GenericTableComponent.prototype._gtData;
|
|
1618
|
-
/** @type {?} */
|
|
1619
|
-
GenericTableComponent.prototype._gtTotals;
|
|
1620
|
-
/** @type {?} */
|
|
1621
|
-
GenericTableComponent.prototype._gtRowComponent;
|
|
1622
|
-
/** @type {?} */
|
|
1623
|
-
GenericTableComponent.prototype.expandedRow;
|
|
1624
|
-
/** @type {?} */
|
|
1625
|
-
GenericTableComponent.prototype.gtDefaultTexts;
|
|
1626
|
-
/** @type {?} */
|
|
1627
|
-
GenericTableComponent.prototype.gtTexts;
|
|
1628
|
-
/** @type {?} */
|
|
1629
|
-
GenericTableComponent.prototype.gtClasses;
|
|
1630
|
-
/** @type {?} */
|
|
1631
|
-
GenericTableComponent.prototype.gtEvent;
|
|
1632
|
-
/** @type {?} */
|
|
1633
|
-
GenericTableComponent.prototype.gtDefaultOptions;
|
|
1634
|
-
/** @type {?} */
|
|
1635
|
-
GenericTableComponent.prototype._gtOptions;
|
|
1636
|
-
/** @type {?} */
|
|
1637
|
-
GenericTableComponent.prototype.store;
|
|
1638
|
-
/** @type {?} */
|
|
1639
|
-
GenericTableComponent.prototype.loading;
|
|
1640
|
-
/** @type {?} */
|
|
1641
|
-
GenericTableComponent.prototype.debounceTimer;
|
|
1642
|
-
/** @type {?} */
|
|
1643
|
-
GenericTableComponent.prototype.loadingProperty;
|
|
1644
|
-
/** @type {?} */
|
|
1645
|
-
GenericTableComponent.prototype.lazyAllSelected;
|
|
1646
|
-
/** @type {?} */
|
|
1647
|
-
GenericTableComponent.prototype.gtInfo;
|
|
1648
|
-
/** @type {?} */
|
|
1649
|
-
GenericTableComponent.prototype.refreshPipe;
|
|
1650
|
-
/** @type {?} */
|
|
1651
|
-
GenericTableComponent.prototype.refreshTotals;
|
|
1652
|
-
/** @type {?} */
|
|
1653
|
-
GenericTableComponent.prototype.refreshSorting;
|
|
1654
|
-
/** @type {?} */
|
|
1655
|
-
GenericTableComponent.prototype.refreshFilter;
|
|
1656
|
-
/** @type {?} */
|
|
1657
|
-
GenericTableComponent.prototype.refreshPageArray;
|
|
1658
|
-
/** @type {?} */
|
|
1659
|
-
GenericTableComponent.prototype.globalInlineEditListener;
|
|
1660
|
-
/** @type {?} */
|
|
1661
|
-
GenericTableComponent.prototype.editedRows;
|
|
1662
|
-
/** @type {?} */
|
|
1663
|
-
GenericTableComponent.prototype.data;
|
|
1664
|
-
/**
|
|
1665
|
-
* Sort table by object key.
|
|
1666
|
-
* \@param objectKey - name of key to sort on.
|
|
1667
|
-
* \@param event - such as key press during sorting.
|
|
1668
|
-
* @type {?}
|
|
1669
|
-
*/
|
|
1670
|
-
GenericTableComponent.prototype.gtSort;
|
|
1671
|
-
/**
|
|
1672
|
-
* Change number of rows to be displayed.
|
|
1673
|
-
* \@param rowLength - total number of rows.
|
|
1674
|
-
* \@param reset - should page be reset to first page.
|
|
1675
|
-
* @type {?}
|
|
1676
|
-
*/
|
|
1677
|
-
GenericTableComponent.prototype.changeRowLength;
|
|
1678
|
-
/**
|
|
1679
|
-
* Force a redraw of table rows.
|
|
1680
|
-
* As the table uses pure pipes, we need to force a redraw if an object in the array is changed to see the changes.
|
|
1681
|
-
* @type {?}
|
|
1682
|
-
*/
|
|
1683
|
-
GenericTableComponent.prototype.redraw;
|
|
1684
|
-
/**
|
|
1685
|
-
* Go to next page.
|
|
1686
|
-
* @type {?}
|
|
1687
|
-
*/
|
|
1688
|
-
GenericTableComponent.prototype.nextPage;
|
|
1689
|
-
/**
|
|
1690
|
-
* Go to previous page.
|
|
1691
|
-
* @type {?}
|
|
1692
|
-
*/
|
|
1693
|
-
GenericTableComponent.prototype.previousPage;
|
|
1694
|
-
/**
|
|
1695
|
-
* Request more data (used when lazy loading)
|
|
1696
|
-
* @type {?}
|
|
1697
|
-
*/
|
|
1698
|
-
GenericTableComponent.prototype.getData;
|
|
1699
|
-
/**
|
|
1700
|
-
* Go to specific page.
|
|
1701
|
-
* \@param page - page number.
|
|
1702
|
-
* @type {?}
|
|
1703
|
-
*/
|
|
1704
|
-
GenericTableComponent.prototype.goToPage;
|
|
1705
|
-
/**
|
|
1706
|
-
* Sort by sort order
|
|
1707
|
-
* @type {?}
|
|
1708
|
-
*/
|
|
1709
|
-
GenericTableComponent.prototype.getSortOrder;
|
|
1710
|
-
/**
|
|
1711
|
-
* Sort by column order
|
|
1712
|
-
* @type {?}
|
|
1713
|
-
*/
|
|
1714
|
-
GenericTableComponent.prototype.getColumnOrder;
|
|
1715
|
-
/**
|
|
1716
|
-
* Create a deep copy of data
|
|
1717
|
-
* @type {?}
|
|
1718
|
-
*/
|
|
1719
|
-
GenericTableComponent.prototype.cloneDeep;
|
|
1720
|
-
/**
|
|
1721
|
-
* Return property
|
|
1722
|
-
* @type {?}
|
|
1723
|
-
*/
|
|
1724
|
-
GenericTableComponent.prototype.getProperty;
|
|
1725
|
-
/** @type {?} */
|
|
1726
|
-
GenericTableComponent.prototype.restructureSorting;
|
|
1727
|
-
/**
|
|
1728
|
-
* Extend object function.
|
|
1729
|
-
* @type {?}
|
|
1730
|
-
*/
|
|
1731
|
-
GenericTableComponent.prototype.extend;
|
|
1732
|
-
/** @type {?} */
|
|
1733
|
-
GenericTableComponent.prototype.renderer;
|
|
1734
|
-
/** @type {?} */
|
|
1735
|
-
GenericTableComponent.prototype.gtMetaPipe;
|
|
1736
|
-
}
|
|
1737
|
-
|
|
1738
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJpYy10YWJsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AYW5ndWxhci1nZW5lcmljLXRhYmxlL2NvcmUvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9nZW5lcmljLXRhYmxlL2dlbmVyaWMtdGFibGUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ04sU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBSUwsTUFBTSxFQUNOLFNBQVMsRUFFVCxJQUFJLEVBQ0osTUFBTSxlQUFlLENBQUM7QUFZdkIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDOzs7Ozs7QUE2SnRELE1BQU0sT0FBTyxxQkFBcUI7Ozs7O0lBd1FqQyxZQUFvQixRQUFtQixFQUFVLFVBQXNCO1FBQW5ELGFBQVEsR0FBUixRQUFRLENBQVc7UUFBVSxlQUFVLEdBQVYsVUFBVSxDQUFZOzJCQW5GMUMsRUFBRTt5QkFFQSxFQUFFO3dCQUNtQixFQUFFOzRCQUNsQixFQUFFO3dCQUNOLEVBQUU7MkJBQ08sRUFBRTt5QkFDRSxFQUFFOzhCQVFkO1lBQ2hDLE9BQU8sRUFBRSxZQUFZO1lBQ3JCLE1BQU0sRUFBRSxTQUFTO1lBQ2pCLGNBQWMsRUFBRSxnQ0FBZ0M7WUFDaEQsdUJBQXVCLEVBQUUsb0JBQW9CO1lBQzdDLGdCQUFnQixFQUFFLGtEQUFrRDtZQUNwRSxTQUFTLEVBQ1Isa0VBQWtFO1lBQ25FLG9CQUFvQixFQUNuQixrSEFBa0g7WUFDbkgsV0FBVyxFQUFFLFVBQVU7WUFDdkIsU0FBUyxFQUFFLE9BQU87WUFDbEIsWUFBWSxFQUFFLFdBQVc7WUFDekIsZ0JBQWdCLEVBQUUsZUFBZTtZQUNqQyxnQkFBZ0IsRUFBRSxxQkFBcUI7U0FDdkM7dUJBQzJCLElBQUksQ0FBQyxjQUFjO3VCQUVKLElBQUksWUFBWSxFQUFFO2dDQUN4QjtZQUNwQyxZQUFZLEVBQUUsR0FBRztZQUNqQixLQUFLLEVBQUUsS0FB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SUFBSSxDQUFDLDZCQUE2QixFQUFFLENBQUM7S0FDckM7OztZQXJuREQsU0FBUyxTQUFDO2dCQUNWLFFBQVEsRUFBRSxlQUFlO2dCQUN6QixRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0F1SlY7YUFDQTs7OztZQTNLQSxTQUFTO1lBZUQsVUFBVTs7OzBCQTJMakIsS0FBSzt5QkFxQkwsS0FBSzt5QkFJTCxLQUFLOzJCQWNMLEtBQUs7dUJBeUNMLEtBQUs7K0JBK0RMLEtBQUs7d0JBdUNMLEtBQUs7MEJBQ0wsS0FBSzt3QkFDTCxNQUFNO3VCQXVCTixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRFdmVudEVtaXR0ZXIsXG5cdElucHV0LFxuXHRPbkNoYW5nZXMsXG5cdE9uRGVzdHJveSxcblx0T25Jbml0LFxuXHRPdXRwdXQsXG5cdFJlbmRlcmVyMixcblx0U2ltcGxlQ2hhbmdlcyxcblx0VHlwZVxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEd0Um93IH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9ndC1yb3cnO1xuaW1wb3J0IHsgR3RFeHBhbmRlZFJvdyB9IGZyb20gJy4uL2d0LWV4cGFuZGluZy1yb3cvZ3QtZXhwYW5kaW5nLXJvdy5jb21wb25lbnQnO1xuaW1wb3J0IHsgR3RPcHRpb25zIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9ndC1vcHRpb25zJztcbmltcG9ydCB7IEd0Q29uZmlnRmllbGQgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL2d0LWNvbmZpZy1maWVsZCc7XG5pbXBvcnQgeyBHdENvbmZpZ1NldHRpbmcgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL2d0LWNvbmZpZy1zZXR0aW5nJztcbmltcG9ydCB7IEd0Um93TWV0YSB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvZ3Qtcm93LW1ldGEnO1xuaW1wb3J0IHsgR3RUZXh0cyB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvZ3QtdGV4dHMnO1xuaW1wb3J0IHsgR3RDb25maWcgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL2d0LWNvbmZpZyc7XG5pbXBvcnQgeyBHdEV2ZW50IH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9ndC1ldmVudCc7XG5pbXBvcnQgeyBHdEluZm9ybWF0aW9uIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9ndC1pbmZvcm1hdGlvbic7XG5pbXBvcnQgeyBHdFJlbmRlckZpZWxkIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9ndC1yZW5kZXItZmllbGQnO1xuaW1wb3J0IHsgR3RNZXRhUGlwZSB9IGZyb20gJy4uLy4uL3BpcGVzL2d0LW1ldGEucGlwZSc7XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogJ2dlbmVyaWMtdGFibGUnLFxuXHR0ZW1wbGF0ZTogYDx0YWJsZSBjbGFzcz1cInRhYmxlXCIgbmdDbGFzcz1cInt7Z3RDbGFzc2VzfX0ge3tndE9wdGlvbnMuc3RhY2sgPyAndGFibGUtc3RhY2tlZCc6Jyd9fVwiXG4gICAgICAgKm5nSWY9XCJndEZpZWxkcyAmJiBndFNldHRpbmdzICYmIChndEZpZWxkcyB8IGd0VmlzaWJsZTpndFNldHRpbmdzOnJlZnJlc2hQaXBlKS5sZW5ndGggPiAwXCI+XG4gIDx0aGVhZD5cbiAgPHRyPlxuICAgIDx0aCBjbGFzcz1cImd0LXNvcnQtbGFiZWxcIiAqbmdJZj1cImd0T3B0aW9ucy5zdGFja1wiPnt7Z3RUZXh0cy5zb3J0TGFiZWx9fTwvdGg+XG4gICAgPHRoICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgZ3RTZXR0aW5ncyB8IGd0VmlzaWJsZTpndFNldHRpbmdzOnJlZnJlc2hQaXBlXCJcbiAgICAgICAgbmdDbGFzcz1cInt7Y29sdW1uLm9iamVjdEtleSArJy1jb2x1bW4nIHwgZGFzaENhc2V9fSB7e2d0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidjbGFzc05hbWVzJ319IHt7Y29sdW1uLnNvcnRFbmFibGVkID8gJ3NvcnQtJytjb2x1bW4uc29ydDonJ319IHt7Y29sdW1uLnNvcnRFbmFibGVkICYmIGNvbHVtbi5zb3J0T3JkZXIgPj0gMCAgPyAnc29ydC1vcmRlci0nK2NvbHVtbi5zb3J0T3JkZXI6Jyd9fSB7eyBndEZpZWxkcyB8IGd0Q29sdW1uQ2xhc3M6Y29sdW1uIH19XCJcbiAgICAgICAgKGNsaWNrKT1cImNvbHVtbi5zb3J0RW5hYmxlZCA/IGd0U29ydChjb2x1bW4ub2JqZWN0S2V5LCRldmVudCk6Jyc7XCI+XG4gICAgICA8c3BhbiAqbmdJZj1cIiEoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2hlYWRlcicpXCI+e3tndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonbmFtZSd9fTwvc3Bhbj5cbiAgICAgIDxndC1jdXN0b20tY29tcG9uZW50LWZhY3RvcnkgKm5nSWY9XCIoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2hlYWRlcicpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3R5cGVdPVwiKGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidoZWFkZXInKT8udHlwZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpbmplY3Rvcl09XCIoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2hlYWRlcicpPy5pbmplY3RvclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjb2x1bW5dPVwiZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J25hbWUnXCI+PC9ndC1jdXN0b20tY29tcG9uZW50LWZhY3Rvcnk+XG4gICAgICA8Z3QtY2hlY2tib3ggKm5nSWY9XCIoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2NvbHVtbkNvbXBvbmVudCcpPy50eXBlID09PSAnY2hlY2tib3gnXCIgW2NoZWNrZWRdPVwiKGd0T3B0aW9ucy5sYXp5TG9hZCA/IGxhenlBbGxTZWxlY3RlZDpzZWxlY3RlZFJvd3MubGVuZ3RoID09PSBndERhdGEubGVuZ3RoKVwiIChjaGFuZ2VkKT1cInRvZ2dsZUFsbFJvd3MoKVwiPjwvZ3QtY2hlY2tib3g+XG4gICAgPC90aD5cbiAgPC90cj5cbiAgPC90aGVhZD5cbiAgPG5nLXRlbXBsYXRlXG4gICAgW25nSWZdPVwiZ3RUb3RhbHMgJiYgKGd0T3B0aW9ucy5sYXp5TG9hZCA9PT0gZmFsc2UgPyAoZ3REYXRhIHwgZ3RGaWx0ZXI6Z3RJbmZvLmZpbHRlcjpndEluZm86cmVmcmVzaEZpbHRlcjpndERhdGEubGVuZ3RoIHwgZ3RTZWFyY2g6Z3RJbmZvLnNlYXJjaFRlcm1zOmd0SW5mbzpndFNldHRpbmdzOmd0RmllbGRzOmd0RGF0YS5sZW5ndGgpLmxlbmd0aCA+IDAgOiBndERhdGEubGVuZ3RoID4gMClcIj5cbiAgICA8dGhlYWQgY2xhc3M9XCJndC10b3RhbHNcIj5cbiAgICA8dHIgKm5nRm9yPVwibGV0IHRvdGFsIG9mIGd0VG90YWxzIHwgZ3RUb3RhbHNQb3NpdGlvblwiPlxuICAgICAgPHRkICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgZ3RTZXR0aW5ncyB8IGd0VmlzaWJsZTpndFNldHRpbmdzOnJlZnJlc2hQaXBlO2xldCBpID0gaW5kZXg7XCJcbiAgICAgICAgICBuZ0NsYXNzPVwie3tjb2x1bW4ub2JqZWN0S2V5ICsnLXRvdGFscy1jb2x1bW4nIHwgZGFzaENhc2V9fSB7e2d0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidjbGFzc05hbWVzJ319IHt7IGd0RmllbGRzIHwgZ3RDb2x1bW5DbGFzczpjb2x1bW4gfX1cIj5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCJpID09PSAwXCIgY2xhc3M9XCJmbG9hdC1sZWZ0XCI+e3t0b3RhbC5uYW1lfX08L3NwYW4+PHNwYW5cbiAgICAgICAgW2lubmVySFRNTF09XCJ0b3RhbC5maWVsZHNbY29sdW1uLm9iamVjdEtleV0gfCBndFRvdGFsczoodG90YWwudXBkYXRlID09PSBmYWxzZSB8fCBndE9wdGlvbnMubGF6eUxvYWQgPT09IHRydWUpID8gZ3REYXRhOihndERhdGEgfCBndEZpbHRlcjpndEluZm8uZmlsdGVyOmd0SW5mbzpyZWZyZXNoRmlsdGVyOmd0RGF0YS5sZW5ndGggfCBndFNlYXJjaDpndEluZm8uc2VhcmNoVGVybXM6Z3RJbmZvOmd0U2V0dGluZ3M6Z3RGaWVsZHM6Z3REYXRhLmxlbmd0aCk6Y29sdW1uLm9iamVjdEtleTpyZWZyZXNoVG90YWxzXCI+PC9zcGFuPlxuICAgICAgPC90ZD5cbiAgICA8L3RyPlxuICAgIDwvdGhlYWQ+XG4gICAgPHRmb290IGNsYXNzPVwiZ3QtdG90YWxzXCI+XG4gICAgPHRyICpuZ0Zvcj1cImxldCB0b3RhbCBvZiBndFRvdGFscyB8IGd0VG90YWxzUG9zaXRpb246J2Zvb3RlcidcIj5cbiAgICAgIDx0ZCAqbmdGb3I9XCJsZXQgY29sdW1uIG9mIGd0U2V0dGluZ3MgfCBndFZpc2libGU6Z3RTZXR0aW5nczpyZWZyZXNoUGlwZTtsZXQgaSA9IGluZGV4O1wiXG4gICAgICAgICAgbmdDbGFzcz1cInt7Y29sdW1uLm9iamVjdEtleSArJy10b3RhbHMtY29sdW1uJyB8IGRhc2hDYXNlfX0ge3tndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonY2xhc3NOYW1lcyd9fSB7eyBndEZpZWxkcyB8IGd0Q29sdW1uQ2xhc3M6Y29sdW1uIH19XCI+XG4gICAgICAgIDxzcGFuICpuZ0lmPVwiaSA9PT0gMFwiIGNsYXNzPVwiZmxvYXQtbGVmdFwiPnt7dG90YWwubmFtZX19PC9zcGFuPjxzcGFuXG4gICAgICAgIFtpbm5lckhUTUxdPVwidG90YWwuZmllbGRzW2NvbHVtbi5vYmplY3RLZXldIHwgZ3RUb3RhbHM6KHRvdGFsLnVwZGF0ZSA9PT0gZmFsc2UgfHwgZ3RPcHRpb25zLmxhenlMb2FkID09PSB0cnVlKSA/IGd0RGF0YTooZ3REYXRhIHwgZ3RGaWx0ZXI6Z3RJbmZvLmZpbHRlcjpndEluZm86cmVmcmVzaEZpbHRlcjpndERhdGEubGVuZ3RoIHwgZ3RTZWFyY2g6Z3RJbmZvLnNlYXJjaFRlcm1zOmd0SW5mbzpndFNldHRpbmdzOmd0RmllbGRzOmd0RGF0YS5sZW5ndGgpOmNvbHVtbi5vYmplY3RLZXk6cmVmcmVzaFRvdGFsc1wiPjwvc3Bhbj5cbiAgICAgIDwvdGQ+XG4gICAgPC90cj5cbiAgICA8L3Rmb290PlxuICA8L25nLXRlbXBsYXRlPlxuICA8dGJvZHkgKm5nSWY9XCJndERhdGEgJiYgZ3RJbmZvXCI+XG4gIDxuZy10ZW1wbGF0ZSBjbGFzcz1cInRhYmxlLXJvd3NcIiBuZ0ZvciBsZXQtcm93IGxldC1sYXN0PVwibGFzdFwiIFtuZ0ZvclRyYWNrQnldPVwidHJhY2tCeUZuXCJcbiAgICAgICAgICAgICAgIFtuZ0Zvck9mXT1cImd0T3B0aW9ucy5sYXp5TG9hZCAmJiBndEluZm8gPyAoZ3REYXRhW2d0SW5mby5wYWdlQ3VycmVudC0xXSkgOiAoZ3REYXRhIHwgZ3RGaWx0ZXI6Z3RJbmZvLmZpbHRlcjpndEluZm86cmVmcmVzaEZpbHRlcjpndERhdGEubGVuZ3RoIHwgZ3RTZWFyY2g6Z3RJbmZvLnNlYXJjaFRlcm1zOmd0SW5mbzpndFNldHRpbmdzOmd0RmllbGRzOmd0RGF0YS5sZW5ndGggfCBndE9yZGVyQnk6c29ydE9yZGVyOmd0RmllbGRzOnJlZnJlc2hTb3J0aW5nOmd0RGF0YS5sZW5ndGggfCBndENodW5rOmd0SW5mbzpndEluZm8ucmVjb3JkTGVuZ3RoOmd0SW5mby5wYWdlQ3VycmVudDpyZWZyZXNoUGFnZUFycmF5Omd0RGF0YS5sZW5ndGg6Z3RFdmVudDpkYXRhIHwgZ3RSb3dDbGFzczpndEZpZWxkcylcIj5cbiAgICA8dHIgW25nQ2xhc3NdPVwieydyb3ctc2VsZWN0ZWQnOm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdPy5pc1NlbGVjdGVkLCAncm93LW9wZW4nOm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdPy5pc09wZW4sICdyb3ctbG9hZGluZyc6bG9hZGluZywgJ3Jvdy1leHBhbmRhYmxlJzpndFJvd0NvbXBvbmVudH1cIlxuICAgICAgICBjbGFzcz1cInt7cm93LiQkZ3RSb3dDbGFzc319XCJcbiAgICAgICAgKGNsaWNrKT1cImd0T3B0aW9ucy5yb3dTZWxlY3Rpb24gPyB0b2dnbGVTZWxlY3Qocm93KTpyb3dDbGljayhyb3csICRldmVudClcIj5cbiAgICAgIDx0ZCAqbmdGb3I9XCJsZXQgY29sdW1uIG9mIHJvdyB8IGd0UmVuZGVyOmd0U2V0dGluZ3M6Z3RGaWVsZHM6cmVmcmVzaFBpcGU6bG9hZGluZzpndE9wdGlvbnMuaGlnaGxpZ2h0U2VhcmNoOmd0SW5mby5zZWFyY2hUZXJtczt0cmFja0J5OnRyYWNrQnlDb2x1bW5GblwiXG4gICAgICAgICAgbmdDbGFzcz1cInt7Y29sdW1uLm9iamVjdEtleSArJy1jb2x1bW4nIHwgZGFzaENhc2V9fSB7e2d0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidjbGFzc05hbWVzJ319IHt7KGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykgPyAnZ3QtaW5saW5lLWVkaXQnOicnfX0ge3tjb2x1bW4uZWRpdGVkID8gJ2d0LWVkaXRlZCc6Jyd9fSB7eyBndEZpZWxkcyB8IGd0Q29sdW1uQ2xhc3M6Y29sdW1uOnJvdyB9fVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJndC1yb3ctbGFiZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJndE9wdGlvbnMuc3RhY2tcIj57eyhndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonc3RhY2tlZEhlYWRpbmcnKSA/IChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonc3RhY2tlZEhlYWRpbmcnKSA6IChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonbmFtZScpfX08L3NwYW4+XG4gICAgICAgIDxndC1jdXN0b20tY29tcG9uZW50LWZhY3RvcnkgKm5nSWY9XCJjb2x1bW4uY29sdW1uQ29tcG9uZW50ICYmIGNvbHVtbi5jb2x1bW5Db21wb25lbnQudHlwZSAhPT0gJ2NoZWNrYm94J1wiIGNsYXNzPVwiZ3Qtcm93LWNvbnRlbnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0eXBlXT1cImNvbHVtbi5jb2x1bW5Db21wb25lbnQudHlwZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2luamVjdG9yXT1cImNvbHVtbi5jb2x1bW5Db21wb25lbnQuaW5qZWN0b3JcIiBbcm93XT1cInJvd1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NvbHVtbl09XCJjb2x1bW5cIiAocmVkcmF3RXZlbnQpPVwicmVkcmF3KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzZWFyY2hUZXJtc109XCJndEluZm8uc2VhcmNoVGVybXNcIiAgKHNlYXJjaEV2ZW50KT1cInJlZHJhdygkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiY29sdW1uLmNsaWNrID8gY29sdW1uLmNsaWNrKHJvdyxjb2x1bW4sJGV2ZW50KTonJztjb2x1bW4uZXhwYW5kID8gdG9nZ2xlQ29sbGFwc2Uocm93LCBjb2x1bW4uZXhwYW5kKTonJ1wiPjwvZ3QtY3VzdG9tLWNvbXBvbmVudC1mYWN0b3J5PlxuICAgICAgICA8c3BhbiAqbmdJZj1cIiFjb2x1bW4uY29sdW1uQ29tcG9uZW50ICYmICghKGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykgfHwgKChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpPy5hY3RpdmUgfCBndElzT2JzZXJ2YWJsZSkgJiYgISgoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2lubGluZUVkaXQnKT8uYWN0aXZlIHwgYXN5bmMpIHx8ICghKChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpPy5hY3RpdmUgfCBndElzT2JzZXJ2YWJsZSkgJiYgISgoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2lubGluZUVkaXQnKT8uYWN0aXZlIHwgZ3RJc0VkaXRhYmxlOnJvdzpyZWZyZXNoUGlwZSkpKVwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiZ3Qtcm93LWNvbnRlbnRcIiBbaW5uZXJIVE1MXT1cImNvbHVtbi5yZW5kZXJWYWx1ZVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJjb2x1bW4uY2xpY2sgPyBjb2x1bW4uY2xpY2socm93LGNvbHVtbiwkZXZlbnQpOicnO2NvbHVtbi5leHBhbmQgPyB0b2dnbGVDb2xsYXBzZShyb3csIGNvbHVtbi5leHBhbmQpOicnXCI+PC9zcGFuPlxuICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICBbbmdJZl09XCIhY29sdW1uLmNvbHVtbkNvbXBvbmVudCAmJiAoKChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpPy5hY3RpdmUgfCBndElzT2JzZXJ2YWJsZSkgJiYgKChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpPy5hY3RpdmUgfCBhc3luYykgfHwgKChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpPy5hY3RpdmUgfCBndElzRWRpdGFibGU6cm93OnJlZnJlc2hQaXBlKSlcIj5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiKFt0cnVlLCdlbWFpbCcsJ251bWJlcicsJ3Bhc3N3b3JkJywgJ3RleHQnXS5pbmRleE9mKChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpLnR5cGUpICE9PSAtMSkgfHwgIShndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpLnR5cGVcIj5cbiAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImlubGluZS1lZGl0XCIgW2F0dHIudHlwZV09XCIhKGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykudHlwZSA/ICd0ZXh0JyA6ICEoKGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykudHlwZSB8IGd0SXNPYnNlcnZhYmxlKSA/IChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpLnR5cGU6KGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykudHlwZSB8IGFzeW5jXCIgWyhuZ01vZGVsKV09XCJjb2x1bW4ucmVuZGVyVmFsdWVcIlxuICAgICAgICAgICAgICAgICAgIChpbnB1dCk9XCJndFVwZGF0ZUNvbHVtbigkZXZlbnQscm93LCBjb2x1bW4pXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImd0LWlubGluZS1lZGl0LW5vdGljZVwiPnt7Z3RUZXh0cy5pbmxpbmVFZGl0RWRpdGVkfX08L3NwYW4+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8Z3QtZHJvcGRvd25cbiAgICAgICAgICAgICpuZ0lmPVwiKCgoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2lubGluZUVkaXQnKS50eXBlKSAmJiAoKGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykudHlwZSkubGVuZ3RoID4gMCkgfHwgKChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpLnR5cGUgfCBndElzT2JzZXJ2YWJsZSlcIlxuICAgICAgICAgICAgW29wdGlvbnNdPVwiISgoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2lubGluZUVkaXQnKS50eXBlIHwgZ3RJc09ic2VydmFibGUpID8gKGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykudHlwZSA6IChndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpLnR5cGUgfCBhc3luY1wiXG4gICAgICAgICAgICBbaWRdPVwiJ18nICsgcm93LiQkZ3RSb3dJZCArICdfJyArIGNvbHVtbi5vYmplY3RLZXlcIlxuICAgICAgICAgICAgWyhzZWxlY3RlZCldPVwiY29sdW1uLnJlbmRlclZhbHVlXCIgKHNlbGVjdGVkQ2hhbmdlKT1cImd0RHJvcGRvd25TZWxlY3Qocm93LCBjb2x1bW4pXCI+QWRkXG4gICAgICAgICAgICBpbmxpbmUgZWRpdGluZyBtb2R1bGVcbiAgICAgICAgICA8L2d0LWRyb3Bkb3duPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIWNvbHVtbi5jb2x1bW5Db21wb25lbnQgJiYgISgoZ3RGaWVsZHMgfCBndFByb3BlcnR5OmNvbHVtbi5vYmplY3RLZXk6J2lubGluZUVkaXQnKT8uYWN0aXZlKSBcIj5cbiAgICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAgIFtuZ0lmXT1cIlt0cnVlLCdlbWFpbCcsJ251bWJlcicsJ3Bhc3N3b3JkJ10uaW5kZXhPZihndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpICE9PSAtMVwiPlxuICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiaW5saW5lLWVkaXRcIiBbYXR0ci50eXBlXT1cIihndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpID09PSB0cnVlID8gJ3RleHQnOihndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonaW5saW5lRWRpdCcpXCIgWyhuZ01vZGVsKV09XCJjb2x1bW4ucmVuZGVyVmFsdWVcIlxuICAgICAgICAgICAgICAgICAgIChpbnB1dCk9XCJndFVwZGF0ZUNvbHVtbigkZXZlbnQscm93LCBjb2x1bW4pXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImd0LWlubGluZS1lZGl0LW5vdGljZVwiPnt7Z3RUZXh0cy5pbmxpbmVFZGl0RWRpdGVkfX08L3NwYW4+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8Z3QtZHJvcGRvd25cbiAgICAgICAgICAgICpuZ0lmPVwiKGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykgJiYgW3RydWUsJ2VtYWlsJywnbnVtYmVyJywncGFzc3dvcmQnXS5pbmRleE9mKGd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0JykgPT09IC0xXCJcbiAgICAgICAgICAgIFtvcHRpb25zXT1cImd0RmllbGRzIHwgZ3RQcm9wZXJ0eTpjb2x1bW4ub2JqZWN0S2V5OidpbmxpbmVFZGl0J1wiXG4gICAgICAgICAgICBbaWRdPVwiJ18nICsgcm93LiQkZ3RSb3dJZCArICdfJyArIGNvbHVtbi5vYmplY3RLZXlcIlxuICAgICAgICAgICAgWyhzZWxlY3RlZCldPVwiY29sdW1uLnJlbmRlclZhbHVlXCIgKHNlbGVjdGVkQ2hhbmdlKT1cImd0RHJvcGRvd25TZWxlY3Qocm93LCBjb2x1bW4pXCI+QWRkXG4gICAgICAgICAgICBpbmxpbmUgZWRpdGluZyBtb2R1bGVcbiAgICAgICAgICA8L2d0LWRyb3Bkb3duPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8Z3QtY2hlY2tib3ggKm5nSWY9XCJjb2x1bW4uY29sdW1uQ29tcG9uZW50ICYmIGNvbHVtbi5jb2x1bW5Db21wb25lbnQudHlwZSA9PT0gJ2NoZWNrYm94J1wiIFtjaGVja2VkXT1cIm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdPy5pc1NlbGVjdGVkXCIgKGNoYW5nZWQpPVwidG9nZ2xlU2VsZWN0KHJvdylcIj48L2d0LWNoZWNrYm94PlxuICAgICAgPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0ciBjbGFzcz1cInJvdy1leHBhbmRlZFwiICpuZ0lmPVwibWV0YUluZm9bcm93LiQkZ3RSb3dJZF0/LmlzT3BlblwiPlxuICAgICAgPHRkIFthdHRyLmNvbHNwYW5dPVwiKGd0RmllbGRzIHwgZ3RWaXNpYmxlOmd0U2V0dGluZ3M6cmVmcmVzaFBpcGUpLmxlbmd0aFwiPlxuICAgICAgICA8Z3QtZXhwYW5kaW5nLXJvdyBbcm93XT1cInJvd1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFt0eXBlXT1cImV4cGFuZGVkUm93LmNvbXBvbmVudCA/IGV4cGFuZGVkUm93LmNvbXBvbmVudDpndFJvd0NvbXBvbmVudFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtjb2x1bW5XaWR0aF09XCJjb2x1bW5XaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtndEZpZWxkc109XCJndEZpZWxkc1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtndE9wdGlvbnNdPVwiZ3RPcHRpb25zXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW2d0RXZlbnRdPVwiZ3RFdmVudFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtndEluZm9dPVwiZ3RJbmZvXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW2d0U2V0dGluZ3NdPVwiZ3RTZXR0aW5nc1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtkYXRhXT1cImV4cGFuZGVkUm93LmRhdGEgPyBleHBhbmRlZFJvdy5kYXRhOnJvd1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIChyZWRyYXdFdmVudCk9XCJyZWRyYXcoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICh0b2dnbGVSb3dFdmVudCk9XCJ0b2dnbGVDb2xsYXBzZSgkZXZlbnQpXCI+PC9ndC1leHBhbmRpbmctcm93PlxuICAgICAgPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0ciAqbmdJZj1cImd0T3B0aW9ucy5yZXBvcnRDb2x1bW5XaWR0aCAmJiBsYXN0XCI+XG4gICAgICA8dGQgc3R5bGU9XCJwYWRkaW5nOiAwOyBib3JkZXI6bm9uZTtcIlxuICAgICAgICAgICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgZ3RTZXR0aW5ncyB8IGd0VmlzaWJsZTpndFNldHRpbmdzOnJlZnJlc2hQaXBlXCIgZ3RDb2x1bW5XaWR0aFxuICAgICAgICAgIFtvYmplY3RLZXldPVwiY29sdW1uLm9iamVjdEtleVwiIFt3aWR0aHNdPVwiY29sdW1uV2lkdGhcIj48L3RkPlxuICAgIDwvdHI+XG4gIDwvbmctdGVtcGxhdGU+XG4gIDx0ciAqbmdJZj1cImd0SW5mby5wYWdlVG90YWwgPT09IDAgJiYgKGd0SW5mby5zZWFyY2hUZXJtcyB8fCBndEluZm8uZmlsdGVyKSAmJiAhbG9hZGluZ1wiPlxuICAgIDx0ZCBjbGFzcz1cImd0LW5vLW1hdGNoaW5nLXJlc3VsdHNcIiBbYXR0ci5jb2xzcGFuXT1cIihndEZpZWxkcyB8IGd0VmlzaWJsZTpndFNldHRpbmdzKS5sZW5ndGhcIj5cbiAgICAgIHt7Z3RUZXh0cy5ub01hdGNoaW5nRGF0YX19XG4gICAgPC90ZD5cbiAgPC90cj5cbiAgPHRyICpuZ0lmPVwiZ3RJbmZvLnBhZ2VUb3RhbCA9PT0gMCAmJiAhKGd0SW5mby5zZWFyY2hUZXJtcyB8fCBndEluZm8uZmlsdGVyKSAmJiAhbG9hZGluZ1wiPlxuICAgIDx0ZCBjbGFzcz1cImd0LW5vLXJlc3VsdHNcIiBbYXR0ci5jb2xzcGFuXT1cIihndEZpZWxkcyB8IGd0VmlzaWJsZTpndFNldHRpbmdzKS5sZW5ndGhcIj57e2d0VGV4dHMubm9EYXRhfX1cbiAgICA8L3RkPlxuICA8L3RyPlxuICA8dHIgKm5nSWY9XCJndEluZm8ucGFnZVRvdGFsID09PSAwICYmIGxvYWRpbmdcIj5cbiAgICA8dGQgY2xhc3M9XCJndC1sb2FkaW5nLWRhdGFcIiBbYXR0ci5jb2xzcGFuXT1cIihndEZpZWxkcyB8IGd0VmlzaWJsZTpndFNldHRpbmdzKS5sZW5ndGhcIj57e2d0VGV4dHMubG9hZGluZ319PC90ZD5cbiAgPC90cj5cbiAgPC90Ym9keT5cbjwvdGFibGU+XG48dGFibGUgY2xhc3M9XCJ0YWJsZVwiIG5nQ2xhc3M9XCJ7e2d0Q2xhc3Nlc319IHt7Z3RPcHRpb25zLnN0YWNrID8gJ3RhYmxlLXN0YWNrZWQnOicnfX1cIlxuICAgICAgICpuZ0lmPVwiZ3RGaWVsZHMgJiYgZ3RTZXR0aW5ncyAmJiAoZ3RGaWVsZHMgfCBndFZpc2libGU6Z3RTZXR0aW5nczpyZWZyZXNoUGlwZSkubGVuZ3RoID09PSAwXCI+XG4gIDx0aGVhZD5cbiAgPHRyPlxuICAgIDx0aCBjbGFzcz1cImd0LW5vLXZpc2libGUtY29sdW1uc1wiPnt7Z3RUZXh0cy5ub1Zpc2libGVDb2x1bW5zSGVhZGluZ319PC90aD5cbiAgPC90cj5cbiAgPC90aGVhZD5cbiAgPHRib2R5PlxuICA8dHI+XG4gICAgPHRkIGNsYXNzPVwiZ3Qtbm8tdmlzaWJsZS1jb2x1bW5zXCI+e3tndFRleHRzLm5vVmlzaWJsZUNvbHVtbnN9fTwvdGQ+XG4gIDwvdHI+XG4gIDwvdGJvZHk+XG48L3RhYmxlPlxuPHRhYmxlIGNsYXNzPVwidGFibGVcIiBuZ0NsYXNzPVwie3tndENsYXNzZXN9fSB7e2d0T3B0aW9ucy5zdGFjayA/ICd0YWJsZS1zdGFja2VkJzonJ319XCJcbiAgICAgICAqbmdJZj1cIiFndEZpZWxkcyB8fCAhZ3RTZXR0aW5nc1wiPlxuICA8dGhlYWQ+XG4gIDx0cj5cbiAgICA8dGggY2xhc3M9XCJndC1sb2FkaW5nLWNvbmZpZ1wiPiZuYnNwOzwvdGg+XG4gIDwvdHI+XG4gIDwvdGhlYWQ+XG4gIDx0Ym9keT5cbiAgPHRyPlxuICAgIDx0ZCBjbGFzcz1cImd0LWxvYWRpbmctY29uZmlnXCI+Jm5ic3A7PC90ZD5cbiAgPC90cj5cbiAgPC90Ym9keT5cbjwvdGFibGU+XG5gXG59KVxuZXhwb3J0IGNsYXNzIEdlbmVyaWNUYWJsZUNvbXBvbmVudDxSIGV4dGVuZHMgR3RSb3csIEMgZXh0ZW5kcyBHdEV4cGFuZGVkUm93PFI+PlxuXHRpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuXHRnZXQgZ3RSb3dDb21wb25lbnQoKTogVHlwZTxDPiB7XG5cdFx0cmV0dXJuIHRoaXMuX2d0Um93Q29tcG9uZW50O1xuXHR9XG5cblx0Z2V0IGhhc0VkaXRzKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBPYmplY3Qua2V5cyh0aGlzLmVkaXRlZFJvd3MpLmxlbmd0aCA+IDA7XG5cdH1cblxuXHRnZXQgZ3RPcHRpb25zKCk6IEd0T3B0aW9ucyB7XG5cdFx0cmV0dXJuIHRoaXMuX2d0T3B0aW9ucztcblx0fVxuXG5cdGdldCBndFRvdGFscygpOiBhbnkge1xuXHRcdHJldHVybiB0aGlzLl9ndFRvdGFscztcblx0fVxuXG5cdGdldCBndEZpZWxkcygpOiBHdENvbmZpZ0ZpZWxkPFIsIGFueT5bXSB7XG5cdFx0cmV0dXJuIHRoaXMuX2d0RmllbGRzO1xuXHR9XG5cblx0Z2V0IGd0U2V0dGluZ3MoKTogR3RDb25maWdTZXR0aW5nW10ge1xuXHRcdHJldHVybiB0aGlzLl9ndFNldHRpbmdzO1xuXHR9XG5cblx0Z2V0IGd0RGF0YSgpOiBBcnJheTxhbnk+IHtcblx0XHRyZXR1cm4gdGhpcy5fZ3REYXRhO1xuXHR9XG5cblx0QElucHV0KClcblx0c2V0IGd0T3B0aW9ucyh2YWx1ZTogR3RPcHRpb25zKSB7XG5cdFx0dGhpcy5fZ3RPcHRpb25zID0gdmFsdWU7XG5cblx0XHQvLyBpZiBudW1iZXIgb2Ygcm93cyBpcyBwYXNzZWQgYW5kIGlmIG51bWJlciBvZiByb3dzIGRpZmZlcnMgZnJvbSBjdXJyZW50IHJlY29yZCBsZW5ndGguLi5cblx0XHRpZiAoXG5cdFx0XHR0aGlzLmd0T3B0aW9ucy5udW1iZXJPZlJvd3MgJiZcblx0XHRcdHRoaXMuZ3RJbmZvLnJlY29yZExlbmd0aCAhPT0gdGhpcy5ndE9wdGlvbnMubnVtYmVyT2ZSb3dzXG5cdFx0KSB7XG5cdFx0XHQvLyAuLi51cGRhdGUgcmVjb3JkIGxlbmd0aCBhbmQgcmVkcmF3IHRhYmxlXG5cdFx0XHR0aGlzLmd0SW5mby5yZWNvcmRMZW5ndGggPSB0aGlzLmd0T3B0aW9ucy5udW1iZXJPZlJvd3M7XG5cdFx0XHR0aGlzLnJlZHJhdygpO1xuXHRcdH1cblxuXHRcdC8vIC4uLmV4dGVuZCBndE9wdGlvbnMgZGVmYXVsdCB2YWx1ZXMgd2l0aCB2YWx1ZXMgcGFzc2VkIGludG8gY29tcG9uZW50XG5cdFx0dGhpcy5fZ3RPcHRpb25zID0gPEd0T3B0aW9ucz50aGlzLmV4dGVuZChcblx0XHRcdHRoaXMuZ3REZWZhdWx0T3B0aW9ucyxcblx0XHRcdHRoaXMuX2d0T3B0aW9uc1xuXHRcdCk7XG5cdH1cblxuXHRASW5wdXQoKVxuXHRzZXQgZ3RUb3RhbHModmFsdWU6IGFueSkge1xuXHRcdHRoaXMuX2d0VG90YWxzID0gdmFsdWU7XG5cdH1cblx0QElucHV0KClcblx0c2V0IGd0RmllbGRzKHZhbHVlOiBHdENvbmZpZ0ZpZWxkPFIsIGFueT5bXSkge1xuXHRcdHRoaXMuX2d0RmllbGRzID0gdmFsdWU7XG5cdFx0Y29uc3QgQ09MVU1OU19XSVRIX0NMQVNTX05BTUVTID0gdGhpcy5fZ3RGaWVsZHNcblx0XHRcdC5tYXAoY29sdW1uID0+IGNvbHVtbilcblx0XHRcdC5maWx0ZXIoY29sdW1uID0+IGNvbHVtbi5jbGFzc05hbWVzKTtcblx0XHQvLyBUT0RPOiByZW1vdmUgZGVwcmVjYXRlZCB3YXJuaW5nIHdoZW4gc2V0dGluZyBoYXMgYmVlbiByZW1vdmVkXG5cdFx0aWYgKENPTFVNTlNfV0lUSF9DTEFTU19OQU1FUy5sZW5ndGggPiAwKSB7XG5cdFx0XHRjb25zb2xlLndhcm4oXG5cdFx0XHRcdCdGaWVsZCBzZXR0aW5nIFwiY2xhc3NOYW1lc1wiIGhhdmUgYmVlbiBkZXByZWNhdGVkIGluIGZhdm9yIGZvciBcImNvbHVtbkNsYXNzXCIgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgZnV0dXJlLCBwbGVhc2UgdXBkYXRlIGZpZWxkIHNldHRpbmdzIGZvciBjb2x1bW4gd2l0aCBvYmplY3Qga2V5OiAnICtcblx0XHRcdFx0XHRDT0xVTU5TX1dJVEhfQ0xBU1NfTkFNRVNbMF0ub2JqZWN0S2V5XG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXHRASW5wdXQoKVxuXHRzZXQgZ3RTZXR0aW5ncyh2YWx1ZTogR3RDb25maWdTZXR0aW5nW10pIHtcblx0XHR0aGlzLl9ndFNldHRpbmdzID0gdmFsdWU7XG5cblx0XHQvLyBsb29wIHRocm91Z2ggY3VycmVudCBzZXR0aW5nc1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fZ3RTZXR0aW5ncy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Ly8gc2V0IHNvcnQgZW5hYmxlZC9kaXNhYmxlZCBzZXR0aW5nXG5cdFx0XHR0aGlzLl9ndFNldHRpbmdzW2ldLnNvcnRFbmFibGVkID1cblx0XHRcdFx0dGhpcy5fZ3RTZXR0aW5nc1tpXS5zb3J0RW5hYmxlZCAhPT0gZmFsc2Vcblx0XHRcdFx0XHQ/ICh0aGlzLl9ndFNldHRpbmdzW2ldLnNvcnRFbmFibGVkID0gIShcblx0XHRcdFx0XHRcdFx0dGhpcy5fZ3RTZXR0aW5nc1tpXS5zb3J0ICYmXG5cdFx0XHRcdFx0XHRcdHRoaXMuX2d0U2V0dGluZ3NbaV0uc29ydC5pbmRleE9mKCdkaXNhYmxlJykgIT09IC0xXG5cdFx0XHRcdFx0ICApKVxuXHRcdFx0XHRcdDogZmFsc2U7XG5cblx0XHRcdC8vIGNoZWNrIGlmIHNvcnRpbmcgaXMgdW5kZWZpbmVkLi4uXG5cdFx0XHRpZiAodHlwZW9mIHRoaXMuX2d0U2V0dGluZ3NbaV0uc29ydCA9PT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdFx0Ly8gLi4uaXMgc28sIHNldCBzb3J0aW5nIHByb3BlcnR5IHRvIGVuYWJsZVxuXHRcdFx0XHR0aGlzLl9ndFNldHRpbmdzW2ldLnNvcnQgPSAnZW5hYmxlJztcblx0XHRcdH1cblxuXHRcdFx0Ly8gY2hlY2sgaWYgY29sdW1uIG9yZGVyIGlzIHVuZGVmaW5lZC4uLlxuXHRcdFx0aWYgKFxuXHRcdFx0XHR0eXBlb2YgdGhpcy5fZ3RTZXR0aW5nc1tpXS5jb2x1bW5PcmRlciA9PT0gJ3VuZGVmaW5lZCcgJiZcblx0XHRcdFx0dGhpcy5fZ3RTZXR0aW5nc1tpXS5lbmFibGVkICE9PSBmYWxzZVxuXHRcdFx0KSB7XG5cdFx0XHRcdC8vIC4uLmlzIHNvLCBzZXQgc29ydGluZyBwcm9wZXJ0eSB0byBlbmFibGVcblx0XHRcdFx0dGhpcy5fZ3RTZXR0aW5nc1tpXS5jb2x1bW5PcmRlciA9IHRoaXMuX2d0U2V0dGluZ3NbaSAtIDFdXG5cdFx0XHRcdFx0PyB0aGlzLl9ndFNldHRpbmdzW2kgLSAxXS5jb2x1bW5PcmRlciArIDFcblx0XHRcdFx0XHQ6IDA7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGNoZWNrIGlmIGNvbHVtbiBsb2NrIHNldHRpbmdzIGFyZSB1bmRlZmluZWQuLi5cblx0XHRcdGlmICh0eXBlb2YgdGhpcy5fZ3RTZXR0aW5nc1tpXS5sb2NrU2V0dGluZ3MgPT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRcdC8vIC4uLmlmIHNvLCBzZXQgbG9jayBzZXR0aW5ncyB0byBmYWxzZSB1bmxlc3MgZmllbGQgaXMgZGlzYWJsZWQgKGVuYWJsZSA9PT0gZmFsc2UpXG5cdFx0XHRcdHRoaXMuX2d0U2V0dGluZ3NbaV0ubG9ja1NldHRpbmdzID1cblx0XHRcdFx0XHR0aGlzLl9ndFNldHRpbmdzW2ldLmVuYWJsZWQgPT09IGZhbHNlIHx8IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR0aGlzLnJlc3RydWN0dXJlU29ydGluZygpO1xuXHR9XG5cdEBJbnB1dCgpXG5cdHNldCBndERhdGEoaW5pdGlhbERhdGE6IEFycmF5PGFueT4pIHtcblx0XHRjb25zdCBkYXRhID0gdGhpcy5fZ3RPcHRpb25zLm11dGF0ZURhdGFcblx0XHRcdD8gWy4uLmluaXRpYWxEYXRhXVxuXHRcdFx0OiB0aGlzLmNsb25lRGVlcChpbml0aWFsRGF0YSk7XG5cdFx0aWYgKHRoaXMuZ3RPcHRpb25zLmxhenlMb2FkICYmIHRoaXMuZ3RJbmZvKSB7XG5cdFx0XHR0aGlzLmd0TWV0YVBpcGUudHJhbnNmb3JtKFxuXHRcdFx0XHRkYXRhLFxuXHRcdFx0XHR0aGlzLmd0T3B0aW9ucy5yb3dJbmRleCxcblx0XHRcdFx0dGhpcy5ndEluZm8ucGFnZUN1cnJlbnQgLSAxLFxuXHRcdFx0XHR0aGlzLmd0SW5mby5yZWNvcmRMZW5ndGhcblx0XHRcdCk7XG5cdFx0XHRpZiAodGhpcy5sYXp5QWxsU2VsZWN0ZWQpIHtcblx0XHRcdFx0Y29uc3QgVU5JUVVFX1JPV1MgPSB0aGlzLnNlbGVjdGVkUm93cy5tYXAocm93ID0+IHJvdy4kJGd0Um93SWQpO1xuXHRcdFx0XHRkYXRhLm1hcChyb3cgPT4ge1xuXHRcdFx0XHRcdGlmIChVTklRVUVfUk9XUy5pbmRleE9mKHJvdy4kJGd0Um93SWQpID09PSAtMSkge1xuXHRcdFx0XHRcdFx0dGhpcy5zZWxlY3RlZFJvd3MucHVzaChyb3cpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHRcdHRoaXMuX3VwZGF0ZU1ldGFJbmZvKHRoaXMuc2VsZWN0ZWRSb3dzLCAnaXNTZWxlY3RlZCcsIHRydWUpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmd0TWV0YVBpcGUudHJhbnNmb3JtKGRhdGEsIHRoaXMuZ3RPcHRpb25zLnJvd0luZGV4KTtcblx0XHR9XG5cdFx0aWYgKHRoaXMuZ3RPcHRpb25zLnJvd1NlbGVjdGlvbkluaXRpYWxTdGF0ZSkge1xuXHRcdFx0ZGF0YS5tYXAocm93ID0+IHtcblx0XHRcdFx0Y29uc3Qgc2VsZWN0ZWQgPVxuXHRcdFx0XHRcdHR5cGVvZiB0aGlzLmd0T3B0aW9ucy5yb3dTZWxlY3Rpb25Jbml0aWFsU3RhdGUgPT09ICdmdW5jdGlvbidcblx0XHRcdFx0XHRcdD8gdGhpcy5ndE9wdGlvbnMucm93U2VsZWN0aW9uSW5pdGlhbFN0YXRlKHJvdylcblx0XHRcdFx0XHRcdDogdGhpcy5ndE9wdGlvbnMucm93U2VsZWN0aW9uSW5pdGlhbFN0YXRlO1xuXHRcdFx0XHRpZiAoc2VsZWN0ZWQpIHtcblx0XHRcdFx0XHRpZiAodHlwZW9mIHRoaXMubWV0YUluZm9bcm93LiQkZ3RSb3dJZF0gPT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRcdFx0XHR0aGlzLm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdID0geyBpc1NlbGVjdGVkOiB0cnVlIH07XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHRoaXMubWV0YUluZm9bcm93LiQkZ3RSb3dJZF0uaXNTZWxlY3RlZCA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHRoaXMuc2VsZWN0ZWRSb3dzLnB1c2gocm93KTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdGlmIChcblx0XHRcdHRoaXMuZ3RPcHRpb25zLnJvd0V4cGFuZEluaXRpYWxTdGF0ZSAmJlxuXHRcdFx0dGhpcy5ndE9wdGlvbnMucm93RXhwYW5kSW5pdGlhbENvbXBvbmVudFxuXHRcdCkge1xuXHRcdFx0ZGF0YS5tYXAocm93ID0+IHtcblx0XHRcdFx0Y29uc3QgZXhwYW5kZWQgPVxuXHRcdFx0XHRcdHR5cGVvZiB0aGlzLmd0T3B0aW9ucy5yb3dFeHBhbmRJbml0aWFsU3RhdGUgPT09ICdmdW5jdGlvbidcblx0XHRcdFx0XHRcdD8gdGhpcy5ndE9wdGlvbnMucm93RXhwYW5kSW5pdGlhbFN0YXRlKHJvdylcblx0XHRcdFx0XHRcdDogdGhpcy5ndE9wdGlvbnMucm93RXhwYW5kSW5pdGlhbFN0YXRlO1xuXHRcdFx0XHR0aGlzLmV4cGFuZGVkUm93ID0gdGhpcy5ndE9wdGlvbnMucm93RXhwYW5kSW5pdGlhbENvbXBvbmVudDtcblxuXHRcdFx0XHRpZiAoZXhwYW5kZWQpIHtcblx0XHRcdFx0XHRpZiAodHlwZW9mIHRoaXMubWV0YUluZm9bcm93LiQkZ3RSb3dJZF0gPT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRcdFx0XHR0aGlzLm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdID0geyBpc09wZW46IHRydWUgfTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0dGhpcy5tZXRhSW5mb1tyb3cuJCRndFJvd0lkXS5pc09wZW4gPSB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdHRoaXMuX2d0RGF0YSA9IGRhdGE7XG5cdH1cblxuXHRASW5wdXQoKVxuXHRzZXQgZ3RSb3dDb21wb25lbnQodmFsdWU6IFR5cGU8Qz4pIHtcblx0XHRjb25zb2xlLndhcm4oXG5cdFx0XHQnR3RSb3dDb21wb25lbnQgaGFzIGJlZW4gZGVwcmVjYXRlZCBhbmQgc3VwcG9ydCB3aWxsIGJlIHJlbW92ZWQgaW4gYSBmdXR1cmUgcmVsZWFzZSwgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9oamFsbWVycy9hbmd1bGFyLWdlbmVyaWMtdGFibGUvaXNzdWVzLzM0J1xuXHRcdCk7XG5cdFx0dGhpcy5fZ3RSb3dDb21wb25lbnQgPSB2YWx1ZTtcblx0fVxuXG5cdHB1YmxpYyBjb2x1bW5XaWR0aDogT2JqZWN0ID0ge307XG5cdHB1YmxpYyBjb25maWdPYmplY3Q6IEd0Q29uZmlnPFI+O1xuXHRwdWJsaWMgc29ydE9yZGVyOiBBcnJheTxhbnk+ID0gW107XG5cdHB1YmxpYyBtZXRhSW5mbzogeyBbZ3RSb3dJZDogc3RyaW5nXTogR3RSb3dNZXRhIH0gPSB7fTtcblx0cHVibGljIHNlbGVjdGVkUm93czogQXJyYXk8R3RSb3c+ID0gW107XG5cdHB1YmxpYyBvcGVuUm93czogQXJyYXk8R3RSb3c+ID0gW107XG5cdHByaXZhdGUgX2d0U2V0dGluZ3M6IEd0Q29uZmlnU2V0dGluZ1tdID0gW107XG5cdHByaXZhdGUgX2d0RmllbGRzOiBHdENvbmZpZ0ZpZWxkPFIsIGFueT5bXSA9IFtdO1xuXHRwcml2YXRlIF9ndERhdGE6IEFycmF5PGFueT47XG5cdHByaXZhdGUgX2d0VG90YWxzOiBhbnk7XG5cdHByaXZhdGUgX2d0Um93Q29tcG9uZW50OiBUeXBlPEM+O1xuXHRwdWJsaWMgZXhwYW5kZWRSb3c6IHtcblx0XHRjb21wb25lbnQ6IFR5cGU8Qz47XG5cdFx0ZGF0YT86IEFycmF5PGFueT47XG5cdH07XG5cdHB1YmxpYyBndERlZmF1bHRUZXh0czogR3RUZXh0cyA9IHtcblx0XHRsb2FkaW5nOiAnTG9hZGluZy4uLicsXG5cdFx0bm9EYXRhOiAnTm8gZGF0YScsXG5cdFx0bm9NYXRjaGluZ0RhdGE6ICdObyBkYXRhIG1hdGNoaW5nIHJlc3VsdHMgZm91bmQnLFxuXHRcdG5vVmlzaWJsZUNvbHVtbnNIZWFkaW5nOiAnTm8gdmlzaWJsZSBjb2x1bW5zJyxcblx0XHRub1Zpc2libGVDb2x1bW5zOiAnUGxlYXNlIHNlbGVjdCBhdCBsZWFzdCBvbmUgY29sdW1uIHRvIGJlIHZpc2libGUuJyxcblx0XHR0YWJsZUluZm86XG5cdFx0XHQnU2hvd2luZyAjcmVjb3JkRnJvbSB0byAjcmVjb3JkVG8gb2YgI3JlY29yZHNBZnRlclNlYXJjaCBlbnRyaWVzLicsXG5cdFx0dGFibGVJbmZvQWZ0ZXJTZWFyY2g6XG5cdFx0XHQnU2hvd2luZyAgI3JlY29yZEZyb20gdG8gI3JlY29yZFRvIG9mICNyZWNvcmRzQWZ0ZXJTZWFyY2ggZW50cmllcyAoZmlsdGVyZWQgZnJvbSBhIHRvdGFsIG9mICNyZWNvcmRzQWxsIGVudHJpZXMpLicsXG5cdFx0Y3N2RG93bmxvYWQ6ICdkb3dubG9hZCcsXG5cdFx0c29ydExhYmVsOiAnU29ydDonLFxuXHRcdHBhZ2luYXRlTmV4dDogJ05leHQgcGFnZScsXG5cdFx0cGFnaW5hdGVQcmV2aW91czogJ1ByZXZpb3VzIHBhZ2UnLFxuXHRcdGlubGluZUVkaXRFZGl0ZWQ6ICdQcmVzcyBlbnRlciB0byBzYXZlJ1xuXHR9O1xuXHRASW5wdXQoKSBndFRleHRzOiBHdFRleHRzID0gdGhpcy5ndERlZmF1bHRUZXh0cztcblx0QElucHV0KCkgZ3RDbGFzc2VzOiBzdHJpbmc7XG5cdEBPdXRwdXQoKSBndEV2ZW50OiBFdmVudEVtaXR0ZXI8R3RFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cdHB1YmxpYyBndERlZmF1bHRPcHRpb25zOiBHdE9wdGlvbnMgPSB7XG5cdFx0Y3N2RGVsaW1pdGVyOiAnOycsXG5cdFx0c3RhY2s6IGZhbHNlLFxuXHRcdGxhenlMb2FkOiBmYWxzZSxcblx0XHRjYWNoZTogZmFsc2UsXG5cdFx0ZGVib3VuY2VUaW1lOiAyMDAsXG5cdFx0aGlnaGxpZ2h0U2VhcmNoOiBmYWxzZSxcblx0XHRyb3dTZWxlY3Rpb246IGZhbHNlLFxuXHRcdHJvd1NlbGVjdGlvbkFsbG93TXVsdGlwbGU6IHRydWUsXG5cdFx0cm93RXhwYW5kQWxsb3dNdWx0aXBsZTogdHJ1ZSxcblx0XHRudW1iZXJPZlJvd3M6IDEwLFxuXHRcdHJlcG9ydENvbHVtbldpZHRoOiBmYWxzZSxcblx0XHRhbGxvd1Vuc29ydGVkOiB0cnVlLFxuXHRcdG11dGF0ZURhdGE6IHRydWVcblx0fTtcblx0cHJpdmF0ZSBfZ3RPcHRpb25zOiBHdE9wdGlvbnMgPSB0aGlzLmd0RGVmYXVsdE9wdGlvbnM7XG5cdHB1YmxpYyBzdG9yZTogQXJyYXk8YW55PiA9IFtdO1xuXHRwdWJsaWMgbG9hZGluZyA9IHRydWU7XG5cdHByaXZhdGUgZGVib3VuY2VUaW1lcjogdm9pZCA9IG51bGw7XG5cdHB1YmxpYyBsb2FkaW5nUHJvcGVydHk6IHN0cmluZztcblx0cHVibGljIGxhenlBbGxTZWxlY3RlZCA9IGZhbHNlO1xuXG5cdEBJbnB1dCgpXG5cdGd0SW5mbzogR3RJbmZvcm1hdGlvbiA9IHtcblx0XHRwYWdlQ3VycmVudDogMSxcblx0XHRwYWdlVG90YWw6IDAsXG5cdFx0cmVjb3JkRnJvbTogMCxcblx0XHRyZWNvcmRUbzogMCxcblx0XHRyZWNvcmRMZW5ndGg6IHRoaXMuZ3RPcHRpb25zLm51bWJlck9mUm93cyxcblx0XHRyZWNvcmRzQWxsOiAwLFxuXHRcdHJlY29yZHNBZnRlckZpbHRlcjogMCxcblx0XHRyZWNvcmRzQWZ0ZXJTZWFyY2g6IDBcblx0fTtcblxuXHRwdWJsaWMgcmVmcmVzaFBpcGUgPSBmYWxzZTtcblx0cHVibGljIHJlZnJlc2hUb3RhbHMgPSBmYWxzZTtcblx0cHVibGljIHJlZnJlc2hTb3J0aW5nID0gZmFsc2U7XG5cdHB1YmxpYyByZWZyZXNoRmlsdGVyID0gZmFsc2U7XG5cdHB1YmxpYyByZWZyZXNoUGFnZUFycmF5ID0gZmFsc2U7XG5cdHByaXZhdGUgZ2xvYmFsSW5saW5lRWRpdExpc3RlbmVyOiBGdW5jdGlvbjtcblx0cHVibGljIGVkaXRlZFJvd3M6IHtcblx0XHRba2V5OiBzdHJpbmddOiB7XG5cdFx0XHRjaGFuZ2VzOiB7IFtrZXk6IHN0cmluZ106IEd0UmVuZGVyRmllbGQ8R3RSb3csIGFueT4gfTtcblx0XHRcdHJvdzogR3RSb3c7XG5cdFx0fTtcblx0fSA9IHt9O1xuXG5cdHB1YmxpYyBkYXRhOiB7IGV4cG9ydERhdGE6IEFycmF5PGFueT4gfSA9IHsgZXhwb3J0RGF0YTogW10gfTsgLy8gU3RvcmUgZmlsdGVyZWQgZGF0YSBmb3IgZXhwb3J0XG5cblx0Y29uc3RydWN0b3IocHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLCBwcml2YXRlIGd0TWV0YVBpcGU6IEd0TWV0YVBpcGUpIHtcblx0XHR0aGlzLmd0RXZlbnQuc3Vic2NyaWJlKCgkZXZlbnQ6IEd0RXZlbnQpID0+IHtcblx0XHRcdGlmICgkZXZlbnQubmFtZSA9PT0gJ2d0LWluZm8nKSB7XG5cdFx0XHRcdHRoaXMudXBkYXRlUmVjb3JkUmFuZ2UoKTtcblx0XHRcdH1cblx0XHRcdGlmICgkZXZlbnQubmFtZSA9PT0gJ2d0LXJvdy11cGRhdGVkJykge1xuXHRcdFx0XHR0aGlzLnVwZGF0ZVRvdGFscygpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNvcnQgdGFibGUgYnkgb2JqZWN0IGtleS5cblx0ICogQHBhcmFtIG9iamVjdEtleSAtIG5hbWUgb2Yga2V5IHRvIHNvcnQgb24uXG5cdCAqIEBwYXJhbSBldmVudCAtIHN1Y2ggYXMga2V5IHByZXNzIGR1cmluZyBzb3J0aW5nLlxuXHQgKi9cblx0cHVibGljIGd0U29ydCA9IGZ1bmN0aW9uKG9iamVjdEtleTogc3RyaW5nLCBldmVudDogYW55KSB7XG5cdFx0dGhpcy5pbmxpbmVFZGl0Q2FuY2VsKCk7IC8vIGNhbmNlbCBpbmxpbmUgZWRpdGluZ1xuXG5cdFx0Ly8gbG9vcCB0aHJvdWdoIGN1cnJlbnQgc2V0dGluZ3Ncblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2d0U2V0dGluZ3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmICh0aGlzLl9ndFNldHRpbmdzW2ldLm9iamVjdEtleSA9PT0gb2JqZWN0S2V5KSB7XG5cdFx0XHRcdC8vIGNoZWNrIGlmIHNvcnRpbmcgaXMgZGlzYWJsZWQuLi5cblx0XHRcdFx0aWYgKFxuXHRcdFx0XHRcdHRoaXMuX2d0U2V0dGluZ3NbaV0uc29ydCAmJlxuXHRcdFx0XHRcdHRoaXMuX2d0U2V0dGluZ3NbaV0uc29ydC5pbmRleE9mKCdkaXNhYmxlJykgIT09IC0xXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdC8vIC4uLmlmIHNvLCBleGl0IGZ1bmN0aW9uIHdpdGhvdXQgYXBwbHlpbmcgYW55IHNvcnRpbmdcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH0gZWxzZSBpZiAoXG5cdFx0XHRcdFx0LyogY2hlY2sgaWYgc29ydGluZyBpcyB1bmRlZmluZWQuLi4gKi8gdHlwZW9mIHRoaXMuX2d0U2V0dGluZ3NbaV1cblx0XHRcdFx0XHRcdC5zb3J0ID09PSAndW5kZWZpbmVkJ1xuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHQvLyAuLi5pcyBzbywgc2V0IHNvcnRpbmcgcHJvcGVydHkgdG8gZW5hYmxlXG5cdFx0XHRcdFx0dGhpcy5fZ3RTZXR0aW5nc1tpXS5zb3J0ID0gJ2VuYWJsZSc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBjaGVjayBsZW5ndGhcblx0XHRjb25zdCBjdHJsS2V5ID0gZXZlbnQubWV0YUtleSB8fCBldmVudC5jdHJsS2V5O1xuXHRcdGNvbnN0IHNvcnQgPSB0aGlzLnNvcnRPcmRlci5zbGljZSgwKTtcblxuXHRcdGxldCBtYXRjaCA9IC0xO1xuXHRcdGxldCBtYXRjaERlc2MgPSAtMTtcblx0XHRsZXQgcG9zID0gLTE7XG5cblx0XHQvLyBjaGVjayBpZiBwcm9wZXJ0eSBhbHJlYWR5IGV4aXRzXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzb3J0Lmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCBoaXQgPSBzb3J0W2ldLmluZGV4T2Yob2JqZWN0S2V5KTtcblx0XHRcdGlmIChoaXQgIT09IC0xKSB7XG5cdFx0XHRcdG1hdGNoID0gdGhpcy5zb3J0T3JkZXIuaW5kZXhPZihvYmplY3RLZXkpO1xuXHRcdFx0XHRtYXRjaERlc2MgPVxuXHRcdFx0XHRcdG1hdGNoID09PSAtMSA/IHRoaXMuc29ydE9yZGVyLmluZGV4T2YoJy0nICsgb2JqZWN0S2V5KSA6IG1hdGNoO1xuXHRcdFx0XHRwb3MgPSBNYXRoLm1heChtYXRjaCwgbWF0Y2hEZXNjKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBpZiBjdHJsIGtleSBvciBtZXRhIGtleSBpcyBwcmVzcyB0b2dldGhlciB3aXRoIHNvcnQuLi5cblx0XHRpZiAoY3RybEtleSkge1xuXHRcdFx0aWYgKHRoaXMuc29ydE9yZGVyW3RoaXMuc29ydE9yZGVyLmxlbmd0aCAtIDFdID09PSAnJCRndEluaXRpYWxSb3dJbmRleCcpIHtcblx0XHRcdFx0dGhpcy5zb3J0T3JkZXIucG9wKCk7XG5cdFx0XHR9XG5cdFx0XHRzd2l0Y2ggKHBvcykge1xuXHRcdFx0XHQvLyAuLi5hbmQgcHJvcGVydHkgaXMgbm90IHNvcnRlZCBiZWZvcmUuLi5cblx0XHRcdFx0Y2FzZSAtMTpcblx0XHRcdFx0XHQvLyAuLi5hZGQgcHJvcGVydHkgdG8gc29ydGluZ1xuXHRcdFx0XHRcdHRoaXMuc29ydE9yZGVyLnB1c2gob2JqZWN0S2V5KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHQvLyAuLi5hbmQgcHJvcGVydHkgaXMgc29ydGVkIGJlZm9yZS4uLlxuXHRcdFx0XHRcdGlmIChtYXRjaCAhPT0gLTEpIHtcblx0XHRcdFx0XHRcdC8vIC4uLmNoYW5nZSBmcm9tIGFzYyB0byBkZXNjIGlmIHNvcnRlZCBhc2Ncblx0XHRcdFx0XHRcdHRoaXMuc29ydE9yZGVyW3Bvc10gPSAnLScgKyBvYmplY3RLZXk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICh0aGlzLnNvcnRPcmRlci5sZW5ndGggPiAxKSB7XG5cdFx0XHRcdFx0XHQvLyAuLi5yZW1vdmUgc29ydGluZyBpZiBzb3J0ZWQgZGVzY1xuXHRcdFx0XHRcdFx0aWYgKGN0cmxLZXkpIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5zb3J0T3JkZXJbcG9zXSA9IG9iamVjdEtleTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuc29ydE9yZGVyLnNwbGljZShwb3MsIDEpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5zb3J0T3JkZXIubGVuZ3RoID09PSAxKSB7XG5cdFx0XHRcdFx0XHQvLyAuLi5zZXQgc29ydGluZyB0byBhc2MgaWYgb25seSBzb3J0ZWQgcHJvcGVydHlcblx0XHRcdFx0XHRcdHRoaXMuc29ydE9yZGVyW3Bvc10gPSBvYmplY3RLZXk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvKiBpZiBjdHJsIGtleSBvciBtZXRhIGtleSBpcyBub3QgcHJlc3MgdG9nZXRoZXIgd2l0aCBzb3J0Li4uICovXG5cdFx0XHRzd2l0Y2ggKHBvcykge1xuXHRcdFx0XHQvLyAuLi5hbmQgcHJvcGVydHkgaXMgbm90IHNvcnRlZCBiZWZvcmUuLi5cblx0XHRcdFx0Y2FzZSAtMTpcblx0XHRcdFx0XHQvLyAuLi5zb3J0IGJ5IHByb3BlcnR5XG5cdFx0XHRcdFx0dGhpcy5zb3J0T3JkZXIgPSBbb2JqZWN0S2V5XTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHQvLyAuLi5jaGFuZ2UgZnJvbSBkZXNjIHRvIGFzYyBhbmQgdmlzZSB2ZXJzYVxuXHRcdFx0XHRcdHRoaXMuc29ydE9yZGVyID1cblx0XHRcdFx0XHRcdG1hdGNoICE9PSAtMVxuXHRcdFx0XHRcdFx0XHQ/IFsnLScgKyBvYmplY3RLZXldXG5cdFx0XHRcdFx0XHRcdDogY3RybEtleSB8fCAhdGhpcy5ndE9wdGlvbnMuYWxsb3dVbnNvcnRlZFxuXHRcdFx0XHRcdFx0XHRcdD8gW29iamVjdEtleV1cblx0XHRcdFx0XHRcdFx0XHQ6IFtdO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIHVwZGF0ZSBzZXR0aW5ncyBvYmplY3Qgd2l0aCBuZXcgc29ydGluZyBpbmZvcm1hdGlvblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fZ3RTZXR0aW5ncy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKHRoaXMuX2d0U2V0dGluZ3NbaV0ub2JqZWN0S2V5ID09PSBvYmplY3RLZXkpIHtcblx0XHRcdFx0c3dpdGNoICh0aGlzLl9ndFNldHRpbmdzW2ldLnNvcnQpIHtcblx0XHRcdFx0XHQvLyBpZiBzb3J0ZWQgYXNjLi4uXG5cdFx0XHRcdFx0Y2FzZSAnYXNjJzpcblx0XHRcdFx0XHRcdC8vIC4uLmNoYW5nZSB0byBkZXNjXG5cdFx0XHRcdFx0XHR0aGlzLl9ndFNldHRpbmdzW2ldLnNvcnQgPSAnZGVzYyc7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHQvLyBpZiBzb3J0ZWQgZGVzYy4uLlxuXHRcdFx0XHRcdGNhc2UgJ2Rlc2MnOlxuXHRcdFx0XHRcdFx0Ly8gLi4uY2hhbmdlIHRvIGFzYyBpZiBpdCdzIHRoZSBvbmx5IHNvcnRlZCBwcm9wZXJ0eSBvdGhlcndpc2UgcmVtb3ZlIHNvcnRpbmdcblx0XHRcdFx0XHRcdHRoaXMuX2d0U2V0dGluZ3NbaV0uc29ydCA9XG5cdFx0XHRcdFx0XHRcdCh0aGlzLnNvcnRPcmRlci5sZW5ndGggPT09IDEgJiYgc29ydC5sZW5ndGggPCAyKSB8fFxuXHRcdFx0XHRcdFx0XHRjdHJsS2V5IHx8XG5cdFx0XHRcdFx0XHRcdCF0aGlzLmd0T3B0aW9ucy5hbGxvd1Vuc29ydGVkXG5cdFx0XHRcdFx0XHRcdFx0PyAnYXNjJ1xuXHRcdFx0XHRcdFx0XHRcdDogJ2VuYWJsZSc7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHQvLyBpZiBzb3J0aW5nIGVuYWJsZWQuLi5cblx0XHRcdFx0XHRjYXNlICdlbmFibGUnOlxuXHRcdFx0XHRcdFx0Ly8gLi4uY2hhbmdlIHRvIGFzY1xuXHRcdFx0XHRcdFx0dGhpcy5fZ3RTZXR0aW5nc1tpXS5zb3J0ID0gJ2FzYyc7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLl9ndFNldHRpbmdzW2ldLnNvcnRPcmRlciA9XG5cdFx0XHRcdFx0dGhpcy5fZ3RTZXR0aW5nc1tpXS5zb3J0ID09PSAnZW5hYmxlJ1xuXHRcdFx0XHRcdFx0PyB0aGlzLl9ndFNldHRpbmdzLmxlbmd0aCAtIDFcblx0XHRcdFx0XHRcdDogdGhpcy5zb3J0T3JkZXIuaW5kZXhPZihvYmplY3RLZXkpID09PSAtMVxuXHRcdFx0XHRcdFx0XHQ/IHRoaXMuc29ydE9yZGVyLmluZGV4T2YoJy0nICsgb2JqZWN0S2V5KVxuXHRcdFx0XHRcdFx0XHQ6IHRoaXMuc29ydE9yZGVyLmluZGV4T2Yob2JqZWN0S2V5KTtcblx0XHRcdH0gZWxzZSBpZiAoXG5cdFx0XHRcdHRoaXMuX2d0U2V0dGluZ3NbaV0uc29ydCAmJlxuXHRcdFx0XHR0aGlzLl9ndFNldHRpbmdzW2ldLnNvcnQuaW5kZXhPZignZGlzYWJsZScpID09PSAtMSAmJlxuXHRcdFx0XHR0aGlzLnNvcnRPcmRlci5pbmRleE9mKHRoaXMuX2d0U2V0dGluZ3NbaV0ub2JqZWN0S2V5KSA9PT0gLTEgJiZcblx0XHRcdFx0dGhpcy5zb3J0T3JkZXIuaW5kZXhPZignLScgKyB0aGlzLl9ndFNldHRpbmdzW2ldLm9iamVjdEtleSkgPT09IC0xXG5cdFx0XHQpIHtcblx0XHRcdFx0dGhpcy5fZ3RTZXR0aW5nc1tpXS5zb3J0ID0gJ2VuYWJsZSc7XG5cdFx0XHRcdHRoaXMuX2d0U2V0dGluZ3NbaV0uc29ydE9yZGVyID0gdGhpcy5fZ3RTZXR0aW5ncy5sZW5ndGggLSAxO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIHJlZnJlc2ggc29ydGluZyBwaXBlXG5cdFx0dGhpcy5yZWZyZXNoU29ydGluZyA9ICF0aGlzLnJlZnJlc2hTb3J0aW5nO1xuXHRcdHRoaXMucmVmcmVzaFBhZ2VBcnJheSA9ICF0aGlzLnJlZnJlc2hQYWdlQXJyYXk7XG5cblx0XHQvLyBzb3J0IGJ5IGluaXRpYWwgc29ydCBvcmRlciBhcyBsYXN0IHJlc29ydFxuXHRcdHRoaXMuc29ydE9yZGVyLnB1c2goJyQkZ3RJbml0aWFsUm93SW5kZXgnKTtcblxuXHRcdC8vIGVtaXQgc29ydCBldmVudFxuXHRcdHRoaXMuZ3RFdmVudC5lbWl0KHtcblx0XHRcdG5hbWU6ICdndC1zb3J0aW5nLWFwcGxpZWQnLFxuXHRcdFx0dmFsdWU6IHRoaXMuc29ydE9yZGVyXG5cdFx0fSk7XG5cdH07XG5cblx0LyoqXG5cdCAqIENoYW5nZSBudW1iZXIgb2Ygcm93cyB0byBiZSBkaXNwbGF5ZWQuXG5cdCAqIEBwYXJhbSByb3dMZW5ndGggLSB0b3RhbCBudW1iZXIgb2Ygcm93cy5cblx0ICogQHBhcmFtIHJlc2V0IC0gc2hvdWxkIHBhZ2UgYmUgcmVzZXQgdG8gZmlyc3QgcGFnZS5cblx0ICovXG5cdHB1YmxpYyBjaGFuZ2VSb3dMZW5ndGggPSBmdW5jdGlvbihyb3dMZW5ndGg6IGFueSwgcmVzZXQ/OiBib29sZWFuKSB7XG5cdFx0bGV0IGxlbmd0aFZhbHVlID0gaXNOYU4ocGFyc2VJbnQocm93TGVuZ3RoLCAxMCkpXG5cdFx0XHQ/IDBcblx0XHRcdDogcGFyc2VJbnQocm93TGVuZ3RoLCAxMCk7XG5cdFx0bGV0IG5ld1Bvc2l0aW9uID0gMTtcblxuXHRcdGlmICghbGVuZ3RoVmFsdWUgJiYgdGhpcy5ndERhdGEpIHtcblx0XHRcdGxlbmd0aFZhbHVlID0gdGhpcy5ndERhdGEubGVuZ3RoO1xuXHRcdH1cblxuXHRcdC8vIGlmIHJlc2V0IGlzIG5vdCB0cnVlIGFuZCB3ZSdyZSBub3QgbGF6eSBsb2FkaW5nIGRhdGEuLi5cblx0XHRpZiAocmVzZXQgIT09IHRydWUgJiYgdGhpcy5fZ3RPcHRpb25zLmxhenlMb2FkICE9PSB0cnVlKSB7XG5cdFx0XHQvLyAuLi5nZXQgY3VycmVudCBwb3NpdGlvbiBpbiByZWNvcmQgc2V0XG5cdFx0XHRjb25zdCBjdXJyZW50UmVjb3JkID1cblx0XHRcdFx0dGhpcy5ndEluZm8ucmVjb3JkTGVuZ3RoICogKHRoaXMuZ3RJbmZvLnBhZ2VDdXJyZW50IC0gMSk7XG5cdFx0XHRjb25zdCBjdXJyZW50UG9zaXRpb24gPVxuXHRcdFx0XHR0aGlzLl9ndERhdGEuaW5kZXhPZih0aGlzLl9ndERhdGFbY3VycmVudFJlY29yZF0pICsgMTtcblxuXHRcdFx0Ly8gLi4uZ2V0IG5ldyBwb3NpdGlvblxuXHRcdFx0bmV3UG9zaXRpb24gPSBNYXRoLmNlaWwoY3VycmVudFBvc2l0aW9uIC8gbGVuZ3RoVmFsdWUpO1xuXHRcdH1cblxuXHRcdC8vIGNoYW5nZSByb3cgbGVuZ3RoXG5cdFx0dGhpcy5ndEluZm8ucmVjb3JkTGVuZ3RoID0gbGVuZ3RoVmFsdWU7XG5cblx0XHQvLyBnbyB0byBuZXcgcG9zaXRpb25cblx0XHR0aGlzLmd0SW5mby5wYWdlQ3VycmVudCA9IG5ld1Bvc2l0aW9uO1xuXG5cdFx0Ly8gaWYgbGF6eSBsb2FkaW5nIGRhdGEuLi5cblx0XHRpZiAodGhpcy5fZ3RPcHRpb25zLmxhenlMb2FkKSB7XG5cdFx0XHQvLyAuLi5yZXBsYWNlIGRhdGEgd2l0aCBwbGFjZSBob2xkZXJzIGZvciBuZXcgZGF0YVxuXHRcdFx0dGhpcy5fZ3REYXRhWzBdID0gdGhpcy5sb2FkaW5nQ29udGVudChsZW5ndGhWYWx1ZSk7XG5cblx0XHRcdC8vIC4uLmVtcHR5IGN1cnJlbnQgc3RvcmVcblx0XHRcdHRoaXMuc3RvcmUgPSBbXTtcblx0XHR9XG5cblx0XHQvLyB0aGlzLnVwZGF0ZVJlY29yZFJhbmdlKCk7XG5cblx0XHR0aGlzLmd0RXZlbnQuZW1pdCh7XG5cdFx0XHRuYW1lOiAnZ3Qtcm93LWxlbmd0aC1jaGFuZ2VkJyxcblx0XHRcdHZhbHVlOiBsZW5ndGhWYWx1ZVxuXHRcdH0pO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBGb3JjZSBhIHJlZHJhdyBvZiB0YWJsZSByb3dzLlxuXHQgKiBBcyB0aGUgdGFibGUgdXNlcyBwdXJlIHBpcGVzLCB3ZSBuZWVkIHRvIGZvcmNlIGEgcmVkcmF3IGlmIGFuIG9iamVjdCBpbiB0aGUgYXJyYXkgaXMgY2hhbmdlZCB0byBzZWUgdGhlIGNoYW5nZXMuXG5cdCAqL1xuXHRwdWJsaWMgcmVkcmF3ID0gZnVuY3Rpb24oJGV2ZW50PzogYW55KSB7XG5cdFx0dGhpcy5yZWZyZXNoU29ydGluZyA9ICF0aGlzLnJlZnJlc2hTb3J0aW5nO1xuXHRcdHRoaXMucmVmcmVzaFBhZ2VBcnJheSA9ICF0aGlzLnJlZnJlc2hQYWdlQXJyYXk7XG5cdFx0dGhpcy5yZWZyZXNoUGlwZSA9ICF0aGlzLnJlZnJlc2hQaXBlO1xuXHR9O1xuXG5cdC8qKiBVcGRhdGUgcmVjb3JkIHJhbmdlLiAqL1xuXHRwcml2YXRlIHVwZGF0ZVJlY29yZFJhbmdlKCkge1xuXHRcdHRoaXMuZ3RJbmZvLnJlY29yZEZyb20gPVxuXHRcdFx0dGhpcy5ndEluZm8ucmVjb3Jkc0FmdGVyU2VhcmNoID09PSAwXG5cdFx0XHRcdD8gMFxuXHRcdFx0XHQ6ICh0aGlzLmd0SW5mby5wYWdlQ3VycmVudCAtIDEpICogdGhpcy5ndEluZm8ucmVjb3JkTGVuZ3RoICsgMTtcblx0XHR0aGlzLmd0SW5mby5yZWNvcmRUbyA9XG5cdFx0XHR0aGlzLmd0SW5mby5yZWNvcmRzQWZ0ZXJTZWFyY2ggPFxuXHRcdFx0dGhpcy5ndEluZm8ucGFnZUN1cnJlbnQgKiB0aGlzLmd0SW5mby5yZWNvcmRMZW5ndGhcblx0XHRcdFx0PyB0aGlzLmd0SW5mby5yZWNvcmRzQWZ0ZXJTZWFyY2hcblx0XHRcdFx0OiB0aGlzLmd0SW5mby5wYWdlQ3VycmVudCAqIHRoaXMuZ3RJbmZvLnJlY29yZExlbmd0aDtcblx0fVxuXG5cdC8qKiBVcGRhdGUgdG90YWxzLiAqL1xuXHRwcml2YXRlIHVwZGF0ZVRvdGFscygpIHtcblx0XHR0aGlzLnJlZnJlc2hUb3RhbHMgPSAhdGhpcy5yZWZyZXNoVG90YWxzO1xuXHR9XG5cblx0LyoqIEdvIHRvIG5leHQgcGFnZS4gKi9cblx0cHVibGljIG5leHRQYWdlID0gZnVuY3Rpb24oKSB7XG5cdFx0Y29uc3QgcGFnZSA9XG5cdFx0XHR0aGlzLmd0SW5mby5wYWdlQ3VycmVudCA9PT0gdGhpcy5ndEluZm8ucGFnZVRvdGFsXG5cdFx0XHRcdD8gdGhpcy5ndEluZm8ucGFnZVRvdGFsXG5cdFx0XHRcdDogdGhpcy5ndEluZm8ucGFnZUN1cnJlbnQgKyAxO1xuXHRcdHRoaXMuZ29Ub1BhZ2UocGFnZSk7XG5cdH07XG5cblx0LyoqIEdvIHRvIHByZXZpb3VzIHBhZ2UuICovXG5cdHB1YmxpYyBwcmV2aW91c1BhZ2UgPSBmdW5jdGlvbigpIHtcblx0XHRjb25zdCBwYWdlID1cblx0XHRcdHRoaXMuZ3RJbmZvLnBhZ2VDdXJyZW50ID09PSAxID8gMSA6IHRoaXMuZ3RJbmZvLnBhZ2VDdXJyZW50IC0gMTtcblx0XHR0aGlzLmdvVG9QYWdlKHBhZ2UpO1xuXHR9O1xuXG5cdC8qKiBSZXF1ZXN0IG1vcmUgZGF0YSAodXNlZCB3aGVuIGxhenkgbG9hZGluZykgKi9cblx0cHJpdmF0ZSBnZXREYXRhID0gZnVuY3Rpb24oKSB7XG5cdFx0Ly8gLi4uZW1pdCBldmVudCByZXF1ZXN0aW5nIGZvciBtb3JlIGRhdGFcblx0XHR0aGlzLmd0RXZlbnQuZW1pdCh7XG5cdFx0XHRuYW1lOiAnZ3QtcGFnZS1jaGFuZ2VkLWxhenknLFxuXHRcdFx0dmFsdWU6IHtcblx0XHRcdFx0cGFnZUN1cnJlbnQ6IHRoaXMuZ3RJbmZvLnBhZ2VDdXJyZW50LFxuXHRcdFx0XHRyZWNvcmRMZW5ndGg6IHRoaXMuZ3RJbmZvLnJlY29yZExlbmd0aFxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBHbyB0byBzcGVjaWZpYyBwYWdlLlxuXHQgKiBAcGFyYW0gcGFnZSAtIHBhZ2UgbnVtYmVyLlxuXHQgKi9cblx0cHVibGljIGdvVG9QYWdlID0gZnVuY3Rpb24ocGFnZTogbnVtYmVyKSB7XG5cdFx0Y29uc3QgcHJldmlvdXNQYWdlID0gdGhpcy5ndEluZm8ucGFnZUN1cnJlbnQ7XG5cdFx0dGhpcy5ndEluZm8ucGFnZUN1cnJlbnQgPSBwYWdlO1xuXHRcdHRoaXMuaW5saW5lRWRpdENhbmNlbCgpOyAvLyBjYW5jZWwgaW5saW5lIGVkaXRcblxuXHRcdC8vIGlmIGxhenkgbG9hZGluZyBhbmQgaWYgcGFnZSBjb250YWlucyBubyByZWNvcmRzLi4uXG5cdFx0aWYgKHRoaXMuX2d0T3B0aW9ucy5sYXp5TG9hZCkge1xuXHRcdFx0Ly8gLi4uaWYgZGF0YSBmb3IgY3VycmVudCBwYWdlIGNvbnRhaW5zIG5vIGVudHJpZXMuLi5cblx0XHRcdGlmIChcblx0XHRcdFx0dGhpcy5fZ3RPcHRpb25zLmNhY2hlID09PSBmYWxzZSB8fFxuXHRcdFx0XHR0aGlzLl9ndERhdGFbdGhpcy5ndEluZm8ucGFnZUN1cnJlbnQgLSAxXS5sZW5ndGggPT09IDBcblx0XHRcdCkge1xuXHRcdFx0XHQvLyAuLi5jcmVhdGUgdGVtcG9yYXJ5IGNvbnRlbnQgd2hpbGUgd2FpdGluZyBmb3IgZGF0YVxuXHRcdFx0XHR0aGlzLl9ndERhdGFbdGhpcy5ndEluZm8ucGFnZUN1cnJlbnQgLSAxXSA9IHRoaXMubG9hZGluZ0NvbnRlbnQoXG5cdFx0XHRcdFx0dGhpcy5ndEluZm8ucmVjb3JkTGVuZ3RoXG5cdFx0XHRcdCk7XG5cdFx0XHRcdHRoaXMubG9hZGluZyA9IHRydWU7IC8vIGxvYWRpbmcgdHJ1ZVxuXHRcdFx0fVxuXHRcdFx0Ly8gLi4uaWYgZmlyc3QgZW50cnkgaW4gY3VycmVudCBwYWdlIGVxdWFscyBvdXIgbG9hZGluZyBwbGFjZWhvbGRlci4uLlxuXHRcdFx0aWYgKFxuXHRcdFx0XHR0aGlzLl9ndERhdGFbdGhpcy5ndEluZm8ucGFnZUN1cnJlbnQgLSAxXVswXVt0aGlzLmxvYWRpbmdQcm9wZXJ0eV0gPT09XG5cdFx0XHRcdHRoaXMuZ3RUZXh0cy5sb2FkaW5nXG5cdFx0XHQpIHtcblx0XHRcdFx0Ly8gLi4uZ2V0IGRhdGFcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuZGVib3VuY2VUaW1lcik7XG5cdFx0XHRcdHRoaXMuZGVib3VuY2VUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRcdHRoaXMuZ2V0RGF0YSgpO1xuXHRcdFx0XHR9LCB0aGlzLl9ndE9wdGlvbnMuZGVib3VuY2VUaW1lKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyB0aGlzLnVwZGF0ZVJlY29yZFJhbmdlKCk7XG5cblx0XHQvLyAuLi5lbWl0IHBhZ2UgY2hhbmdlIGV2ZW50XG5cdFx0aWYgKHByZXZpb3VzUGFnZSAhPT0gcGFnZSkge1xuXHRcdFx0dGhpcy5ndEV2ZW50LmVtaXQoe1xuXHRcdFx0XHRuYW1lOiAnZ3QtcGFnZS1jaGFuZ2VkJyxcblx0XHRcdFx0dmFsdWU6IHtcblx0XHRcdFx0XHRwYWdlQ3VycmVudDogdGhpcy5ndEluZm8ucGFnZUN1cnJlbnQsXG5cdFx0XHRcdFx0cGFnZVByZXZpb3VzOiBwcmV2aW91c1BhZ2UsXG5cdFx0XHRcdFx0cmVjb3JkTGVuZ3RoOiB0aGlzLmd0SW5mby5yZWNvcmRMZW5ndGhcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuXHQgKiBHZXQgbWV0YSBkYXRhIGZvciByb3cuXG5cdCAqL1xuXHRwdWJsaWMgZ2V0Um93U3RhdGUocm93OiBSKTogR3RSb3dNZXRhIHtcblx0XHRyZXR1cm4gdHlwZW9mIHRoaXMubWV0YUluZm9bcm93LiQkZ3RSb3dJZF0gPT09ICd1bmRlZmluZWQnXG5cdFx0XHQ/IG51bGxcblx0XHRcdDogdGhpcy5tZXRhSW5mb1tyb3cuJCRndFJvd0lkXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeHBhbmQgYWxsIHJvd3MuXG5cdCAqIEBwYXJhbSBleHBhbmRlZFJvdyAtIGNvbXBvbmVudCB0byByZW5kZXIgd2hlbiByb3dzIGFyZSBleHBhbmRlZC5cblx0ICovXG5cdHB1YmxpYyBleHBhbmRBbGxSb3dzKGV4cGFuZGVkUm93OiB7IGNvbXBvbmVudDogVHlwZTxDPjsgZGF0YT86IGFueSB9KTogdm9pZCB7XG5cdFx0dGhpcy5leHBhbmRlZFJvdyA9IGV4cGFuZGVkUm93O1xuXHRcdHRoaXMuX3RvZ2dsZUFsbFJvd1Byb3BlcnR5KCdpc09wZW4nLCB0cnVlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb2xsYXBzZSBhbGwgcm93cy5cblx0ICovXG5cdHB1YmxpYyBjb2xsYXBzZUFsbFJvd3MoKTogdm9pZCB7XG5cdFx0dGhpcy5fdG9nZ2xlQWxsUm93UHJvcGVydHkoJ2lzT3BlbicsIGZhbHNlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZWxlY3QgYWxsIHJvd3MuXG5cdCAqL1xuXHRwdWJsaWMgc2VsZWN0QWxsUm93cygpOiB2b2lkIHtcblx0XHR0aGlzLl90b2dnbGVBbGxSb3dQcm9wZXJ0eSgnaXNTZWxlY3RlZCcsIHRydWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERlc2VsZWN0IGFsbCByb3dzLlxuXHQgKi9cblx0cHVibGljIGRlc2VsZWN0QWxsUm93cygpOiB2b2lkIHtcblx0XHR0aGlzLl90b2dnbGVBbGxSb3dQcm9wZXJ0eSgnaXNTZWxlY3RlZCcsIGZhbHNlKTtcblx0fVxuXHQvKipcblx0ICogVG9nZ2xlIGFsbCByb3dzLlxuXHQgKi9cblx0cHVibGljIHRvZ2dsZUFsbFJvd3MoKTogdm9pZCB7XG5cdFx0aWYgKHRoaXMuX2d0T3B0aW9ucy5sYXp5TG9hZCkge1xuXHRcdFx0aWYgKCF0aGlzLmxhenlBbGxTZWxlY3RlZCB8fCB0aGlzLnNlbGVjdGVkUm93cy5sZW5ndGggPT09IDApIHtcblx0XHRcdFx0dGhpcy5zZWxlY3RBbGxSb3dzKCk7XG5cdFx0XHRcdHRoaXMubGF6eUFsbFNlbGVjdGVkID0gdHJ1ZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuZGVzZWxlY3RBbGxSb3dzKCk7XG5cdFx0XHRcdHRoaXMubGF6eUFsbFNlbGVjdGVkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICh0aGlzLnNlbGVjdGVkUm93cy5sZW5ndGggIT09IHRoaXMuZ3REYXRhLmxlbmd0aCkge1xuXHRcdFx0XHR0aGlzLnNlbGVjdEFsbFJvd3MoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuZGVzZWxlY3RBbGxSb3dzKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRvZ2dsZSByb3cgY29sbGFwc2VkIHN0YXRlIGllLiBleHBhbmRlZC9vcGVuIG9yIGNvbGxhcHNlZC9jbG9zZWQuXG5cdCAqIEBwYXJhbSByb3cgLSByb3cgb2JqZWN0IHRoYXQgc2hvdWxkIGJlIGV4cGFuZGVkL2NvbGxhcHNlZC5cblx0ICogQHBhcmFtIGV4cGFuZGVkUm93IC0gY29tcG9uZW50IHRvIHJlbmRlciB3aGVuIHJvdyBpcyBleHBhbmRlZC5cblx0ICovXG5cdHB1YmxpYyB0b2dnbGVDb2xsYXBzZShcblx0XHRyb3c6IEd0Um93LFxuXHRcdGV4cGFuZGVkUm93PzogeyBjb21wb25lbnQ6IFR5cGU8Qz47IGRhdGE/OiBhbnkgfVxuXHQpIHtcblx0XHRpZiAoZXhwYW5kZWRSb3cpIHtcblx0XHRcdHRoaXMuZXhwYW5kZWRSb3cgPSBleHBhbmRlZFJvdztcblx0XHR9XG5cdFx0dGhpcy5fdG9nZ2xlUm93UHJvcGVydHkocm93LCAnaXNPcGVuJyk7XG5cdH1cblxuXHQvKipcblx0ICogVG9nZ2xlIHJvdyBzZWxlY3RlZCBzdGF0ZSBpZS4gc2VsZWN0ZWQgb3Igbm90LlxuXHQgKiBAcGFyYW0gcm93IC0gcm93IG9iamVjdCB0aGF0IHNob3VsZCBiZSBzZWxlY3RlZC9kZXNlbGVjdGVkLlxuXHQgKi9cblx0cHVibGljIHRvZ2dsZVNlbGVjdChyb3c6IEd0Um93KSB7XG5cdFx0dGhpcy5fdG9nZ2xlUm93UHJvcGVydHkocm93LCAnaXNTZWxlY3RlZCcpO1xuXHR9XG5cblx0cHVibGljIHJvd0NsaWNrKHJvdzogR3RSb3csICRldmVudDogTW91c2VFdmVudCkge1xuXHRcdHRoaXMuZ3RFdmVudC5lbWl0KHtcblx0XHRcdG5hbWU6ICdndC1yb3ctY2xpY2tlZCcsXG5cdFx0XHR2YWx1ZTogeyByb3c6IHJvdywgZXZlbnQ6ICRldmVudCB9XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlIHJvdyBkYXRhLlxuXHQgKiBAcGFyYW0gcm93IC0gcm93IG9iamVjdCB0aGF0IGhhcyBiZWVuIGVkaXRlZC5cblx0ICogQHBhcmFtIG9sZFZhbHVlIC0gcm93IG9iamVjdCBiZWZvcmUgZWRpdC5cblx0ICovXG5cdHB1YmxpYyB1cGRhdGVSb3cocm93OiBHdFJvdywgb2xkVmFsdWU6IEd0Um93KSB7XG5cdFx0dGhpcy5fdG9nZ2xlUm93UHJvcGVydHkocm93LCAnaXNVcGRhdGVkJywgb2xkVmFsdWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIHJlbW92ZXMgYSByb3cgZnJvbSB0aGUgdGFibGVcblx0ICogQHBhcmFtIHJvdyAtIHRoZSByb3cgb2JqZWN0IHRvIHJlbW92ZVxuXHQgKi9cblx0cHVibGljIHJlbW92ZVJvdyhyb3c6IEd0Um93KSB7XG5cdFx0aWYgKHRoaXMuaXNSb3dTZWxlY3RlZChyb3cpKSB7XG5cdFx0XHR0aGlzLnRvZ2dsZVNlbGVjdChyb3cpO1xuXHRcdH1cblx0XHRjb25zdCBpbmRleCA9IHRoaXMuX2d0RGF0YS5pbmRleE9mKHJvdyk7XG5cdFx0dGhpcy5fZ3REYXRhLnNwbGljZShpbmRleCwgMSk7XG5cdH1cblxuXHQvKipcblx0ICogY2hlY2sgaWYgYSByb3cgaXMgc2VsZWN0ZWRcblx0ICogQHBhcmFtIHJvdyAtIHJvdyBvYmplY3Rcblx0ICovXG5cdHB1YmxpYyBpc1Jvd1NlbGVjdGVkKHJvdzogR3RSb3cpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0dGhpcy5tZXRhSW5mb1tyb3cuJCRndFJvd0lkXSAmJiB0aGlzLm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdLmlzU2VsZWN0ZWRcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZSBtZXRhIGluZm8gZm9yIGFsbCByb3dzLCBpZS4gaXNTZWxlY3RlZCwgaXNPcGVuLlxuXHQgKiBAcGFyYW0gYXJyYXkgLSBhcnJheSB0aGF0IGhvbGRzIHJvd3MgdGhhdCBuZWVkIHRvIGJlIHVwZGF0ZWQuXG5cdCAqIEBwYXJhbSBwcm9wZXJ0eSAtIG5hbWUgb2YgcHJvcGVydHkgdGhhdCBzaG91bGQgYmUgY2hhbmdlZC90b2dnbGVkLlxuXHQgKiBAcGFyYW0gYWN0aXZlIC0gc2hvdWxkIHJvd3MgYmUgZXhwYW5kZWQvb3Blbiwgc2VsZWN0ZWQuXG5cdCAqIEBwYXJhbSBleGNlcHRpb24gLSB1cGRhdGUgYWxsIHJvd3MgZXhjZXB0IHRoaXMgb25lLlxuXHQgKi9cblx0cHJpdmF0ZSBfdXBkYXRlTWV0YUluZm8oXG5cdFx0YXJyYXk6IEFycmF5PEd0Um93Pixcblx0XHRwcm9wZXJ0eTogc3RyaW5nLFxuXHRcdGFjdGl2ZTogYm9vbGVhbixcblx0XHRleGNlcHRpb24/OiBHdFJvd1xuXHQpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAoIXRoaXMubWV0YUluZm9bYXJyYXlbaV0uJCRndFJvd0lkXSkge1xuXHRcdFx0XHR0aGlzLm1ldGFJbmZvW2FycmF5W2ldLiQkZ3RSb3dJZF0gPSB7fTtcblx0XHRcdH1cblx0XHRcdGlmIChleGNlcHRpb24gJiYgYXJyYXlbaV0uJCRndFJvd0lkID09PSBleGNlcHRpb24uJCRndFJvd0lkKSB7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLm1ldGFJbmZvW2FycmF5W2ldLiQkZ3RSb3dJZF1bcHJvcGVydHldID0gYWN0aXZlO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBQdXNoIHNlbGVjdGVkL2V4cGFuZGVkIGxhenkgbG9hZGVkIHJvd3MgdG8gYXJyYXkgd2l0aCBtZXRhIGRhdGEuXG5cdCAqIEBwYXJhbSB0YXJnZXQgLSBhcnJheSB0byB3aGljaCByb3dzIHNob3VsZCBiZSBhZGRlZC5cblx0ICogQHBhcmFtIHNvdXJjZSAtIGFycmF5IHRoYXQgaG9sZHMgcm93cyB0aGF0IHNob3VsZCBiZSBhZGRlZC5cblx0ICogQHJldHVybnMgYXJyYXkgd2l0aCBhZGRlZCByb3dzLlxuXHQgKi9cblx0cHJpdmF0ZSBfcHVzaExhenlSb3dzKFxuXHRcdHRhcmdldDogQXJyYXk8R3RSb3c+LFxuXHRcdHNvdXJjZTogQXJyYXk8R3RSb3c+XG5cdCk6IEFycmF5PEd0Um93PiB7XG5cdFx0Y29uc3QgVU5JUVVFX1JPV1MgPSB0YXJnZXQubWFwKHJvdyA9PiByb3cuJCRndFJvd0lkKTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZS5sZW5ndGg7IGkrKykge1xuXHRcdFx0Ly8gb25seSBhZGQgaWYgbm90IGFscmVhZHkgaW4gbGlzdFxuXHRcdFx0aWYgKFVOSVFVRV9ST1dTLmluZGV4T2Yoc291cmNlW2ldLiQkZ3RSb3dJZCkgPT09IC0xKSB7XG5cdFx0XHRcdHRhcmdldC5wdXNoKHNvdXJjZVtpXSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0YXJnZXQ7XG5cdH1cblxuXHQvKipcblx0ICogVG9nZ2xlIG1ldGEgaW5mbyBmb3IgYWxsIHJvd3MsIGllLiBpc1NlbGVjdGVkLCBpc09wZW4uXG5cdCAqIEBwYXJhbSBwcm9wZXJ0eSAtIG5hbWUgb2YgcHJvcGVydHkgdGhhdCBzaG91bGQgYmUgY2hhbmdlZC90b2dnbGVkLlxuXHQgKiBAcGFyYW0gYWN0aXZlIC0gc2hvdWxkIHJvd3MgYmUgZXhwYW5kZWQvb3Blbiwgc2VsZWN0ZWQuXG5cdCAqL1xuXHRwcml2YXRlIF90b2dnbGVBbGxSb3dQcm9wZXJ0eShwcm9wZXJ0eTogc3RyaW5nLCBhY3RpdmU6IGJvb2xlYW4pIHtcblx0XHRsZXQgZXZlbnROYW1lOiBzdHJpbmc7XG5cdFx0bGV0IGV2ZW50VmFsdWU6IGFueTtcblx0XHRzd2l0Y2ggKHByb3BlcnR5KSB7XG5cdFx0XHRjYXNlICdpc09wZW4nOlxuXHRcdFx0XHQvLyBjaGVjayBpZiBtdWx0aXBsZSBleHBhbmRlZCByb3dzIGFyZSBhbGxvd2VkLi4uXG5cdFx0XHRcdGlmICh0aGlzLl9ndE9wdGlvbnMucm93RXhwYW5kQWxsb3dNdWx0aXBsZSA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHQvLyAuLi5pZiBub3QsIGV4aXQgZnVuY3Rpb25cblx0XHRcdFx0XHRjb25zb2xlLmxvZyhcblx0XHRcdFx0XHRcdCdmZWF0dXJlIGRpc2FibGVkOiBlbmFibGUgYnkgc2V0dGluZyBcInJvd0V4cGFuZEFsbG93TXVsdGlwbGUgPSB0cnVlXCInXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKGFjdGl2ZSkge1xuXHRcdFx0XHRcdGV2ZW50TmFtZSA9ICdleHBhbmQtYWxsJztcblx0XHRcdFx0XHR0aGlzLm9wZW5Sb3dzID0gdGhpcy5fZ3RPcHRpb25zLmxhenlMb2FkXG5cdFx0XHRcdFx0XHQ/IHRoaXMuX3B1c2hMYXp5Um93cyhcblx0XHRcdFx0XHRcdFx0XHR0aGlzLm9wZW5Sb3dzLFxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuX2d0RGF0YVt0aGlzLmd0SW5mby5wYWdlQ3VycmVudCAtIDFdLnNsaWNlKClcblx0XHRcdFx0XHRcdCAgKVxuXHRcdFx0XHRcdFx0OiB0aGlzLl9ndERhdGEuc2xpY2UoKTtcblx0XHRcdFx0XHR0aGlzLl91cGRhdGVNZXRhSW5mbyh0aGlzLm9wZW5Sb3dzLCBwcm9wZXJ0eSwgYWN0aXZlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRldmVudE5hbWUgPSAnY29sbGFwc2UtYWxsJztcblx0XHRcdFx0XHR0aGlzLl91cGRhdGVNZXRhSW5mbyh0aGlzLm9wZW5Sb3dzLCBwcm9wZXJ0eSwgYWN0aXZlKTtcblx0XHRcdFx0XHR0aGlzLm9wZW5Sb3dzID0gW107XG5cdFx0XHRcdH1cblx0XHRcdFx0ZXZlbnRWYWx1ZSA9IHtcblx0XHRcdFx0XHRleHBhbmRlZFJvd3M6IHRoaXMub3BlblJvd3MsXG5cdFx0XHRcdFx0Y2hhbmdlZFJvdzogJ2FsbCdcblx0XHRcdFx0fTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdpc1NlbGVjdGVkJzpcblx0XHRcdFx0Ly8gY2hlY2sgaWYgbXVsdGkgcm93IHNlbGVjdGlvbiBpcyBhbGxvd2VkLi4uXG5cdFx0XHRcdGlmICh0aGlzLl9ndE9wdGlvbnMucm93U2VsZWN0aW9uQWxsb3dNdWx0aXBsZSA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHQvLyAuLi5pZiBub3QsIGV4aXQgZnVuY3Rpb25cblx0XHRcdFx0XHRjb25zb2xlLmxvZyhcblx0XHRcdFx0XHRcdCdmZWF0dXJlIGRpc2FibGVkOiBlbmFibGUgYnkgc2V0dGluZyBcInJvd1NlbGVjdGlvbkFsbG93TXVsdGlwbGUgPSB0cnVlXCInXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKGFjdGl2ZSkge1xuXHRcdFx0XHRcdGV2ZW50TmFtZSA9ICdzZWxlY3QtYWxsJztcblx0XHRcdFx0XHR0aGlzLnNlbGVjdGVkUm93cyA9IHRoaXMuX2d0T3B0aW9ucy5sYXp5TG9hZFxuXHRcdFx0XHRcdFx0PyB0aGlzLl9wdXNoTGF6eVJvd3MoXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5zZWxlY3RlZFJvd3MsXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5fZ3REYXRhW3RoaXMuZ3RJbmZvLnBhZ2VDdXJyZW50IC0gMV0uc2xpY2UoKVxuXHRcdFx0XHRcdFx0ICApXG5cdFx0XHRcdFx0XHQ6IHRoaXMuX2d0RGF0YS5zbGljZSgpO1xuXHRcdFx0XHRcdHRoaXMuX3VwZGF0ZU1ldGFJbmZvKHRoaXMuc2VsZWN0ZWRSb3dzLCBwcm9wZXJ0eSwgYWN0aXZlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRldmVudE5hbWUgPSAnZGVzZWxlY3QtYWxsJztcblx0XHRcdFx0XHR0aGlzLl91cGRhdGVNZXRhSW5mbyh0aGlzLnNlbGVjdGVkUm93cywgcHJvcGVydHksIGFjdGl2ZSk7XG5cdFx0XHRcdFx0dGhpcy5zZWxlY3RlZFJvd3MgPSBbXTtcblx0XHRcdFx0fVxuXHRcdFx0XHRldmVudFZhbHVlID0ge1xuXHRcdFx0XHRcdHNlbGVjdGVkUm93czogdGhpcy5zZWxlY3RlZFJvd3MsXG5cdFx0XHRcdFx0Y2hhbmdlZFJvdzogJ2FsbCdcblx0XHRcdFx0fTtcblxuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdFx0dGhpcy5ndEV2ZW50LmVtaXQoe1xuXHRcdFx0bmFtZTogJ2d0LXJvdy0nICsgZXZlbnROYW1lLFxuXHRcdFx0dmFsdWU6IGV2ZW50VmFsdWVcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUb2dnbGUgbWV0YSBpbmZvIGZvciByb3csIGllLiBpc1NlbGVjdGVkLCBpc09wZW4uXG5cdCAqIEBwYXJhbSByb3cgLSByb3cgb2JqZWN0LlxuXHQgKiBAcGFyYW0gcHJvcGVydHkgLSBuYW1lIG9mIHByb3BlcnR5IHRoYXQgc2hvdWxkIGJlIGNoYW5nZWQvdG9nZ2xlZC5cblx0ICogQHBhcmFtIHByb3BlcnR5VmFsdWVzIC0gb3B0aW9uYWwgcHJvcGVydHkgdmFsdWVzIHRoYXQgY2FuIGJlIHBhc3NlZC5cblx0ICovXG5cdHByaXZhdGUgX3RvZ2dsZVJvd1Byb3BlcnR5KFxuXHRcdHJvdzogR3RSb3csXG5cdFx0cHJvcGVydHk6IHN0cmluZyxcblx0XHRwcm9wZXJ0eVZhbHVlcz86IGFueVxuXHQpIHtcblx0XHRsZXQgZXZlbnROYW1lOiBzdHJpbmc7XG5cdFx0bGV0IGV2ZW50VmFsdWU6IGFueTtcblx0XHQvLyBtYWtlIHN1cmUgZ3RSb3dJZCBleGlzdHMgb24gcm93IG9iamVjdFxuXHRcdGlmICh0eXBlb2Ygcm93LiQkZ3RSb3dJZCAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdC8vIGNoZWNrIGlmIG1ldGEgaW5mbyBleGlzdHMgZm9yIHJvd1xuXHRcdFx0aWYgKCF0aGlzLm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdKSB7XG5cdFx0XHRcdC8vIGlmIG5vdCwgYWRkIG9iamVjdCB0byBzdG9yZSBtZXRhIGluZm9cblx0XHRcdFx0dGhpcy5tZXRhSW5mb1tyb3cuJCRndFJvd0lkXSA9IHt9O1xuXHRcdFx0fVxuXG5cdFx0XHRzd2l0Y2ggKHByb3BlcnR5KSB7XG5cdFx0XHRcdGNhc2UgJ2lzT3Blbic6XG5cdFx0XHRcdFx0Y29uc3Qgb3BlbmVkID0gdGhpcy5tZXRhSW5mb1tyb3cuJCRndFJvd0lkXVtwcm9wZXJ0eV07XG5cblx0XHRcdFx0XHQvLyBjaGVjayBpZiBtdWx0aXBsZSBleHBhbmRlZCByb3dzIGFyZSBhbGxvd2VkLi4uXG5cdFx0XHRcdFx0aWYgKHRoaXMuX2d0T3B0aW9ucy5yb3dFeHBhbmRBbGxvd011bHRpcGxlID09PSBmYWxzZSkge1xuXHRcdFx0XHRcdFx0Ly8gLi4uaWYgbm90LCBjb2xsYXBzZSBhbGwgcm93cyBleGNlcHQgY3VycmVudCByb3dcblx0XHRcdFx0XHRcdHRoaXMuX3VwZGF0ZU1ldGFJbmZvKHRoaXMub3BlblJvd3MsIHByb3BlcnR5LCBmYWxzZSwgcm93KTtcblx0XHRcdFx0XHRcdHRoaXMub3BlblJvd3MgPSBbXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBjaGVjayBpZiByb3cgaXMgZXhwYW5kZWRcblx0XHRcdFx0XHRpZiAoIW9wZW5lZCkge1xuXHRcdFx0XHRcdFx0ZXZlbnROYW1lID0gJ2V4cGFuZCc7XG5cdFx0XHRcdFx0XHQvLyBhZGQgcm93IHRvIGV4cGFuZGVkIHJvd3Ncblx0XHRcdFx0XHRcdHRoaXMub3BlblJvd3MucHVzaChyb3cpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRldmVudE5hbWUgPSAnY29sbGFwc2UnO1xuXHRcdFx0XHRcdFx0Ly8gbG9vcCB0aHJvdWdoIGV4cGFuZGVkIHJvd3MuLi5cblx0XHRcdFx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5vcGVuUm93cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRcdFx0XHQvLyBpZiBleHBhbmRlZCByb3cgZXF1YWxzIHBhc3NlZCByb3cuLi5cblx0XHRcdFx0XHRcdFx0aWYgKHRoaXMub3BlblJvd3NbaV0uJCRndFJvd0lkID09PSByb3cuJCRndFJvd0lkKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gLi4ucmVtb3ZlIHJvdyBmcm9tIGV4cGFuZGVkIHJvd3MuLi5cblx0XHRcdFx0XHRcdFx0XHR0aGlzLm9wZW5Sb3dzLnNwbGljZShpLCAxKTtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBleGl0IGxvb3Bcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRldmVudFZhbHVlID0ge1xuXHRcdFx0XHRcdFx0ZXhwYW5kZWRSb3dzOiB0aGlzLm9wZW5Sb3dzLFxuXHRcdFx0XHRcdFx0Y2hhbmdlZFJvdzogcm93XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnaXNTZWxlY3RlZCc6XG5cdFx0XHRcdFx0Y29uc3Qgc2VsZWN0ZWQgPSB0aGlzLm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdW3Byb3BlcnR5XTtcblxuXHRcdFx0XHRcdC8vIGNoZWNrIGlmIG11bHRpIHJvdyBzZWxlY3Rpb24gaXMgYWxsb3dlZC4uLlxuXHRcdFx0XHRcdGlmICh0aGlzLl9ndE9wdGlvbnMucm93U2VsZWN0aW9uQWxsb3dNdWx0aXBsZSA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHRcdC8vIC4uLmlmIG5vdCwgZGVzZWxlY3QgYWxsIHJvd3MgZXhjZXB0IGN1cnJlbnQgcm93XG5cdFx0XHRcdFx0XHR0aGlzLl91cGRhdGVNZXRhSW5mbyh0aGlzLnNlbGVjdGVkUm93cywgcHJvcGVydHksIGZhbHNlLCByb3cpO1xuXHRcdFx0XHRcdFx0dGhpcy5zZWxlY3RlZFJvd3MgPSBbXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBjaGVjayBpZiByb3cgaXMgc2VsZWN0ZWRcblx0XHRcdFx0XHRpZiAoIXNlbGVjdGVkKSB7XG5cdFx0XHRcdFx0XHRldmVudE5hbWUgPSAnc2VsZWN0Jztcblx0XHRcdFx0XHRcdC8vIGFkZCByb3cgdG8gc2VsZWN0ZWQgcm93c1xuXHRcdFx0XHRcdFx0dGhpcy5zZWxlY3RlZFJvd3MucHVzaChyb3cpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRpZiAodGhpcy5ndE9wdGlvbnMubGF6eUxvYWQgJiYgdGhpcy5sYXp5QWxsU2VsZWN0ZWQpIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5sYXp5QWxsU2VsZWN0ZWQgPSBmYWxzZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGV2ZW50TmFtZSA9ICdkZXNlbGVjdCc7XG5cdFx0XHRcdFx0XHQvLyBsb29wIHRocm91Z2ggc2VsZWN0ZWQgcm93cy4uLlxuXHRcdFx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlbGVjdGVkUm93cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRcdFx0XHQvLyBpZiBzZWxlY3RlZCByb3cgZXF1YWxzIHBhc3NlZCByb3cuLi5cblx0XHRcdFx0XHRcdFx0aWYgKHRoaXMuc2VsZWN0ZWRSb3dzW2ldLiQkZ3RSb3dJZCA9PT0gcm93LiQkZ3RSb3dJZCkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIC4uLnJlbW92ZSByb3cgZnJvbSBzZWxlY3RlZCByb3dzLi4uXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5zZWxlY3RlZFJvd3Muc3BsaWNlKGksIDEpO1xuXG5cdFx0XHRcdFx0XHRcdFx0Ly8gLi4uYW5kIGV4aXQgbG9vcFxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGV2ZW50VmFsdWUgPSB7XG5cdFx0XHRcdFx0XHRzZWxlY3RlZFJvd3M6IHRoaXMuc2VsZWN0ZWRSb3dzLFxuXHRcdFx0XHRcdFx0Y2hhbmdlZFJvdzogcm93XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRjYXNlICdpc1VwZGF0ZWQnOlxuXHRcdFx0XHRcdGV2ZW50TmFtZSA9ICd1cGRhdGVkJztcblx0XHRcdFx0XHRjb25zdCBvbGRWYWx1ZSA9IHByb3BlcnR5VmFsdWVzO1xuXHRcdFx0XHRcdC8vIGNoZWNrIGlmIGVkaXQgb2JqZWN0IGV4aXN0cyBmb3Igcm93XG5cdFx0XHRcdFx0aWYgKHR5cGVvZiB0aGlzLm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdW3Byb3BlcnR5XSA9PT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdFx0XHRcdHRoaXMubWV0YUluZm9bcm93LiQkZ3RSb3dJZF1bcHJvcGVydHldID0ge1xuXHRcdFx0XHRcdFx0XHRvcmlnaW5hbFZhbHVlOiBvbGRWYWx1ZSxcblx0XHRcdFx0XHRcdFx0b2xkVmFsdWU6IG9sZFZhbHVlLFxuXHRcdFx0XHRcdFx0XHRuZXdWYWx1ZTogcm93XG5cdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0aGlzLm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdW3Byb3BlcnR5XS5vbGRWYWx1ZSA9IG9sZFZhbHVlO1xuXHRcdFx0XHRcdFx0dGhpcy5tZXRhSW5mb1tyb3cuJCRndFJvd0lkXVtwcm9wZXJ0eV0ubmV3VmFsdWUgPSByb3c7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGV2ZW50VmFsdWUgPSB0aGlzLm1ldGFJbmZvW3Jvdy4kJGd0Um93SWRdW3Byb3BlcnR5XTtcblx0XHRcdFx0XHR0aGlzLnJlZHJhdygpO1xuXHRcdFx0XHRcdHRoaXMuaW5saW5lRWRpdENhbmNlbChyb3cpO1xuXHRcdFx0XHRcdC8vIHRoaXMuZ3REYXRhID0gWy4uLnRoaXMuZ3REYXRhLm1hcCgocikgPT4geyByZXR1cm57Li4ucn07IH0pXTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdHRoaXMuZ3RFdmVudC5lbWl0KHtcblx0XHRcdFx0bmFtZTogJ2d0LXJvdy0nICsgZXZlbnROYW1lLFxuXHRcdFx0XHR2YWx1ZTogZXZlbnRWYWx1ZVxuXHRcdFx0fSk7XG5cdFx0XHRpZiAocHJvcGVydHkgIT09ICdpc1VwZGF0ZWQnKSB7XG5cdFx0XHRcdHRoaXMubWV0YUluZm9bcm93LiQkZ3RSb3dJZF1bcHJvcGVydHldID0gIXRoaXMubWV0YUluZm9bcm93LiQkZ3RSb3dJZF1bXG5cdFx0XHRcdFx0cHJvcGVydHlcblx0XHRcdFx0XTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlIGNvbHVtbi5cblx0ICogQHBhcmFtICRldmVudCAtIGtleSB1cCBldmVudC5cblx0ICogQHBhcmFtIHJvdyAtIHJvdyBvYmplY3QuXG5cdCAqIEBwYXJhbSBjb2x1bW4gLSBjb2x1bW4gb2JqZWN0LlxuXHQgKi9cblx0cHVibGljIGd0VXBkYXRlQ29sdW1uKFxuXHRcdCRldmVudDogS2V5Ym9hcmRFdmVudCxcblx0XHRyb3c6IEd0Um93LFxuXHRcdGNvbHVtbjogR3RSZW5kZXJGaWVsZDxhbnksIGFueT5cblx0KSB7XG5cdFx0dGhpcy5fZWRpdFJvdyhyb3csIGNvbHVtbik7XG5cdH1cblxuXHQvKipcblx0ICogRHJvcGRvd24gc2VsZWN0LlxuXHQgKiBAcGFyYW0gcm93IC0gcm93IG9iamVjdC5cblx0ICogQHBhcmFtIGNvbHVtbiAtIGNvbHVtbiBvYmplY3QuXG5cdCAqL1xuXHRwdWJsaWMgZ3REcm9wZG93blNlbGVjdChyb3c6IEd0Um93LCBjb2x1bW46IEd0UmVuZGVyRmllbGQ8YW55LCBhbnk+KSB7XG5cdFx0Y29uc3Qgb2xkVmFsdWUgPSB7IC4uLnJvdyB9O1xuXHRcdHJvd1tjb2x1bW4ub2JqZWN0S2V5XSA9IGNvbHVtbi5yZW5kZXJWYWx1ZTtcblx0XHR0aGlzLnVwZGF0ZVJvdyhyb3csIG9sZFZhbHVlKTtcblx0fVxuXG5cdHByaXZhdGUgX2VkaXRSb3cocm93OiBHdFJvdywgY29sdW1uOiBHdFJlbmRlckZpZWxkPGFueSwgYW55Pikge1xuXHRcdGNvbnN0IE9CSkVDVF9LRVkgPSBjb2x1bW4ub2JqZWN0S2V5OyAvLyBkZWNsYXJlIG9iamVjdCBrZXkgd2hpY2ggY29udGFpbnMgY2hhbmdlc1xuXG5cdFx0Ly8gY2hlY2sgaWYgY2VsbCBoYXMgY2hhbmdlZCB2YWx1ZVxuXHRcdGNvbHVtbi5lZGl0ZWQgPSByb3dbY29sdW1uLm9iamVjdEtleV0gIT09IGNvbHVtbi5yZW5kZXJWYWx1ZTtcblx0XHQvLyBjaGVjayBpZiByb3cgY29udGFpbnMgY2hhbmdlcy4uLlxuXHRcdGlmICghdGhpcy5lZGl0ZWRSb3dzW3Jvdy4kJGd0Um93SWRdKSB7XG5cdFx0XHQvLyBpZiBub3QsIGNyZWF0ZSBhbiBvYmplY3QgZm9yIHRoZSBjaGFuZ2VkIHJvd1xuXHRcdFx0dGhpcy5lZGl0ZWRSb3dzW3Jvdy4kJGd0Um93SWRdID0ge1xuXHRcdFx0XHRjaGFuZ2VzOiB7fSwgLy8gY3JlYXRlIHBsYWNlaG9sZGVyIGZvciBjaGFuZ2VzXG5cdFx0XHRcdHJvdzogcm93IC8vIHN0b3JlIHJlZmVyZW5jZSB0byB0aGUgcm93IHRoYXQgc2hvdWxkIGJlIHVwZGF0ZWRcblx0XHRcdH07XG5cdFx0fVxuXG5cdFx0Ly8gc3RvcmUgY2hhbmdlZCBjb2x1bW4gdW5kZXIgY2hhbmdlcyBpZiBpdCBoYXMgYmVlbiBlZGl0ZWRcblx0XHRpZiAoY29sdW1uLmVkaXRlZCkge1xuXHRcdFx0dGhpcy5lZGl0ZWRSb3dzW3Jvdy4kJGd0Um93SWRdLmNoYW5nZXNbT0JKRUNUX0tFWV0gPSBjb2x1bW47XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIGRlbGV0ZSBjaGFuZ2Ugb2JqZWN0IGlmIGNvbHVtbiBpcyB1bmNoYW5nZWRcblx0XHRcdGRlbGV0ZSB0aGlzLmVkaXRlZFJvd3Nbcm93LiQkZ3RSb3dJZF0uY2hhbmdlc1tPQkpFQ1RfS0VZXTtcblx0XHRcdC8vIGNoZWNrIGhvdyBtYW55IGNvbHVtbnMgaGF2ZSBiZWVuIGNoYW5nZWRcblx0XHRcdGNvbnN0IENIQU5HRURfQ09MVU1OUyA9IE9iamVjdC5rZXlzKFxuXHRcdFx0XHR0aGlzLmVkaXRlZFJvd3Nbcm93LiQkZ3RSb3dJZF0uY2hhbmdlc1xuXHRcdFx0KS5sZW5ndGg7XG5cdFx0XHRpZiAoQ0hBTkdFRF9DT0xVTU5TID09PSAwKSB7XG5cdFx0XHRcdC8vIGRlbGV0ZSByb3cgZnJvbSBlZGl0ZWQgcm93cyBpZiBubyBjb2x1bW5zIGhhdmUgYmVlbiBlZGl0ZWRcblx0XHRcdFx0ZGVsZXRlIHRoaXMuZWRpdGVkUm93c1tyb3cuJCRndFJvd0lkXTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Ly8gaWYgbm8gbGlzdGVuZXIgaXMgcHJlc2VudC4uLlxuXHRcdGlmICghdGhpcy5nbG9iYWxJbmxpbmVFZGl0TGlzdGVuZXIpIHtcblx0XHRcdC8vIC4uLmxpc3RlbiBmb3IgdXBkYXRlIGV2ZW50XG5cdFx0XHR0aGlzLl9saXN0ZW5Gb3JLZXlkb3duRXZlbnQoKTtcblx0XHR9XG5cdH1cblx0LyoqXG5cdCAqIExpc3RlbiBmb3Iga2V5IGRvd24gZXZlbnQgLSBsaXN0ZW4gZm9yIGtleSBkb3duIGV2ZW50IGR1cmluZyBpbmxpbmUgZWRpdC5cblx0ICovXG5cdHByaXZhdGUgX2xpc3RlbkZvcktleWRvd25FdmVudCgpIHtcblx0XHQvLyBhZGQgZ2xvYmFsIGxpc3RlbmVyIGZvciBrZXkgZG93biBldmVudHNcblx0XHR0aGlzLmdsb2JhbElubGluZUVkaXRMaXN0ZW5lciA9IHRoaXMucmVuZGVyZXIubGlzdGVuKFxuXHRcdFx0J2RvY3VtZW50Jyxcblx0XHRcdCdrZXlkb3duJyxcblx0XHRcdCRldmVudCA9PiB7XG5cdFx0XHRcdHN3aXRjaCAoJGV2ZW50LmtleSkge1xuXHRcdFx0XHRcdGNhc2UgJ0VudGVyJzogLy8gdXBkYXRlIGRhdGEgb2JqZWN0XG5cdFx0XHRcdFx0XHR0aGlzLmlubGluZUVkaXRVcGRhdGUoKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ0VzY2FwZSc6IC8vIGNhbmNlbFxuXHRcdFx0XHRcdFx0dGhpcy5pbmxpbmVFZGl0Q2FuY2VsKCk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdCk7XG5cdH1cblx0LyoqXG5cdCAqIElubGluZSBlZGl0IHVwZGF0ZSAtIGFjY2VwdCBjaGFuZ2VzIGFuZCB1cGRhdGUgcm93IHZhbHVlcy5cblx0ICovXG5cdHB1YmxpYyBpbmxpbmVFZGl0VXBkYXRlKCkge1xuXHRcdC8vIGxvb3AgdGhyb3VnaCByb3dzIHRoYXQgaGF2ZSBiZWVuIGVkaXRlZFxuXHRcdE9iamVjdC5rZXlzKHRoaXMuZWRpdGVkUm93cykubWFwKGtleSA9PiB7XG5cdFx0XHRjb25zdCBST1cgPSB0aGlzLmVkaXRlZFJvd3Nba2V5XS5yb3c7IC8vIHJvdyB0byB1cGRhdGVcblx0XHRcdGNvbnN0IENIQU5HRVMgPSB0aGlzLmVkaXRlZFJvd3Nba2V5XS5jaGFuZ2VzOyAvLyBjaGFuZ2VzIHRvIHRoZSByb3dcblxuXHRcdFx0Ly8gbG9vcCB0aHJvdWdoIGNoYW5nZXMgaW4gcm93XG5cdFx0XHRPYmplY3Qua2V5cyhDSEFOR0VTKS5tYXAob2JqZWN0S2V5ID0+IHtcblx0XHRcdFx0Y29uc3Qgb2xkVmFsdWUgPSB7IC4uLlJPVyB9O1xuXHRcdFx0XHRST1dbb2JqZWN0S2V5XSA9IENIQU5HRVNbb2JqZWN0S2V5XS5yZW5kZXJWYWx1ZTsgLy8gdXBkYXRlIGRhdGEgdmFsdWVcblx0XHRcdFx0dGhpcy51cGRhdGVSb3coUk9XLCBvbGRWYWx1ZSk7IC8vIHVwZGF0ZSBtZXRhIGluZm8gZm9yIHJvdyBhbmQgc2VuZCBldmVudFxuXHRcdFx0XHRDSEFOR0VTW29iamVjdEtleV0uZWRpdGVkID0gZmFsc2U7IC8vIGRpc2FibGUgZWRpdCBtb2RlXG5cdFx0XHR9KTtcblx0XHR9KTtcblx0XHQvLyBjbGVhciByb3dzIG1hcmtlZCBhcyBlZGl0ZWQgYXMgdGhlIHJvd3MgaGF2ZSBiZWVuIHVwZGF0ZWRcblx0XHR0aGlzLmVkaXRlZFJvd3MgPSB7fTtcblx0XHQvLyByZW1vdmUgbGlzdGVuZXJcblx0XHR0aGlzLl9zdG9wTGlzdGVuaW5nRm9yS2V5ZG93bkV2ZW50KCk7XG5cdH1cblx0LyoqXG5cdCAqIElubGluZSBlZGl0IGNhbmNlbCAtIGNhbmNlbCBhbmQgcmVzZXQgaW5saW5lIGVkaXRzLlxuXHQgKi9cblx0cHVibGljIGlubGluZUVkaXRDYW5jZWwocm93PzogR3RSb3cpIHtcblx0XHRpZiAocm93KSB7XG5cdFx0XHRkZWxldGUgdGhpcy5lZGl0ZWRSb3dzW3Jvdy4kJGd0Um93SWRdO1xuXHRcdFx0Ly8gcmVtb3ZlIGxpc3RlbmVyXG5cdFx0XHR0aGlzLl9zdG9wTGlzdGVuaW5nRm9yS2V5ZG93bkV2ZW50KCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gbG9vcCB0aHJvdWdoIHJvd3MgdGhhdCBoYXZlIGJlZW4gZWRpdGVkXG5cdFx0T2JqZWN0LmtleXModGhpcy5lZGl0ZWRSb3dzKS5tYXAoa2V5ID0+IHtcblx0XHRcdGNvbnN0IFJPVyA9IHRoaXMuZWRpdGVkUm93c1trZXldLnJvdzsgLy8gcm93IHRvIHVwZGF0ZVxuXHRcdFx0Y29uc3QgQ0hBTkdFUyA9IHRoaXMuZWRpdGVkUm93c1trZXldLmNoYW5nZXM7IC8vIGNoYW5nZXMgdG8gdGhlIHJvd1xuXG5cdFx0XHQvLyBsb29wIHRocm91Z2ggY2hhbmdlcyBpbiByb3dcblx0XHRcdE9iamVjdC5rZXlzKENIQU5HRVMpLm1hcChvYmplY3RLZXkgPT4ge1xuXHRcdFx0XHRDSEFOR0VTW29iamVjdEtleV0ucmVuZGVyVmFsdWUgPSBST1dbb2JqZWN0S2V5XTsgLy8gcmVzZXQgcmVuZGVyZWQgdmFsdWVcblx0XHRcdFx0Q0hBTkdFU1tvYmplY3RLZXldLmVkaXRlZCA9IGZhbHNlOyAvLyBkaXNhYmxlIGVkaXQgbW9kZVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdFx0Ly8gY2xlYXIgcm93cyBtYXJrZWQgYXMgZWRpdGVkIGFzIHRoZSByb3dzIGhhdmUgYmVlbiB1cGRhdGVkXG5cdFx0dGhpcy5lZGl0ZWRSb3dzID0ge307XG5cdFx0Ly8gcmVtb3ZlIGxpc3RlbmVyXG5cdFx0dGhpcy5fc3RvcExpc3RlbmluZ0ZvcktleWRvd25FdmVudCgpO1xuXHR9XG5cdC8qKlxuXHQgKiBTdG9wIGxpc3RlbmluZyBmb3Iga2V5IGRvd24gZXZlbnQgLSBzdG9wIGxpc3RlbmluZyBmb3Iga2V5IGRvd24gZXZlbnRzIHBhc3NlZCBkdXJpbmcgaW5saW5lIGVkaXQuXG5cdCAqL1xuXHRwcml2YXRlIF9zdG9wTGlzdGVuaW5nRm9yS2V5ZG93bkV2ZW50KCkge1xuXHRcdGlmICh0aGlzLmdsb2JhbElubGluZUVkaXRMaXN0ZW5lcikge1xuXHRcdFx0dGhpcy5nbG9iYWxJbmxpbmVFZGl0TGlzdGVuZXIoKTtcblx0XHRcdHRoaXMuZ2xvYmFsSW5saW5lRWRpdExpc3RlbmVyID0gbnVsbDtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQXBwbHkgZmlsdGVyKHMpLlxuXHQgKiBAcGFyYW0gZmlsdGVyIC0gb2JqZWN0IGNvbnRhaW5pbmcga2V5IHZhbHVlIHBhaXJzLCB3aGVyZSB2YWx1ZSBzaG91bGQgYmUgYXJyYXkgb2YgdmFsdWVzLlxuXHQgKi9cblx0cHVibGljIGd0QXBwbHlGaWx0ZXIoZmlsdGVyOiBPYmplY3QpIHtcblx0XHR0aGlzLmd0SW5mby5maWx0ZXIgPSBmaWx0ZXI7XG5cdFx0Ly8gZ28gdG8gZmlyc3QgcGFnZVxuXHRcdHRoaXMuZ29Ub1BhZ2UoMSk7XG5cdFx0dGhpcy51cGRhdGVUb3RhbHMoKTtcblx0fVxuXG5cdC8qKiBDbGVhci9yZW1vdmUgYXBwbGllZCBmaWx0ZXIocykuICovXG5cdHB1YmxpYyBndENsZWFyRmlsdGVyKCkge1xuXHRcdHRoaXMuZ3RJbmZvLmZpbHRlciA9IGZhbHNlO1xuXHRcdHRoaXMudXBkYXRlVG90YWxzKCk7XG5cdFx0Ly8gdGhpcy51cGRhdGVSZWNvcmRSYW5nZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNlYXJjaFxuXHQgKiBAcGFyYW0gdmFsdWUgLSBzdHJpbmcgY29udGFpbmluZyBvbmUgb3IgbW9yZSB3b3Jkc1xuXHQgKi9cblx0cHVibGljIGd0U2VhcmNoKHZhbHVlOiBzdHJpbmcpIHtcblx0XHR0aGlzLmd0SW5mby5zZWFyY2hUZXJtcyA9IHZhbHVlO1xuXHRcdC8vIGFsd2F5cyBnbyB0byBmaXJzdCBwYWdlIHdoZW4gc2VhcmNoaW5nXG5cdFx0dGhpcy5nb1RvUGFnZSgxKTtcblx0XHR0aGlzLnVwZGF0ZVRvdGFscygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZCByb3dzXG5cdCAqIEBwYXJhbSByb3dzIC0gcm93cyB0byBhZGRcblx0ICogQHJldHVybnMgbmV3IGRhdGEgYXJyYXkuXG5cdCAqL1xuXHRwdWJsaWMgZ3RBZGQocm93czogQXJyYXk8Uj4pOiBSZWFkb25seUFycmF5PFI+IHtcblx0XHR0aGlzLmd0RGF0YSA9IFsuLi50aGlzLmd0RGF0YSwgLi4ucm93c107XG5cdFx0cmV0dXJuIFsuLi50aGlzLmd0RGF0YV07XG5cdH1cblxuXHQvKipcblx0ICogRGVsZXRlIHJvd1xuXHQgKiBAcGFyYW0gb2JqZWN0S2V5IC0gb2JqZWN0IGtleSB5b3Ugd2FudCB0byBmaW5kIG1hdGNoIHdpdGhcblx0ICogQHBhcmFtIHZhbHVlIC0gdGhlIHZhbHVlIHRoYXQgc2hvdWxkIGJlIGRlbGV0ZWRcblx0ICogQHBhcmFtIG1hdGNoIC0gYWxsOiBkZWxldGUgYWxsIG1hdGNoZXMsIGZpcnN0OiBkZWxldGUgZmlyc3QgbWF0Y2ggKGRlZmF1bHQpXG5cdCAqIEByZXR1cm5zIG5ldyBkYXRhIGFycmF5LlxuXHQgKi9cblx0cHVibGljIGd0RGVsZXRlKFxuXHRcdG9iamVjdEtleTogc3RyaW5nLFxuXHRcdHZhbHVlOiBzdHJpbmcgfCBudW1iZXIsXG5cdFx0bWF0Y2g6ICdmaXJzdCcgfCAnYWxsJyA9ICdmaXJzdCdcblx0KTogUmVhZG9ubHlBcnJheTxSPiB7XG5cdFx0aWYgKG1hdGNoID09PSAnZmlyc3QnKSB7XG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZ3REYXRhLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmICh0aGlzLmd0RGF0YVtpXVtvYmplY3RLZXldID09PSB2YWx1ZSkge1xuXHRcdFx0XHRcdGlmICh0aGlzLmlzUm93U2VsZWN0ZWQodGhpcy5ndERhdGFbaV0pKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnRvZ2dsZVNlbGVjdCh0aGlzLmd0RGF0YVtpXSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHRoaXMuZ3REYXRhLnNwbGljZShpLCAxKTtcblx0XHRcdFx0XHR0aGlzLmd0RGF0YSA9IFsuLi50aGlzLmd0RGF0YV07XG5cdFx0XHRcdFx0aWYgKG1hdGNoID09PSAnZmlyc3QnKSB7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm9yIChsZXQgaSA9IHRoaXMuZ3REYXRhLmxlbmd0aDsgaSA+IDA7IGktLSkge1xuXHRcdFx0XHRpZiAodGhpcy5ndERhdGFbaSAtIDFdW29iamVjdEtleV0gPT09IHZhbHVlKSB7XG5cdFx0XHRcdFx0aWYgKHRoaXMuaXNSb3dTZWxlY3RlZCh0aGlzLmd0RGF0YVtpIC0gMV0pKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnRvZ2dsZVNlbGVjdCh0aGlzLmd0RGF0YVtpIC0gMV0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0aGlzLmd0RGF0YS5zcGxpY2UoaSAtIDEsIDEpO1xuXHRcdFx0XHRcdHRoaXMuZ3REYXRhID0gWy4uLnRoaXMuZ3REYXRhXTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gWy4uLnRoaXMuZ3REYXRhXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGUgc3RvcmUgdG8gaG9sZCBwcmV2aW91c2x5IGxvYWRlZCByZWNvcmRzLlxuXHQgKiBAcGFyYW0gcmVjb3JkcyAtIHRvdGFsIG51bWJlciBvZiByZWNvcmRzIGluIHN0b3JlLlxuXHQgKiBAcGFyYW0gcGVyUGFnZSAtIGhvdyBtYW55IHJlY29yZHMgdG8gc2hvdyBwZXIgcGFnZS5cblx0ICogQHJldHVybnMgYSBuZXN0ZWQgYXJyYXkgdG8gaG9sZCByZWNvcmRzIHBlciBwYWdlLlxuXHQgKi9cblx0cHJpdmF0ZSBjcmVhdGVTdG9yZShyZWNvcmRzOiBudW1iZXIsIHBlclBhZ2U6IG51bWJlcik6IEFycmF5PEFycmF5PGFueT4+IHtcblx0XHRjb25zdCBzdG9yZXMgPSBNYXRoLmNlaWwocmVjb3JkcyAvIHBlclBhZ2UpO1xuXHRcdGNvbnN0IHN0b3JlOiBBcnJheTxBcnJheTxhbnk+PiA9IFtdO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgc3RvcmVzOyBpKyspIHtcblx0XHRcdHN0b3JlW2ldID0gW107XG5cdFx0fVxuXHRcdHJldHVybiBzdG9yZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGUgcGxhY2Vob2xkZXJzIGZvciByb3dzIHdoaWxlIGxvYWRpbmcgZGF0YSBmcm9tIGJhY2stZW5kLlxuXHQgKiBAcGFyYW0gcGVyUGFnZSAtIGhvdyBtYW55IHJlY29yZHMgdG8gc2hvdyBwZXIgcGFnZS5cblx0ICogQHJldHVybnMgYW4gYXJyYXkgY29udGFpbmluZyBlbXB0eSByZWNvcmRzIHRvIGJlIHByZXNlbnRlZCB3aGlsZSBmZXRjaGluZyByZWFsIGRhdGEuXG5cdCAqL1xuXHRwcml2YXRlIGxvYWRpbmdDb250ZW50KHBlclBhZ2U6IG51bWJlcikge1xuXHRcdC8vIGNyZWF0ZSByb3cgb2JqZWN0XG5cdFx0Y29uc3Qgcm93T2JqZWN0OiBPYmplY3QgPSB7XG5cdFx0XHQkJGxvYWRpbmc6IHRydWVcblx0XHR9O1xuXHRcdGxldCBvcmRlciA9IDA7XG5cblx0XHQvLyBzb3J0IHNldHRpbmdzIGJ5IGNvbHVtbiBvcmRlclxuXHRcdHRoaXMuX2d0U2V0dGluZ3Muc29ydCh0aGlzLmdldENvbHVtbk9yZGVyKTtcblxuXHRcdC8vIGxvb3AgdGhyb3VnaCBhbGwgc2V0dGluZ3Mgb2JqZWN0cy4uLlxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fZ3RTZXR0aW5ncy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3Qgc2V0dGluZyA9IHRoaXMuX2d0U2V0dGluZ3NbaV07XG5cblx0XHRcdC8vIC4uLmlmIGNvbHVtbiBpcyB2aXNpYmxlIGFuZCBlbmFibGVkLi4uXG5cdFx0XHRpZiAoc2V0dGluZy52aXNpYmxlICE9PSBmYWxzZSAmJiBzZXR0aW5nLmVuYWJsZWQgIT09IGZhbHNlKSB7XG5cdFx0XHRcdC8vIC4uLmlmIGZpcnN0IGNvbHVtbiwgc2V0IHZhbHVlIHRvIGxvYWRpbmcgdGV4dCBvdGhlcndpc2UgbGVhdmUgaXQgZW1wdHlcblx0XHRcdFx0aWYgKG9yZGVyID09PSAwKSB7XG5cdFx0XHRcdFx0cm93T2JqZWN0W3NldHRpbmcub2JqZWN0S2V5XSA9IHRoaXMuZ3RUZXh0cy5sb2FkaW5nO1xuXHRcdFx0XHRcdHRoaXMubG9hZGluZ1Byb3BlcnR5ID0gc2V0dGluZy5vYmplY3RLZXk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cm93T2JqZWN0W3NldHRpbmcub2JqZWN0S2V5XSA9ICcnO1xuXHRcdFx0XHR9XG5cdFx0XHRcdG9yZGVyKys7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyb3dPYmplY3Rbc2V0dGluZy5vYmplY3RLZXldID0gJyc7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gY3JlYXRlIGNvbnRlbnQgcGxhY2Vob2xkZXJcblx0XHRjb25zdCBjb250ZW50UGxhY2Vob2xkZXI6IEFycmF5PGFueT4gPSBbXTtcblxuXHRcdC8vIGNyZWF0ZSBlcXVhbCBudW1iZXIgb2Ygcm93cyBhcyByb3dzIHBlciBwYWdlXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBwZXJQYWdlOyBpKyspIHtcblx0XHRcdC8vIC4uLmFkZCB0ZW1wb3Jhcnkgcm93IG9iamVjdFxuXHRcdFx0Y29udGVudFBsYWNlaG9sZGVyLnB1c2gocm93T2JqZWN0KTtcblx0XHR9XG5cdFx0cmV0dXJuIGNvbnRlbnRQbGFjZWhvbGRlcjtcblx0fVxuXG5cdC8vIFRPRE86IG1vdmUgdG8gaGVscGVyIGZ1bmN0aW9uc1xuXHQvKiogU29ydCBieSBzb3J0IG9yZGVyICovXG5cdHByaXZhdGUgZ2V0U29ydE9yZGVyID0gZnVuY3Rpb24oYTogR3RDb25maWdTZXR0aW5nLCBiOiBHdENvbmZpZ1NldHRpbmcpIHtcblx0XHRpZiAoYS5zb3J0T3JkZXIgPCBiLnNvcnRPcmRlcikge1xuXHRcdFx0cmV0dXJuIC0xO1xuXHRcdH1cblx0XHRpZiAoYS5zb3J0T3JkZXIgPiBiLnNvcnRPcmRlciB8fCB0eXBlb2YgYS5zb3J0T3JkZXIgPT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRyZXR1cm4gMTtcblx0XHR9XG5cdFx0cmV0dXJuIDA7XG5cdH07XG5cblx0Ly8gVE9ETzogbW92ZSB0byBoZWxwZXIgZnVuY3Rpb25zXG5cdC8qKiBTb3J0IGJ5IGNvbHVtbiBvcmRlciAqL1xuXHRwcml2YXRlIGdldENvbHVtbk9yZGVyID0gZnVuY3Rpb24oYTogR3RDb25maWdTZXR0aW5nLCBiOiBHdENvbmZpZ1NldHRpbmcpIHtcblx0XHRpZiAoYS5jb2x1bW5PcmRlciA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gLTE7XG5cdFx0fVxuXHRcdGlmIChhLmNvbHVtbk9yZGVyIDwgYi5jb2x1bW5PcmRlcikge1xuXHRcdFx0cmV0dXJuIC0xO1xuXHRcdH1cblx0XHRpZiAoYS5jb2x1bW5PcmRlciA+IGIuY29sdW1uT3JkZXIpIHtcblx0XHRcdHJldHVybiAxO1xuXHRcdH1cblx0XHRyZXR1cm4gMDtcblx0fTtcblxuXHQvLyBUT0RPOiBtb3ZlIHRvIGhlbHBlciBmdW5jdGlvbnNcblx0LyoqIENyZWF0ZSBhIGRlZXAgY29weSBvZiBkYXRhICovXG5cdHByaXZhdGUgY2xvbmVEZWVwID0gZnVuY3Rpb24obzogYW55KSB7XG5cdFx0cmV0dXJuIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkobykpO1xuXHR9O1xuXG5cdC8qKiBFeHBvcnQgZGF0YSBhcyBDU1Zcblx0ICogQHBhcmFtIGZpbGVOYW1lIC0gb3B0aW9uYWwgZmlsZSBuYW1lIChvdmVycmlkZXMgZGVmYXVsdCBmaWxlIG5hbWUpLlxuXHQgKiBAcGFyYW0gdXNlQk9NIC0gdXNlIEJPTSAoYnl0ZSBvcmRlciBtYXJrZXIpLlxuXHQgKi9cblx0cHVibGljIGV4cG9ydENTVihmaWxlTmFtZT86IHN0cmluZywgdXNlQk9NOiBib29sZWFuID0gZmFsc2UpIHtcblx0XHRjb25zdCBkYXRhID0gdGhpcy5kYXRhLmV4cG9ydERhdGE7XG5cdFx0bGV0IGNzdiA9ICcnO1xuXHRcdGNvbnN0IEJPTSA9ICdcXHVGRUZGJztcblxuXHRcdC8vIGNzdiBleHBvcnQgaGVhZGVyc1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fZ3RTZXR0aW5ncy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKHRoaXMuX2d0U2V0dGluZ3NbaV0uZXhwb3J0ICE9PSBmYWxzZSkge1xuXHRcdFx0XHRjc3YgKz0gdGhpcy5nZXRQcm9wZXJ0eSh0aGlzLl9ndEZpZWxkcywgdGhpcy5fZ3RTZXR0aW5nc1tpXS5vYmplY3RLZXkpXG5cdFx0XHRcdFx0Lm5hbWU7XG5cblx0XHRcdFx0aWYgKGkgPCB0aGlzLl9ndFNldHRpbmdzLmxlbmd0aCAtIDEpIHtcblx0XHRcdFx0XHRjc3YgKz0gdGhpcy5fZ3RPcHRpb25zLmNzdkRlbGltaXRlcjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIGNzdiBleHBvcnQgYm9keVxuXHRcdGRhdGEuZm9yRWFjaChyb3cgPT4ge1xuXHRcdFx0Y3N2ICs9ICdcXG4nO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9ndFNldHRpbmdzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmICh0aGlzLl9ndFNldHRpbmdzW2ldLmV4cG9ydCAhPT0gZmFsc2UpIHtcblx0XHRcdFx0XHQvLyBnZXQgZmllbGQgc2V0dGluZ3Ncblx0XHRcdFx0XHRjb25zdCBmaWVsZFNldHRpbmcgPSB0aGlzLmdldFByb3BlcnR5KFxuXHRcdFx0XHRcdFx0dGhpcy5fZ3RGaWVsZHMsXG5cdFx0XHRcdFx0XHR0aGlzLl9ndFNldHRpbmdzW2ldLm9iamVjdEtleVxuXHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHQvLyBnZXQgZXhwb3J0IHZhbHVlLCBpZiBleHBvcnQgZnVuY3Rpb24gaXMgZGVmaW5lZCB1c2UgaXQgb3RoZXJ3aXNlIGNoZWNrIGZvciB2YWx1ZSBmdW5jdGlvbiBhbmQgYXMgYSBsYXN0IHJlc29ydCBleHBvcnQgcmF3IGRhdGFcblx0XHRcdFx0XHRsZXQgZXhwb3J0VmFsdWU6IHN0cmluZyA9XG5cdFx0XHRcdFx0XHRmaWVsZFNldHRpbmcuZXhwb3J0ICYmIHR5cGVvZiBmaWVsZFNldHRpbmcuZXhwb3J0ID09PSAnZnVuY3Rpb24nXG5cdFx0XHRcdFx0XHRcdD8gZmllbGRTZXR0aW5nLmV4cG9ydChyb3cpXG5cdFx0XHRcdFx0XHRcdDogZmllbGRTZXR0aW5nLnZhbHVlICYmIHR5cGVvZiBmaWVsZFNldHRpbmcudmFsdWUgPT09ICdmdW5jdGlvbidcblx0XHRcdFx0XHRcdFx0XHQ/IGZpZWxkU2V0dGluZy52YWx1ZShyb3cpXG5cdFx0XHRcdFx0XHRcdFx0OiByb3dbdGhpcy5fZ3RTZXR0aW5nc1tpXS5vYmplY3RLZXldO1xuXG5cdFx0XHRcdFx0Ly8gZXNjYXBlIGV4cG9ydCB2YWx1ZSB1c2luZyBkb3VibGUgcXVvdGVzIChcIikgaWYgZXhwb3J0IHZhbHVlIGNvbnRhaW5zIGRlbGltaXRlclxuXHRcdFx0XHRcdGV4cG9ydFZhbHVlID1cblx0XHRcdFx0XHRcdHR5cGVvZiBleHBvcnRWYWx1ZSA9PT0gJ3N0cmluZycgJiZcblx0XHRcdFx0XHRcdGV4cG9ydFZhbHVlLmluZGV4T2YodGhpcy5fZ3RPcHRpb25zLmNzdkRlbGltaXRlcikgIT09IC0xXG5cdFx0XHRcdFx0XHRcdD8gJ1wiJyArIGV4cG9ydFZhbHVlICsgJ1wiJ1xuXHRcdFx0XHRcdFx0XHQ6IGV4cG9ydFZhbHVlO1xuXG5cdFx0XHRcdFx0Y3N2ICs9IGV4cG9ydFZhbHVlO1xuXHRcdFx0XHRcdGlmIChpIDwgdGhpcy5fZ3RTZXR0aW5ncy5sZW5ndGggLSAxKSB7XG5cdFx0XHRcdFx0XHRjc3YgKz0gdGhpcy5fZ3RPcHRpb25zLmNzdkRlbGltaXRlcjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdGNvbnN0IGJsb2IgPSBuZXcgQmxvYihbKHVzZUJPTSA/IEJPTSA6ICcnKSArIGNzdl0sIHtcblx0XHRcdHR5cGU6ICd0ZXh0L2NzdjtjaGFyc2V0PXV0Zi04J1xuXHRcdH0pO1xuXG5cdFx0aWYgKHdpbmRvdy5uYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYikge1xuXHRcdFx0bmF2aWdhdG9yLm1zU2F2ZU9yT3BlbkJsb2IoXG5cdFx0XHRcdGJsb2IsXG5cdFx0XHRcdGZpbGVOYW1lID8gZmlsZU5hbWUgKyAnLmNzdicgOiB0aGlzLmd0VGV4dHMuY3N2RG93bmxvYWQgKyAnLmNzdidcblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnN0IGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG5cdFx0XHRsaW5rLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0XHRkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGxpbmspO1xuXHRcdFx0aWYgKGxpbmsuZG93bmxvYWQgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRsaW5rLnNldEF0dHJpYnV0ZShcblx0XHRcdFx0XHQnaHJlZicsXG5cdFx0XHRcdFx0J2RhdGE6dGV4dC9jc3Y7Y2hhcnNldD11dGYtOCwnICtcblx0XHRcdFx0XHRcdGVuY29kZVVSSUNvbXBvbmVudCgodXNlQk9NID8gQk9NIDogJycpICsgY3N2KVxuXHRcdFx0XHQpOyAvLyBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpKTtcblx0XHRcdFx0bGluay5zZXRBdHRyaWJ1dGUoXG5cdFx0XHRcdFx0J2Rvd25sb2FkJyxcblx0XHRcdFx0XHRmaWxlTmFtZSA/IGZpbGVOYW1lICsgJy5jc3YnIDogdGhpcy5ndFRleHRzLmNzdkRvd25sb2FkICsgJy5jc3YnXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQobGluayk7XG5cdFx0XHRcdGxpbmsuY2xpY2soKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNzdiA9ICdkYXRhOnRleHQvY3N2O2NoYXJzZXQ9dXRmLTgsJyArICh1c2VCT00gPyBCT00gOiAnJykgKyBjc3Y7XG5cdFx0XHRcdHdpbmRvdy5vcGVuKGVuY29kZVVSSUNvbXBvbmVudChjc3YpKTtcblx0XHRcdH1cblx0XHRcdGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQobGluayk7XG5cdFx0fVxuXG5cdFx0Ly8gZW1pdCBleHBvcnQgZXZlbnRcblx0XHR0aGlzLmd0RXZlbnQuZW1pdCh7XG5cdFx0XHRuYW1lOiAnZ3QtZXhwb3J0ZWQtY3N2Jyxcblx0XHRcdHZhbHVlOiBmaWxlTmFtZSA/IGZpbGVOYW1lIDogdGhpcy5ndFRleHRzLmNzdkRvd25sb2FkICsgJy5jc3YnXG5cdFx0fSk7XG5cdH1cblxuXHQvKiogUmV0dXJuIHByb3BlcnR5ICovXG5cdHByaXZhdGUgZ2V0UHJvcGVydHkgPSBmdW5jdGlvbihhcnJheTogQXJyYXk8YW55Piwga2V5OiBzdHJpbmcpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAoYXJyYXlbaV0ub2JqZWN0S2V5ID09PSBrZXkpIHtcblx0XHRcdFx0cmV0dXJuIGFycmF5W2ldO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHRwcml2YXRlIHJlc3RydWN0dXJlU29ydGluZyA9IGZ1bmN0aW9uKCkge1xuXHRcdC8qKiBDaGVjayBhbmQgc3RvcmUgc29ydCBvcmRlciB1cG9uIGluaXRpYWxpemF0aW9uLlxuXHRcdCAqICBUaGlzIGlzIGRvbmUgYnkgY2hlY2tpbmcgc29ydCBwcm9wZXJ0aWVzIGluIHRoZSBzZXR0aW5ncyBhcnJheSBvZiB0aGUgdGFibGUsIGlmIG5vIHNvcnRpbmcgaXMgZGVmaW5lZFxuXHRcdCAqICB3ZSdsbCBzb3J0IHRoZSBkYXRhIGJ5IHRoZSBmaXJzdCB2aXNpYmxlIGFuZCBlbmFibGVkIGNvbHVtbiBpbiB0aGUgdGFibGUoYXNjZW5kaW5nKS4gUGxlYXNlIG5vdGUgdGhhdCBhY3R1YWxseVxuXHRcdCAqICBzb3J0aW5nIGhhdmUgdG8gYmUgZG9uZSBzZXJ2ZXIgc2lkZSB3aGVuIGxhenkgbG9hZGluZyBkYXRhIGZvciBvYnZpb3VzIHJlYXNvbnMuICAqL1xuXHRcdC8vIGNyZWF0ZSBzb3J0aW5nIGFycmF5XG5cdFx0Y29uc3Qgc29ydGluZyA9IFtdO1xuXHRcdGlmICh0aGlzLl9ndFNldHRpbmdzKSB7XG5cdFx0XHQvLyAuLi5zb3J0IHNldHRpbmdzIGJ5IHNvcnQgb3JkZXJcblx0XHRcdHRoaXMuX2d0U2V0dGluZ3Muc29ydCh0aGlzLmdldFNvcnRPcmRlcik7XG5cblx0XHRcdC8vIC4uLmxvb3AgdGhyb3VnaCBzZXR0aW5nc1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9ndFNldHRpbmdzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGNvbnN0IHNldHRpbmcgPSB0aGlzLl9ndFNldHRpbmdzW2ldO1xuXG5cdFx0XHRcdC8vIC4uLmlmIHNvcnRlZCBhc2NlbmRpbmcuLi5cblx0XHRcdFx0aWYgKHNldHRpbmcuc29ydCA9PT0gJ2FzYycpIHtcblx0XHRcdFx0XHQvLyAuLi4gYWRkIHRvIHNvcnRpbmdcblx0XHRcdFx0XHRzb3J0aW5nLnB1c2goc2V0dGluZy5vYmplY3RLZXkpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKHNldHRpbmcuc29ydCA9PT0gJ2Rlc2MnKSB7XG5cdFx0XHRcdFx0LyogLi4uZWxzZSBpZiBzb3J0ZWQgZGVzY2VuZGluZy4uLiAqLyAvLyAuLi4gYWRkIHRvIHNvcnRpbmdcblx0XHRcdFx0XHRzb3J0aW5nLnB1c2goJy0nICsgc2V0dGluZy5vYmplY3RLZXkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHQvLyAuLi5pZiBubyBzb3J0aW5nIGFwcGxpZWQuLi5cblx0XHRcdGlmIChzb3J0aW5nLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0XHRzb3J0aW5nLnB1c2goJyQkZ3RSb3dJZCcpO1xuXHRcdFx0XHQvKi8vIC4uLnNvcnQgc2V0dGluZ3MgYnkgY29sdW1uIG9yZGVyXG5cdFx0XHRcdHRoaXMuX2d0U2V0dGluZ3Muc29ydCh0aGlzLmdldENvbHVtbk9yZGVyKTtcblxuXHRcdFx0XHQvLyAuLi5sb29wIHRocm91Z2ggc2V0dGluZ3Ncblx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9ndFNldHRpbmdzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdFx0Y29uc3Qgc2V0dGluZyA9IHRoaXMuX2d0U2V0dGluZ3NbaV07XG5cblx0XHRcdFx0XHQvLyAuLi5pZiBjb2x1bW4gaXMgZW5hYmxlZCBhbmQgdmlzaWJsZS4uLlxuXHRcdFx0XHRcdGlmIChzZXR0aW5nLmVuYWJsZWQgIT09IGZhbHNlICYmIHNldHRpbmcudmlzaWJsZSAhPT0gZmFsc2UpIHtcblx0XHRcdFx0XHRcdC8vIC4uLmFkZCBmaXJzdCBtYXRjaCBhbmQgZXhpdCBmdW5jdGlvblxuXHRcdFx0XHRcdFx0dGhpcy5zb3J0T3JkZXIgPSBbdGhpcy5fZ3RTZXR0aW5nc1tpXS5vYmplY3RLZXldO1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSovXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMuc29ydE9yZGVyLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0dGhpcy5zb3J0T3JkZXIgPSBzb3J0aW5nO1xuXHRcdH1cblx0fTtcblxuXHRuZ09uSW5pdCgpIHtcblx0XHQvLyBpZiBudW1iZXIgb2Ygcm93IHRvIGRpc3BsYXkgZnJvbSBzdGFydCBpcyBzZXQgdG8gbnVsbCBvciAwLi4uXG5cdFx0aWYgKCF0aGlzLmd0T3B0aW9ucy5udW1iZXJPZlJvd3MpIHtcblx0XHRcdC8vIC4uLmNoYW5nZSByb3cgbGVuZ3RoXG5cdFx0XHR0aGlzLmNoYW5nZVJvd0xlbmd0aCh0aGlzLmd0T3B0aW9ucy5udW1iZXJPZlJvd3MpO1xuXHRcdH1cblx0XHR0aGlzLnJlc3RydWN0dXJlU29ydGluZygpO1xuXHR9XG5cblx0LyoqXG5cdCAqICBFeHRlbmQgb2JqZWN0IGZ1bmN0aW9uLlxuXHQgKi9cblx0cHJpdmF0ZSBleHRlbmQgPSBmdW5jdGlvbihhOiBPYmplY3QsIGI6IE9iamVjdCkge1xuXHRcdGZvciAoY29uc3Qga2V5IGluIGIpIHtcblx0XHRcdGlmIChiLmhhc093blByb3BlcnR5KGtleSkpIHtcblx0XHRcdFx0YVtrZXldID0gYltrZXldO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gYTtcblx0fTtcblxuXHRuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG5cdFx0Ly8gaWYgZ3QgdGV4dHMgaGF2ZSBjaGFuZ2VkLi4uXG5cdFx0aWYgKGNoYW5nZXNbJ2d0VGV4dHMnXSkge1xuXHRcdFx0Ly8gLi4uZXh0ZW5kIGd0T3B0aW9ucyBkZWZhdWx0IHZhbHVlcyB3aXRoIHZhbHVlcyBwYXNzZWQgaW50byBjb21wb25lbnRcblx0XHRcdHRoaXMuZ3RUZXh0cyA9IDxHdFRleHRzPnRoaXMuZXh0ZW5kKHRoaXMuZ3REZWZhdWx0VGV4dHMsIHRoaXMuZ3RUZXh0cyk7XG5cdFx0fVxuXG5cdFx0Ly8gaWYgbGF6eSBsb2FkaW5nIGRhdGEgYW5kIHBhZ2luZyBpbmZvcm1hdGlvbiBpcyBhdmFpbGFibGUuLi5cblx0XHRpZiAodGhpcy5ndE9wdGlvbnMubGF6eUxvYWQgJiYgdGhpcy5ndEluZm8pIHtcblx0XHRcdC8vIC4uLmNhbGN1bGF0ZSB0b3RhbCBudW1iZXIgb2YgcGFnZXNcblx0XHRcdHRoaXMuZ3RJbmZvLnBhZ2VUb3RhbCA9IE1hdGguY2VpbChcblx0XHRcdFx0dGhpcy5ndEluZm8ucmVjb3Jkc0FmdGVyU2VhcmNoIC8gdGhpcy5ndEluZm8ucmVjb3JkTGVuZ3RoXG5cdFx0XHQpO1xuXG5cdFx0XHQvLyAuLi5kZWNsYXJlIHN0b3JlIHBvc2l0aW9uXG5cdFx0XHRjb25zdCBzdG9yZVBvc2l0aW9uID0gdGhpcy5ndEluZm8ucGFnZUN1cnJlbnQgLSAxO1xuXG5cdFx0XHQvLyAuLi5hbmQgaWYgc3RvcmUgaXMgZW1wdHkgb3IgcGFnZSBsZW5ndGggaGFzIGNoYW5nZWQuLi5cblx0XHRcdGlmIChcblx0XHRcdFx0dGhpcy5zdG9yZS5sZW5ndGggPT09IDAgfHxcblx0XHRcdFx0dGhpcy5zdG9yZVswXS5sZW5ndGggIT09IHRoaXMuZ3RJbmZvLnJlY29yZExlbmd0aFxuXHRcdFx0KSB7XG5cdFx0XHRcdC8vIC4uLmNyZWF0ZSBzdG9yZVxuXHRcdFx0XHR0aGlzLnN0b3JlID0gdGhpcy5jcmVhdGVTdG9yZShcblx0XHRcdFx0XHR0aGlzLmd0SW5mby5yZWNvcmRzQWZ0ZXJTZWFyY2gsXG5cdFx0XHRcdFx0dGhpcy5ndEluZm8ucmVjb3JkTGVuZ3RoXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIC4uLnN0b3JlIHJldHJpZXZlZCBkYXRhIGluIHN0b3JlIGF0IHN0b3JlIHBvc2l0aW9uXG5cdFx0XHR0aGlzLnN0b3JlW3N0b3JlUG9zaXRpb25dID0gdGhpcy5ndERhdGE7XG5cdFx0XHR0aGlzLmd0SW5mby52aXNpYmxlUmVjb3JkcyA9IFsuLi50aGlzLmd0RGF0YV07IC8vIGFkZCB2aXNpYmxlIHJvd3NcblxuXHRcdFx0Ly8gcmVwbGFjZSBkYXRhIHdpdGggc3RvcmVcblx0XHRcdHRoaXMuX2d0RGF0YSA9IHRoaXMuc3RvcmU7XG5cdFx0XHR0aGlzLmxvYWRpbmcgPSBmYWxzZTtcblx0XHRcdHRoaXMudXBkYXRlUmVjb3JkUmFuZ2UoKTtcblx0XHRcdHRoaXMuZ3RFdmVudC5lbWl0KHtcblx0XHRcdFx0bmFtZTogJ2d0LWluZm8nLFxuXHRcdFx0XHR2YWx1ZTogdGhpcy5ndEluZm9cblx0XHRcdH0pO1xuXHRcdH0gZWxzZSBpZiAoXG5cdFx0XHR0aGlzLl9ndERhdGEgJiZcblx0XHRcdHRoaXMuX2d0RGF0YS5sZW5ndGggPj0gMCAmJlxuXHRcdFx0Y2hhbmdlc1snZ3REYXRhJ10gJiZcblx0XHRcdGNoYW5nZXNbJ2d0RGF0YSddLnByZXZpb3VzVmFsdWVcblx0XHQpIHtcblx0XHRcdHRoaXMubG9hZGluZyA9IGZhbHNlO1xuXHRcdH0gZWxzZSBpZiAoXG5cdFx0XHRjaGFuZ2VzWydndERhdGEnXSAmJlxuXHRcdFx0Y2hhbmdlc1snZ3REYXRhJ10uZmlyc3RDaGFuZ2UgJiZcblx0XHRcdHRoaXMuX2d0RGF0YSAmJlxuXHRcdFx0dGhpcy5fZ3REYXRhLmxlbmd0aCA+IDBcblx0XHQpIHtcblx0XHRcdHRoaXMubG9hZGluZyA9IGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdHRyYWNrQnlGbihpbmRleDogbnVtYmVyLCBpdGVtOiBHdFJvdykge1xuXHRcdHJldHVybiBpdGVtLiQkZ3RSb3dJZDtcblx0fVxuXG5cdHRyYWNrQnlDb2x1bW5GbihpbmRleDogbnVtYmVyLCBpdGVtOiBHdENvbmZpZ0ZpZWxkPGFueSwgYW55Pikge1xuXHRcdHJldHVybiBpdGVtLm9iamVjdEtleTtcblx0fVxuXG5cdG5nT25EZXN0cm95KCkge1xuXHRcdC8vIHJlbW92ZSBsaXN0ZW5lclxuXHRcdHRoaXMuX3N0b3BMaXN0ZW5pbmdGb3JLZXlkb3duRXZlbnQoKTtcblx0fVxufVxuIl19
|