@aquera/ngx-smart-table 0.0.2-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/README.md +152 -0
  2. package/aquera-ngx-smart-table.d.ts +5 -0
  3. package/esm2020/aquera-ngx-smart-table.mjs +5 -0
  4. package/esm2020/lib/builder/components/builder-preview/builder-preview.component.mjs +63 -0
  5. package/esm2020/lib/builder/components/builder-toolbar/builder-toolbar.component.mjs +115 -0
  6. package/esm2020/lib/builder/components/column-editor/column-editor.component.mjs +206 -0
  7. package/esm2020/lib/builder/components/column-list/column-list.component.mjs +125 -0
  8. package/esm2020/lib/builder/components/definition-builder/definition-builder.component.mjs +105 -0
  9. package/esm2020/lib/builder/components/table-config-editor/table-config-editor.component.mjs +132 -0
  10. package/esm2020/lib/builder/definition-builder.module.mjs +70 -0
  11. package/esm2020/lib/builder/models/builder-state.interface.mjs +5 -0
  12. package/esm2020/lib/builder/services/definition-builder.service.mjs +251 -0
  13. package/esm2020/lib/builder/services/definition-export.service.mjs +167 -0
  14. package/esm2020/lib/builder/services/definition-import.service.mjs +193 -0
  15. package/esm2020/lib/builder/services/sample-data-generator.service.mjs +126 -0
  16. package/esm2020/lib/builder/utils/config-validator.util.mjs +165 -0
  17. package/esm2020/lib/builder/utils/typescript-generator.util.mjs +206 -0
  18. package/esm2020/lib/editors/index.mjs +9 -0
  19. package/esm2020/lib/editors/nile-autocomplete-editor.mjs +228 -0
  20. package/esm2020/lib/editors/nile-calendar-editor.mjs +214 -0
  21. package/esm2020/lib/editors/nile-date-picker-editor.mjs +227 -0
  22. package/esm2020/lib/editors/nile-input-editor.mjs +235 -0
  23. package/esm2020/lib/editors/nile-select-editor.mjs +317 -0
  24. package/esm2020/lib/factories/column-config.factory.mjs +231 -0
  25. package/esm2020/lib/models/autosave-config.interface.mjs +8 -0
  26. package/esm2020/lib/models/base-column-config.class.mjs +253 -0
  27. package/esm2020/lib/models/cell-strategies.interface.mjs +6 -0
  28. package/esm2020/lib/models/cell-types.mjs +147 -0
  29. package/esm2020/lib/models/column-action.interface.mjs +6 -0
  30. package/esm2020/lib/models/column-config.interface.mjs +43 -0
  31. package/esm2020/lib/models/column-config.utils.mjs +101 -0
  32. package/esm2020/lib/models/row-action.interface.mjs +5 -0
  33. package/esm2020/lib/models/row-validator.interface.mjs +2 -0
  34. package/esm2020/lib/models/schema-validation.interface.mjs +2 -0
  35. package/esm2020/lib/models/sheet-action.interface.mjs +5 -0
  36. package/esm2020/lib/models/sheet-config.interface.mjs +5 -0
  37. package/esm2020/lib/models/table-config.interface.mjs +106 -0
  38. package/esm2020/lib/models/table-validator.interface.mjs +2 -0
  39. package/esm2020/lib/models/workbook-action.interface.mjs +5 -0
  40. package/esm2020/lib/models/workbook-config.interface.mjs +5 -0
  41. package/esm2020/lib/renderer/components/st-add-column-button/st-add-column-button.component.mjs +24 -0
  42. package/esm2020/lib/renderer/components/st-cell/st-cell.component.mjs +391 -0
  43. package/esm2020/lib/renderer/components/st-column-editor-modal/st-column-editor-modal.component.mjs +103 -0
  44. package/esm2020/lib/renderer/components/st-column-filter/st-column-filter.component.mjs +383 -0
  45. package/esm2020/lib/renderer/components/st-column-menu/st-column-menu.component.mjs +232 -0
  46. package/esm2020/lib/renderer/components/st-column-visibility/st-column-visibility.component.mjs +97 -0
  47. package/esm2020/lib/renderer/components/st-header/st-header.component.mjs +157 -0
  48. package/esm2020/lib/renderer/components/st-pagination/st-pagination.component.mjs +87 -0
  49. package/esm2020/lib/renderer/components/st-row-actions-dropdown/st-row-actions-dropdown.component.mjs +167 -0
  50. package/esm2020/lib/renderer/components/st-sheet/st-sheet.component.mjs +165 -0
  51. package/esm2020/lib/renderer/components/st-sheet-actions/st-sheet-actions.component.mjs +112 -0
  52. package/esm2020/lib/renderer/components/st-table/st-table.component.mjs +1246 -0
  53. package/esm2020/lib/renderer/components/st-table-actions/st-table-actions.component.mjs +171 -0
  54. package/esm2020/lib/renderer/components/st-workbook/st-workbook.component.mjs +489 -0
  55. package/esm2020/lib/renderer/directives/click-outside.directive.mjs +28 -0
  56. package/esm2020/lib/renderer/directives/st-column-resize.directive.mjs +108 -0
  57. package/esm2020/lib/renderer/directives/st-keyboard-navigation.directive.mjs +73 -0
  58. package/esm2020/lib/renderer/models/cell-state.interface.mjs +66 -0
  59. package/esm2020/lib/renderer/models/cell.class.mjs +389 -0
  60. package/esm2020/lib/renderer/models/row-validation-state.interface.mjs +7 -0
  61. package/esm2020/lib/renderer/models/sheet-state.class.mjs +90 -0
  62. package/esm2020/lib/renderer/models/sheet-state.interface.mjs +5 -0
  63. package/esm2020/lib/renderer/models/table-state.class.mjs +841 -0
  64. package/esm2020/lib/renderer/models/table-state.interface.mjs +5 -0
  65. package/esm2020/lib/renderer/models/table-types.mjs +29 -0
  66. package/esm2020/lib/renderer/models/table-validation-state.interface.mjs +7 -0
  67. package/esm2020/lib/renderer/models/workbook-state.class.mjs +174 -0
  68. package/esm2020/lib/renderer/models/workbook-state.interface.mjs +5 -0
  69. package/esm2020/lib/renderer/models/z-index.enum.mjs +55 -0
  70. package/esm2020/lib/schemas/table-config.schema.mjs +472 -0
  71. package/esm2020/lib/services/autosave.service.mjs +92 -0
  72. package/esm2020/lib/services/custom-validation-rules.util.mjs +124 -0
  73. package/esm2020/lib/services/json-schema-validator.service.mjs +216 -0
  74. package/esm2020/lib/services/row-validation.service.mjs +42 -0
  75. package/esm2020/lib/services/validation-logger.service.mjs +177 -0
  76. package/esm2020/lib/services/virtual-scroll.service.mjs +52 -0
  77. package/esm2020/lib/shared/shared-table-components.module.mjs +35 -0
  78. package/esm2020/lib/smart-table.module.mjs +124 -0
  79. package/esm2020/lib/strategies/default-editors.mjs +433 -0
  80. package/esm2020/lib/strategies/default-formatters.mjs +238 -0
  81. package/esm2020/lib/strategies/default-validators.mjs +327 -0
  82. package/esm2020/public-api.mjs +146 -0
  83. package/fesm2015/aquera-ngx-smart-table.mjs +11860 -0
  84. package/fesm2015/aquera-ngx-smart-table.mjs.map +1 -0
  85. package/fesm2020/aquera-ngx-smart-table.mjs +11897 -0
  86. package/fesm2020/aquera-ngx-smart-table.mjs.map +1 -0
  87. package/lib/builder/components/builder-preview/builder-preview.component.d.ts +31 -0
  88. package/lib/builder/components/builder-toolbar/builder-toolbar.component.d.ts +53 -0
  89. package/lib/builder/components/column-editor/column-editor.component.d.ts +69 -0
  90. package/lib/builder/components/column-list/column-list.component.d.ts +65 -0
  91. package/lib/builder/components/definition-builder/definition-builder.component.d.ts +58 -0
  92. package/lib/builder/components/table-config-editor/table-config-editor.component.d.ts +32 -0
  93. package/lib/builder/definition-builder.module.d.ts +15 -0
  94. package/lib/builder/models/builder-state.interface.d.ts +93 -0
  95. package/lib/builder/services/definition-builder.service.d.ts +80 -0
  96. package/lib/builder/services/definition-export.service.d.ts +59 -0
  97. package/lib/builder/services/definition-import.service.d.ts +31 -0
  98. package/lib/builder/services/sample-data-generator.service.d.ts +41 -0
  99. package/lib/builder/utils/config-validator.util.d.ts +32 -0
  100. package/lib/builder/utils/typescript-generator.util.d.ts +29 -0
  101. package/lib/editors/index.d.ts +8 -0
  102. package/lib/editors/nile-autocomplete-editor.d.ts +102 -0
  103. package/lib/editors/nile-calendar-editor.d.ts +89 -0
  104. package/lib/editors/nile-date-picker-editor.d.ts +95 -0
  105. package/lib/editors/nile-input-editor.d.ts +67 -0
  106. package/lib/editors/nile-select-editor.d.ts +109 -0
  107. package/lib/factories/column-config.factory.d.ts +73 -0
  108. package/lib/models/autosave-config.interface.d.ts +23 -0
  109. package/lib/models/base-column-config.class.d.ts +115 -0
  110. package/lib/models/cell-strategies.interface.d.ts +181 -0
  111. package/lib/models/cell-types.d.ts +337 -0
  112. package/lib/models/column-action.interface.d.ts +86 -0
  113. package/lib/models/column-config.interface.d.ts +272 -0
  114. package/lib/models/column-config.utils.d.ts +37 -0
  115. package/lib/models/row-action.interface.d.ts +86 -0
  116. package/lib/models/row-validator.interface.d.ts +37 -0
  117. package/lib/models/schema-validation.interface.d.ts +42 -0
  118. package/lib/models/sheet-action.interface.d.ts +59 -0
  119. package/lib/models/sheet-config.interface.d.ts +41 -0
  120. package/lib/models/table-config.interface.d.ts +245 -0
  121. package/lib/models/table-validator.interface.d.ts +40 -0
  122. package/lib/models/workbook-action.interface.d.ts +90 -0
  123. package/lib/models/workbook-config.interface.d.ts +107 -0
  124. package/lib/renderer/components/st-add-column-button/st-add-column-button.component.d.ts +9 -0
  125. package/lib/renderer/components/st-cell/st-cell.component.d.ts +69 -0
  126. package/lib/renderer/components/st-column-editor-modal/st-column-editor-modal.component.d.ts +39 -0
  127. package/lib/renderer/components/st-column-filter/st-column-filter.component.d.ts +139 -0
  128. package/lib/renderer/components/st-column-menu/st-column-menu.component.d.ts +81 -0
  129. package/lib/renderer/components/st-column-visibility/st-column-visibility.component.d.ts +44 -0
  130. package/lib/renderer/components/st-header/st-header.component.d.ts +93 -0
  131. package/lib/renderer/components/st-pagination/st-pagination.component.d.ts +42 -0
  132. package/lib/renderer/components/st-row-actions-dropdown/st-row-actions-dropdown.component.d.ts +67 -0
  133. package/lib/renderer/components/st-sheet/st-sheet.component.d.ts +98 -0
  134. package/lib/renderer/components/st-sheet-actions/st-sheet-actions.component.d.ts +58 -0
  135. package/lib/renderer/components/st-table/st-table.component.d.ts +349 -0
  136. package/lib/renderer/components/st-table-actions/st-table-actions.component.d.ts +77 -0
  137. package/lib/renderer/components/st-workbook/st-workbook.component.d.ts +235 -0
  138. package/lib/renderer/directives/click-outside.directive.d.ts +10 -0
  139. package/lib/renderer/directives/st-column-resize.directive.d.ts +44 -0
  140. package/lib/renderer/directives/st-keyboard-navigation.directive.d.ts +15 -0
  141. package/lib/renderer/models/cell-state.interface.d.ts +118 -0
  142. package/lib/renderer/models/cell.class.d.ts +174 -0
  143. package/lib/renderer/models/row-validation-state.interface.d.ts +27 -0
  144. package/lib/renderer/models/sheet-state.class.d.ts +67 -0
  145. package/lib/renderer/models/sheet-state.interface.d.ts +55 -0
  146. package/lib/renderer/models/table-state.class.d.ts +313 -0
  147. package/lib/renderer/models/table-state.interface.d.ts +18 -0
  148. package/lib/renderer/models/table-types.d.ts +228 -0
  149. package/lib/renderer/models/table-validation-state.interface.d.ts +34 -0
  150. package/lib/renderer/models/workbook-state.class.d.ts +117 -0
  151. package/lib/renderer/models/workbook-state.interface.d.ts +71 -0
  152. package/lib/renderer/models/z-index.enum.d.ts +44 -0
  153. package/lib/schemas/table-config.schema.d.ts +455 -0
  154. package/lib/services/autosave.service.d.ts +73 -0
  155. package/lib/services/custom-validation-rules.util.d.ts +12 -0
  156. package/lib/services/json-schema-validator.service.d.ts +49 -0
  157. package/lib/services/row-validation.service.d.ts +17 -0
  158. package/lib/services/validation-logger.service.d.ts +87 -0
  159. package/lib/services/virtual-scroll.service.d.ts +44 -0
  160. package/lib/shared/shared-table-components.module.d.ts +9 -0
  161. package/lib/smart-table.module.d.ts +26 -0
  162. package/lib/strategies/default-editors.d.ts +109 -0
  163. package/lib/strategies/default-formatters.d.ts +116 -0
  164. package/lib/strategies/default-validators.d.ts +113 -0
  165. package/package.json +42 -0
  166. package/public-api.d.ts +70 -0
  167. package/src/lib/builder/README.md +30 -0
  168. package/src/lib/editors/README.md +303 -0
  169. package/src/lib/renderer/components/st-column-filter/README.md +286 -0
@@ -0,0 +1,841 @@
1
+ /**
2
+ * TableState - Reactive state management for table operations
3
+ * Event-driven architecture: tracks state, emits events, consumer handles async data operations
4
+ */
5
+ import { BehaviorSubject, Subject } from 'rxjs';
6
+ import { map, distinctUntilChanged } from 'rxjs/operators';
7
+ import { SortDirection, FilterOperator } from './table-types';
8
+ import { NavigationDirection } from '../../models/cell-types';
9
+ /**
10
+ * TableState class - Column-driven, event-emitting state management
11
+ * NO data manipulation - only state tracking and event emission
12
+ */
13
+ export class TableState {
14
+ /**
15
+ * Constructor
16
+ * @param columns Reference to columns array
17
+ * @param config Initial configuration
18
+ */
19
+ constructor(columns, config) {
20
+ // Row number column width for sticky offset calculation
21
+ this._rowNumberWidth = 0;
22
+ // Settings column width for sticky offset calculation
23
+ this._settingsColumnWidth = 0;
24
+ // Dimensions for boundary checking
25
+ this._rowCount = 0;
26
+ this._columnCount = 0;
27
+ this._columns = columns;
28
+ this._initialConfig = {
29
+ initialPage: config?.initialPage ?? 0,
30
+ pageSize: config?.pageSize ?? 25
31
+ };
32
+ // Initialize pagination state
33
+ this._pagination$ = new BehaviorSubject({
34
+ currentPage: this._initialConfig.initialPage,
35
+ pageSize: this._initialConfig.pageSize,
36
+ totalItems: 0,
37
+ totalPages: 0
38
+ });
39
+ // Initialize state change subject
40
+ this._stateChange$ = new Subject();
41
+ // Initialize focus and editing position tracking
42
+ this._focusedCellPosition$ = new BehaviorSubject(null);
43
+ this.focusedCellPosition$ = this._focusedCellPosition$.asObservable();
44
+ this._editingCellPosition$ = new BehaviorSubject(null);
45
+ this.editingCellPosition$ = this._editingCellPosition$.asObservable();
46
+ // Initialize validation state
47
+ this._tableValidationState$ = new BehaviorSubject({
48
+ isValid: true,
49
+ totalRows: 0,
50
+ validRows: 0,
51
+ invalidRows: 0,
52
+ rowStates: new Map(),
53
+ lastUpdated: new Date()
54
+ });
55
+ this.tableValidationState$ = this._tableValidationState$.asObservable();
56
+ this._columnCount = columns.filter(c => c.visible !== false).length;
57
+ // Setup observables
58
+ this.paginationChange$ = this._pagination$.asObservable().pipe(distinctUntilChanged((a, b) => a.currentPage === b.currentPage &&
59
+ a.pageSize === b.pageSize &&
60
+ a.totalItems === b.totalItems));
61
+ this.state$ = this._pagination$.pipe(map(() => this.buildStateSnapshot()));
62
+ this.stateChange$ = this._stateChange$.asObservable();
63
+ // Clear focus/editing on pagination changes
64
+ this.paginationChange$.subscribe(() => {
65
+ this.clearFocus();
66
+ this.clearEditingCell();
67
+ });
68
+ }
69
+ // ============================================================================
70
+ // STATE ACCESS METHODS
71
+ // ============================================================================
72
+ /**
73
+ * Get current state snapshot
74
+ */
75
+ getState() {
76
+ return this.buildStateSnapshot();
77
+ }
78
+ /**
79
+ * Get current pagination state
80
+ */
81
+ getPagination() {
82
+ return { ...this._pagination$.value };
83
+ }
84
+ /**
85
+ * Get columns with sorting enabled
86
+ */
87
+ getSortedColumns() {
88
+ return this._columns.filter(col => col.sortEnabled === true);
89
+ }
90
+ /**
91
+ * Get columns with filtering enabled
92
+ */
93
+ getFilteredColumns() {
94
+ return this._columns.filter(col => col.filterConfig?.enabled === true);
95
+ }
96
+ /**
97
+ * Get current columns reference
98
+ */
99
+ getColumns() {
100
+ return this._columns;
101
+ }
102
+ // ============================================================================
103
+ // PAGINATION METHODS
104
+ // ============================================================================
105
+ /**
106
+ * Set current page
107
+ * @param page Page number (0-indexed)
108
+ */
109
+ setPage(page) {
110
+ const currentState = this._pagination$.value;
111
+ if (page < 0 || page >= currentState.totalPages) {
112
+ console.warn(`Invalid page number: ${page}. Valid range: 0-${currentState.totalPages - 1}`);
113
+ return;
114
+ }
115
+ this._pagination$.next({
116
+ ...currentState,
117
+ currentPage: page
118
+ });
119
+ this.emitStateChange('pagination');
120
+ }
121
+ /**
122
+ * Set page size
123
+ * @param size Number of items per page
124
+ */
125
+ setPageSize(size) {
126
+ if (size <= 0) {
127
+ console.warn(`Invalid page size: ${size}. Must be greater than 0.`);
128
+ return;
129
+ }
130
+ const currentState = this._pagination$.value;
131
+ const newTotalPages = this.calculateTotalPages(currentState.totalItems, size);
132
+ this._pagination$.next({
133
+ currentPage: 0,
134
+ pageSize: size,
135
+ totalItems: currentState.totalItems,
136
+ totalPages: newTotalPages
137
+ });
138
+ this.emitStateChange('pagination');
139
+ }
140
+ /**
141
+ * Set total items (called after API response)
142
+ * @param total Total number of items
143
+ */
144
+ setTotalItems(total) {
145
+ const currentState = this._pagination$.value;
146
+ const newTotalPages = this.calculateTotalPages(total, currentState.pageSize);
147
+ this._pagination$.next({
148
+ ...currentState,
149
+ totalItems: total,
150
+ totalPages: newTotalPages
151
+ });
152
+ // Don't emit state change here - this is called after data load
153
+ }
154
+ /**
155
+ * Go to next page
156
+ */
157
+ nextPage() {
158
+ const currentState = this._pagination$.value;
159
+ if (this.hasNextPage()) {
160
+ this.setPage(currentState.currentPage + 1);
161
+ }
162
+ }
163
+ /**
164
+ * Go to previous page
165
+ */
166
+ previousPage() {
167
+ const currentState = this._pagination$.value;
168
+ if (this.hasPreviousPage()) {
169
+ this.setPage(currentState.currentPage - 1);
170
+ }
171
+ }
172
+ /**
173
+ * Go to first page
174
+ */
175
+ firstPage() {
176
+ this.setPage(0);
177
+ }
178
+ /**
179
+ * Go to last page
180
+ */
181
+ lastPage() {
182
+ const currentState = this._pagination$.value;
183
+ if (currentState.totalPages > 0) {
184
+ this.setPage(currentState.totalPages - 1);
185
+ }
186
+ }
187
+ /**
188
+ * Check if there is a next page
189
+ */
190
+ hasNextPage() {
191
+ const currentState = this._pagination$.value;
192
+ return currentState.currentPage < currentState.totalPages - 1;
193
+ }
194
+ /**
195
+ * Check if there is a previous page
196
+ */
197
+ hasPreviousPage() {
198
+ const currentState = this._pagination$.value;
199
+ return currentState.currentPage > 0;
200
+ }
201
+ // ============================================================================
202
+ // SORTING METHODS (operate on column configs)
203
+ // ============================================================================
204
+ /**
205
+ * Set sort on a column (clears other sorts)
206
+ * @param columnKey Column key
207
+ * @param direction Sort direction
208
+ */
209
+ setSortOnColumn(columnKey, direction) {
210
+ const column = this.findColumn(columnKey);
211
+ if (!column) {
212
+ console.warn(`Column not found: ${columnKey}`);
213
+ return;
214
+ }
215
+ if (column.sortable === false) {
216
+ console.warn(`Column ${columnKey} is not sortable`);
217
+ return;
218
+ }
219
+ // Clear all other sorts
220
+ this._columns.forEach(col => {
221
+ if (col.key !== columnKey) {
222
+ col.sortDirection = SortDirection.NONE;
223
+ col.sortEnabled = false;
224
+ }
225
+ });
226
+ // Set sort on target column
227
+ column.sortDirection = direction;
228
+ column.sortEnabled = direction !== SortDirection.NONE;
229
+ this.emitStateChange('sorting');
230
+ }
231
+ /**
232
+ * Add sort to a column (for multi-column sorting)
233
+ * @param columnKey Column key
234
+ * @param direction Sort direction
235
+ */
236
+ addSortToColumn(columnKey, direction) {
237
+ const column = this.findColumn(columnKey);
238
+ if (!column) {
239
+ console.warn(`Column not found: ${columnKey}`);
240
+ return;
241
+ }
242
+ if (column.sortable === false) {
243
+ console.warn(`Column ${columnKey} is not sortable`);
244
+ return;
245
+ }
246
+ column.sortDirection = direction;
247
+ column.sortEnabled = direction !== SortDirection.NONE;
248
+ this.emitStateChange('sorting');
249
+ }
250
+ /**
251
+ * Toggle sort on a column (cycles through none -> asc -> desc -> none)
252
+ * @param columnKey Column key
253
+ */
254
+ toggleSortOnColumn(columnKey) {
255
+ const column = this.findColumn(columnKey);
256
+ if (!column) {
257
+ console.warn(`Column not found: ${columnKey}`);
258
+ return;
259
+ }
260
+ if (column.sortable === false) {
261
+ console.warn(`Column ${columnKey} is not sortable`);
262
+ return;
263
+ }
264
+ const currentDirection = column.sortDirection || SortDirection.NONE;
265
+ let newDirection;
266
+ switch (currentDirection) {
267
+ case SortDirection.NONE:
268
+ newDirection = SortDirection.ASC;
269
+ break;
270
+ case SortDirection.ASC:
271
+ newDirection = SortDirection.DESC;
272
+ break;
273
+ case SortDirection.DESC:
274
+ newDirection = SortDirection.NONE;
275
+ break;
276
+ default:
277
+ newDirection = SortDirection.ASC;
278
+ }
279
+ column.sortDirection = newDirection;
280
+ column.sortEnabled = newDirection !== SortDirection.NONE;
281
+ this.clearFocus();
282
+ this.clearEditingCell();
283
+ this.emitStateChange('sorting');
284
+ }
285
+ /**
286
+ * Clear all sorting
287
+ */
288
+ clearAllSorting() {
289
+ this._columns.forEach(col => {
290
+ col.sortDirection = SortDirection.NONE;
291
+ col.sortEnabled = false;
292
+ });
293
+ this.clearFocus();
294
+ this.clearEditingCell();
295
+ this.emitStateChange('sorting');
296
+ }
297
+ /**
298
+ * Get sort configuration for a column
299
+ * @param columnKey Column key
300
+ * @returns Sort configuration or null
301
+ */
302
+ getSortForColumn(columnKey) {
303
+ const column = this.findColumn(columnKey);
304
+ if (!column) {
305
+ return null;
306
+ }
307
+ return {
308
+ direction: column.sortDirection || SortDirection.NONE,
309
+ enabled: column.sortEnabled || false
310
+ };
311
+ }
312
+ // ============================================================================
313
+ // FILTERING METHODS (operate on column configs)
314
+ // ============================================================================
315
+ /**
316
+ * Set filter on a column
317
+ * @param columnKey Column key
318
+ * @param operator Filter operator
319
+ * @param value Filter value
320
+ */
321
+ setFilterOnColumn(columnKey, operator, value) {
322
+ const column = this.findColumn(columnKey);
323
+ if (!column) {
324
+ console.warn(`Column not found: ${columnKey}`);
325
+ return;
326
+ }
327
+ if (column.filterable === false) {
328
+ console.warn(`Column ${columnKey} is not filterable`);
329
+ return;
330
+ }
331
+ // Initialize filterConfig if it doesn't exist
332
+ if (!column.filterConfig) {
333
+ column.filterConfig = {};
334
+ }
335
+ column.filterConfig.operator = operator;
336
+ column.filterConfig.value = value;
337
+ column.filterConfig.enabled = true;
338
+ this.clearFocus();
339
+ this.clearEditingCell();
340
+ this.emitStateChange('filtering');
341
+ }
342
+ /**
343
+ * Clear filter on a column
344
+ * @param columnKey Column key
345
+ */
346
+ clearFilterOnColumn(columnKey) {
347
+ const column = this.findColumn(columnKey);
348
+ if (!column) {
349
+ console.warn(`Column not found: ${columnKey}`);
350
+ return;
351
+ }
352
+ // Initialize filterConfig if it doesn't exist (for consistency with setFilterOnColumn)
353
+ if (!column.filterConfig) {
354
+ column.filterConfig = {};
355
+ }
356
+ column.filterConfig.value = undefined;
357
+ column.filterConfig.enabled = false;
358
+ this.clearFocus();
359
+ this.clearEditingCell();
360
+ this.emitStateChange('filtering');
361
+ }
362
+ /**
363
+ * Clear all filters
364
+ */
365
+ clearAllFilters() {
366
+ this._columns.forEach(col => {
367
+ // Initialize filterConfig if it doesn't exist (for consistency with setFilterOnColumn)
368
+ if (!col.filterConfig) {
369
+ col.filterConfig = {};
370
+ }
371
+ col.filterConfig.value = undefined;
372
+ col.filterConfig.enabled = false;
373
+ });
374
+ this.clearFocus();
375
+ this.clearEditingCell();
376
+ this.emitStateChange('filtering');
377
+ }
378
+ /**
379
+ * Set filter enabled state
380
+ * @param columnKey Column key
381
+ * @param enabled Whether filter is enabled
382
+ */
383
+ setFilterEnabled(columnKey, enabled) {
384
+ const column = this.findColumn(columnKey);
385
+ if (!column) {
386
+ console.warn(`Column not found: ${columnKey}`);
387
+ return;
388
+ }
389
+ // Initialize filterConfig if it doesn't exist
390
+ if (!column.filterConfig) {
391
+ column.filterConfig = {};
392
+ }
393
+ column.filterConfig.enabled = enabled;
394
+ this.emitStateChange('filtering');
395
+ }
396
+ /**
397
+ * Get filter configuration for a column
398
+ * @param columnKey Column key
399
+ * @returns Filter configuration or null
400
+ */
401
+ getFilterForColumn(columnKey) {
402
+ const column = this.findColumn(columnKey);
403
+ if (!column) {
404
+ return null;
405
+ }
406
+ return {
407
+ operator: column.filterConfig?.operator || FilterOperator.CONTAINS,
408
+ value: column.filterConfig?.value,
409
+ enabled: column.filterConfig?.enabled || false
410
+ };
411
+ }
412
+ // ============================================================================
413
+ // STICKY COLUMN MANAGEMENT
414
+ // ============================================================================
415
+ /**
416
+ * Get sticky columns grouped by position
417
+ * @returns Object with left and right sticky column keys
418
+ */
419
+ getStickyColumns() {
420
+ const left = this._columns
421
+ .filter(col => col.sticky === 'left')
422
+ .map(col => col.key);
423
+ const right = this._columns
424
+ .filter(col => col.sticky === 'right')
425
+ .map(col => col.key);
426
+ return { left, right };
427
+ }
428
+ /**
429
+ * Set sticky position for a column
430
+ * @param columnKey Column key
431
+ * @param position Sticky position ('left', 'right', or false)
432
+ */
433
+ setStickyColumn(columnKey, position) {
434
+ const column = this.findColumn(columnKey);
435
+ if (!column) {
436
+ console.warn(`Column not found: ${columnKey}`);
437
+ return;
438
+ }
439
+ column.sticky = position;
440
+ this.calculateStickyOffsets();
441
+ this.emitStateChange('column-config');
442
+ }
443
+ /**
444
+ * Calculate sticky offsets for all sticky columns
445
+ * This calculates cumulative widths for positioning
446
+ * @param rowNumberWidth Optional width of row number column to account for in left offset
447
+ * @param settingsColumnWidth Optional width of settings column to account for in right offset
448
+ */
449
+ calculateStickyOffsets(rowNumberWidth, settingsColumnWidth) {
450
+ // Update stored row number width if provided
451
+ if (rowNumberWidth !== undefined) {
452
+ this._rowNumberWidth = rowNumberWidth;
453
+ }
454
+ // Update stored settings column width if provided
455
+ if (settingsColumnWidth !== undefined) {
456
+ this._settingsColumnWidth = settingsColumnWidth;
457
+ }
458
+ // Calculate left sticky offsets
459
+ // Account for row number column width
460
+ let leftOffset = this._rowNumberWidth;
461
+ this._columns.forEach(col => {
462
+ if (col.sticky === 'left') {
463
+ col.stickyOffset = leftOffset;
464
+ leftOffset += col.width || 100;
465
+ }
466
+ });
467
+ // Calculate right sticky offsets
468
+ // Account for settings column width (row actions column)
469
+ let rightOffset = this._settingsColumnWidth;
470
+ for (let i = this._columns.length - 1; i >= 0; i--) {
471
+ const col = this._columns[i];
472
+ if (col.sticky === 'right') {
473
+ col.stickyOffset = rightOffset;
474
+ rightOffset += col.width || 100;
475
+ }
476
+ }
477
+ }
478
+ // ============================================================================
479
+ // COLUMN MANAGEMENT
480
+ // ============================================================================
481
+ /**
482
+ * Update columns reference
483
+ * @param columns New columns array
484
+ */
485
+ updateColumns(columns) {
486
+ this._columns = columns;
487
+ this.calculateStickyOffsets();
488
+ this.emitStateChange('column-config');
489
+ }
490
+ // ============================================================================
491
+ // COLUMN VISIBILITY METHODS
492
+ // ============================================================================
493
+ /**
494
+ * Toggle visibility of a column
495
+ * @param columnKey Column key
496
+ */
497
+ toggleColumnVisibility(columnKey) {
498
+ const column = this.findColumn(columnKey);
499
+ if (!column) {
500
+ console.warn(`Column not found: ${columnKey}`);
501
+ return;
502
+ }
503
+ // Check if column is hideable
504
+ if (column.hideable === false) {
505
+ console.warn(`Column ${columnKey} cannot be hidden (hideable is false)`);
506
+ return;
507
+ }
508
+ const currentVisibility = column.visible !== false; // Default to true if not set
509
+ column.visible = !currentVisibility;
510
+ this.emitStateChange('column-visibility');
511
+ }
512
+ /**
513
+ * Set visibility of a column
514
+ * @param columnKey Column key
515
+ * @param visible Whether column should be visible
516
+ */
517
+ setColumnVisibility(columnKey, visible) {
518
+ const column = this.findColumn(columnKey);
519
+ if (!column) {
520
+ console.warn(`Column not found: ${columnKey}`);
521
+ return;
522
+ }
523
+ // Check if column is hideable (only when trying to hide)
524
+ if (!visible && column.hideable === false) {
525
+ console.warn(`Column ${columnKey} cannot be hidden (hideable is false)`);
526
+ return;
527
+ }
528
+ column.visible = visible;
529
+ this.emitStateChange('column-visibility');
530
+ }
531
+ /**
532
+ * Get all visible columns
533
+ * @returns Array of visible column configs
534
+ */
535
+ getVisibleColumns() {
536
+ return this._columns.filter(col => col.visible !== false); // Default to true if not set
537
+ }
538
+ /**
539
+ * Get visibility state for all columns
540
+ * @returns Array of column visibility info
541
+ */
542
+ getAllColumnsVisibility() {
543
+ return this._columns.map(col => ({
544
+ key: col.key,
545
+ header: col.header || col.key,
546
+ visible: col.visible !== false,
547
+ hideable: col.hideable !== false // Default to true if not set
548
+ }));
549
+ }
550
+ // ============================================================================
551
+ // KEYBOARD NAVIGATION & FOCUS MANAGEMENT
552
+ // ============================================================================
553
+ /**
554
+ * Set table dimensions for navigation boundaries
555
+ */
556
+ setDimensions(rowCount, columnCount) {
557
+ this._rowCount = rowCount;
558
+ this._columnCount = columnCount;
559
+ // Update total rows in validation state
560
+ this.setValidationRowCount(rowCount);
561
+ }
562
+ /**
563
+ * Focus a cell by position
564
+ */
565
+ focusCell(rowIndex, columnIndex) {
566
+ if (rowIndex < 0 || rowIndex >= this._rowCount)
567
+ return;
568
+ if (columnIndex < 0 || columnIndex >= this._columnCount)
569
+ return;
570
+ this._focusedCellPosition$.next({ rowIndex, columnIndex });
571
+ this.emitStateChange('cell-focus');
572
+ }
573
+ /**
574
+ * Get currently focused position
575
+ */
576
+ getFocusedPosition() {
577
+ return this._focusedCellPosition$.value;
578
+ }
579
+ /**
580
+ * Notify that a cell entered edit mode
581
+ */
582
+ setEditingCell(rowIndex, columnIndex) {
583
+ this._editingCellPosition$.next({ rowIndex, columnIndex });
584
+ this.emitStateChange('cell-edit-start');
585
+ }
586
+ /**
587
+ * Notify that edit mode ended
588
+ */
589
+ clearEditingCell() {
590
+ this._editingCellPosition$.next(null);
591
+ this.emitStateChange('cell-edit-end');
592
+ }
593
+ /**
594
+ * Check if any cell is currently editing
595
+ */
596
+ isAnyCellEditing() {
597
+ return this._editingCellPosition$.value !== null;
598
+ }
599
+ /**
600
+ * Get currently editing position
601
+ */
602
+ getEditingPosition() {
603
+ return this._editingCellPosition$.value;
604
+ }
605
+ /**
606
+ * Move focus in a direction using NavigationDirection enum
607
+ */
608
+ moveFocus(direction) {
609
+ // Block navigation if any cell is editing
610
+ if (this.isAnyCellEditing()) {
611
+ return false;
612
+ }
613
+ const current = this._focusedCellPosition$.value;
614
+ if (!current)
615
+ return false;
616
+ let newRow = current.rowIndex;
617
+ let newCol = current.columnIndex;
618
+ // Use NavigationDirection enum values
619
+ switch (direction) {
620
+ case NavigationDirection.UP:
621
+ newRow--;
622
+ break;
623
+ case NavigationDirection.DOWN:
624
+ newRow++;
625
+ break;
626
+ case NavigationDirection.LEFT:
627
+ newCol--;
628
+ break;
629
+ case NavigationDirection.RIGHT:
630
+ newCol++;
631
+ break;
632
+ }
633
+ if (newRow < 0 || newRow >= this._rowCount)
634
+ return false;
635
+ if (newCol < 0 || newCol >= this._columnCount)
636
+ return false;
637
+ this.focusCell(newRow, newCol);
638
+ return true;
639
+ }
640
+ /**
641
+ * Clear focus
642
+ */
643
+ clearFocus() {
644
+ this._focusedCellPosition$.next(null);
645
+ this.emitStateChange('cell-focus');
646
+ }
647
+ /**
648
+ * Check if navigation is active
649
+ */
650
+ isNavigationActive() {
651
+ return this._focusedCellPosition$.value !== null;
652
+ }
653
+ // ============================================================================
654
+ // VALIDATION STATE METHODS
655
+ // ============================================================================
656
+ /**
657
+ * Update cell validation and accumulate into row/table validation state
658
+ * Only stores invalid states - valid rows are automatically removed
659
+ */
660
+ updateCellValidation(rowIndex, columnKey, isValid, error) {
661
+ const currentState = this._tableValidationState$.value;
662
+ const rowStates = new Map(currentState.rowStates);
663
+ // Get existing row state (only exists if row has errors)
664
+ let rowState = rowStates.get(rowIndex);
665
+ if (!isValid && error) {
666
+ // Cell is invalid - add or update error
667
+ if (!rowState) {
668
+ // Create new row state for this invalid row
669
+ rowState = {
670
+ rowIndex,
671
+ isValid: false,
672
+ invalidCellCount: 1,
673
+ cellErrors: new Map([[columnKey, error]]),
674
+ lastValidated: new Date()
675
+ };
676
+ }
677
+ else {
678
+ // Update existing row state
679
+ const cellErrors = new Map(rowState.cellErrors);
680
+ cellErrors.set(columnKey, error);
681
+ rowState = {
682
+ rowIndex,
683
+ isValid: false,
684
+ invalidCellCount: cellErrors.size,
685
+ cellErrors,
686
+ lastValidated: new Date()
687
+ };
688
+ }
689
+ rowStates.set(rowIndex, rowState);
690
+ }
691
+ else {
692
+ // Cell is valid - remove error if it exists
693
+ if (rowState) {
694
+ const cellErrors = new Map(rowState.cellErrors);
695
+ cellErrors.delete(columnKey);
696
+ if (cellErrors.size === 0) {
697
+ // No more errors in this row - remove row state completely
698
+ rowStates.delete(rowIndex);
699
+ }
700
+ else {
701
+ // Still has other errors - update row state
702
+ rowState = {
703
+ rowIndex,
704
+ isValid: false,
705
+ invalidCellCount: cellErrors.size,
706
+ cellErrors,
707
+ lastValidated: new Date()
708
+ };
709
+ rowStates.set(rowIndex, rowState);
710
+ }
711
+ }
712
+ // If rowState doesn't exist, cell was already valid - do nothing
713
+ }
714
+ // Recalculate table state
715
+ // All rows in rowStates map are invalid by definition
716
+ const invalidRows = rowStates.size;
717
+ const newTableState = {
718
+ isValid: invalidRows === 0,
719
+ totalRows: currentState.totalRows,
720
+ validRows: currentState.totalRows - invalidRows,
721
+ invalidRows,
722
+ rowStates,
723
+ lastUpdated: new Date()
724
+ };
725
+ // Emit new state
726
+ this._tableValidationState$.next(newTableState);
727
+ }
728
+ /**
729
+ * Get current table validation state
730
+ */
731
+ getTableValidationState() {
732
+ return this._tableValidationState$.value;
733
+ }
734
+ /**
735
+ * Set total rows for validation state tracking
736
+ */
737
+ setValidationRowCount(totalRows) {
738
+ const currentState = this._tableValidationState$.value;
739
+ this._tableValidationState$.next({
740
+ ...currentState,
741
+ totalRows,
742
+ lastUpdated: new Date()
743
+ });
744
+ }
745
+ // ============================================================================
746
+ // STATE RESET
747
+ // ============================================================================
748
+ /**
749
+ * Reset to initial configuration
750
+ */
751
+ reset() {
752
+ this.resetPagination();
753
+ this.resetAllSorting();
754
+ this.resetAllFilters();
755
+ }
756
+ /**
757
+ * Reset pagination only
758
+ */
759
+ resetPagination() {
760
+ this._pagination$.next({
761
+ currentPage: this._initialConfig.initialPage,
762
+ pageSize: this._initialConfig.pageSize,
763
+ totalItems: 0,
764
+ totalPages: 0
765
+ });
766
+ this.emitStateChange('pagination');
767
+ }
768
+ /**
769
+ * Reset all column sorts
770
+ */
771
+ resetAllSorting() {
772
+ this.clearAllSorting();
773
+ }
774
+ /**
775
+ * Reset all column filters
776
+ */
777
+ resetAllFilters() {
778
+ this.clearAllFilters();
779
+ }
780
+ // ============================================================================
781
+ // INTERNAL METHODS
782
+ // ============================================================================
783
+ /**
784
+ * Find a column by key
785
+ * @param columnKey Column key
786
+ * @returns Column config or undefined
787
+ */
788
+ findColumn(columnKey) {
789
+ return this._columns.find(col => col.key === columnKey);
790
+ }
791
+ /**
792
+ * Calculate total pages
793
+ * @param totalItems Total number of items
794
+ * @param pageSize Page size
795
+ * @returns Total number of pages
796
+ */
797
+ calculateTotalPages(totalItems = 0, pageSize = 25) {
798
+ if (totalItems === 0 || pageSize === 0) {
799
+ return 0;
800
+ }
801
+ return Math.ceil(totalItems / pageSize);
802
+ }
803
+ /**
804
+ * Emit state change event
805
+ * @param type Type of change
806
+ */
807
+ emitStateChange(type) {
808
+ const state = this.buildStateSnapshot();
809
+ this._stateChange$.next({
810
+ type,
811
+ state
812
+ });
813
+ }
814
+ /**
815
+ * Build state snapshot from current state
816
+ * @returns State snapshot
817
+ */
818
+ buildStateSnapshot() {
819
+ return {
820
+ pagination: this.getPagination(),
821
+ // Build full sort state with direction and priority
822
+ sortedColumns: this._columns
823
+ .filter(col => col.sortEnabled === true)
824
+ .map((col, index) => ({
825
+ columnKey: col.key,
826
+ direction: col.sortDirection || SortDirection.NONE,
827
+ priority: index // Sort order based on enablement order
828
+ })),
829
+ // Build full filter state with operator and value
830
+ filteredColumns: this._columns
831
+ .filter(col => col.filterConfig?.enabled === true)
832
+ .map(col => ({
833
+ columnKey: col.key,
834
+ operator: col.filterConfig?.operator || FilterOperator.CONTAINS,
835
+ value: col.filterConfig?.value,
836
+ enabled: true
837
+ }))
838
+ };
839
+ }
840
+ }
841
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtc3RhdGUuY2xhc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zbWFydC10YWJsZS9zcmMvbGliL3JlbmRlcmVyL21vZGVscy90YWJsZS1zdGF0ZS5jbGFzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsZUFBZSxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM1RCxPQUFPLEVBQUUsR0FBRyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0QsT0FBTyxFQUVMLGFBQWEsRUFDYixjQUFjLEVBSWYsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFJOUQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFrRHJCOzs7O09BSUc7SUFDSCxZQUFZLE9BQTRCLEVBQUUsTUFBeUI7UUExQ25FLHdEQUF3RDtRQUNoRCxvQkFBZSxHQUFXLENBQUMsQ0FBQztRQUVwQyxzREFBc0Q7UUFDOUMseUJBQW9CLEdBQVcsQ0FBQyxDQUFDO1FBY3pDLG1DQUFtQztRQUMzQixjQUFTLEdBQVcsQ0FBQyxDQUFDO1FBQ3RCLGlCQUFZLEdBQVcsQ0FBQyxDQUFDO1FBdUIvQixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQztRQUN4QixJQUFJLENBQUMsY0FBYyxHQUFHO1lBQ3BCLFdBQVcsRUFBRSxNQUFNLEVBQUUsV0FBVyxJQUFJLENBQUM7WUFDckMsUUFBUSxFQUFFLE1BQU0sRUFBRSxRQUFRLElBQUksRUFBRTtTQUNqQyxDQUFDO1FBRUYsOEJBQThCO1FBQzlCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxlQUFlLENBQWtCO1lBQ3ZELFdBQVcsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVk7WUFDN0MsUUFBUSxFQUFFLElBQUksQ0FBQyxjQUFjLENB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LENBQUMsSUFBSSxDQUFDO1lBQ3RCLElBQUk7WUFDSixLQUFLO1NBQ04sQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNLLGtCQUFrQjtRQUN4QixPQUFPO1lBQ0wsVUFBVSxFQUFFLElBQUksQ0FBQyxhQUFhLEVBQUU7WUFFaEMsb0RBQW9EO1lBQ3BELGFBQWEsRUFBRSxJQUFJLENBQUMsUUFBUTtpQkFDekIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFdBQVcsS0FBSyxJQUFJLENBQUM7aUJBQ3ZDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ3BCLFNBQVMsRUFBRSxHQUFHLENBQUMsR0FBRztnQkFDbEIsU0FBUyxFQUFFLEdBQUcsQ0FBQyxhQUFhLElBQUksYUFBYSxDQUFDLElBQUk7Z0JBQ2xELFFBQVEsRUFBRSxLQUFLLENBQUUsdUNBQXVDO2FBQ3pELENBQUMsQ0FBQztZQUVMLGtEQUFrRDtZQUNsRCxlQUFlLEVBQUUsSUFBSSxDQUFDLFFBQVE7aUJBQzNCLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsT0FBTyxLQUFLLElBQUksQ0FBQztpQkFDakQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDWCxTQUFTLEVBQUUsR0FBRyxDQUFDLEdBQUc7Z0JBQ2xCLFFBQVEsRUFBRSxHQUFHLENBQUMsWUFBWSxFQUFFLFFBQVEsSUFBSSxjQUFjLENBQUMsUUFBUTtnQkFDL0QsS0FBSyxFQUFFLEdBQUcsQ0FBQyxZQUFZLEVBQUUsS0FBSztnQkFDOUIsT0FBTyxFQUFFLElBQUk7YUFDZCxDQUFDLENBQUM7U0FDTixDQUFDO0lBQ0osQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUYWJsZVN0YXRlIC0gUmVhY3RpdmUgc3RhdGUgbWFuYWdlbWVudCBmb3IgdGFibGUgb3BlcmF0aW9uc1xuICogRXZlbnQtZHJpdmVuIGFyY2hpdGVjdHVyZTogdHJhY2tzIHN0YXRlLCBlbWl0cyBldmVudHMsIGNvbnN1bWVyIGhhbmRsZXMgYXN5bmMgZGF0YSBvcGVyYXRpb25zXG4gKi9cblxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAsIGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQ29sdW1uQ29uZmlnIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2NvbHVtbi1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IFxuICBQYWdpbmF0aW9uU3RhdGUsIFxuICBTb3J0RGlyZWN0aW9uLCBcbiAgRmlsdGVyT3BlcmF0b3IsXG4gIFRhYmxlU3RhdGVDaGFuZ2VFdmVudCxcbiAgVGFibGVTdGF0ZVNuYXBzaG90LFxuICBDZWxsRm9jdXNQb3NpdGlvblxufSBmcm9tICcuL3RhYmxlLXR5cGVzJztcbmltcG9ydCB7IFRhYmxlU3RhdGVDb25maWcgfSBmcm9tICcuL3RhYmxlLXN0YXRlLmludGVyZmFjZSc7XG5pbXBvcnQgeyBOYXZpZ2F0aW9uRGlyZWN0aW9uIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2NlbGwtdHlwZXMnO1xuaW1wb3J0IHsgUm93VmFsaWRhdGlvblN0YXRlIH0gZnJvbSAnLi9yb3ctdmFsaWRhdGlvbi1zdGF0ZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgVGFibGVWYWxpZGF0aW9uU3RhdGUgfSBmcm9tICcuL3RhYmxlLXZhbGlkYXRpb24tc3RhdGUuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBUYWJsZVN0YXRlIGNsYXNzIC0gQ29sdW1uLWRyaXZlbiwgZXZlbnQtZW1pdHRpbmcgc3RhdGUgbWFuYWdlbWVudFxuICogTk8gZGF0YSBtYW5pcHVsYXRpb24gLSBvbmx5IHN0YXRlIHRyYWNraW5nIGFuZCBldmVudCBlbWlzc2lvblxuICovXG5leHBvcnQgY2xhc3MgVGFibGVTdGF0ZSB7XG4gIC8vIFJlZmVyZW5jZSB0byBjb2x1bW5zIGFycmF5IChjb2x1bW4tZHJpdmVuIGFyY2hpdGVjdHVyZSlcbiAgcHJpdmF0ZSBfY29sdW1uczogQ29sdW1uQ29uZmlnPGFueT5bXTtcbiAgXG4gIC8vIFBhZ2luYXRpb24gc3RhdGVcbiAgcHJpdmF0ZSBfcGFnaW5hdGlvbiQ6IEJlaGF2aW9yU3ViamVjdDxQYWdpbmF0aW9uU3RhdGU+O1xuICBcbiAgLy8gU3RhdGUgY2hhbmdlIGV2ZW50c1xuICBwcml2YXRlIF9zdGF0ZUNoYW5nZSQ6IFN1YmplY3Q8VGFibGVTdGF0ZUNoYW5nZUV2ZW50PjtcbiAgXG4gIC8vIEluaXRpYWwgY29uZmlndXJhdGlvblxuICBwcml2YXRlIF9pbml0aWFsQ29uZmlnOiBUYWJsZVN0YXRlQ29uZmlnO1xuICBcbiAgLy8gUm93IG51bWJlciBjb2x1bW4gd2lkdGggZm9yIHN0aWNreSBvZmZzZXQgY2FsY3VsYXRpb25cbiAgcHJpdmF0ZSBfcm93TnVtYmVyV2lkdGg6IG51bWJlciA9IDA7XG5cbiAgLy8gU2V0dGluZ3MgY29sdW1uIHdpZHRoIGZvciBzdGlja3kgb2Zmc2V0IGNhbGN1bGF0aW9uXG4gIHByaXZhdGUgX3NldHRpbmdzQ29sdW1uV2lkdGg6IG51bWJlciA9IDA7XG4gIFxuICAvLyBGb2N1cyBwb3NpdGlvbiB0cmFja2luZ1xuICBwcml2YXRlIF9mb2N1c2VkQ2VsbFBvc2l0aW9uJDogQmVoYXZpb3JTdWJqZWN0PENlbGxGb2N1c1Bvc2l0aW9uIHwgbnVsbD47XG4gIHB1YmxpYyByZWFkb25seSBmb2N1c2VkQ2VsbFBvc2l0aW9uJDogT2JzZXJ2YWJsZTxDZWxsRm9jdXNQb3NpdGlvbiB8IG51bGw+O1xuICBcbiAgLy8gRWRpdGluZyBwb3NpdGlvbiB0cmFja2luZ1xuICBwcml2YXRlIF9lZGl0aW5nQ2VsbFBvc2l0aW9uJDogQmVoYXZpb3JTdWJqZWN0PENlbGxGb2N1c1Bvc2l0aW9uIHwgbnVsbD47XG4gIHB1YmxpYyByZWFkb25seSBlZGl0aW5nQ2VsbFBvc2l0aW9uJDogT2JzZXJ2YWJsZTxDZWxsRm9jdXNQb3NpdGlvbiB8IG51bGw+O1xuICBcbiAgLy8gVmFsaWRhdGlvbiBzdGF0ZSB0cmFja2luZ1xuICBwcml2YXRlIF90YWJsZVZhbGlkYXRpb25TdGF0ZSQ6IEJlaGF2aW9yU3ViamVjdDxUYWJsZVZhbGlkYXRpb25TdGF0ZT47XG4gIHB1YmxpYyByZWFkb25seSB0YWJsZVZhbGlkYXRpb25TdGF0ZSQ6IE9ic2VydmFibGU8VGFibGVWYWxpZGF0aW9uU3RhdGU+O1xuICBcbiAgLy8gRGltZW5zaW9ucyBmb3IgYm91bmRhcnkgY2hlY2tpbmdcbiAgcHJpdmF0ZSBfcm93Q291bnQ6IG51bWJlciA9IDA7XG4gIHByaXZhdGUgX2NvbHVtbkNvdW50OiBudW1iZXIgPSAwO1xuXG4gIC8qKlxuICAgKiBPYnNlcnZhYmxlIG9mIGNvbXBsZXRlIHN0YXRlIHNuYXBzaG90XG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc3RhdGUkOiBPYnNlcnZhYmxlPFRhYmxlU3RhdGVTbmFwc2hvdD47XG5cbiAgLyoqXG4gICAqIE9ic2VydmFibGUgb2Ygc3RhdGUgY2hhbmdlIGV2ZW50c1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHN0YXRlQ2hhbmdlJDogT2JzZXJ2YWJsZTxUYWJsZVN0YXRlQ2hhbmdlRXZlbnQ+O1xuXG4gIC8qKlxuICAgKiBPYnNlcnZhYmxlIG9mIHBhZ2luYXRpb24gc3RhdGUgY2hhbmdlc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBhZ2luYXRpb25DaGFuZ2UkOiBPYnNlcnZhYmxlPFBhZ2luYXRpb25TdGF0ZT47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSBjb2x1bW5zIFJlZmVyZW5jZSB0byBjb2x1bW5zIGFycmF5XG4gICAqIEBwYXJhbSBjb25maWcgSW5pdGlhbCBjb25maWd1cmF0aW9uXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihjb2x1bW5zOiBDb2x1bW5Db25maWc8YW55PltdLCBjb25maWc/OiBUYWJsZVN0YXRlQ29uZmlnKSB7XG4gICAgdGhpcy5fY29sdW1ucyA9IGNvbHVtbnM7XG4gICAgdGhpcy5faW5pdGlhbENvbmZpZyA9IHtcbiAgICAgIGluaXRpYWxQYWdlOiBjb25maWc/LmluaXRpYWxQYWdlID8/IDAsXG4gICAgICBwYWdlU2l6ZTogY29uZmlnPy5wYWdlU2l6ZSA/PyAyNVxuICAgIH07XG5cbiAgICAvLyBJbml0aWFsaXplIHBhZ2luYXRpb24gc3RhdGVcbiAgICB0aGlzLl9wYWdpbmF0aW9uJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8UGFnaW5hdGlvblN0YXRlPih7XG4gICAgICBjdXJyZW50UGFnZTogdGhpcy5faW5pdGlhbENvbmZpZy5pbml0aWFsUGFnZSEsXG4gICAgICBwYWdlU2l6ZTogdGhpcy5faW5pdGlhbENvbmZpZy5wYWdlU2l6ZSEsXG4gICAgICB0b3RhbEl0ZW1zOiAwLFxuICAgICAgdG90YWxQYWdlczogMFxuICAgIH0pO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzdGF0ZSBjaGFuZ2Ugc3ViamVjdFxuICAgIHRoaXMuX3N0YXRlQ2hhbmdlJCA9IG5ldyBTdWJqZWN0PFRhYmxlU3RhdGVDaGFuZ2VFdmVudD4oKTtcbiAgICBcbiAgICAvLyBJbml0aWFsaXplIGZvY3VzIGFuZCBlZGl0aW5nIHBvc2l0aW9uIHRyYWNraW5nXG4gICAgdGhpcy5fZm9jdXNlZENlbGxQb3NpdGlvbiQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PENlbGxGb2N1c1Bvc2l0aW9uIHwgbnVsbD4obnVsbCk7XG4gICAgdGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uJCA9IHRoaXMuX2ZvY3VzZWRDZWxsUG9zaXRpb24kLmFzT2JzZXJ2YWJsZSgpO1xuICAgIFxuICAgIHRoaXMuX2VkaXRpbmdDZWxsUG9zaXRpb24kID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDZWxsRm9jdXNQb3NpdGlvbiB8IG51bGw+KG51bGwpO1xuICAgIHRoaXMuZWRpdGluZ0NlbGxQb3NpdGlvbiQgPSB0aGlzLl9lZGl0aW5nQ2VsbFBvc2l0aW9uJC5hc09ic2VydmFibGUoKTtcbiAgICBcbiAgICAvLyBJbml0aWFsaXplIHZhbGlkYXRpb24gc3RhdGVcbiAgICB0aGlzLl90YWJsZVZhbGlkYXRpb25TdGF0ZSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFRhYmxlVmFsaWRhdGlvblN0YXRlPih7XG4gICAgICBpc1ZhbGlkOiB0cnVlLFxuICAgICAgdG90YWxSb3dzOiAwLFxuICAgICAgdmFsaWRSb3dzOiAwLFxuICAgICAgaW52YWxpZFJvd3M6IDAsXG4gICAgICByb3dTdGF0ZXM6IG5ldyBNYXAoKSxcbiAgICAgIGxhc3RVcGRhdGVkOiBuZXcgRGF0ZSgpXG4gICAgfSk7XG4gICAgdGhpcy50YWJsZVZhbGlkYXRpb25TdGF0ZSQgPSB0aGlzLl90YWJsZVZhbGlkYXRpb25TdGF0ZSQuYXNPYnNlcnZhYmxlKCk7XG4gICAgXG4gICAgdGhpcy5fY29sdW1uQ291bnQgPSBjb2x1bW5zLmZpbHRlcihjID0+IGMudmlzaWJsZSAhPT0gZmFsc2UpLmxlbmd0aDtcblxuICAgIC8vIFNldHVwIG9ic2VydmFibGVzXG4gICAgdGhpcy5wYWdpbmF0aW9uQ2hhbmdlJCA9IHRoaXMuX3BhZ2luYXRpb24kLmFzT2JzZXJ2YWJsZSgpLnBpcGUoXG4gICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgoYSwgYikgPT4gXG4gICAgICAgIGEuY3VycmVudFBhZ2UgPT09IGIuY3VycmVudFBhZ2UgJiYgXG4gICAgICAgIGEucGFnZVNpemUgPT09IGIucGFnZVNpemUgJiZcbiAgICAgICAgYS50b3RhbEl0ZW1zID09PSBiLnRvdGFsSXRlbXNcbiAgICAgIClcbiAgICApO1xuXG4gICAgdGhpcy5zdGF0ZSQgPSB0aGlzLl9wYWdpbmF0aW9uJC5waXBlKFxuICAgICAgbWFwKCgpID0+IHRoaXMuYnVpbGRTdGF0ZVNuYXBzaG90KCkpXG4gICAgKTtcblxuICAgIHRoaXMuc3RhdGVDaGFuZ2UkID0gdGhpcy5fc3RhdGVDaGFuZ2UkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIFxuICAgIC8vIENsZWFyIGZvY3VzL2VkaXRpbmcgb24gcGFnaW5hdGlvbiBjaGFuZ2VzXG4gICAgdGhpcy5wYWdpbmF0aW9uQ2hhbmdlJC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5jbGVhckZvY3VzKCk7XG4gICAgICB0aGlzLmNsZWFyRWRpdGluZ0NlbGwoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gU1RBVEUgQUNDRVNTIE1FVEhPRFNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBHZXQgY3VycmVudCBzdGF0ZSBzbmFwc2hvdFxuICAgKi9cbiAgZ2V0U3RhdGUoKTogVGFibGVTdGF0ZVNuYXBzaG90IHtcbiAgICByZXR1cm4gdGhpcy5idWlsZFN0YXRlU25hcHNob3QoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY3VycmVudCBwYWdpbmF0aW9uIHN0YXRlXG4gICAqL1xuICBnZXRQYWdpbmF0aW9uKCk6IFBhZ2luYXRpb25TdGF0ZSB7XG4gICAgcmV0dXJuIHsgLi4udGhpcy5fcGFnaW5hdGlvbiQudmFsdWUgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY29sdW1ucyB3aXRoIHNvcnRpbmcgZW5hYmxlZFxuICAgKi9cbiAgZ2V0U29ydGVkQ29sdW1ucygpOiBDb2x1bW5Db25maWc8YW55PltdIHtcbiAgICByZXR1cm4gdGhpcy5fY29sdW1ucy5maWx0ZXIoY29sID0+IGNvbC5zb3J0RW5hYmxlZCA9PT0gdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNvbHVtbnMgd2l0aCBmaWx0ZXJpbmcgZW5hYmxlZFxuICAgKi9cbiAgZ2V0RmlsdGVyZWRDb2x1bW5zKCk6IENvbHVtbkNvbmZpZzxhbnk+W10ge1xuICAgIHJldHVybiB0aGlzLl9jb2x1bW5zLmZpbHRlcihjb2wgPT4gY29sLmZpbHRlckNvbmZpZz8uZW5hYmxlZCA9PT0gdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGN1cnJlbnQgY29sdW1ucyByZWZlcmVuY2VcbiAgICovXG4gIGdldENvbHVtbnMoKTogQ29sdW1uQ29uZmlnPGFueT5bXSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbHVtbnM7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFBBR0lOQVRJT04gTUVUSE9EU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIFNldCBjdXJyZW50IHBhZ2VcbiAgICogQHBhcmFtIHBhZ2UgUGFnZSBudW1iZXIgKDAtaW5kZXhlZClcbiAgICovXG4gIHNldFBhZ2UocGFnZTogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy5fcGFnaW5hdGlvbiQudmFsdWU7XG4gICAgaWYgKHBhZ2UgPCAwIHx8IHBhZ2UgPj0gY3VycmVudFN0YXRlLnRvdGFsUGFnZXMpIHtcbiAgICAgIGNvbnNvbGUud2FybihgSW52YWxpZCBwYWdlIG51bWJlcjogJHtwYWdlfS4gVmFsaWQgcmFuZ2U6IDAtJHtjdXJyZW50U3RhdGUudG90YWxQYWdlcyAtIDF9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fcGFnaW5hdGlvbiQubmV4dCh7XG4gICAgICAuLi5jdXJyZW50U3RhdGUsXG4gICAgICBjdXJyZW50UGFnZTogcGFnZVxuICAgIH0pO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdwYWdpbmF0aW9uJyk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHBhZ2Ugc2l6ZVxuICAgKiBAcGFyYW0gc2l6ZSBOdW1iZXIgb2YgaXRlbXMgcGVyIHBhZ2VcbiAgICovXG4gIHNldFBhZ2VTaXplKHNpemU6IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChzaXplIDw9IDApIHtcbiAgICAgIGNvbnNvbGUud2FybihgSW52YWxpZCBwYWdlIHNpemU6ICR7c2l6ZX0uIE11c3QgYmUgZ3JlYXRlciB0aGFuIDAuYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy5fcGFnaW5hdGlvbiQudmFsdWU7XG4gICAgY29uc3QgbmV3VG90YWxQYWdlcyA9IHRoaXMuY2FsY3VsYXRlVG90YWxQYWdlcyhjdXJyZW50U3RhdGUudG90YWxJdGVtcywgc2l6ZSk7XG4gICAgXG4gICAgdGhpcy5fcGFnaW5hdGlvbiQubmV4dCh7XG4gICAgICBjdXJyZW50UGFnZTogMCwgLy8gUmVzZXQgdG8gZmlyc3QgcGFnZVxuICAgICAgcGFnZVNpemU6IHNpemUsXG4gICAgICB0b3RhbEl0ZW1zOiBjdXJyZW50U3RhdGUudG90YWxJdGVtcyxcbiAgICAgIHRvdGFsUGFnZXM6IG5ld1RvdGFsUGFnZXNcbiAgICB9KTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgncGFnaW5hdGlvbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0b3RhbCBpdGVtcyAoY2FsbGVkIGFmdGVyIEFQSSByZXNwb25zZSlcbiAgICogQHBhcmFtIHRvdGFsIFRvdGFsIG51bWJlciBvZiBpdGVtc1xuICAgKi9cbiAgc2V0VG90YWxJdGVtcyh0b3RhbDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy5fcGFnaW5hdGlvbiQudmFsdWU7XG4gICAgY29uc3QgbmV3VG90YWxQYWdlcyA9IHRoaXMuY2FsY3VsYXRlVG90YWxQYWdlcyh0b3RhbCwgY3VycmVudFN0YXRlLnBhZ2VTaXplKTtcbiAgICBcbiAgICB0aGlzLl9wYWdpbmF0aW9uJC5uZXh0KHtcbiAgICAgIC4uLmN1cnJlbnRTdGF0ZSxcbiAgICAgIHRvdGFsSXRlbXM6IHRvdGFsLFxuICAgICAgdG90YWxQYWdlczogbmV3VG90YWxQYWdlc1xuICAgIH0pO1xuICAgIC8vIERvbid0IGVtaXQgc3RhdGUgY2hhbmdlIGhlcmUgLSB0aGlzIGlzIGNhbGxlZCBhZnRlciBkYXRhIGxvYWRcbiAgfVxuXG4gIC8qKlxuICAgKiBHbyB0byBuZXh0IHBhZ2VcbiAgICovXG4gIG5leHRQYWdlKCk6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMuX3BhZ2luYXRpb24kLnZhbHVlO1xuICAgIGlmICh0aGlzLmhhc05leHRQYWdlKCkpIHtcbiAgICAgIHRoaXMuc2V0UGFnZShjdXJyZW50U3RhdGUuY3VycmVudFBhZ2UgKyAxKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR28gdG8gcHJldmlvdXMgcGFnZVxuICAgKi9cbiAgcHJldmlvdXNQYWdlKCk6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMuX3BhZ2luYXRpb24kLnZhbHVlO1xuICAgIGlmICh0aGlzLmhhc1ByZXZpb3VzUGFnZSgpKSB7XG4gICAgICB0aGlzLnNldFBhZ2UoY3VycmVudFN0YXRlLmN1cnJlbnRQYWdlIC0gMSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdvIHRvIGZpcnN0IHBhZ2VcbiAgICovXG4gIGZpcnN0UGFnZSgpOiB2b2lkIHtcbiAgICB0aGlzLnNldFBhZ2UoMCk7XG4gIH1cblxuICAvKipcbiAgICogR28gdG8gbGFzdCBwYWdlXG4gICAqL1xuICBsYXN0UGFnZSgpOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLl9wYWdpbmF0aW9uJC52YWx1ZTtcbiAgICBpZiAoY3VycmVudFN0YXRlLnRvdGFsUGFnZXMgPiAwKSB7XG4gICAgICB0aGlzLnNldFBhZ2UoY3VycmVudFN0YXRlLnRvdGFsUGFnZXMgLSAxKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlcmUgaXMgYSBuZXh0IHBhZ2VcbiAgICovXG4gIGhhc05leHRQYWdlKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMuX3BhZ2luYXRpb24kLnZhbHVlO1xuICAgIHJldHVybiBjdXJyZW50U3RhdGUuY3VycmVudFBhZ2UgPCBjdXJyZW50U3RhdGUudG90YWxQYWdlcyAtIDE7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlcmUgaXMgYSBwcmV2aW91cyBwYWdlXG4gICAqL1xuICBoYXNQcmV2aW91c1BhZ2UoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy5fcGFnaW5hdGlvbiQudmFsdWU7XG4gICAgcmV0dXJuIGN1cnJlbnRTdGF0ZS5jdXJyZW50UGFnZSA+IDA7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFNPUlRJTkcgTUVUSE9EUyAob3BlcmF0ZSBvbiBjb2x1bW4gY29uZmlncylcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBTZXQgc29ydCBvbiBhIGNvbHVtbiAoY2xlYXJzIG90aGVyIHNvcnRzKVxuICAgKiBAcGFyYW0gY29sdW1uS2V5IENvbHVtbiBrZXlcbiAgICogQHBhcmFtIGRpcmVjdGlvbiBTb3J0IGRpcmVjdGlvblxuICAgKi9cbiAgc2V0U29ydE9uQ29sdW1uKGNvbHVtbktleTogc3RyaW5nLCBkaXJlY3Rpb246IFNvcnREaXJlY3Rpb24pOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gbm90IGZvdW5kOiAke2NvbHVtbktleX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY29sdW1uLnNvcnRhYmxlID09PSBmYWxzZSkge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gJHtjb2x1bW5LZXl9IGlzIG5vdCBzb3J0YWJsZWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENsZWFyIGFsbCBvdGhlciBzb3J0c1xuICAgIHRoaXMuX2NvbHVtbnMuZm9yRWFjaChjb2wgPT4ge1xuICAgICAgaWYgKGNvbC5rZXkgIT09IGNvbHVtbktleSkge1xuICAgICAgICBjb2wuc29ydERpcmVjdGlvbiA9IFNvcnREaXJlY3Rpb24uTk9ORTtcbiAgICAgICAgY29sLnNvcnRFbmFibGVkID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBTZXQgc29ydCBvbiB0YXJnZXQgY29sdW1uXG4gICAgY29sdW1uLnNvcnREaXJlY3Rpb24gPSBkaXJlY3Rpb247XG4gICAgY29sdW1uLnNvcnRFbmFibGVkID0gZGlyZWN0aW9uICE9PSBTb3J0RGlyZWN0aW9uLk5PTkU7XG5cbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnc29ydGluZycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBzb3J0IHRvIGEgY29sdW1uIChmb3IgbXVsdGktY29sdW1uIHNvcnRpbmcpXG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcGFyYW0gZGlyZWN0aW9uIFNvcnQgZGlyZWN0aW9uXG4gICAqL1xuICBhZGRTb3J0VG9Db2x1bW4oY29sdW1uS2V5OiBzdHJpbmcsIGRpcmVjdGlvbjogU29ydERpcmVjdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZmluZENvbHVtbihjb2x1bW5LZXkpO1xuICAgIGlmICghY29sdW1uKSB7XG4gICAgICBjb25zb2xlLndhcm4oYENvbHVtbiBub3QgZm91bmQ6ICR7Y29sdW1uS2V5fWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjb2x1bW4uc29ydGFibGUgPT09IGZhbHNlKSB7XG4gICAgICBjb25zb2xlLndhcm4oYENvbHVtbiAke2NvbHVtbktleX0gaXMgbm90IHNvcnRhYmxlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29sdW1uLnNvcnREaXJlY3Rpb24gPSBkaXJlY3Rpb247XG4gICAgY29sdW1uLnNvcnRFbmFibGVkID0gZGlyZWN0aW9uICE9PSBTb3J0RGlyZWN0aW9uLk5PTkU7XG5cbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnc29ydGluZycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvZ2dsZSBzb3J0IG9uIGEgY29sdW1uIChjeWNsZXMgdGhyb3VnaCBub25lIC0+IGFzYyAtPiBkZXNjIC0+IG5vbmUpXG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKi9cbiAgdG9nZ2xlU29ydE9uQ29sdW1uKGNvbHVtbktleTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5maW5kQ29sdW1uKGNvbHVtbktleSk7XG4gICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uIG5vdCBmb3VuZDogJHtjb2x1bW5LZXl9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNvbHVtbi5zb3J0YWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uICR7Y29sdW1uS2V5fSBpcyBub3Qgc29ydGFibGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50RGlyZWN0aW9uID0gY29sdW1uLnNvcnREaXJlY3Rpb24gfHwgU29ydERpcmVjdGlvbi5OT05FO1xuICAgIGxldCBuZXdEaXJlY3Rpb246IFNvcnREaXJlY3Rpb247XG5cbiAgICBzd2l0Y2ggKGN1cnJlbnREaXJlY3Rpb24pIHtcbiAgICAgIGNhc2UgU29ydERpcmVjdGlvbi5OT05FOlxuICAgICAgICBuZXdEaXJlY3Rpb24gPSBTb3J0RGlyZWN0aW9uLkFTQztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFNvcnREaXJlY3Rpb24uQVNDOlxuICAgICAgICBuZXdEaXJlY3Rpb24gPSBTb3J0RGlyZWN0aW9uLkRFU0M7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBTb3J0RGlyZWN0aW9uLkRFU0M6XG4gICAgICAgIG5ld0RpcmVjdGlvbiA9IFNvcnREaXJlY3Rpb24uTk9ORTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBuZXdEaXJlY3Rpb24gPSBTb3J0RGlyZWN0aW9uLkFTQztcbiAgICB9XG5cbiAgICBjb2x1bW4uc29ydERpcmVjdGlvbiA9IG5ld0RpcmVjdGlvbjtcbiAgICBjb2x1bW4uc29ydEVuYWJsZWQgPSBuZXdEaXJlY3Rpb24gIT09IFNvcnREaXJlY3Rpb24uTk9ORTtcblxuICAgIHRoaXMuY2xlYXJGb2N1cygpO1xuICAgIHRoaXMuY2xlYXJFZGl0aW5nQ2VsbCgpO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdzb3J0aW5nJyk7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgYWxsIHNvcnRpbmdcbiAgICovXG4gIGNsZWFyQWxsU29ydGluZygpOiB2b2lkIHtcbiAgICB0aGlzLl9jb2x1bW5zLmZvckVhY2goY29sID0+IHtcbiAgICAgIGNvbC5zb3J0RGlyZWN0aW9uID0gU29ydERpcmVjdGlvbi5OT05FO1xuICAgICAgY29sLnNvcnRFbmFibGVkID0gZmFsc2U7XG4gICAgfSk7XG5cbiAgICB0aGlzLmNsZWFyRm9jdXMoKTtcbiAgICB0aGlzLmNsZWFyRWRpdGluZ0NlbGwoKTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnc29ydGluZycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBzb3J0IGNvbmZpZ3VyYXRpb24gZm9yIGEgY29sdW1uXG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcmV0dXJucyBTb3J0IGNvbmZpZ3VyYXRpb24gb3IgbnVsbFxuICAgKi9cbiAgZ2V0U29ydEZvckNvbHVtbihjb2x1bW5LZXk6IHN0cmluZyk6IHsgZGlyZWN0aW9uOiBTb3J0RGlyZWN0aW9uOyBlbmFibGVkOiBib29sZWFuIH0gfCBudWxsIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRpcmVjdGlvbjogY29sdW1uLnNvcnREaXJlY3Rpb24gfHwgU29ydERpcmVjdGlvbi5OT05FLFxuICAgICAgZW5hYmxlZDogY29sdW1uLnNvcnRFbmFibGVkIHx8IGZhbHNlXG4gICAgfTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gRklMVEVSSU5HIE1FVEhPRFMgKG9wZXJhdGUgb24gY29sdW1uIGNvbmZpZ3MpXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogU2V0IGZpbHRlciBvbiBhIGNvbHVtblxuICAgKiBAcGFyYW0gY29sdW1uS2V5IENvbHVtbiBrZXlcbiAgICogQHBhcmFtIG9wZXJhdG9yIEZpbHRlciBvcGVyYXRvclxuICAgKiBAcGFyYW0gdmFsdWUgRmlsdGVyIHZhbHVlXG4gICAqL1xuICBzZXRGaWx0ZXJPbkNvbHVtbihjb2x1bW5LZXk6IHN0cmluZywgb3BlcmF0b3I6IEZpbHRlck9wZXJhdG9yLCB2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5maW5kQ29sdW1uKGNvbHVtbktleSk7XG4gICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uIG5vdCBmb3VuZDogJHtjb2x1bW5LZXl9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNvbHVtbi5maWx0ZXJhYmxlID09PSBmYWxzZSkge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gJHtjb2x1bW5LZXl9IGlzIG5vdCBmaWx0ZXJhYmxlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSW5pdGlhbGl6ZSBmaWx0ZXJDb25maWcgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgIGlmICghY29sdW1uLmZpbHRlckNvbmZpZykge1xuICAgICAgY29sdW1uLmZpbHRlckNvbmZpZyA9IHt9O1xuICAgIH1cblxuICAgIGNvbHVtbi5maWx0ZXJDb25maWcub3BlcmF0b3IgPSBvcGVyYXRvcjtcbiAgICBjb2x1bW4uZmlsdGVyQ29uZmlnLnZhbHVlID0gdmFsdWU7XG4gICAgY29sdW1uLmZpbHRlckNvbmZpZy5lbmFibGVkID0gdHJ1ZTtcblxuICAgIHRoaXMuY2xlYXJGb2N1cygpO1xuICAgIHRoaXMuY2xlYXJFZGl0aW5nQ2VsbCgpO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdmaWx0ZXJpbmcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBmaWx0ZXIgb24gYSBjb2x1bW5cbiAgICogQHBhcmFtIGNvbHVtbktleSBDb2x1bW4ga2V5XG4gICAqL1xuICBjbGVhckZpbHRlck9uQ29sdW1uKGNvbHVtbktleTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5maW5kQ29sdW1uKGNvbHVtbktleSk7XG4gICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uIG5vdCBmb3VuZDogJHtjb2x1bW5LZXl9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSW5pdGlhbGl6ZSBmaWx0ZXJDb25maWcgaWYgaXQgZG9lc24ndCBleGlzdCAoZm9yIGNvbnNpc3RlbmN5IHdpdGggc2V0RmlsdGVyT25Db2x1bW4pXG4gICAgaWYgKCFjb2x1bW4uZmlsdGVyQ29uZmlnKSB7XG4gICAgICBjb2x1bW4uZmlsdGVyQ29uZmlnID0ge307XG4gICAgfVxuXG4gICAgY29sdW1uLmZpbHRlckNvbmZpZy52YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICBjb2x1bW4uZmlsdGVyQ29uZmlnLmVuYWJsZWQgPSBmYWxzZTtcblxuICAgIHRoaXMuY2xlYXJGb2N1cygpO1xuICAgIHRoaXMuY2xlYXJFZGl0aW5nQ2VsbCgpO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdmaWx0ZXJpbmcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBhbGwgZmlsdGVyc1xuICAgKi9cbiAgY2xlYXJBbGxGaWx0ZXJzKCk6IHZvaWQge1xuICAgIHRoaXMuX2NvbHVtbnMuZm9yRWFjaChjb2wgPT4ge1xuICAgICAgLy8gSW5pdGlhbGl6ZSBmaWx0ZXJDb25maWcgaWYgaXQgZG9lc24ndCBleGlzdCAoZm9yIGNvbnNpc3RlbmN5IHdpdGggc2V0RmlsdGVyT25Db2x1bW4pXG4gICAgICBpZiAoIWNvbC5maWx0ZXJDb25maWcpIHtcbiAgICAgICAgY29sLmZpbHRlckNvbmZpZyA9IHt9O1xuICAgICAgfVxuICAgICAgXG4gICAgICBjb2wuZmlsdGVyQ29uZmlnLnZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgY29sLmZpbHRlckNvbmZpZy5lbmFibGVkID0gZmFsc2U7XG4gICAgfSk7XG5cbiAgICB0aGlzLmNsZWFyRm9jdXMoKTtcbiAgICB0aGlzLmNsZWFyRWRpdGluZ0NlbGwoKTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnZmlsdGVyaW5nJyk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGZpbHRlciBlbmFibGVkIHN0YXRlXG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcGFyYW0gZW5hYmxlZCBXaGV0aGVyIGZpbHRlciBpcyBlbmFibGVkXG4gICAqL1xuICBzZXRGaWx0ZXJFbmFibGVkKGNvbHVtbktleTogc3RyaW5nLCBlbmFibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5maW5kQ29sdW1uKGNvbHVtbktleSk7XG4gICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uIG5vdCBmb3VuZDogJHtjb2x1bW5LZXl9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSW5pdGlhbGl6ZSBmaWx0ZXJDb25maWcgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgIGlmICghY29sdW1uLmZpbHRlckNvbmZpZykge1xuICAgICAgY29sdW1uLmZpbHRlckNvbmZpZyA9IHt9O1xuICAgIH1cblxuICAgIGNvbHVtbi5maWx0ZXJDb25maWcuZW5hYmxlZCA9IGVuYWJsZWQ7XG5cbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnZmlsdGVyaW5nJyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGZpbHRlciBjb25maWd1cmF0aW9uIGZvciBhIGNvbHVtblxuICAgKiBAcGFyYW0gY29sdW1uS2V5IENvbHVtbiBrZXlcbiAgICogQHJldHVybnMgRmlsdGVyIGNvbmZpZ3VyYXRpb24gb3IgbnVsbFxuICAgKi9cbiAgZ2V0RmlsdGVyRm9yQ29sdW1uKGNvbHVtbktleTogc3RyaW5nKTogeyBvcGVyYXRvcjogRmlsdGVyT3BlcmF0b3I7IHZhbHVlOiBhbnk7IGVuYWJsZWQ6IGJvb2xlYW4gfSB8IG51bGwge1xuICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZmluZENvbHVtbihjb2x1bW5LZXkpO1xuICAgIGlmICghY29sdW1uKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgb3BlcmF0b3I6IGNvbHVtbi5maWx0ZXJDb25maWc/Lm9wZXJhdG9yIHx8IEZpbHRlck9wZXJhdG9yLkNPTlRBSU5TLFxuICAgICAgdmFsdWU6IGNvbHVtbi5maWx0ZXJDb25maWc/LnZhbHVlLFxuICAgICAgZW5hYmxlZDogY29sdW1uLmZpbHRlckNvbmZpZz8uZW5hYmxlZCB8fCBmYWxzZVxuICAgIH07XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFNUSUNLWSBDT0xVTU4gTUFOQUdFTUVOVFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEdldCBzdGlja3kgY29sdW1ucyBncm91cGVkIGJ5IHBvc2l0aW9uXG4gICAqIEByZXR1cm5zIE9iamVjdCB3aXRoIGxlZnQgYW5kIHJpZ2h0IHN0aWNreSBjb2x1bW4ga2V5c1xuICAgKi9cbiAgZ2V0U3RpY2t5Q29sdW1ucygpOiB7IGxlZnQ6IHN0cmluZ1tdOyByaWdodDogc3RyaW5nW10gfSB7XG4gICAgY29uc3QgbGVmdCA9IHRoaXMuX2NvbHVtbnNcbiAgICAgIC5maWx0ZXIoY29sID0+IGNvbC5zdGlja3kgPT09ICdsZWZ0JylcbiAgICAgIC5tYXAoY29sID0+IGNvbC5rZXkpO1xuICAgIFxuICAgIGNvbnN0IHJpZ2h0ID0gdGhpcy5fY29sdW1uc1xuICAgICAgLmZpbHRlcihjb2wgPT4gY29sLnN0aWNreSA9PT0gJ3JpZ2h0JylcbiAgICAgIC5tYXAoY29sID0+IGNvbC5rZXkpO1xuICAgIFxuICAgIHJldHVybiB7IGxlZnQsIHJpZ2h0IH07XG4gIH1cblxuICAvKipcbiAgICogU2V0IHN0aWNreSBwb3NpdGlvbiBmb3IgYSBjb2x1bW5cbiAgICogQHBhcmFtIGNvbHVtbktleSBDb2x1bW4ga2V5XG4gICAqIEBwYXJhbSBwb3NpdGlvbiBTdGlja3kgcG9zaXRpb24gKCdsZWZ0JywgJ3JpZ2h0Jywgb3IgZmFsc2UpXG4gICAqL1xuICBzZXRTdGlja3lDb2x1bW4oY29sdW1uS2V5OiBzdHJpbmcsIHBvc2l0aW9uOiAnbGVmdCcgfCAncmlnaHQnIHwgZmFsc2UpOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gbm90IGZvdW5kOiAke2NvbHVtbktleX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAoY29sdW1uIGFzIGFueSkuc3RpY2t5ID0gcG9zaXRpb247XG4gICAgdGhpcy5jYWxjdWxhdGVTdGlja3lPZmZzZXRzKCk7XG4gICAgdGhpcy5lbWl0U3RhdGVDaGFuZ2UoJ2NvbHVtbi1jb25maWcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgc3RpY2t5IG9mZnNldHMgZm9yIGFsbCBzdGlja3kgY29sdW1uc1xuICAgKiBUaGlzIGNhbGN1bGF0ZXMgY3VtdWxhdGl2ZSB3aWR0aHMgZm9yIHBvc2l0aW9uaW5nXG4gICAqIEBwYXJhbSByb3dOdW1iZXJXaWR0aCBPcHRpb25hbCB3aWR0aCBvZiByb3cgbnVtYmVyIGNvbHVtbiB0byBhY2NvdW50IGZvciBpbiBsZWZ0IG9mZnNldFxuICAgKiBAcGFyYW0gc2V0dGluZ3NDb2x1bW5XaWR0aCBPcHRpb25hbCB3aWR0aCBvZiBzZXR0aW5ncyBjb2x1bW4gdG8gYWNjb3VudCBmb3IgaW4gcmlnaHQgb2Zmc2V0XG4gICAqL1xuICBjYWxjdWxhdGVTdGlja3lPZmZzZXRzKHJvd051bWJlcldpZHRoPzogbnVtYmVyLCBzZXR0aW5nc0NvbHVtbldpZHRoPzogbnVtYmVyKTogdm9pZCB7XG4gICAgLy8gVXBkYXRlIHN0b3JlZCByb3cgbnVtYmVyIHdpZHRoIGlmIHByb3ZpZGVkXG4gICAgaWYgKHJvd051bWJlcldpZHRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX3Jvd051bWJlcldpZHRoID0gcm93TnVtYmVyV2lkdGg7XG4gICAgfVxuICAgIFxuICAgIC8vIFVwZGF0ZSBzdG9yZWQgc2V0dGluZ3MgY29sdW1uIHdpZHRoIGlmIHByb3ZpZGVkXG4gICAgaWYgKHNldHRpbmdzQ29sdW1uV2lkdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5fc2V0dGluZ3NDb2x1bW5XaWR0aCA9IHNldHRpbmdzQ29sdW1uV2lkdGg7XG4gICAgfVxuICAgIFxuICAgIC8vIENhbGN1bGF0ZSBsZWZ0IHN0aWNreSBvZmZzZXRzXG4gICAgLy8gQWNjb3VudCBmb3Igcm93IG51bWJlciBjb2x1bW4gd2lkdGhcbiAgICBsZXQgbGVmdE9mZnNldCA9IHRoaXMuX3Jvd051bWJlcldpZHRoO1xuICAgIHRoaXMuX2NvbHVtbnMuZm9yRWFjaChjb2wgPT4ge1xuICAgICAgaWYgKGNvbC5zdGlja3kgPT09ICdsZWZ0Jykge1xuICAgICAgICAoY29sIGFzIGFueSkuc3RpY2t5T2Zmc2V0ID0gbGVmdE9mZnNldDtcbiAgICAgICAgbGVmdE9mZnNldCArPSAoY29sLndpZHRoIGFzIG51bWJlcikgfHwgMTAwO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHJpZ2h0IHN0aWNreSBvZmZzZXRzXG4gICAgLy8gQWNjb3VudCBmb3Igc2V0dGluZ3MgY29sdW1uIHdpZHRoIChyb3cgYWN0aW9ucyBjb2x1bW4pXG4gICAgbGV0IHJpZ2h0T2Zmc2V0ID0gdGhpcy5fc2V0dGluZ3NDb2x1bW5XaWR0aDtcbiAgICBmb3IgKGxldCBpID0gdGhpcy5fY29sdW1ucy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgY29uc3QgY29sID0gdGhpcy5fY29sdW1uc1tpXTtcbiAgICAgIGlmIChjb2wuc3RpY2t5ID09PSAncmlnaHQnKSB7XG4gICAgICAgIChjb2wgYXMgYW55KS5zdGlja3lPZmZzZXQgPSByaWdodE9mZnNldDtcbiAgICAgICAgcmlnaHRPZmZzZXQgKz0gKGNvbC53aWR0aCBhcyBudW1iZXIpIHx8IDEwMDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIENPTFVNTiBNQU5BR0VNRU5UXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogVXBkYXRlIGNvbHVtbnMgcmVmZXJlbmNlXG4gICAqIEBwYXJhbSBjb2x1bW5zIE5ldyBjb2x1bW5zIGFycmF5XG4gICAqL1xuICB1cGRhdGVDb2x1bW5zKGNvbHVtbnM6IENvbHVtbkNvbmZpZzxhbnk+W10pOiB2b2lkIHtcbiAgICB0aGlzLl9jb2x1bW5zID0gY29sdW1ucztcbiAgICB0aGlzLmNhbGN1bGF0ZVN0aWNreU9mZnNldHMoKTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnY29sdW1uLWNvbmZpZycpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBDT0xVTU4gVklTSUJJTElUWSBNRVRIT0RTXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogVG9nZ2xlIHZpc2liaWxpdHkgb2YgYSBjb2x1bW5cbiAgICogQHBhcmFtIGNvbHVtbktleSBDb2x1bW4ga2V5XG4gICAqL1xuICB0b2dnbGVDb2x1bW5WaXNpYmlsaXR5KGNvbHVtbktleTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5maW5kQ29sdW1uKGNvbHVtbktleSk7XG4gICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uIG5vdCBmb3VuZDogJHtjb2x1bW5LZXl9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgY29sdW1uIGlzIGhpZGVhYmxlXG4gICAgaWYgKGNvbHVtbi5oaWRlYWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uICR7Y29sdW1uS2V5fSBjYW5ub3QgYmUgaGlkZGVuIChoaWRlYWJsZSBpcyBmYWxzZSlgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50VmlzaWJpbGl0eSA9IGNvbHVtbi52aXNpYmxlICE9PSBmYWxzZTsgLy8gRGVmYXVsdCB0byB0cnVlIGlmIG5vdCBzZXRcbiAgICAoY29sdW1uIGFzIGFueSkudmlzaWJsZSA9ICFjdXJyZW50VmlzaWJpbGl0eTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnY29sdW1uLXZpc2liaWxpdHknKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdmlzaWJpbGl0eSBvZiBhIGNvbHVtblxuICAgKiBAcGFyYW0gY29sdW1uS2V5IENvbHVtbiBrZXlcbiAgICogQHBhcmFtIHZpc2libGUgV2hldGhlciBjb2x1bW4gc2hvdWxkIGJlIHZpc2libGVcbiAgICovXG4gIHNldENvbHVtblZpc2liaWxpdHkoY29sdW1uS2V5OiBzdHJpbmcsIHZpc2libGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gbm90IGZvdW5kOiAke2NvbHVtbktleX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiBjb2x1bW4gaXMgaGlkZWFibGUgKG9ubHkgd2hlbiB0cnlpbmcgdG8gaGlkZSlcbiAgICBpZiAoIXZpc2libGUgJiYgY29sdW1uLmhpZGVhYmxlID09PSBmYWxzZSkge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gJHtjb2x1bW5LZXl9IGNhbm5vdCBiZSBoaWRkZW4gKGhpZGVhYmxlIGlzIGZhbHNlKWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIChjb2x1bW4gYXMgYW55KS52aXNpYmxlID0gdmlzaWJsZTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnY29sdW1uLXZpc2liaWxpdHknKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYWxsIHZpc2libGUgY29sdW1uc1xuICAgKiBAcmV0dXJucyBBcnJheSBvZiB2aXNpYmxlIGNvbHVtbiBjb25maWdzXG4gICAqL1xuICBnZXRWaXNpYmxlQ29sdW1ucygpOiBDb2x1bW5Db25maWc8YW55PltdIHtcbiAgICByZXR1cm4gdGhpcy5fY29sdW1ucy5maWx0ZXIoY29sID0+IGNvbC52aXNpYmxlICE9PSBmYWxzZSk7IC8vIERlZmF1bHQgdG8gdHJ1ZSBpZiBub3Qgc2V0XG4gIH1cblxuICAvKipcbiAgICogR2V0IHZpc2liaWxpdHkgc3RhdGUgZm9yIGFsbCBjb2x1bW5zXG4gICAqIEByZXR1cm5zIEFycmF5IG9mIGNvbHVtbiB2aXNpYmlsaXR5IGluZm9cbiAgICovXG4gIGdldEFsbENvbHVtbnNWaXNpYmlsaXR5KCk6IHsga2V5OiBzdHJpbmc7IGhlYWRlcjogc3RyaW5nOyB2aXNpYmxlOiBib29sZWFuOyBoaWRlYWJsZTogYm9vbGVhbiB9W10ge1xuICAgIHJldHVybiB0aGlzLl9jb2x1bW5zLm1hcChjb2wgPT4gKHtcbiAgICAgIGtleTogY29sLmtleSxcbiAgICAgIGhlYWRlcjogY29sLmhlYWRlciB8fCBjb2wua2V5LFxuICAgICAgdmlzaWJsZTogY29sLnZpc2libGUgIT09IGZhbHNlLCAvLyBEZWZhdWx0IHRvIHRydWUgaWYgbm90IHNldFxuICAgICAgaGlkZWFibGU6IGNvbC5oaWRlYWJsZSAhPT0gZmFsc2UgLy8gRGVmYXVsdCB0byB0cnVlIGlmIG5vdCBzZXRcbiAgICB9KSk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIEtFWUJPQVJEIE5BVklHQVRJT04gJiBGT0NVUyBNQU5BR0VNRU5UXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogU2V0IHRhYmxlIGRpbWVuc2lvbnMgZm9yIG5hdmlnYXRpb24gYm91bmRhcmllc1xuICAgKi9cbiAgc2V0RGltZW5zaW9ucyhyb3dDb3VudDogbnVtYmVyLCBjb2x1bW5Db3VudDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5fcm93Q291bnQgPSByb3dDb3VudDtcbiAgICB0aGlzLl9jb2x1bW5Db3VudCA9IGNvbHVtbkNvdW50O1xuICAgIFxuICAgIC8vIFVwZGF0ZSB0b3RhbCByb3dzIGluIHZhbGlkYXRpb24gc3RhdGVcbiAgICB0aGlzLnNldFZhbGlkYXRpb25Sb3dDb3VudChyb3dDb3VudCk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBGb2N1cyBhIGNlbGwgYnkgcG9zaXRpb25cbiAgICovXG4gIGZvY3VzQ2VsbChyb3dJbmRleDogbnVtYmVyLCBjb2x1bW5JbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHJvd0luZGV4IDwgMCB8fCByb3dJbmRleCA+PSB0aGlzLl9yb3dDb3VudCkgcmV0dXJuO1xuICAgIGlmIChjb2x1bW5JbmRleCA8IDAgfHwgY29sdW1uSW5kZXggPj0gdGhpcy5fY29sdW1uQ291bnQpIHJldHVybjtcbiAgICBcbiAgICB0aGlzLl9mb2N1c2VkQ2VsbFBvc2l0aW9uJC5uZXh0KHsgcm93SW5kZXgsIGNvbHVtbkluZGV4IH0pO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdjZWxsLWZvY3VzJyk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgY3VycmVudGx5IGZvY3VzZWQgcG9zaXRpb25cbiAgICovXG4gIGdldEZvY3VzZWRQb3NpdGlvbigpOiBDZWxsRm9jdXNQb3NpdGlvbiB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl9mb2N1c2VkQ2VsbFBvc2l0aW9uJC52YWx1ZTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIE5vdGlmeSB0aGF0IGEgY2VsbCBlbnRlcmVkIGVkaXQgbW9kZVxuICAgKi9cbiAgc2V0RWRpdGluZ0NlbGwocm93SW5kZXg6IG51bWJlciwgY29sdW1uSW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuX2VkaXRpbmdDZWxsUG9zaXRpb24kLm5leHQoeyByb3dJbmRleCwgY29sdW1uSW5kZXggfSk7XG4gICAgdGhpcy5lbWl0U3RhdGVDaGFuZ2UoJ2NlbGwtZWRpdC1zdGFydCcpO1xuICB9XG4gIFxuICAvKipcbiAgICogTm90aWZ5IHRoYXQgZWRpdCBtb2RlIGVuZGVkXG4gICAqL1xuICBjbGVhckVkaXRpbmdDZWxsKCk6IHZvaWQge1xuICAgIHRoaXMuX2VkaXRpbmdDZWxsUG9zaXRpb24kLm5leHQobnVsbCk7XG4gICAgdGhpcy5lbWl0U3RhdGVDaGFuZ2UoJ2NlbGwtZWRpdC1lbmQnKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIENoZWNrIGlmIGFueSBjZWxsIGlzIGN1cnJlbnRseSBlZGl0aW5nXG4gICAqL1xuICBpc0FueUNlbGxFZGl0aW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9lZGl0aW5nQ2VsbFBvc2l0aW9uJC52YWx1ZSAhPT0gbnVsbDtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCBjdXJyZW50bHkgZWRpdGluZyBwb3NpdGlvblxuICAgKi9cbiAgZ2V0RWRpdGluZ1Bvc2l0aW9uKCk6IENlbGxGb2N1c1Bvc2l0aW9uIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX2VkaXRpbmdDZWxsUG9zaXRpb24kLnZhbHVlO1xuICB9XG4gIFxuICAvKipcbiAgICogTW92ZSBmb2N1cyBpbiBhIGRpcmVjdGlvbiB1c2luZyBOYXZpZ2F0aW9uRGlyZWN0aW9uIGVudW1cbiAgICovXG4gIG1vdmVGb2N1cyhkaXJlY3Rpb246IE5hdmlnYXRpb25EaXJlY3Rpb24pOiBib29sZWFuIHtcbiAgICAvLyBCbG9jayBuYXZpZ2F0aW9uIGlmIGFueSBjZWxsIGlzIGVkaXRpbmdcbiAgICBpZiAodGhpcy5pc0FueUNlbGxFZGl0aW5nKCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgXG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuX2ZvY3VzZWRDZWxsUG9zaXRpb24kLnZhbHVlO1xuICAgIGlmICghY3VycmVudCkgcmV0dXJuIGZhbHNlO1xuICAgIFxuICAgIGxldCBuZXdSb3cgPSBjdXJyZW50LnJvd0luZGV4O1xuICAgIGxldCBuZXdDb2wgPSBjdXJyZW50LmNvbHVtbkluZGV4O1xuICAgIFxuICAgIC8vIFVzZSBOYXZpZ2F0aW9uRGlyZWN0aW9uIGVudW0gdmFsdWVzXG4gICAgc3dpdGNoIChkaXJlY3Rpb24pIHtcbiAgICAgIGNhc2UgTmF2aWdhdGlvbkRpcmVjdGlvbi5VUDogbmV3Um93LS07IGJyZWFrO1xuICAgICAgY2FzZSBOYXZpZ2F0aW9uRGlyZWN0aW9uLkRPV046IG5ld1JvdysrOyBicmVhaztcbiAgICAgIGNhc2UgTmF2aWdhdGlvbkRpcmVjdGlvbi5MRUZUOiBuZXdDb2wtLTsgYnJlYWs7XG4gICAgICBjYXNlIE5hdmlnYXRpb25EaXJlY3Rpb24uUklHSFQ6IG5ld0NvbCsrOyBicmVhaztcbiAgICB9XG4gICAgXG4gICAgaWYgKG5ld1JvdyA8IDAgfHwgbmV3Um93ID49IHRoaXMuX3Jvd0NvdW50KSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKG5ld0NvbCA8IDAgfHwgbmV3Q29sID49IHRoaXMuX2NvbHVtbkNvdW50KSByZXR1cm4gZmFsc2U7XG4gICAgXG4gICAgdGhpcy5mb2N1c0NlbGwobmV3Um93LCBuZXdDb2wpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2xlYXIgZm9jdXNcbiAgICovXG4gIGNsZWFyRm9jdXMoKTogdm9pZCB7XG4gICAgdGhpcy5fZm9jdXNlZENlbGxQb3NpdGlvbiQubmV4dChudWxsKTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnY2VsbC1mb2N1cycpO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2hlY2sgaWYgbmF2aWdhdGlvbiBpcyBhY3RpdmVcbiAgICovXG4gIGlzTmF2aWdhdGlvbkFjdGl2ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZm9jdXNlZENlbGxQb3NpdGlvbiQudmFsdWUgIT09IG51bGw7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFZBTElEQVRJT04gU1RBVEUgTUVUSE9EU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIFxuICAvKipcbiAgICogVXBkYXRlIGNlbGwgdmFsaWRhdGlvbiBhbmQgYWNjdW11bGF0ZSBpbnRvIHJvdy90YWJsZSB2YWxpZGF0aW9uIHN0YXRlXG4gICAqIE9ubHkgc3RvcmVzIGludmFsaWQgc3RhdGVzIC0gdmFsaWQgcm93cyBhcmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAqL1xuICB1cGRhdGVDZWxsVmFsaWRhdGlvbihyb3dJbmRleDogbnVtYmVyLCBjb2x1bW5LZXk6IHN0cmluZywgaXNWYWxpZDogYm9vbGVhbiwgZXJyb3I/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLl90YWJsZVZhbGlkYXRpb25TdGF0ZSQudmFsdWU7XG4gICAgY29uc3Qgcm93U3RhdGVzID0gbmV3IE1hcChjdXJyZW50U3RhdGUucm93U3RhdGVzKTtcbiAgICBcbiAgICAvLyBHZXQgZXhpc3Rpbmcgcm93IHN0YXRlIChvbmx5IGV4aXN0cyBpZiByb3cgaGFzIGVycm9ycylcbiAgICBsZXQgcm93U3RhdGUgPSByb3dTdGF0ZXMuZ2V0KHJvd0luZGV4KTtcbiAgICBcbiAgICBpZiAoIWlzVmFsaWQgJiYgZXJyb3IpIHtcbiAgICAgIC8vIENlbGwgaXMgaW52YWxpZCAtIGFkZCBvciB1cGRhdGUgZXJyb3JcbiAgICAgIGlmICghcm93U3RhdGUpIHtcbiAgICAgICAgLy8gQ3JlYXRlIG5ldyByb3cgc3RhdGUgZm9yIHRoaXMgaW52YWxpZCByb3dcbiAgICAgICAgcm93U3RhdGUgPSB7XG4gICAgICAgICAgcm93SW5kZXgsXG4gICAgICAgICAgaXNWYWxpZDogZmFsc2UsXG4gICAgICAgICAgaW52YWxpZENlbGxDb3VudDogMSxcbiAgICAgICAgICBjZWxsRXJyb3JzOiBuZXcgTWFwKFtbY29sdW1uS2V5LCBlcnJvcl1dKSxcbiAgICAgICAgICBsYXN0VmFsaWRhdGVkOiBuZXcgRGF0ZSgpXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBVcGRhdGUgZXhpc3Rpbmcgcm93IHN0YXRlXG4gICAgICAgIGNvbnN0IGNlbGxFcnJvcnMgPSBuZXcgTWFwKHJvd1N0YXRlLmNlbGxFcnJvcnMpO1xuICAgICAgICBjZWxsRXJyb3JzLnNldChjb2x1bW5LZXksIGVycm9yKTtcbiAgICAgICAgXG4gICAgICAgIHJvd1N0YXRlID0ge1xuICAgICAgICAgIHJvd0luZGV4LFxuICAgICAgICAgIGlzVmFsaWQ6IGZhbHNlLFxuICAgICAgICAgIGludmFsaWRDZWxsQ291bnQ6IGNlbGxFcnJvcnMuc2l6ZSxcbiAgICAgICAgICBjZWxsRXJyb3JzLFxuICAgICAgICAgIGxhc3RWYWxpZGF0ZWQ6IG5ldyBEYXRlKClcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJvd1N0YXRlcy5zZXQocm93SW5kZXgsIHJvd1N0YXRlKTtcbiAgICAgIFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDZWxsIGlzIHZhbGlkIC0gcmVtb3ZlIGVycm9yIGlmIGl0IGV4aXN0c1xuICAgICAgaWYgKHJvd1N0YXRlKSB7XG4gICAgICAgIGNvbnN0IGNlbGxFcnJvcnMgPSBuZXcgTWFwKHJvd1N0YXRlLmNlbGxFcnJvcnMpO1xuICAgICAgICBjZWxsRXJyb3JzLmRlbGV0ZShjb2x1bW5LZXkpO1xuICAgICAgICBcbiAgICAgICAgaWYgKGNlbGxFcnJvcnMuc2l6ZSA9PT0gMCkge1xuICAgICAgICAgIC8vIE5vIG1vcmUgZXJyb3JzIGluIHRoaXMgcm93IC0gcmVtb3ZlIHJvdyBzdGF0ZSBjb21wbGV0ZWx5XG4gICAgICAgICAgcm93U3RhdGVzLmRlbGV0ZShyb3dJbmRleCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU3RpbGwgaGFzIG90aGVyIGVycm9ycyAtIHVwZGF0ZSByb3cgc3RhdGVcbiAgICAgICAgICByb3dTdGF0ZSA9IHtcbiAgICAgICAgICAgIHJvd0luZGV4LFxuICAgICAgICAgICAgaXNWYWxpZDogZmFsc2UsXG4gICAgICAgICAgICBpbnZhbGlkQ2VsbENvdW50OiBjZWxsRXJyb3JzLnNpemUsXG4gICAgICAgICAgICBjZWxsRXJyb3JzLFxuICAgICAgICAgICAgbGFzdFZhbGlkYXRlZDogbmV3IERhdGUoKVxuICAgICAgICAgIH07XG4gICAgICAgICAgcm93U3RhdGVzLnNldChyb3dJbmRleCwgcm93U3RhdGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBJZiByb3dTdGF0ZSBkb2Vzbid0IGV4aXN0LCBjZWxsIHdhcyBhbHJlYWR5IHZhbGlkIC0gZG8gbm90aGluZ1xuICAgIH1cbiAgICBcbiAgICAvLyBSZWNhbGN1bGF0ZSB0YWJsZSBzdGF0ZVxuICAgIC8vIEFsbCByb3dzIGluIHJvd1N0YXRlcyBtYXAgYXJlIGludmFsaWQgYnkgZGVmaW5pdGlvblxuICAgIGNvbnN0IGludmFsaWRSb3dzID0gcm93U3RhdGVzLnNpemU7XG4gICAgXG4gICAgY29uc3QgbmV3VGFibGVTdGF0ZTogVGFibGVWYWxpZGF0aW9uU3RhdGUgPSB7XG4gICAgICBpc1ZhbGlkOiBpbnZhbGlkUm93cyA9PT0gMCxcbiAgICAgIHRvdGFsUm93czogY3VycmVudFN0YXRlLnRvdGFsUm93cywgLy8gS2VlcCB0cmFjayBvZiB0b3RhbCByb3dzIHNlcGFyYXRlbHlcbiAgICAgIHZhbGlkUm93czogY3VycmVudFN0YXRlLnRvdGFsUm93cyAtIGludmFsaWRSb3dzLFxuICAgICAgaW52YWxpZFJvd3MsXG4gICAgICByb3dTdGF0ZXMsXG4gICAgICBsYXN0VXBkYXRlZDogbmV3IERhdGUoKVxuICAgIH07XG4gICAgXG4gICAgLy8gRW1pdCBuZXcgc3RhdGVcbiAgICB0aGlzLl90YWJsZVZhbGlkYXRpb25TdGF0ZSQubmV4dChuZXdUYWJsZVN0YXRlKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IHRhYmxlIHZhbGlkYXRpb24gc3RhdGVcbiAgICovXG4gIGdldFRhYmxlVmFsaWRhdGlvblN0YXRlKCk6IFRhYmxlVmFsaWRhdGlvblN0YXRlIHtcbiAgICByZXR1cm4gdGhpcy5fdGFibGVWYWxpZGF0aW9uU3RhdGUkLnZhbHVlO1xuICB9XG4gIFxuICAvKipcbiAgICogU2V0IHRvdGFsIHJvd3MgZm9yIHZhbGlkYXRpb24gc3RhdGUgdHJhY2tpbmdcbiAgICovXG4gIHNldFZhbGlkYXRpb25Sb3dDb3VudCh0b3RhbFJvd3M6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMuX3RhYmxlVmFsaWRhdGlvblN0YXRlJC52YWx1ZTtcbiAgICB0aGlzLl90YWJsZVZhbGlkYXRpb25TdGF0ZSQubmV4dCh7XG4gICAgICAuLi5jdXJyZW50U3RhdGUsXG4gICAgICB0b3RhbFJvd3MsXG4gICAgICBsYXN0VXBkYXRlZDogbmV3IERhdGUoKVxuICAgIH0pO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBTVEFURSBSRVNFVFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRvIGluaXRpYWwgY29uZmlndXJhdGlvblxuICAgKi9cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5yZXNldFBhZ2luYXRpb24oKTtcbiAgICB0aGlzLnJlc2V0QWxsU29ydGluZygpO1xuICAgIHRoaXMucmVzZXRBbGxGaWx0ZXJzKCk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgcGFnaW5hdGlvbiBvbmx5XG4gICAqL1xuICByZXNldFBhZ2luYXRpb24oKTogdm9pZCB7XG4gICAgdGhpcy5fcGFnaW5hdGlvbiQubmV4dCh7XG4gICAgICBjdXJyZW50UGFnZTogdGhpcy5faW5pdGlhbENvbmZpZy5pbml0aWFsUGFnZSEsXG4gICAgICBwYWdlU2l6ZTogdGhpcy5faW5pdGlhbENvbmZpZy5wYWdlU2l6ZSEsXG4gICAgICB0b3RhbEl0ZW1zOiAwLFxuICAgICAgdG90YWxQYWdlczogMFxuICAgIH0pO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdwYWdpbmF0aW9uJyk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgYWxsIGNvbHVtbiBzb3J0c1xuICAgKi9cbiAgcmVzZXRBbGxTb3J0aW5nKCk6IHZvaWQge1xuICAgIHRoaXMuY2xlYXJBbGxTb3J0aW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgYWxsIGNvbHVtbiBmaWx0ZXJzXG4gICAqL1xuICByZXNldEFsbEZpbHRlcnMoKTogdm9pZCB7XG4gICAgdGhpcy5jbGVhckFsbEZpbHRlcnMoKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gSU5URVJOQUwgTUVUSE9EU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEZpbmQgYSBjb2x1bW4gYnkga2V5XG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcmV0dXJucyBDb2x1bW4gY29uZmlnIG9yIHVuZGVmaW5lZFxuICAgKi9cbiAgcHJpdmF0ZSBmaW5kQ29sdW1uKGNvbHVtbktleTogc3RyaW5nKTogQ29sdW1uQ29uZmlnPGFueT4gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9jb2x1bW5zLmZpbmQoY29sID0+IGNvbC5rZXkgPT09IGNvbHVtbktleSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRvdGFsIHBhZ2VzXG4gICAqIEBwYXJhbSB0b3RhbEl0ZW1zIFRvdGFsIG51bWJlciBvZiBpdGVtc1xuICAgKiBAcGFyYW0gcGFnZVNpemUgUGFnZSBzaXplXG4gICAqIEByZXR1cm5zIFRvdGFsIG51bWJlciBvZiBwYWdlc1xuICAgKi9cbiAgcHJpdmF0ZSBjYWxjdWxhdGVUb3RhbFBhZ2VzKHRvdGFsSXRlbXM6IG51bWJlciA9IDAsIHBhZ2VTaXplOiBudW1iZXIgPSAyNSk6IG51bWJlciB7XG4gICAgaWYgKHRvdGFsSXRlbXMgPT09IDAgfHwgcGFnZVNpemUgPT09IDApIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICByZXR1cm4gTWF0aC5jZWlsKHRvdGFsSXRlbXMgLyBwYWdlU2l6ZSk7XG4gIH1cblxuICAvKipcbiAgICogRW1pdCBzdGF0ZSBjaGFuZ2UgZXZlbnRcbiAgICogQHBhcmFtIHR5cGUgVHlwZSBvZiBjaGFuZ2VcbiAgICovXG4gIHByaXZhdGUgZW1pdFN0YXRlQ2hhbmdlKHR5cGU6IFRhYmxlU3RhdGVDaGFuZ2VFdmVudFsndHlwZSddKTogdm9pZCB7XG4gICAgY29uc3Qgc3RhdGUgPSB0aGlzLmJ1aWxkU3RhdGVTbmFwc2hvdCgpO1xuICAgIHRoaXMuX3N0YXRlQ2hhbmdlJC5uZXh0KHtcbiAgICAgIHR5cGUsXG4gICAgICBzdGF0ZVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIHN0YXRlIHNuYXBzaG90IGZyb20gY3VycmVudCBzdGF0ZVxuICAgKiBAcmV0dXJucyBTdGF0ZSBzbmFwc2hvdFxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZFN0YXRlU25hcHNob3QoKTogVGFibGVTdGF0ZVNuYXBzaG90IHtcbiAgICByZXR1cm4ge1xuICAgICAgcGFnaW5hdGlvbjogdGhpcy5nZXRQYWdpbmF0aW9uKCksXG4gICAgICBcbiAgICAgIC8vIEJ1aWxkIGZ1bGwgc29ydCBzdGF0ZSB3aXRoIGRpcmVjdGlvbiBhbmQgcHJpb3JpdHlcbiAgICAgIHNvcnRlZENvbHVtbnM6IHRoaXMuX2NvbHVtbnNcbiAgICAgICAgLmZpbHRlcihjb2wgPT4gY29sLnNvcnRFbmFibGVkID09PSB0cnVlKVxuICAgICAgICAubWFwKChjb2wsIGluZGV4KSA9PiAoe1xuICAgICAgICAgIGNvbHVtbktleTogY29sLmtleSxcbiAgICAgICAgICBkaXJlY3Rpb246IGNvbC5zb3J0RGlyZWN0aW9uIHx8IFNvcnREaXJlY3Rpb24uTk9ORSxcbiAgICAgICAgICBwcmlvcml0eTogaW5kZXggIC8vIFNvcnQgb3JkZXIgYmFzZWQgb24gZW5hYmxlbWVudCBvcmRlclxuICAgICAgICB9KSksXG4gICAgICBcbiAgICAgIC8vIEJ1aWxkIGZ1bGwgZmlsdGVyIHN0YXRlIHdpdGggb3BlcmF0b3IgYW5kIHZhbHVlXG4gICAgICBmaWx0ZXJlZENvbHVtbnM6IHRoaXMuX2NvbHVtbnNcbiAgICAgICAgLmZpbHRlcihjb2wgPT4gY29sLmZpbHRlckNvbmZpZz8uZW5hYmxlZCA9PT0gdHJ1ZSlcbiAgICAgICAgLm1hcChjb2wgPT4gKHtcbiAgICAgICAgICBjb2x1bW5LZXk6IGNvbC5rZXksXG4gICAgICAgICAgb3BlcmF0b3I6IGNvbC5maWx0ZXJDb25maWc/Lm9wZXJhdG9yIHx8IEZpbHRlck9wZXJhdG9yLkNPTlRBSU5TLFxuICAgICAgICAgIHZhbHVlOiBjb2wuZmlsdGVyQ29uZmlnPy52YWx1ZSxcbiAgICAgICAgICBlbmFibGVkOiB0cnVlXG4gICAgICAgIH0pKVxuICAgIH07XG4gIH1cbn1cblxuIl19