@sumaris-net/ngx-components 2.3.6 → 2.4.0-rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/public_api.mjs +4 -1
- package/esm2020/src/app/admin/users/users.mjs +3 -2
- package/esm2020/src/app/core/services/storage/entities-storage.service.mjs +9 -6
- package/esm2020/src/app/core/table/async-table.class.mjs +1615 -0
- package/esm2020/src/app/core/table/entities-async-table-datasource.class.mjs +383 -0
- package/esm2020/src/app/core/table/table.class.mjs +2 -12
- package/esm2020/src/app/core/table/table.model.mjs +12 -0
- package/esm2020/src/app/core/table/testing/table.testing.mjs +3 -2
- package/esm2020/src/app/shared/interceptors/progess.interceptor.mjs +10 -3
- package/esm2020/src/app/shared/material/datetime/material.datetime.mjs +2 -2
- package/esm2020/src/app/shared/services/progress-bar.service.mjs +3 -2
- package/esm2020/src/app/shared/shared.module.mjs +4 -4
- package/esm2020/src/app/shared/toolbar/toolbar.mjs +12 -9
- package/fesm2015/sumaris-net.ngx-components.mjs +2214 -127
- package/fesm2015/sumaris-net.ngx-components.mjs.map +1 -1
- package/fesm2020/sumaris-net.ngx-components.mjs +2101 -128
- package/fesm2020/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +3 -0
- package/src/app/core/services/storage/entities-storage.service.d.ts +2 -2
- package/src/app/core/table/async-table.class.d.ts +368 -0
- package/src/app/core/table/entities-async-table-datasource.class.d.ts +79 -0
- package/src/app/core/table/table.class.d.ts +1 -22
- package/src/app/core/table/table.model.d.ts +23 -0
- package/src/app/shared/interceptors/progess.interceptor.d.ts +2 -2
- package/src/app/shared/services/progress-bar.service.d.ts +9 -2
- package/src/app/shared/toolbar/toolbar.d.ts +2 -2
|
@@ -0,0 +1,1615 @@
|
|
|
1
|
+
import { Directive, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
|
2
|
+
import { MatPaginator } from '@angular/material/paginator';
|
|
3
|
+
import { MatSort } from '@angular/material/sort';
|
|
4
|
+
import { MatTable } from '@angular/material/table';
|
|
5
|
+
import { BehaviorSubject, EMPTY, merge, of, Subject, Subscription } from 'rxjs';
|
|
6
|
+
import { catchError, debounceTime, distinctUntilChanged, filter, first, mergeMap, startWith, switchMap, takeUntil, tap } from 'rxjs/operators';
|
|
7
|
+
import { SelectionModel } from '@angular/cdk/collections';
|
|
8
|
+
import { EntityUtils } from '../services/model/entity.model';
|
|
9
|
+
import { AlertController, ModalController, ToastController } from '@ionic/angular';
|
|
10
|
+
import { ActivatedRoute, Router } from '@angular/router';
|
|
11
|
+
import { TableSelectColumnsComponent } from './table-select-columns.component';
|
|
12
|
+
import { Location } from '@angular/common';
|
|
13
|
+
import { ErrorCodes } from '../services/errors';
|
|
14
|
+
import { AppFormUtils } from '../form/form.utils';
|
|
15
|
+
import { LocalSettingsService } from '../services/local-settings.service';
|
|
16
|
+
import { TranslateService } from '@ngx-translate/core';
|
|
17
|
+
import { MatAutocompleteConfigHolder } from '../../shared/material/autocomplete/material.autocomplete.config';
|
|
18
|
+
import { createPromiseEventEmitter, emitPromiseEvent } from '../../shared/events';
|
|
19
|
+
import { changeCaseToUnderscore, isEmptyArray, isNil, isNotNil, toBoolean } from '../../shared/functions';
|
|
20
|
+
import { waitFor, waitForFalse, waitForTrue } from '../../shared/observables';
|
|
21
|
+
import { Toasts } from '../../shared/toast/toasts';
|
|
22
|
+
import { Alerts } from '../../shared/alerts';
|
|
23
|
+
import { FormErrorTranslator } from '../../shared/validator/form-error-adapter.class';
|
|
24
|
+
import { DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_REQUIRED_COLUMNS, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN } from './table.model';
|
|
25
|
+
import * as i0 from "@angular/core";
|
|
26
|
+
import * as i1 from "./entities-async-table-datasource.class";
|
|
27
|
+
// @dynamic
|
|
28
|
+
// noinspection DuplicatedCode
|
|
29
|
+
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
|
30
|
+
export class AppAsyncTable {
|
|
31
|
+
constructor(injector, columns, _dataSource, _filter) {
|
|
32
|
+
this.columns = columns;
|
|
33
|
+
this._dataSource = _dataSource;
|
|
34
|
+
this._filter = _filter;
|
|
35
|
+
this._initialized = false;
|
|
36
|
+
this._subscription = new Subscription();
|
|
37
|
+
this._cellValueChangesDefs = {};
|
|
38
|
+
this._enabled = true;
|
|
39
|
+
this.allowRowDetail = true;
|
|
40
|
+
this.destroySubject = new Subject();
|
|
41
|
+
this.excludesColumns = [];
|
|
42
|
+
this.totalRowCount = null;
|
|
43
|
+
this.readySubject = new BehaviorSubject(false);
|
|
44
|
+
this.loadingSubject = new BehaviorSubject(true);
|
|
45
|
+
this.savingSubject = new BehaviorSubject(false);
|
|
46
|
+
this.touchedSubject = new BehaviorSubject(false);
|
|
47
|
+
this.dirtySubject = new BehaviorSubject(false);
|
|
48
|
+
this.errorSubject = new BehaviorSubject(undefined);
|
|
49
|
+
this.selection = new SelectionModel(true, []);
|
|
50
|
+
this.i18nColumnPrefix = 'COMMON.';
|
|
51
|
+
this.autoLoad = true;
|
|
52
|
+
this.focusFirstColumn = false;
|
|
53
|
+
this.confirmBeforeDelete = false;
|
|
54
|
+
this.confirmBeforeCancel = false;
|
|
55
|
+
this.undoableDeletion = false;
|
|
56
|
+
this.propagateRowError = false;
|
|
57
|
+
this.defaultPageSize = DEFAULT_PAGE_SIZE;
|
|
58
|
+
this.defaultPageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS;
|
|
59
|
+
this.onRefresh = new EventEmitter();
|
|
60
|
+
this.onOpenRow = new EventEmitter();
|
|
61
|
+
this.onNewRow = new EventEmitter();
|
|
62
|
+
this.onStartEditingRow = new EventEmitter();
|
|
63
|
+
this.onConfirmEditCreateRow = new EventEmitter();
|
|
64
|
+
this.onCancelOrDeleteRow = new EventEmitter();
|
|
65
|
+
this.onBeforeDeleteRows = createPromiseEventEmitter();
|
|
66
|
+
this.onBeforeCancelRows = createPromiseEventEmitter();
|
|
67
|
+
this.onBeforeSave = createPromiseEventEmitter();
|
|
68
|
+
this.onAfterDeletedRows = new EventEmitter();
|
|
69
|
+
this.onSort = new EventEmitter();
|
|
70
|
+
this.onDirty = new EventEmitter();
|
|
71
|
+
this.onError = new EventEmitter();
|
|
72
|
+
this._paginator = null;
|
|
73
|
+
this.route = injector.get(ActivatedRoute);
|
|
74
|
+
this.router = injector.get(Router);
|
|
75
|
+
this.location = injector.get(Location);
|
|
76
|
+
this.settings = injector.get(LocalSettingsService);
|
|
77
|
+
this.translate = injector.get(TranslateService);
|
|
78
|
+
this.modalCtrl = injector.get(ModalController);
|
|
79
|
+
this.alertCtrl = injector.get(AlertController);
|
|
80
|
+
this.toastController = injector.get(ToastController);
|
|
81
|
+
this.formErrorAdapter = injector.get(FormErrorTranslator);
|
|
82
|
+
this.mobile = this.settings.mobile;
|
|
83
|
+
// Autocomplete fields
|
|
84
|
+
this._autocompleteConfigHolder = new MatAutocompleteConfigHolder({
|
|
85
|
+
getUserAttributes: (a, b) => this.settings.getFieldDisplayAttributes(a, b)
|
|
86
|
+
});
|
|
87
|
+
this.autocompleteFields = this._autocompleteConfigHolder.fields;
|
|
88
|
+
}
|
|
89
|
+
get error() {
|
|
90
|
+
return this.errorSubject.value;
|
|
91
|
+
}
|
|
92
|
+
set error(error) {
|
|
93
|
+
this.setError(error);
|
|
94
|
+
}
|
|
95
|
+
get firstUserColumn() {
|
|
96
|
+
return this.displayedColumns[RESERVED_START_COLUMNS.length];
|
|
97
|
+
}
|
|
98
|
+
get lastUserColumn() {
|
|
99
|
+
return this.displayedColumns[this.displayedColumns.length - RESERVED_END_COLUMNS.length - 1];
|
|
100
|
+
}
|
|
101
|
+
set dataSource(value) {
|
|
102
|
+
this.setDatasource(value);
|
|
103
|
+
}
|
|
104
|
+
get dataSource() {
|
|
105
|
+
return this._dataSource;
|
|
106
|
+
}
|
|
107
|
+
set filter(value) {
|
|
108
|
+
this.setFilter(value);
|
|
109
|
+
}
|
|
110
|
+
get filter() {
|
|
111
|
+
return this._filter;
|
|
112
|
+
}
|
|
113
|
+
get empty() {
|
|
114
|
+
return this.loading || this.totalRowCount === 0;
|
|
115
|
+
}
|
|
116
|
+
get dirty() {
|
|
117
|
+
return this.dirtySubject.value;
|
|
118
|
+
}
|
|
119
|
+
get valid() {
|
|
120
|
+
return this.dataSource.getRows().every(row => row.editing ? row.valid : true);
|
|
121
|
+
}
|
|
122
|
+
get invalid() {
|
|
123
|
+
return this.dataSource.getRows().some(row => row.editing ? row.invalid : false);
|
|
124
|
+
}
|
|
125
|
+
get pending() {
|
|
126
|
+
return this.dataSource.getRows().some(row => row.editing ? row.pending : false);
|
|
127
|
+
}
|
|
128
|
+
get touched() {
|
|
129
|
+
return this.touchedSubject.value;
|
|
130
|
+
}
|
|
131
|
+
get untouched() {
|
|
132
|
+
return !this.touchedSubject.value;
|
|
133
|
+
}
|
|
134
|
+
disable(opts) {
|
|
135
|
+
if (this.sort)
|
|
136
|
+
this.sort.disabled = true;
|
|
137
|
+
this._enabled = false;
|
|
138
|
+
if (!opts || opts.emitEvent != false)
|
|
139
|
+
this.markForCheck();
|
|
140
|
+
}
|
|
141
|
+
enable(opts) {
|
|
142
|
+
if (this.sort)
|
|
143
|
+
this.sort.disabled = false;
|
|
144
|
+
this._enabled = true;
|
|
145
|
+
if (!opts || opts.emitEvent != false)
|
|
146
|
+
this.markForCheck();
|
|
147
|
+
}
|
|
148
|
+
get enabled() {
|
|
149
|
+
return this._enabled;
|
|
150
|
+
}
|
|
151
|
+
// FIXME: need to hidden buttons (in HTML), etc. when disabled
|
|
152
|
+
set disabled(value) {
|
|
153
|
+
if (value !== !this._enabled) {
|
|
154
|
+
if (value)
|
|
155
|
+
this.disable({ emitEvent: false });
|
|
156
|
+
else
|
|
157
|
+
this.enable({ emitEvent: false });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
get disabled() {
|
|
161
|
+
return !this._enabled;
|
|
162
|
+
}
|
|
163
|
+
markAsDirty(opts) {
|
|
164
|
+
if (this.dirtySubject.value !== true) {
|
|
165
|
+
this.dirtySubject.next(true);
|
|
166
|
+
if (!opts || opts.emitEvent !== false) {
|
|
167
|
+
this.markForCheck();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
markAsPristine(opts) {
|
|
172
|
+
if (this.dirtySubject.value !== false) {
|
|
173
|
+
this.dirtySubject.next(false);
|
|
174
|
+
if (!opts || opts.emitEvent !== false) {
|
|
175
|
+
this.markForCheck();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async markAsUntouched(opts) {
|
|
180
|
+
let needEmitEvent = false;
|
|
181
|
+
if (this.touchedSubject.value) {
|
|
182
|
+
this.touchedSubject.next(false);
|
|
183
|
+
needEmitEvent = true;
|
|
184
|
+
}
|
|
185
|
+
if (this.dirty || this.dataSource.hasSomeEditingRow()) {
|
|
186
|
+
for (const row of this.dataSource.getEditingRows()) {
|
|
187
|
+
// Cancel the current editing row only if editing and if it was not previously saved
|
|
188
|
+
await this.dataSource.cancelOrDelete(row);
|
|
189
|
+
// Mark row as pristine
|
|
190
|
+
await this.checkIfRowPristine(row, { emitEvent: false });
|
|
191
|
+
}
|
|
192
|
+
needEmitEvent = true;
|
|
193
|
+
}
|
|
194
|
+
this.previouslyEditedRowId = undefined;
|
|
195
|
+
if (needEmitEvent && (!opts || opts.emitEvent !== false))
|
|
196
|
+
this.markForCheck();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* @deprecated prefer to use markAllAsTouched()
|
|
200
|
+
* @param opts
|
|
201
|
+
*/
|
|
202
|
+
markAsTouched(opts) {
|
|
203
|
+
console.warn('TODO: Replace this call by markAllAsTouched() - because of changes in ngx-components >= 0.16.0');
|
|
204
|
+
if (this.dataSource.hasSomeEditingRow()) {
|
|
205
|
+
this.dataSource.getEditingRows().forEach(row => row.validator?.markAllAsTouched());
|
|
206
|
+
if (!opts || opts.emitEvent !== false) {
|
|
207
|
+
this.markForCheck();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
markAllAsTouched(opts) {
|
|
212
|
+
if (this.touchedSubject.value !== true) {
|
|
213
|
+
this.touchedSubject.next(true);
|
|
214
|
+
if (!opts || opts.emitEvent !== false)
|
|
215
|
+
this.markForCheck();
|
|
216
|
+
}
|
|
217
|
+
if (this.dataSource.hasSomeEditingRow()) {
|
|
218
|
+
this.dataSource.getEditingRows().forEach(row => row.validator?.markAllAsTouched());
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
markAsSaving(opts) {
|
|
222
|
+
if (this.savingSubject.value !== true) {
|
|
223
|
+
this.focusColumn = undefined; // unselect focus column
|
|
224
|
+
this.savingSubject.next(true);
|
|
225
|
+
if (!opts || opts.emitEvent !== false)
|
|
226
|
+
this.markForCheck();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
markAsSaved(opts) {
|
|
230
|
+
if (this.savingSubject.value !== false) {
|
|
231
|
+
this.savingSubject.next(false);
|
|
232
|
+
if (!opts || opts.emitEvent !== false)
|
|
233
|
+
this.markForCheck();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
markAsLoading(opts) {
|
|
237
|
+
this.setLoading(true, opts);
|
|
238
|
+
}
|
|
239
|
+
markAsLoaded(opts) {
|
|
240
|
+
this.setLoading(false, opts);
|
|
241
|
+
}
|
|
242
|
+
markAsReady(opts) {
|
|
243
|
+
if (this.readySubject.value !== true) {
|
|
244
|
+
this.readySubject.next(true);
|
|
245
|
+
// If subclasses implements OnReady
|
|
246
|
+
if (typeof this['ngOnReady'] === 'function') {
|
|
247
|
+
this.ngOnReady();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
get loading() {
|
|
252
|
+
return this.loadingSubject.value;
|
|
253
|
+
}
|
|
254
|
+
get loaded() {
|
|
255
|
+
return !this.loadingSubject.value;
|
|
256
|
+
}
|
|
257
|
+
enableSort() {
|
|
258
|
+
if (this.sort)
|
|
259
|
+
this.sort.disabled = false;
|
|
260
|
+
}
|
|
261
|
+
disableSort() {
|
|
262
|
+
if (this.sort)
|
|
263
|
+
this.sort.disabled = true;
|
|
264
|
+
}
|
|
265
|
+
set pageSize(value) {
|
|
266
|
+
this.defaultPageSize = value;
|
|
267
|
+
if (this.paginator) {
|
|
268
|
+
this.paginator.pageSize = value;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
get pageSize() {
|
|
272
|
+
return this.paginator && this.paginator.pageSize || this.defaultPageSize || DEFAULT_PAGE_SIZE;
|
|
273
|
+
}
|
|
274
|
+
get pageOffset() {
|
|
275
|
+
return this.paginator && this.paginator.pageIndex * this.paginator.pageSize || 0;
|
|
276
|
+
}
|
|
277
|
+
get sortActive() {
|
|
278
|
+
return this.sort && this.sort.active;
|
|
279
|
+
}
|
|
280
|
+
get sortDirection() {
|
|
281
|
+
return this.sort && this.sort.direction && (this.sort.direction === 'desc' ? 'desc' : 'asc') || undefined;
|
|
282
|
+
}
|
|
283
|
+
set paginator(value) {
|
|
284
|
+
this._paginator = value;
|
|
285
|
+
}
|
|
286
|
+
get paginator() {
|
|
287
|
+
return this._paginator || this.childPaginator;
|
|
288
|
+
}
|
|
289
|
+
get destroyed() {
|
|
290
|
+
return this.destroySubject?.closed !== false;
|
|
291
|
+
}
|
|
292
|
+
ngOnInit() {
|
|
293
|
+
if (this._initialized)
|
|
294
|
+
return; // Init only once
|
|
295
|
+
this._initialized = true;
|
|
296
|
+
// Set defaults
|
|
297
|
+
this.readOnly = toBoolean(this.readOnly, this.dataSource?.config.readOnly || false); // read/write by default
|
|
298
|
+
this.inlineEdition = !this.readOnly && toBoolean(this.inlineEdition, false); // force to false when readonly
|
|
299
|
+
this.saveBeforeDelete = toBoolean(this.saveBeforeDelete, !this.readOnly); // force to false when readonly
|
|
300
|
+
this.saveBeforeSort = toBoolean(this.saveBeforeSort, !this.readOnly); // force to false when readonly
|
|
301
|
+
this.saveBeforeFilter = toBoolean(this.saveBeforeFilter, !this.readOnly); // force to false when readonly
|
|
302
|
+
this.keepEditedRowOnSave = toBoolean(this.keepEditedRowOnSave, this.inlineEdition);
|
|
303
|
+
this.errorTranslatorOptions = this.errorTranslatorOptions || { separator: ', ', controlPathTranslator: this }; // Can be override in subclasses constructors
|
|
304
|
+
// Check ask user confirmation is possible
|
|
305
|
+
if (this.confirmBeforeDelete && !this.alertCtrl)
|
|
306
|
+
throw Error('Missing \'alertCtrl\' or \'injector\' in component\'s constructor.');
|
|
307
|
+
// Defined unique id for settings for the page
|
|
308
|
+
this.settingsId = this.settingsId || this.generateTableId();
|
|
309
|
+
this.displayedColumns = this.getDisplayColumns();
|
|
310
|
+
// Load the sorted columns, from settings
|
|
311
|
+
{
|
|
312
|
+
const sortedColumn = this.getSortedColumn();
|
|
313
|
+
this.defaultSortBy = sortedColumn.id;
|
|
314
|
+
this.defaultSortDirection = sortedColumn.start;
|
|
315
|
+
}
|
|
316
|
+
this.defaultPageSize = this.getPageSize();
|
|
317
|
+
// Propagate error to event emitter
|
|
318
|
+
this.registerSubscription(this.errorSubject
|
|
319
|
+
.subscribe(value => this.onError.emit(value)));
|
|
320
|
+
// Propagate dirty to event emitter
|
|
321
|
+
this.registerSubscription(this.dirtySubject
|
|
322
|
+
.subscribe(value => this.onDirty.emit(value)));
|
|
323
|
+
// Propagate row dirty state to table
|
|
324
|
+
this.registerSubscription(this.onStartEditingRow
|
|
325
|
+
.pipe(filter(row => row?.validator && true), mergeMap(row => row.validator.valueChanges
|
|
326
|
+
.pipe(filter(row => row.dirty), first(),
|
|
327
|
+
// DEBUG
|
|
328
|
+
//tap(() => console.debug("Propagate row's dirty to table..."))
|
|
329
|
+
// Stop if next another row, or destroying
|
|
330
|
+
takeUntil(this.onStartEditingRow), takeUntil(this.destroySubject))))
|
|
331
|
+
.subscribe(() => this.markAsDirty()));
|
|
332
|
+
// Call datasource refresh, on each refresh events
|
|
333
|
+
this.registerSubscription(this.onRefresh
|
|
334
|
+
.pipe(startWith((this.autoLoad ? {} : 'skip')), switchMap((event) => {
|
|
335
|
+
this.dirtySubject.next(false);
|
|
336
|
+
this.selection.clear();
|
|
337
|
+
if (event === 'skip') {
|
|
338
|
+
return of(undefined);
|
|
339
|
+
}
|
|
340
|
+
if (!this._dataSource) {
|
|
341
|
+
if (this.debug)
|
|
342
|
+
console.debug('[table] Skipping data load: no dataSource defined');
|
|
343
|
+
return of(undefined);
|
|
344
|
+
}
|
|
345
|
+
if (this.debug)
|
|
346
|
+
console.debug('[table] Calling dataSource.watchAll()...');
|
|
347
|
+
return this._dataSource.watchAll(this.pageOffset, this.pageSize, this.sortActive, this.sortDirection, this._filter);
|
|
348
|
+
}), catchError(err => {
|
|
349
|
+
if (this.debug)
|
|
350
|
+
console.error(err);
|
|
351
|
+
this.setError(err && err.message || err);
|
|
352
|
+
return of(undefined); // Continue
|
|
353
|
+
}))
|
|
354
|
+
.subscribe(res => this.updateView(res)));
|
|
355
|
+
// Listen dataSource loading events
|
|
356
|
+
if (this._dataSource)
|
|
357
|
+
this.listenDatasourceLoading(this._dataSource);
|
|
358
|
+
}
|
|
359
|
+
ngAfterViewInit() {
|
|
360
|
+
// Detect when parent ngOnInit() not call
|
|
361
|
+
if (this.debug && !this.displayedColumns)
|
|
362
|
+
console.warn(`[table] Missing 'displayedColumns'. Did you call parent ngOnInit() in component ${this.constructor.name} ?`);
|
|
363
|
+
// Start listening sort and paginator events
|
|
364
|
+
// noinspection JSIgnoredPromiseFromCall
|
|
365
|
+
this.listenSortAndPaginationEvents();
|
|
366
|
+
}
|
|
367
|
+
ngOnDestroy() {
|
|
368
|
+
this._subscription.unsubscribe();
|
|
369
|
+
// Unsubscribe column value changes
|
|
370
|
+
Object.keys(this._cellValueChangesDefs).forEach(col => this.stopCellValueChanges(col, true));
|
|
371
|
+
this._cellValueChangesDefs = {};
|
|
372
|
+
this.readySubject.unsubscribe();
|
|
373
|
+
this.loadingSubject.unsubscribe();
|
|
374
|
+
this.savingSubject.unsubscribe();
|
|
375
|
+
this.errorSubject.unsubscribe();
|
|
376
|
+
this.dirtySubject.unsubscribe();
|
|
377
|
+
this.onRefresh.unsubscribe();
|
|
378
|
+
this.onOpenRow.unsubscribe();
|
|
379
|
+
this.onNewRow.unsubscribe();
|
|
380
|
+
this.onStartEditingRow.unsubscribe();
|
|
381
|
+
this.onConfirmEditCreateRow.unsubscribe();
|
|
382
|
+
this.onCancelOrDeleteRow.unsubscribe();
|
|
383
|
+
this.onBeforeDeleteRows.unsubscribe();
|
|
384
|
+
this.onBeforeCancelRows.unsubscribe();
|
|
385
|
+
this.onBeforeSave.unsubscribe();
|
|
386
|
+
this.onAfterDeletedRows.unsubscribe();
|
|
387
|
+
this.onSort.unsubscribe();
|
|
388
|
+
this.onDirty.unsubscribe();
|
|
389
|
+
this.onError.unsubscribe();
|
|
390
|
+
this.destroySubject.next();
|
|
391
|
+
this.destroySubject.unsubscribe();
|
|
392
|
+
}
|
|
393
|
+
async updateView(res, opts) {
|
|
394
|
+
if (!res)
|
|
395
|
+
return; // Skip (e.g error)
|
|
396
|
+
if (res && res.data) {
|
|
397
|
+
this.visibleRowCount = res.data.length;
|
|
398
|
+
this.totalRowCount = isNotNil(res.total) ? res.total : ((this.paginator && this.paginator.pageIndex * (this.paginator.pageSize || DEFAULT_PAGE_SIZE) || 0) + this.visibleRowCount);
|
|
399
|
+
if (this.debug)
|
|
400
|
+
console.debug(`[table] ${res.data.length} rows loaded`);
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
//if (this.debug) console.debug('[table] NO rows loaded');
|
|
404
|
+
this.totalRowCount = 0;
|
|
405
|
+
this.visibleRowCount = 0;
|
|
406
|
+
}
|
|
407
|
+
if (!opts || opts.emitEvent !== false) {
|
|
408
|
+
await this.markAsUntouched({ emitEvent: false });
|
|
409
|
+
this.markAsPristine({ emitEvent: false });
|
|
410
|
+
this.markAsLoaded({ emitEvent: false });
|
|
411
|
+
}
|
|
412
|
+
this.markForCheck();
|
|
413
|
+
}
|
|
414
|
+
setDatasource(datasource) {
|
|
415
|
+
if (this._dataSource)
|
|
416
|
+
throw new Error('[table] dataSource already set !');
|
|
417
|
+
if (datasource && this._dataSource !== datasource) {
|
|
418
|
+
this._dataSource = datasource;
|
|
419
|
+
if (this._initialized)
|
|
420
|
+
this.listenDatasourceLoading(datasource);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
resetDataSource() {
|
|
424
|
+
if (this._dataSourceLoadingSubscription) {
|
|
425
|
+
this._dataSourceLoadingSubscription.unsubscribe();
|
|
426
|
+
this._subscription.remove(this._dataSourceLoadingSubscription);
|
|
427
|
+
}
|
|
428
|
+
//this._dataSource?.close();
|
|
429
|
+
this._dataSource = null;
|
|
430
|
+
}
|
|
431
|
+
addColumnDef(column) {
|
|
432
|
+
this.table.addColumnDef(column);
|
|
433
|
+
}
|
|
434
|
+
removeColumnDef(column) {
|
|
435
|
+
this.table.removeColumnDef(column);
|
|
436
|
+
}
|
|
437
|
+
setFilter(filter, opts) {
|
|
438
|
+
opts = opts || { emitEvent: true };
|
|
439
|
+
if (this.saveBeforeFilter) {
|
|
440
|
+
// if a dirty table is to be saved before filter
|
|
441
|
+
if (this.dirty) {
|
|
442
|
+
// Save
|
|
443
|
+
this.saveBeforeAction('filter').then(saved => {
|
|
444
|
+
// Apply filter only if user didn't cancel the save or the save is ok
|
|
445
|
+
if (saved) {
|
|
446
|
+
this.applyFilter(filter, opts);
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
// apply filter on non-dirty table
|
|
452
|
+
this.applyFilter(filter, opts);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
// apply filter directly
|
|
457
|
+
this.applyFilter(filter, opts);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
async confirmAndAdd(event, row) {
|
|
461
|
+
if (!await this.confirmEditCreate(event, row)) {
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
// Add row
|
|
465
|
+
return await this.addRow(event);
|
|
466
|
+
}
|
|
467
|
+
async confirmAndBackward(event, row) {
|
|
468
|
+
// Deleting edited row, if empty and not dirty
|
|
469
|
+
if (this.dataSource.hasSomeEditingRow()) {
|
|
470
|
+
for (const editingRow of this.dataSource.getEditingRows().filter(row => row.id === -1 && row.invalid && !row.dirty)) {
|
|
471
|
+
await this.deleteNewRow(event, editingRow);
|
|
472
|
+
}
|
|
473
|
+
// Wait deletion is done, then edit previous row (by id, because of reloading)
|
|
474
|
+
await this.waitIdle();
|
|
475
|
+
await this.editRowById(event, row.id, { focusColumn: this.lastUserColumn });
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
// Edit previous row
|
|
479
|
+
await this.editRow(event, row, { focusColumn: this.lastUserColumn });
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
async confirmAndForward(event, row) {
|
|
483
|
+
if (!this.inlineEdition)
|
|
484
|
+
return false;
|
|
485
|
+
await this.confirmEditCreate(event, row);
|
|
486
|
+
// Edit next row
|
|
487
|
+
await this.editRowById(event, row.id + 1, { focusColumn: this.firstUserColumn });
|
|
488
|
+
return true;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Confirm the creation of the given row, or if not specified the currently edited row
|
|
492
|
+
*
|
|
493
|
+
* @param event
|
|
494
|
+
* @param row
|
|
495
|
+
*/
|
|
496
|
+
async confirmEditCreate(event, row) {
|
|
497
|
+
row = row || this.dataSource.getSingleEditingRow();
|
|
498
|
+
if (!row || !row.editing)
|
|
499
|
+
return true; // no row to confirm
|
|
500
|
+
// Stop event
|
|
501
|
+
event?.stopPropagation();
|
|
502
|
+
// Confirmation edition or creation
|
|
503
|
+
const confirmed = await row.confirmEditCreate();
|
|
504
|
+
if (confirmed) {
|
|
505
|
+
// Mark table as dirty (if row is dirty)
|
|
506
|
+
if (row.dirty) {
|
|
507
|
+
this.markAsDirty({ emitEvent: false /* because of resetError() */ });
|
|
508
|
+
}
|
|
509
|
+
// Clear error
|
|
510
|
+
this.resetError();
|
|
511
|
+
// Emit the confirm event
|
|
512
|
+
this.onConfirmEditCreateRow.next(row);
|
|
513
|
+
return true; // Continue
|
|
514
|
+
}
|
|
515
|
+
if (row.validator) {
|
|
516
|
+
// If pending: Wait end of validation
|
|
517
|
+
// TODO: remove when using async isValid() function
|
|
518
|
+
if (row.pending) {
|
|
519
|
+
await AppFormUtils.waitWhilePending(row.validator);
|
|
520
|
+
}
|
|
521
|
+
// NOT confirmed = row has error
|
|
522
|
+
if (this.debug) {
|
|
523
|
+
console.warn('[table] Cannot confirm row, because invalid');
|
|
524
|
+
AppFormUtils.logFormErrors(row.validator, '[table] ');
|
|
525
|
+
}
|
|
526
|
+
// fix: mark all controls as touched to show errors
|
|
527
|
+
row.validator.markAllAsTouched();
|
|
528
|
+
// Compute row error, and propagate to table's error
|
|
529
|
+
if (this.propagateRowError) {
|
|
530
|
+
const error = this.getRowError(row);
|
|
531
|
+
this.setError(error);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// Not confirmed
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
async cancelOrDelete(event, row, opts) {
|
|
538
|
+
// Delete new row
|
|
539
|
+
if (row.id === -1) {
|
|
540
|
+
await this.deleteNewRow(event, row);
|
|
541
|
+
}
|
|
542
|
+
// Delete existing (but not editing) row
|
|
543
|
+
else if (!row.editing) {
|
|
544
|
+
await this.deleteExistingRow(event, row, opts);
|
|
545
|
+
}
|
|
546
|
+
// Cancel existing (and editing) row
|
|
547
|
+
else {
|
|
548
|
+
await this.cancelExistingRow(event, row, opts);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
async addRow(event, insertAt, opts) {
|
|
552
|
+
if (this.debug)
|
|
553
|
+
console.debug('[table] Asking for new row...');
|
|
554
|
+
if (!this._enabled)
|
|
555
|
+
return false;
|
|
556
|
+
// Use modal if inline edition is disabled
|
|
557
|
+
if (!this.inlineEdition) {
|
|
558
|
+
await this.openNewRowDetail(event);
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
// Try to finish edited row first
|
|
562
|
+
if (!await this.confirmEditCreate()) {
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
// Add new row
|
|
566
|
+
const row = await this.addRowToTable(insertAt, opts);
|
|
567
|
+
return !!row;
|
|
568
|
+
}
|
|
569
|
+
async save(opts) {
|
|
570
|
+
opts = {
|
|
571
|
+
keepEditing: this.keepEditedRowOnSave,
|
|
572
|
+
...opts
|
|
573
|
+
};
|
|
574
|
+
if (this.readOnly) {
|
|
575
|
+
throw { code: ErrorCodes.TABLE_READ_ONLY, message: 'ERROR.TABLE_READ_ONLY' };
|
|
576
|
+
}
|
|
577
|
+
this.resetError();
|
|
578
|
+
// Keep edited row id (should be done BEFORE confirmEditCreate() )
|
|
579
|
+
const editedRow = this.dataSource.getSingleEditingRow();
|
|
580
|
+
this.previouslyEditedRowId = opts.keepEditing ? ((editedRow?.editing ? editedRow.id : undefined) || this.singleSelectedRow?.id) : undefined;
|
|
581
|
+
const previouslyEditedData = opts.keepEditing ? (isNotNil(this.previouslyEditedRowId) && editedRow?.currentData || this.singleSelectedRow?.currentData) : undefined;
|
|
582
|
+
if (!await this.confirmEditCreate()) {
|
|
583
|
+
throw { code: ErrorCodes.TABLE_INVALID_ROW_ERROR, message: 'ERROR.TABLE_INVALID_ROW_ERROR' };
|
|
584
|
+
}
|
|
585
|
+
// Mark as saving
|
|
586
|
+
this.markAsSaving();
|
|
587
|
+
try {
|
|
588
|
+
// Calling service save()
|
|
589
|
+
if (this.debug)
|
|
590
|
+
console.debug('[table] Calling dataSource.save()...');
|
|
591
|
+
const isOK = await this._dataSource.save();
|
|
592
|
+
if (isOK)
|
|
593
|
+
this.markAsPristine();
|
|
594
|
+
return isOK;
|
|
595
|
+
}
|
|
596
|
+
catch (err) {
|
|
597
|
+
this.setError(err && err.message || err);
|
|
598
|
+
throw err;
|
|
599
|
+
}
|
|
600
|
+
finally {
|
|
601
|
+
this.markAsSaved();
|
|
602
|
+
// Restore previous row
|
|
603
|
+
if (isNotNil(this.previouslyEditedRowId)) {
|
|
604
|
+
await this.selectRowByIdOrData(this.previouslyEditedRowId, previouslyEditedData);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
async cancel(event, opts) {
|
|
609
|
+
// Check confirmation
|
|
610
|
+
if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
|
|
611
|
+
event?.stopPropagation();
|
|
612
|
+
if (!await this.canCancelRows()) {
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
this.onRefresh.emit();
|
|
617
|
+
}
|
|
618
|
+
async duplicateRow(event, row, opts) {
|
|
619
|
+
event?.stopPropagation();
|
|
620
|
+
row = row || this.singleSelectedRow;
|
|
621
|
+
if (!row || !await this.confirmEditCreate(event, row)) {
|
|
622
|
+
return false;
|
|
623
|
+
}
|
|
624
|
+
const newRow = await this.addRowToTable(row.id + 1);
|
|
625
|
+
if (!newRow)
|
|
626
|
+
throw new Error('Cannot add new row to table');
|
|
627
|
+
const json = { ...row.currentData, id: null };
|
|
628
|
+
// Reset some properties (e.g. rankOrder, etc)
|
|
629
|
+
if (opts && opts.skipProperties) {
|
|
630
|
+
const newData = newRow.currentData;
|
|
631
|
+
opts.skipProperties.forEach(key => json[key] = newData[key]);
|
|
632
|
+
}
|
|
633
|
+
if (newRow.validator) {
|
|
634
|
+
newRow.validator.patchValue(json);
|
|
635
|
+
newRow.validator.markAsDirty();
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
if (newRow.currentData?.fromObject) {
|
|
639
|
+
newRow.currentData.fromObject(json);
|
|
640
|
+
}
|
|
641
|
+
else {
|
|
642
|
+
newRow.currentData = json;
|
|
643
|
+
}
|
|
644
|
+
this.markAsDirty();
|
|
645
|
+
}
|
|
646
|
+
// select
|
|
647
|
+
await this.clickRow(undefined, newRow);
|
|
648
|
+
}
|
|
649
|
+
/** Whether the number of selected elements matches the total number of rows. */
|
|
650
|
+
isAllSelected() {
|
|
651
|
+
// DEBUG
|
|
652
|
+
//console.debug('isAllSelected. lengths', this.selection.selected.length, this.totalRowCount);
|
|
653
|
+
return this.selection.selected.length === this.totalRowCount ||
|
|
654
|
+
this.selection.selected.length === this.visibleRowCount;
|
|
655
|
+
}
|
|
656
|
+
/** Selects all rows if they are not all selected; otherwise clear selection. */
|
|
657
|
+
async masterToggle() {
|
|
658
|
+
if (this.loading)
|
|
659
|
+
return;
|
|
660
|
+
if (this.isAllSelected()) {
|
|
661
|
+
this.selection.clear();
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
const rows = this._dataSource.getRows();
|
|
665
|
+
rows.forEach(row => this.selection.select(row));
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
deleteSelection(event, opts) {
|
|
669
|
+
return this.deleteRows(event, this.selection.selected, opts);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
*
|
|
673
|
+
* @param event
|
|
674
|
+
* @param row
|
|
675
|
+
* @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
|
|
676
|
+
* And to force deletion even if table is busy
|
|
677
|
+
*/
|
|
678
|
+
async deleteRow(event, row, opts) {
|
|
679
|
+
const deleteCount = await this.deleteRows(event, [row], opts);
|
|
680
|
+
return deleteCount === 1;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
*
|
|
684
|
+
* @param event
|
|
685
|
+
* @param rows
|
|
686
|
+
* @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
|
|
687
|
+
* And to force deletion even if table is busy
|
|
688
|
+
*/
|
|
689
|
+
async deleteRows(event, rows, opts) {
|
|
690
|
+
if (this.readOnly) {
|
|
691
|
+
throw { code: ErrorCodes.TABLE_READ_ONLY, message: 'ERROR.TABLE_READ_ONLY' };
|
|
692
|
+
}
|
|
693
|
+
if (event?.defaultPrevented)
|
|
694
|
+
return 0; // SKip
|
|
695
|
+
event?.preventDefault();
|
|
696
|
+
if (!this._enabled || isEmptyArray(rows))
|
|
697
|
+
return 0; // Skip is disabled, or no rows to delete
|
|
698
|
+
if (this.loading && (!opts || opts.interactive !== false)) {
|
|
699
|
+
console.warn('[app-table] Skip deleteRows() because table is busy (loading). Use opts.interactive = false to force deletion');
|
|
700
|
+
return 0; // Skip if loading
|
|
701
|
+
}
|
|
702
|
+
// Make sure to keep newly created row
|
|
703
|
+
const editedRow = this.dataSource.getSingleEditingRow();
|
|
704
|
+
if (editedRow?.id === -1 && editedRow.editing && !rows.includes(editedRow)) {
|
|
705
|
+
const confirmed = await this.confirmEditCreate();
|
|
706
|
+
if (!confirmed)
|
|
707
|
+
return 0; // Cannot delete (e.g. edited row is invalid)
|
|
708
|
+
}
|
|
709
|
+
// Check if it can delete
|
|
710
|
+
const canDelete = await this.canDeleteRows(rows, opts);
|
|
711
|
+
if (!canDelete)
|
|
712
|
+
return 0; // Cannot delete
|
|
713
|
+
// Reverse row order (on a copy)
|
|
714
|
+
// This is a workaround, need because row.delete() has async execution
|
|
715
|
+
// and index cache is updated with a delay
|
|
716
|
+
let tempRows = rows.slice()
|
|
717
|
+
.sort((a, b) => a.id > b.id ? -1 : 1);
|
|
718
|
+
let deletedRows = [];
|
|
719
|
+
// If data need to be saved first
|
|
720
|
+
if (this.saveBeforeDelete) {
|
|
721
|
+
// Exclude invalid rows (because of save() will fail, when exists some invalid rows)
|
|
722
|
+
tempRows = tempRows.filter(row => {
|
|
723
|
+
// Delete the row :
|
|
724
|
+
// - if newly created row (id = -1),
|
|
725
|
+
// - or if invalid and not editing (= not cancellable)
|
|
726
|
+
if (row.id === -1 || (!row.editing && row.invalid /*do not use !valid because if row is disabled, it will be always !valid */)) {
|
|
727
|
+
if (this.debug)
|
|
728
|
+
console.debug(`[table] Delete row #${row.id}`);
|
|
729
|
+
row.delete();
|
|
730
|
+
this.visibleRowCount--;
|
|
731
|
+
this.totalRowCount--;
|
|
732
|
+
deletedRows.push(row);
|
|
733
|
+
return false; // Exclude from the list to delete using the service
|
|
734
|
+
}
|
|
735
|
+
// Cancel the row (and mark as pristine), when not valid but in edition
|
|
736
|
+
else if (row.editing && !row.valid) {
|
|
737
|
+
row.cancel();
|
|
738
|
+
// Mark row as pristine (if possible)
|
|
739
|
+
this.checkIfRowPristine(row, { emitEvent: false, onlySelf: true /*avoid propagation to table*/ });
|
|
740
|
+
return true; // Keep the row. the row will be deleted after the save
|
|
741
|
+
}
|
|
742
|
+
return true;
|
|
743
|
+
});
|
|
744
|
+
// Apply save, only if there is still some rows to delete
|
|
745
|
+
// WARN: If no more rows (e.g. because all has been cancelled) then continue anyway to clear editedRow and selection (issue IMAGINE-669)
|
|
746
|
+
if (deletedRows.length || tempRows.length) {
|
|
747
|
+
// Save data (e.g. when using memory service)
|
|
748
|
+
const saved = await this.saveBeforeAction('delete');
|
|
749
|
+
if (!saved) {
|
|
750
|
+
// Stop if save cancelled or save failed
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
try {
|
|
756
|
+
// Apply deletion on datasource
|
|
757
|
+
// If no more rows to delete, continue anyway to clear editedRow and selection (issue IMAGINE-669)
|
|
758
|
+
if (tempRows.length) {
|
|
759
|
+
if (this.debug)
|
|
760
|
+
console.debug(`[table] Delete ${tempRows.length} rows...`);
|
|
761
|
+
await this._dataSource.deleteAll(tempRows);
|
|
762
|
+
}
|
|
763
|
+
// DO not update manually, because watchALl().subscribe() will update this count
|
|
764
|
+
//this.totalRowCount -= deleteCount;
|
|
765
|
+
//this.visibleRowCount -= deleteCount;
|
|
766
|
+
this.selection.clear();
|
|
767
|
+
this.markAsDirty({ emitEvent: false /*markForCheck() is called just after*/ });
|
|
768
|
+
this.markForCheck();
|
|
769
|
+
this.onAfterDeletedRows.next(rows);
|
|
770
|
+
return rows.length;
|
|
771
|
+
}
|
|
772
|
+
catch (err) {
|
|
773
|
+
this.setError(err && err.message || err);
|
|
774
|
+
throw err;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
async selectRowById(id) {
|
|
778
|
+
if (id === undefined)
|
|
779
|
+
return false;
|
|
780
|
+
await this.waitIdle();
|
|
781
|
+
const row = this.dataSource.getRow(id);
|
|
782
|
+
if (!row)
|
|
783
|
+
return false;
|
|
784
|
+
return this.clickRow(null, row);
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Try to select row by data. Will use dataEquals() (that call EntityUtils.equals()) to find same row's data
|
|
788
|
+
* @param data
|
|
789
|
+
*/
|
|
790
|
+
async selectRowByData(data) {
|
|
791
|
+
if (data === undefined)
|
|
792
|
+
return Promise.resolve(false);
|
|
793
|
+
await this.waitIdle();
|
|
794
|
+
const row = this.dataSource.getRows()
|
|
795
|
+
.find(row => this.equals(row.currentData, data));
|
|
796
|
+
if (!row)
|
|
797
|
+
return false;
|
|
798
|
+
return this.clickRow(null, row);
|
|
799
|
+
}
|
|
800
|
+
async clickRow(event, row) {
|
|
801
|
+
if (this.loading) {
|
|
802
|
+
// Wait while loading, and loop
|
|
803
|
+
if (this.debug)
|
|
804
|
+
console.debug('[table] Waiting before apply clickRow() (datasource is busy)...');
|
|
805
|
+
await this.waitIdle({ timeout: 2000 });
|
|
806
|
+
}
|
|
807
|
+
// DEBUG
|
|
808
|
+
//console.debug("[table] Detect click on row");
|
|
809
|
+
if (row.id === -1 || row.editing)
|
|
810
|
+
return true; // Already in edition
|
|
811
|
+
if (event?.defaultPrevented)
|
|
812
|
+
return false; // Cancelled by event
|
|
813
|
+
// Open the detail page (if not inline editing)
|
|
814
|
+
if (!this.inlineEdition) {
|
|
815
|
+
if (event) {
|
|
816
|
+
event.stopPropagation();
|
|
817
|
+
event.preventDefault();
|
|
818
|
+
}
|
|
819
|
+
this.markAsLoading();
|
|
820
|
+
this.selection.clear();
|
|
821
|
+
this.openRow(row.currentData.id, row)
|
|
822
|
+
.then(() => this.markAsLoaded())
|
|
823
|
+
.catch(() => this.markAsLoaded());
|
|
824
|
+
return true;
|
|
825
|
+
}
|
|
826
|
+
// Start editing row
|
|
827
|
+
return this.editRow(event, row, { focusColumn: undefined /*force to use the click target*/ });
|
|
828
|
+
}
|
|
829
|
+
async moveRow(id, direction) {
|
|
830
|
+
await this.dataSource.move(id, direction);
|
|
831
|
+
}
|
|
832
|
+
ready(opts) {
|
|
833
|
+
return waitForTrue(this.readySubject, opts);
|
|
834
|
+
}
|
|
835
|
+
waitIdle(opts) {
|
|
836
|
+
return waitForFalse(this.loadingSubject, opts);
|
|
837
|
+
}
|
|
838
|
+
async openSelectColumnsModal(event) {
|
|
839
|
+
event?.preventDefault();
|
|
840
|
+
// Copy current columns (deep copy)
|
|
841
|
+
const columns = this.getCurrentColumns();
|
|
842
|
+
const hasTopModal = !!(await this.modalCtrl.getTop());
|
|
843
|
+
const modal = await this.modalCtrl.create({
|
|
844
|
+
component: TableSelectColumnsComponent,
|
|
845
|
+
componentProps: { columns },
|
|
846
|
+
cssClass: hasTopModal && 'stack-modal'
|
|
847
|
+
});
|
|
848
|
+
// Open the modal
|
|
849
|
+
await modal.present();
|
|
850
|
+
// On dismiss
|
|
851
|
+
const { data } = await modal.onDidDismiss();
|
|
852
|
+
if (!data)
|
|
853
|
+
return; // CANCELLED
|
|
854
|
+
// Apply columns
|
|
855
|
+
const userColumns = (data || []).filter(c => c.canHide === false || c.visible).map(c => c.name) || [];
|
|
856
|
+
this.displayedColumns = RESERVED_START_COLUMNS.concat(userColumns).concat(RESERVED_END_COLUMNS);
|
|
857
|
+
this.markForCheck();
|
|
858
|
+
// Update user settings
|
|
859
|
+
await this.settings.savePageSetting(this.settingsId, userColumns, SETTINGS_DISPLAY_COLUMNS);
|
|
860
|
+
}
|
|
861
|
+
trackByFn(index, row) {
|
|
862
|
+
return row.id;
|
|
863
|
+
}
|
|
864
|
+
doRefresh(event) {
|
|
865
|
+
this.onRefresh.emit(event);
|
|
866
|
+
// When target wait for a complete (e.g. IonRefresher)
|
|
867
|
+
if (event?.target && event.target.complete) {
|
|
868
|
+
setTimeout(async () => {
|
|
869
|
+
await this.waitIdle();
|
|
870
|
+
event.target.complete();
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
getCurrentColumns() {
|
|
875
|
+
const hiddenColumns = this.columns.slice(RESERVED_START_COLUMNS.length)
|
|
876
|
+
.filter(name => this.displayedColumns.indexOf(name) === -1);
|
|
877
|
+
return this.displayedColumns
|
|
878
|
+
.concat(hiddenColumns)
|
|
879
|
+
.filter(name => !RESERVED_START_COLUMNS.includes(name) && !RESERVED_END_COLUMNS.includes(name)
|
|
880
|
+
&& !this.excludesColumns.includes(name))
|
|
881
|
+
.map(name => ({
|
|
882
|
+
name,
|
|
883
|
+
label: this.getI18nColumnName(name),
|
|
884
|
+
visible: this.displayedColumns.indexOf(name) !== -1,
|
|
885
|
+
canHide: this.getRequiredColumns().indexOf(name) === -1
|
|
886
|
+
}));
|
|
887
|
+
}
|
|
888
|
+
async escapeEditingRow(event, row) {
|
|
889
|
+
row = row || this.dataSource.getSingleEditingRow();
|
|
890
|
+
if (!row || !row.editing)
|
|
891
|
+
return;
|
|
892
|
+
// DEBUG
|
|
893
|
+
//console.debug('[app-table] Cancel the row (keydown.escape)');
|
|
894
|
+
if (event) {
|
|
895
|
+
// Avoid to cancel the editor
|
|
896
|
+
event.preventDefault();
|
|
897
|
+
event.stopPropagation();
|
|
898
|
+
}
|
|
899
|
+
// If new row (no id)
|
|
900
|
+
if (row.id === -1) {
|
|
901
|
+
if (row.validator) {
|
|
902
|
+
// If pending: Wait end of validation, then loop
|
|
903
|
+
if (row.pending) {
|
|
904
|
+
await AppFormUtils.waitWhilePending(row.validator);
|
|
905
|
+
}
|
|
906
|
+
// Row is invalid: delete the row
|
|
907
|
+
if (row.invalid) {
|
|
908
|
+
await this.deleteNewRow(event, row);
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
// If the row exists (has an id)
|
|
914
|
+
else {
|
|
915
|
+
// need to call cancel function (if confirmation will be called before)
|
|
916
|
+
if (this.confirmBeforeCancel) {
|
|
917
|
+
await this.cancelExistingRow(event, row, { keepEditing: false });
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
// By default, try to confirm the row
|
|
922
|
+
await this.confirmEditCreate(event, row);
|
|
923
|
+
}
|
|
924
|
+
translateControlPath(path) {
|
|
925
|
+
// Can be overridden by subclasses, to resolve all field name
|
|
926
|
+
// Use columns key, has default name
|
|
927
|
+
const i18nColumnKey = this.getI18nColumnName(path);
|
|
928
|
+
return this.translate?.instant(i18nColumnKey) || i18nColumnKey;
|
|
929
|
+
}
|
|
930
|
+
/* -- protected method -- */
|
|
931
|
+
async editRow(event, row, opts) {
|
|
932
|
+
if (!this._enabled || !this.inlineEdition)
|
|
933
|
+
return false;
|
|
934
|
+
if (this.dataSource.getEditingRows().includes(row))
|
|
935
|
+
return true; // Already the edited row
|
|
936
|
+
if (event?.defaultPrevented)
|
|
937
|
+
return false;
|
|
938
|
+
if (!await this.confirmEditCreate()) {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
if (!row.editing && !this.loading) {
|
|
942
|
+
this.focusColumn = opts && opts.focusColumn || this.focusColumn;
|
|
943
|
+
await this._dataSource.startEdit(row);
|
|
944
|
+
}
|
|
945
|
+
this.onStartEditingRow.emit(row);
|
|
946
|
+
return true;
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Try to select row, by row.id, or by data. WIll use EntityUtils.equals()
|
|
950
|
+
* @param id
|
|
951
|
+
* @param data
|
|
952
|
+
* @protected
|
|
953
|
+
*/
|
|
954
|
+
async selectRowByIdOrData(id, data) {
|
|
955
|
+
let done = false;
|
|
956
|
+
try {
|
|
957
|
+
// Select by row id (if NOT a new row)
|
|
958
|
+
if (isNotNil(id) || id !== -1) {
|
|
959
|
+
done = await this.selectRowById(id);
|
|
960
|
+
if (done)
|
|
961
|
+
return true;
|
|
962
|
+
console.warn('[app-table] Save: Cannot reselect row by row.id: ', id);
|
|
963
|
+
}
|
|
964
|
+
// Try by data
|
|
965
|
+
if (data) {
|
|
966
|
+
done = await this.selectRowByData(data);
|
|
967
|
+
if (done)
|
|
968
|
+
return true;
|
|
969
|
+
console.warn('[app-table] Save: Cannot reselect row by data: ', data);
|
|
970
|
+
}
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
catch (err) {
|
|
974
|
+
// Log, but continue
|
|
975
|
+
console.error(err && err.message || err);
|
|
976
|
+
return false;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* return the selected row if unique in selection
|
|
981
|
+
*/
|
|
982
|
+
get singleSelectedRow() {
|
|
983
|
+
return this.selection.selected?.length === 1 ? this.selection.selected[0] : undefined;
|
|
984
|
+
}
|
|
985
|
+
async canDeleteRows(rows, opts) {
|
|
986
|
+
// Check using emitter
|
|
987
|
+
if (this.onBeforeDeleteRows.observers.length > 0) {
|
|
988
|
+
try {
|
|
989
|
+
const canDelete = await emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
|
|
990
|
+
detail: { rows }
|
|
991
|
+
});
|
|
992
|
+
if (!canDelete)
|
|
993
|
+
return false;
|
|
994
|
+
}
|
|
995
|
+
catch (err) {
|
|
996
|
+
if (err === 'CANCELLED')
|
|
997
|
+
return false; // User cancel
|
|
998
|
+
console.error('Error while checking if can delete rows', err);
|
|
999
|
+
throw err;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
// Ask user confirmation
|
|
1003
|
+
if (this.confirmBeforeDelete && (!opts || opts.interactive !== false)) {
|
|
1004
|
+
return this.askDeleteConfirmation(null, rows);
|
|
1005
|
+
}
|
|
1006
|
+
return true;
|
|
1007
|
+
}
|
|
1008
|
+
async canCancelRows(rows, opts) {
|
|
1009
|
+
// Get dirty rows
|
|
1010
|
+
rows = rows || this.dataSource.getRows().filter(row => row.validator?.dirty);
|
|
1011
|
+
if (isEmptyArray(rows))
|
|
1012
|
+
return true; // No dirty: OK
|
|
1013
|
+
// Check using emitter
|
|
1014
|
+
if (this.onBeforeCancelRows.observers.length > 0) {
|
|
1015
|
+
try {
|
|
1016
|
+
const isCancel = await emitPromiseEvent(this.onBeforeCancelRows, 'canCancel', {
|
|
1017
|
+
detail: { rows }
|
|
1018
|
+
});
|
|
1019
|
+
if (!isCancel)
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
catch (err) {
|
|
1023
|
+
if (err === 'CANCELLED')
|
|
1024
|
+
return false; // User cancel
|
|
1025
|
+
console.error('Error while checking if can cancel rows', err);
|
|
1026
|
+
throw err;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
// Ask user confirmation
|
|
1030
|
+
if (this.confirmBeforeCancel && (!opts || opts.interactive !== false)) {
|
|
1031
|
+
return this.askCancelConfirmation(null, rows);
|
|
1032
|
+
}
|
|
1033
|
+
return true;
|
|
1034
|
+
}
|
|
1035
|
+
async saveBeforeAction(saveAction) {
|
|
1036
|
+
if (!this.dirty) {
|
|
1037
|
+
// Continue without save
|
|
1038
|
+
return true;
|
|
1039
|
+
}
|
|
1040
|
+
let save;
|
|
1041
|
+
switch (saveAction) {
|
|
1042
|
+
case 'delete':
|
|
1043
|
+
save = this.saveBeforeDelete;
|
|
1044
|
+
break;
|
|
1045
|
+
case 'filter':
|
|
1046
|
+
save = this.saveBeforeFilter;
|
|
1047
|
+
break;
|
|
1048
|
+
case 'sort':
|
|
1049
|
+
save = this.saveBeforeSort;
|
|
1050
|
+
break;
|
|
1051
|
+
default:
|
|
1052
|
+
save = true;
|
|
1053
|
+
}
|
|
1054
|
+
// Default behavior
|
|
1055
|
+
let confirmed = true;
|
|
1056
|
+
if (save) {
|
|
1057
|
+
if (this.onBeforeSave.observers.length > 0) {
|
|
1058
|
+
// Ask confirmation
|
|
1059
|
+
try {
|
|
1060
|
+
const res = await emitPromiseEvent(this.onBeforeSave, 'beforeSave', {
|
|
1061
|
+
detail: { action: saveAction, valid: this.valid }
|
|
1062
|
+
});
|
|
1063
|
+
confirmed = res.confirmed;
|
|
1064
|
+
save = res.save;
|
|
1065
|
+
}
|
|
1066
|
+
catch (err) {
|
|
1067
|
+
if (err === 'CANCELLED')
|
|
1068
|
+
return false; // User cancel
|
|
1069
|
+
console.error('Error while checking if can delete rows', err);
|
|
1070
|
+
throw err;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
if (confirmed) {
|
|
1075
|
+
if (save) {
|
|
1076
|
+
// User confirmed save
|
|
1077
|
+
const saved = await this.save();
|
|
1078
|
+
this.markAsDirty(); // Restore dirty flag
|
|
1079
|
+
return saved;
|
|
1080
|
+
}
|
|
1081
|
+
return true; // No save but continue action
|
|
1082
|
+
}
|
|
1083
|
+
return false; // User cancel the action
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Open a row detail view. By default, will to open row detail page.
|
|
1087
|
+
* Can be overridden by subclasses, BUT prefer to subscribe on onOpenRow
|
|
1088
|
+
* @param id
|
|
1089
|
+
* @param row
|
|
1090
|
+
* @protected
|
|
1091
|
+
*/
|
|
1092
|
+
async openRow(id, row) {
|
|
1093
|
+
if (this.allowRowDetail) {
|
|
1094
|
+
if (this.debug && this.dirty) {
|
|
1095
|
+
console.warn('[table] Opening row details, but table has unsaved changes!');
|
|
1096
|
+
}
|
|
1097
|
+
if (this.onOpenRow.observers.length) {
|
|
1098
|
+
this.onOpenRow.emit(row);
|
|
1099
|
+
return true;
|
|
1100
|
+
}
|
|
1101
|
+
// No ID defined: unable to open details
|
|
1102
|
+
if (isNil(id)) {
|
|
1103
|
+
console.warn('[table] Opening row details, but data has no id!');
|
|
1104
|
+
return false;
|
|
1105
|
+
}
|
|
1106
|
+
return this.router.navigate(['.', id.toString()], {
|
|
1107
|
+
relativeTo: this.route,
|
|
1108
|
+
queryParams: {}
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
return false;
|
|
1112
|
+
}
|
|
1113
|
+
async openNewRowDetail(event) {
|
|
1114
|
+
if (!this.allowRowDetail)
|
|
1115
|
+
return false;
|
|
1116
|
+
if (this.onNewRow.observers.length > 0) {
|
|
1117
|
+
this.onNewRow.emit(event);
|
|
1118
|
+
return true;
|
|
1119
|
+
}
|
|
1120
|
+
return await this.router.navigate(['new'], {
|
|
1121
|
+
relativeTo: this.route
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
// can be overridden to add more required columns
|
|
1125
|
+
getRequiredColumns() {
|
|
1126
|
+
return DEFAULT_REQUIRED_COLUMNS;
|
|
1127
|
+
}
|
|
1128
|
+
getUserColumns() {
|
|
1129
|
+
return this.settings.getPageSettings(this.settingsId, SETTINGS_DISPLAY_COLUMNS);
|
|
1130
|
+
}
|
|
1131
|
+
getSortedColumn() {
|
|
1132
|
+
const data = this.settings.getPageSettings(this.settingsId, SETTINGS_SORTED_COLUMN);
|
|
1133
|
+
const parts = data && data.split(':');
|
|
1134
|
+
if (parts && parts.length === 2 && this.columns.includes(parts[0])) {
|
|
1135
|
+
return { id: parts[0], start: parts[1] === 'desc' ? 'desc' : 'asc', disableClear: false };
|
|
1136
|
+
}
|
|
1137
|
+
if (this.defaultSortBy) {
|
|
1138
|
+
return { id: this.defaultSortBy, start: this.defaultSortDirection || 'asc', disableClear: false };
|
|
1139
|
+
}
|
|
1140
|
+
return { id: 'id', start: 'asc', disableClear: false };
|
|
1141
|
+
}
|
|
1142
|
+
getPageSize() {
|
|
1143
|
+
const pageSize = this.settings.getPageSettings(this.settingsId, SETTINGS_PAGE_SIZE);
|
|
1144
|
+
return pageSize || this.defaultPageSize;
|
|
1145
|
+
}
|
|
1146
|
+
getDisplayColumns() {
|
|
1147
|
+
let userColumns = this.getUserColumns();
|
|
1148
|
+
// No user override
|
|
1149
|
+
if (!userColumns) {
|
|
1150
|
+
// Return default, without columns to hide
|
|
1151
|
+
return this.columns.filter(column => !this.excludesColumns.includes(column));
|
|
1152
|
+
}
|
|
1153
|
+
// Get fixed start columns
|
|
1154
|
+
const fixedStartColumns = this.columns.filter(c => RESERVED_START_COLUMNS.includes(c));
|
|
1155
|
+
// Remove end columns
|
|
1156
|
+
const fixedEndColumns = this.columns.filter(c => RESERVED_END_COLUMNS.includes(c));
|
|
1157
|
+
// Remove fixed columns from user columns
|
|
1158
|
+
userColumns = userColumns.filter(c => !fixedStartColumns.includes(c) && !fixedEndColumns.includes(c) && this.columns.includes(c));
|
|
1159
|
+
// Add required columns if missing
|
|
1160
|
+
userColumns.push(...this.getRequiredColumns().filter(c => !fixedStartColumns.includes(c) && !fixedEndColumns.includes(c) && !userColumns.includes(c)));
|
|
1161
|
+
return fixedStartColumns
|
|
1162
|
+
.concat(userColumns)
|
|
1163
|
+
.concat(fixedEndColumns)
|
|
1164
|
+
// Remove columns to hide
|
|
1165
|
+
.filter(column => !this.excludesColumns.includes(column));
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Recompute display columns
|
|
1169
|
+
*
|
|
1170
|
+
* @protected
|
|
1171
|
+
*/
|
|
1172
|
+
updateColumns() {
|
|
1173
|
+
this.displayedColumns = this.getDisplayColumns();
|
|
1174
|
+
if (!this.loading)
|
|
1175
|
+
this.markForCheck();
|
|
1176
|
+
}
|
|
1177
|
+
registerSubscription(sub) {
|
|
1178
|
+
this._subscription.add(sub);
|
|
1179
|
+
}
|
|
1180
|
+
unregisterSubscription(sub) {
|
|
1181
|
+
this._subscription.remove(sub);
|
|
1182
|
+
}
|
|
1183
|
+
registerAutocompleteField(fieldName, options) {
|
|
1184
|
+
return this._autocompleteConfigHolder.add(fieldName, options);
|
|
1185
|
+
}
|
|
1186
|
+
getI18nColumnName(columnName) {
|
|
1187
|
+
return (this.i18nColumnPrefix || '') + changeCaseToUnderscore(columnName).toUpperCase();
|
|
1188
|
+
}
|
|
1189
|
+
generateTableId() {
|
|
1190
|
+
// noinspection JSNonASCIINames
|
|
1191
|
+
const id = this.location.path(true)
|
|
1192
|
+
.replace(/[?].*$/g, '')
|
|
1193
|
+
.replace(/\/\d+/g, '_id')
|
|
1194
|
+
+ '_'
|
|
1195
|
+
// Get a component unique name - See https://stackoverflow.com/questions/60114682/how-to-access-components-unique-encapsulation-id-in-angular-9
|
|
1196
|
+
+ (this.constructor['ɵcmp']?.id || this.constructor.name);
|
|
1197
|
+
//if (this.debug) console.debug("[table] id = " + id);
|
|
1198
|
+
return id;
|
|
1199
|
+
}
|
|
1200
|
+
async addRowToTable(insertAt, opts) {
|
|
1201
|
+
// Try to finish edited row first
|
|
1202
|
+
if (!await this.confirmEditCreate()) {
|
|
1203
|
+
console.warn('[table] Cannot add new row, because the previous edited row cannot be confirmed');
|
|
1204
|
+
return undefined;
|
|
1205
|
+
}
|
|
1206
|
+
const editing = this.inlineEdition && (!opts || opts.editing !== false); // true by default, if inlineEdition
|
|
1207
|
+
const row = await this._dataSource.createNew(insertAt, { editing });
|
|
1208
|
+
if (!row)
|
|
1209
|
+
return undefined;
|
|
1210
|
+
if (row.editing) {
|
|
1211
|
+
// Update focused column
|
|
1212
|
+
this.focusFirstColumn = true;
|
|
1213
|
+
this.focusColumn = opts?.focusColumn || this.firstUserColumn;
|
|
1214
|
+
// Emit start editing event
|
|
1215
|
+
this.onStartEditingRow.emit(row);
|
|
1216
|
+
}
|
|
1217
|
+
this.totalRowCount++;
|
|
1218
|
+
this.visibleRowCount++;
|
|
1219
|
+
this.markAsDirty({ emitEvent: false /*markForCheck() is called just after*/ });
|
|
1220
|
+
// Emit event
|
|
1221
|
+
if (!opts || opts.emitEvent !== false)
|
|
1222
|
+
this.markForCheck();
|
|
1223
|
+
return row;
|
|
1224
|
+
}
|
|
1225
|
+
registerCellValueChanges(name, formPath, emitInitialValue) {
|
|
1226
|
+
formPath = formPath || name;
|
|
1227
|
+
emitInitialValue = emitInitialValue || false;
|
|
1228
|
+
let def = this._cellValueChangesDefs[name];
|
|
1229
|
+
if (def && (def.formPath !== formPath || def.emitInitialValue !== emitInitialValue)) {
|
|
1230
|
+
throw Error('Already register a cell value change for this name, with different \'formPath\' or \'emitInitialValue\'. Please use same arguments.');
|
|
1231
|
+
}
|
|
1232
|
+
// Not exists: register new definition
|
|
1233
|
+
if (!def) {
|
|
1234
|
+
if (this.debug)
|
|
1235
|
+
console.debug(`[table] New listener {${name}} for value changes on path ${formPath}`);
|
|
1236
|
+
def = {
|
|
1237
|
+
subject: new Subject(),
|
|
1238
|
+
subscription: null,
|
|
1239
|
+
formPath,
|
|
1240
|
+
emitInitialValue
|
|
1241
|
+
};
|
|
1242
|
+
this._cellValueChangesDefs[name] = def;
|
|
1243
|
+
// Start the listener, when editing starts
|
|
1244
|
+
this.registerSubscription(this.onStartEditingRow.subscribe(row => this.startCellValueChanges(name, row)));
|
|
1245
|
+
}
|
|
1246
|
+
return def.subject;
|
|
1247
|
+
}
|
|
1248
|
+
setShowColumn(columnName, show, opts) {
|
|
1249
|
+
if (!this.excludesColumns.includes(columnName) !== show) {
|
|
1250
|
+
if (!show) {
|
|
1251
|
+
this.excludesColumns.push(columnName);
|
|
1252
|
+
}
|
|
1253
|
+
else {
|
|
1254
|
+
const index = this.excludesColumns.findIndex(value => value === columnName);
|
|
1255
|
+
if (index >= 0)
|
|
1256
|
+
this.excludesColumns.splice(index, 1);
|
|
1257
|
+
}
|
|
1258
|
+
// Recompute display columns
|
|
1259
|
+
if (this.displayedColumns && (!opts || opts.emitEvent !== false)) {
|
|
1260
|
+
this.updateColumns();
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
getShowColumn(columnName) {
|
|
1265
|
+
return !this.excludesColumns.includes(columnName);
|
|
1266
|
+
}
|
|
1267
|
+
startsWithUpperCase(input, search) {
|
|
1268
|
+
return input && input.toUpperCase().startsWith(search);
|
|
1269
|
+
}
|
|
1270
|
+
markForCheck() {
|
|
1271
|
+
// Should be overridden by subclasses, depending on ChangeDetectionStrategy
|
|
1272
|
+
}
|
|
1273
|
+
async askDeleteConfirmation(event, rows) {
|
|
1274
|
+
if (this.undoableDeletion) {
|
|
1275
|
+
// Special message, for undoable deletion
|
|
1276
|
+
return Alerts.askConfirmation(rows?.length === 1 ? 'CONFIRM.DELETE_ROW' : 'CONFIRM.DELETE_ROWS', this.alertCtrl, this.translate, event);
|
|
1277
|
+
}
|
|
1278
|
+
// Immediate deletion action
|
|
1279
|
+
return Alerts.askActionConfirmation(this.alertCtrl, this.translate, true, event);
|
|
1280
|
+
}
|
|
1281
|
+
async askCancelConfirmation(event, rows) {
|
|
1282
|
+
return Alerts.askConfirmation(rows?.length === 1 ? 'CONFIRM.CANCEL_ROW' : 'CONFIRM.CANCEL_ROWS', this.alertCtrl, this.translate, event);
|
|
1283
|
+
}
|
|
1284
|
+
async askRestoreConfirmation(event) {
|
|
1285
|
+
return Alerts.askActionConfirmation(this.alertCtrl, this.translate, false, event);
|
|
1286
|
+
}
|
|
1287
|
+
async showToast(opts) {
|
|
1288
|
+
if (!this.toastController)
|
|
1289
|
+
throw new Error('Missing toastController in component\'s constructor');
|
|
1290
|
+
return Toasts.show(this.toastController, this.translate, opts);
|
|
1291
|
+
}
|
|
1292
|
+
resetError(opts) {
|
|
1293
|
+
this.setError(undefined, opts);
|
|
1294
|
+
}
|
|
1295
|
+
getRowError(row, opts) {
|
|
1296
|
+
row = row || this.dataSource.getSingleEditingRow();
|
|
1297
|
+
if (!row || !this.formErrorAdapter)
|
|
1298
|
+
return undefined;
|
|
1299
|
+
return this.formErrorAdapter.translateFormErrors(row.validator, {
|
|
1300
|
+
...this.errorTranslatorOptions,
|
|
1301
|
+
...opts
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
setError(value, opts) {
|
|
1305
|
+
if (this.errorSubject.value !== value) {
|
|
1306
|
+
this.errorSubject.next(value);
|
|
1307
|
+
if (!opts || opts.emitEvent !== false) {
|
|
1308
|
+
this.markForCheck();
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Compare data equality (default by id)
|
|
1314
|
+
* Can be overridden to add additional properties to compare
|
|
1315
|
+
*
|
|
1316
|
+
* @param d1
|
|
1317
|
+
* @param d2
|
|
1318
|
+
* @protected
|
|
1319
|
+
*/
|
|
1320
|
+
equals(d1, d2) {
|
|
1321
|
+
return EntityUtils.equals(d1, d2, 'id');
|
|
1322
|
+
}
|
|
1323
|
+
markRowAsDirty(row, opts) {
|
|
1324
|
+
row = row || this.dataSource.getSingleEditingRow();
|
|
1325
|
+
if (row)
|
|
1326
|
+
row.validator?.markAsDirty(opts);
|
|
1327
|
+
this.markAsDirty(opts);
|
|
1328
|
+
}
|
|
1329
|
+
/* -- private method -- */
|
|
1330
|
+
async listenSortAndPaginationEvents() {
|
|
1331
|
+
if (!this.table) {
|
|
1332
|
+
// DEBUG only -- alert user that table not found in template
|
|
1333
|
+
if (this.debug) {
|
|
1334
|
+
setTimeout(() => !this.table && console.warn(`[table] Missing <mat-table> in the HTML template (after waiting 500ms)! Component: ${this.constructor.name}`), 500);
|
|
1335
|
+
}
|
|
1336
|
+
// Make sure to wait the table
|
|
1337
|
+
await waitFor(() => !!this.table, { stop: this.destroySubject, stopError: false /*avoid error when destorying the table*/ });
|
|
1338
|
+
}
|
|
1339
|
+
this.registerSubscription(merge(
|
|
1340
|
+
// Listen sort events
|
|
1341
|
+
this.sort && this.sort.sortChange
|
|
1342
|
+
.pipe(filter(() => !this.sort.disabled), mergeMap(async () => this.saveBeforeAction('sort')), filter(res => res === true),
|
|
1343
|
+
// Save sort in settings
|
|
1344
|
+
tap(() => {
|
|
1345
|
+
const value = [this.sort.active, this.sort.direction || 'asc'].join(':');
|
|
1346
|
+
this.settings.savePageSetting(this.settingsId, value, SETTINGS_SORTED_COLUMN);
|
|
1347
|
+
}))
|
|
1348
|
+
|| EMPTY,
|
|
1349
|
+
// Listen paginator events
|
|
1350
|
+
this.paginator && this.paginator.page
|
|
1351
|
+
.pipe(mergeMap((_) => this.saveBeforeAction('sort')), filter(saved => saved === true),
|
|
1352
|
+
// Save page size in settings
|
|
1353
|
+
tap(() => this.settings.savePageSetting(this.settingsId, this.paginator.pageSize, SETTINGS_PAGE_SIZE))) || EMPTY)
|
|
1354
|
+
// Refresh on any sort or paginator events
|
|
1355
|
+
.subscribe(value => {
|
|
1356
|
+
this.onSort.emit(value);
|
|
1357
|
+
this.onRefresh.emit(value);
|
|
1358
|
+
}));
|
|
1359
|
+
// If the user changes the sort order, reset back to the first page.
|
|
1360
|
+
if (this.sort && this.paginator) {
|
|
1361
|
+
this.registerSubscription(this.sort.sortChange
|
|
1362
|
+
.pipe(filter(() => !this.sort.disabled))
|
|
1363
|
+
.subscribe(() => this.paginator.pageIndex = 0));
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
async editRowById(event, id, opts) {
|
|
1367
|
+
if (id < 0)
|
|
1368
|
+
return;
|
|
1369
|
+
if (id >= this.visibleRowCount) {
|
|
1370
|
+
await this.addRow(event, undefined, { ...opts, editing: true });
|
|
1371
|
+
}
|
|
1372
|
+
else {
|
|
1373
|
+
const row = await this.dataSource.getRow(id);
|
|
1374
|
+
await this.editRow(event, row, opts);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
setLoading(value, opts) {
|
|
1378
|
+
if (this.loadingSubject.value !== value) {
|
|
1379
|
+
this.loadingSubject.next(value);
|
|
1380
|
+
if (!opts || opts.emitEvent !== false) {
|
|
1381
|
+
this.markForCheck();
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
async deleteNewRow(event, row) {
|
|
1386
|
+
if (row.id !== -1)
|
|
1387
|
+
throw new Error('Row must have id = -1');
|
|
1388
|
+
event?.stopPropagation();
|
|
1389
|
+
this.selection.clear();
|
|
1390
|
+
await this._dataSource.cancelOrDelete(row);
|
|
1391
|
+
this.onCancelOrDeleteRow.next(row);
|
|
1392
|
+
this.resetError();
|
|
1393
|
+
this.totalRowCount--;
|
|
1394
|
+
this.visibleRowCount--;
|
|
1395
|
+
}
|
|
1396
|
+
async deleteExistingRow(event, row, opts) {
|
|
1397
|
+
// Make sure row will be cancelled, and NOT deleted
|
|
1398
|
+
if (row.id === -1)
|
|
1399
|
+
throw new Error('Row must have an id');
|
|
1400
|
+
if (event?.defaultPrevented)
|
|
1401
|
+
return 0; // SKip
|
|
1402
|
+
event?.preventDefault();
|
|
1403
|
+
await this.deleteRow(null, row, opts);
|
|
1404
|
+
}
|
|
1405
|
+
async cancelExistingRow(event, row, opts) {
|
|
1406
|
+
// Make sure row will be cancelled, and NOT deleted
|
|
1407
|
+
if (row.id === -1 || !row.editing)
|
|
1408
|
+
throw new Error('Row cannot be canceling, but only deleting');
|
|
1409
|
+
const confirmed = (!opts || opts.interactive !== false);
|
|
1410
|
+
// Ask user confirmation, if cancel
|
|
1411
|
+
if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
|
|
1412
|
+
event.stopPropagation();
|
|
1413
|
+
if (!await this.canCancelRows([row], opts)) {
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
const keepEditing = row.editing && (!opts || opts.keepEditing !== false);
|
|
1418
|
+
await this._dataSource.cancelOrDelete(row);
|
|
1419
|
+
this.onCancelOrDeleteRow.next(row);
|
|
1420
|
+
// Mark row as pristine
|
|
1421
|
+
await this.checkIfRowPristine(row);
|
|
1422
|
+
// Restore editing state
|
|
1423
|
+
if (keepEditing) {
|
|
1424
|
+
await this.editRow(undefined, row);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
async checkIfRowPristine(row, opts) {
|
|
1428
|
+
// Mark row as pristine
|
|
1429
|
+
const markRowAsPristine = this.dataSource?.config.restoreOriginalDataOnCancel === true;
|
|
1430
|
+
if (markRowAsPristine) {
|
|
1431
|
+
row.validator?.markAsPristine();
|
|
1432
|
+
// Check if table is now pristine
|
|
1433
|
+
if (!opts || opts.onlySelf !== true) {
|
|
1434
|
+
await this.checkIfPristine(opts);
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
async checkIfPristine(opts) {
|
|
1439
|
+
if (!this.dirty)
|
|
1440
|
+
return; // Already pristine
|
|
1441
|
+
const rows = this._dataSource.getRows();
|
|
1442
|
+
const pristine = (rows || []).findIndex(row => row.dirty) === -1;
|
|
1443
|
+
if (pristine)
|
|
1444
|
+
this.markAsPristine(opts);
|
|
1445
|
+
}
|
|
1446
|
+
applyFilter(filter, opts) {
|
|
1447
|
+
if (this.debug)
|
|
1448
|
+
console.debug('[table] Applying filter', filter);
|
|
1449
|
+
this._filter = filter;
|
|
1450
|
+
if (opts && opts.emitEvent) {
|
|
1451
|
+
if (this.paginator && this.paginator.pageIndex > 0) {
|
|
1452
|
+
this.paginator.pageIndex = 0;
|
|
1453
|
+
}
|
|
1454
|
+
this.onRefresh.emit();
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
listenDatasourceLoading(dataSource) {
|
|
1458
|
+
if (!dataSource)
|
|
1459
|
+
throw new Error('[table] dataSource not set !');
|
|
1460
|
+
// Cleaning previous subscription on datasource
|
|
1461
|
+
if (isNotNil(this._dataSourceLoadingSubscription)) {
|
|
1462
|
+
if (this.debug)
|
|
1463
|
+
console.debug('[table] Many call to listenDatasource(): Cleaning previous subscriptions...');
|
|
1464
|
+
this._dataSourceLoadingSubscription.unsubscribe();
|
|
1465
|
+
this.unregisterSubscription(this._dataSourceLoadingSubscription);
|
|
1466
|
+
}
|
|
1467
|
+
// Propage loading to table
|
|
1468
|
+
this._dataSourceLoadingSubscription = this._dataSource.loadingSubject
|
|
1469
|
+
.pipe(distinctUntilChanged(),
|
|
1470
|
+
// If changed to True: propagate as soon as possible
|
|
1471
|
+
tap((loading) => loading && this.setLoading(true)),
|
|
1472
|
+
// If changed to False: wait 250ms before propagate (to make sure the spinner has been displayed)
|
|
1473
|
+
debounceTime(250), tap(loading => !loading && this.setLoading(false)))
|
|
1474
|
+
.subscribe();
|
|
1475
|
+
this.registerSubscription(this._dataSourceLoadingSubscription);
|
|
1476
|
+
}
|
|
1477
|
+
startCellValueChanges(name, row) {
|
|
1478
|
+
const def = this._cellValueChangesDefs[name];
|
|
1479
|
+
if (!def) {
|
|
1480
|
+
console.warn('[table] Listener with name {' + name + '} not registered! Please call registerCellValueChanges() before;');
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
// Stop previous subscription
|
|
1484
|
+
if (def.subscription) {
|
|
1485
|
+
def.subscription.unsubscribe();
|
|
1486
|
+
def.subscription = null;
|
|
1487
|
+
}
|
|
1488
|
+
else {
|
|
1489
|
+
if (this.debug)
|
|
1490
|
+
console.debug(`[table] Start values changes on row path {${def.formPath}}`);
|
|
1491
|
+
}
|
|
1492
|
+
// Listen value changes, and redirect to event emitter
|
|
1493
|
+
const control = row.validator && AppFormUtils.getControlFromPath(row.validator, def.formPath);
|
|
1494
|
+
if (!control) {
|
|
1495
|
+
console.warn(`[table] Could not listen cell changes: no validator or invalid form path {${def.formPath}}`);
|
|
1496
|
+
}
|
|
1497
|
+
else {
|
|
1498
|
+
def.subscription = control.valueChanges
|
|
1499
|
+
.pipe(
|
|
1500
|
+
// don't emit if control is disabled
|
|
1501
|
+
filter(() => control.enabled))
|
|
1502
|
+
.subscribe((value) => def.subject.next(value));
|
|
1503
|
+
// Emit the actual value
|
|
1504
|
+
if (def.emitInitialValue !== false) {
|
|
1505
|
+
def.subject.next(control.value);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
stopCellValueChanges(name, destroy) {
|
|
1510
|
+
const def = this._cellValueChangesDefs[name];
|
|
1511
|
+
if (!def)
|
|
1512
|
+
return;
|
|
1513
|
+
if (def.subscription) {
|
|
1514
|
+
if (this.debug)
|
|
1515
|
+
console.debug('[table] Stop value changes on row path {' + def.formPath + '}');
|
|
1516
|
+
def.subscription.unsubscribe();
|
|
1517
|
+
def.subscription = null;
|
|
1518
|
+
}
|
|
1519
|
+
if (destroy && def.subject) {
|
|
1520
|
+
def.subject.complete();
|
|
1521
|
+
def.subject.unsubscribe();
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
AppAsyncTable.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AppAsyncTable, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
|
|
1526
|
+
AppAsyncTable.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: AppAsyncTable, inputs: { settingsId: "settingsId", debug: "debug", i18nColumnPrefix: "i18nColumnPrefix", i18nColumnSuffix: "i18nColumnSuffix", autoLoad: "autoLoad", readOnly: "readOnly", inlineEdition: "inlineEdition", focusFirstColumn: "focusFirstColumn", confirmBeforeDelete: "confirmBeforeDelete", confirmBeforeCancel: "confirmBeforeCancel", undoableDeletion: "undoableDeletion", saveBeforeDelete: "saveBeforeDelete", keepEditedRowOnSave: "keepEditedRowOnSave", saveBeforeSort: "saveBeforeSort", saveBeforeFilter: "saveBeforeFilter", propagateRowError: "propagateRowError", defaultSortBy: "defaultSortBy", defaultSortDirection: "defaultSortDirection", defaultPageSize: "defaultPageSize", defaultPageSizeOptions: "defaultPageSizeOptions", focusColumn: "focusColumn", dataSource: "dataSource", filter: "filter", disabled: "disabled", paginator: "paginator" }, outputs: { onRefresh: "onRefresh", onOpenRow: "onOpenRow", onNewRow: "onNewRow", onStartEditingRow: "onStartEditingRow", onConfirmEditCreateRow: "onConfirmEditCreateRow", onCancelOrDeleteRow: "onCancelOrDeleteRow", onBeforeDeleteRows: "onBeforeDeleteRows", onBeforeCancelRows: "onBeforeCancelRows", onBeforeSave: "onBeforeSave", onAfterDeletedRows: "onAfterDeletedRows", onSort: "onSort", onDirty: "onDirty", onError: "onError" }, viewQueries: [{ propertyName: "table", first: true, predicate: MatTable, descendants: true }, { propertyName: "childPaginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }], ngImport: i0 });
|
|
1527
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AppAsyncTable, decorators: [{
|
|
1528
|
+
type: Directive
|
|
1529
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: undefined }, { type: i1.EntitiesAsyncTableDataSource }, { type: undefined }]; }, propDecorators: { settingsId: [{
|
|
1530
|
+
type: Input
|
|
1531
|
+
}], debug: [{
|
|
1532
|
+
type: Input
|
|
1533
|
+
}], i18nColumnPrefix: [{
|
|
1534
|
+
type: Input
|
|
1535
|
+
}], i18nColumnSuffix: [{
|
|
1536
|
+
type: Input
|
|
1537
|
+
}], autoLoad: [{
|
|
1538
|
+
type: Input
|
|
1539
|
+
}], readOnly: [{
|
|
1540
|
+
type: Input
|
|
1541
|
+
}], inlineEdition: [{
|
|
1542
|
+
type: Input
|
|
1543
|
+
}], focusFirstColumn: [{
|
|
1544
|
+
type: Input
|
|
1545
|
+
}], confirmBeforeDelete: [{
|
|
1546
|
+
type: Input
|
|
1547
|
+
}], confirmBeforeCancel: [{
|
|
1548
|
+
type: Input
|
|
1549
|
+
}], undoableDeletion: [{
|
|
1550
|
+
type: Input
|
|
1551
|
+
}], saveBeforeDelete: [{
|
|
1552
|
+
type: Input
|
|
1553
|
+
}], keepEditedRowOnSave: [{
|
|
1554
|
+
type: Input
|
|
1555
|
+
}], saveBeforeSort: [{
|
|
1556
|
+
type: Input
|
|
1557
|
+
}], saveBeforeFilter: [{
|
|
1558
|
+
type: Input
|
|
1559
|
+
}], propagateRowError: [{
|
|
1560
|
+
type: Input
|
|
1561
|
+
}], defaultSortBy: [{
|
|
1562
|
+
type: Input
|
|
1563
|
+
}], defaultSortDirection: [{
|
|
1564
|
+
type: Input
|
|
1565
|
+
}], defaultPageSize: [{
|
|
1566
|
+
type: Input
|
|
1567
|
+
}], defaultPageSizeOptions: [{
|
|
1568
|
+
type: Input
|
|
1569
|
+
}], focusColumn: [{
|
|
1570
|
+
type: Input
|
|
1571
|
+
}], dataSource: [{
|
|
1572
|
+
type: Input
|
|
1573
|
+
}], filter: [{
|
|
1574
|
+
type: Input
|
|
1575
|
+
}], onRefresh: [{
|
|
1576
|
+
type: Output
|
|
1577
|
+
}], onOpenRow: [{
|
|
1578
|
+
type: Output
|
|
1579
|
+
}], onNewRow: [{
|
|
1580
|
+
type: Output
|
|
1581
|
+
}], onStartEditingRow: [{
|
|
1582
|
+
type: Output
|
|
1583
|
+
}], onConfirmEditCreateRow: [{
|
|
1584
|
+
type: Output
|
|
1585
|
+
}], onCancelOrDeleteRow: [{
|
|
1586
|
+
type: Output
|
|
1587
|
+
}], onBeforeDeleteRows: [{
|
|
1588
|
+
type: Output
|
|
1589
|
+
}], onBeforeCancelRows: [{
|
|
1590
|
+
type: Output
|
|
1591
|
+
}], onBeforeSave: [{
|
|
1592
|
+
type: Output
|
|
1593
|
+
}], onAfterDeletedRows: [{
|
|
1594
|
+
type: Output
|
|
1595
|
+
}], onSort: [{
|
|
1596
|
+
type: Output
|
|
1597
|
+
}], onDirty: [{
|
|
1598
|
+
type: Output
|
|
1599
|
+
}], onError: [{
|
|
1600
|
+
type: Output
|
|
1601
|
+
}], disabled: [{
|
|
1602
|
+
type: Input
|
|
1603
|
+
}], paginator: [{
|
|
1604
|
+
type: Input
|
|
1605
|
+
}], table: [{
|
|
1606
|
+
type: ViewChild,
|
|
1607
|
+
args: [MatTable, { static: false }]
|
|
1608
|
+
}], childPaginator: [{
|
|
1609
|
+
type: ViewChild,
|
|
1610
|
+
args: [MatPaginator, { static: false }]
|
|
1611
|
+
}], sort: [{
|
|
1612
|
+
type: ViewChild,
|
|
1613
|
+
args: [MatSort, { static: false }]
|
|
1614
|
+
}] } });
|
|
1615
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtdGFibGUuY2xhc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2NvcmUvdGFibGUvYXN5bmMtdGFibGUuY2xhc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixTQUFTLEVBQUUsWUFBWSxFQUFZLEtBQUssRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM5SCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDM0QsT0FBTyxFQUFFLE9BQU8sRUFBOEIsTUFBTSx3QkFBd0IsQ0FBQztBQUM3RSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzVGLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9JLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsV0FBVyxFQUFXLE1BQU0sZ0NBQWdDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkYsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RCxPQUFPLEVBQWMsMkJBQTJCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUMzRixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFVB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WUFBWTtzQkFBckIsTUFBTTtnQkFDRyxrQkFBa0I7c0JBQTNCLE1BQU07Z0JBQ0csTUFBTTtzQkFBZixNQUFNO2dCQUNHLE9BQU87c0JBQWhCLE1BQU07Z0JBQ0csT0FBTztzQkFBaEIsTUFBTTtnQkEyQ00sUUFBUTtzQkFBcEIsS0FBSztnQkFxSk8sU0FBUztzQkFBckIsS0FBSztnQkFZa0MsS0FBSztzQkFBNUMsU0FBUzt1QkFBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUNNLGNBQWM7c0JBQXpELFNBQVM7dUJBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFDSCxJQUFJO3NCQUExQyxTQUFTO3VCQUFDLE9BQU8sRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBZnRlclZpZXdJbml0LCBEaXJlY3RpdmUsIEV2ZW50RW1pdHRlciwgSW5qZWN0b3IsIElucHV0LCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE1hdFBhZ2luYXRvciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3BhZ2luYXRvcic7XG5pbXBvcnQgeyBNYXRTb3J0LCBNYXRTb3J0YWJsZSwgU29ydERpcmVjdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NvcnQnO1xuaW1wb3J0IHsgTWF0VGFibGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJsZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIEVNUFRZLCBtZXJnZSwgT2JzZXJ2YWJsZSwgb2YsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgZmlsdGVyLCBmaXJzdCwgbWVyZ2VNYXAsIHN0YXJ0V2l0aCwgc3dpdGNoTWFwLCB0YWtlVW50aWwsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFNlbGVjdGlvbk1vZGVsIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvbGxlY3Rpb25zJztcbmltcG9ydCB7IEVudGl0eVV0aWxzLCBJRW50aXR5IH0gZnJvbSAnLi4vc2VydmljZXMvbW9kZWwvZW50aXR5Lm1vZGVsJztcbmltcG9ydCB7IEFsZXJ0Q29udHJvbGxlciwgTW9kYWxDb250cm9sbGVyLCBUb2FzdENvbnRyb2xsZXIgfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IENvbHVtbkl0ZW0sIFRhYmxlU2VsZWN0Q29sdW1uc0NvbXBvbmVudCB9IGZyb20gJy4vdGFibGUtc2VsZWN0LWNvbHVtbnMuY29tcG9uZW50JztcbmltcG9ydCB7IExvY2F0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEVycm9yQ29kZXMgfSBmcm9tICcuLi9zZXJ2aWNlcy9lcnJvcnMnO1xuaW1wb3J0IHsgQXBwRm9ybVV0aWxzLCBJQXBwRm9ybSwgT25SZWFkeSB9IGZyb20gJy4uL2Zvcm0vZm9ybS51dGlscyc7XG5pbXBvcnQgeyBMb2NhbFNldHRpbmdzU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2xvY2FsLXNldHRpbmdzLnNlcnZpY2UnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgTWF0QXV0b2NvbXBsZXRlQ29uZmlnSG9sZGVyLCBNYXRBdXRvY29tcGxldGVGaWVsZEFkZE9wdGlvbnMsIE1hdEF1dG9jb21wbGV0ZUZpZWxkQ29uZmlnIH0gZnJvbSAnLi4vLi4vc2hhcmVkL21hdGVyaWFsL2F1dG9jb21wbGV0ZS9tYXRlcmlhbC5hdXRvY29tcGxldGUuY29uZmlnJztcbmltcG9ydCB7IENvbXBsZXRhYmxlRXZlbnQsIGNyZWF0ZVByb21pc2VFdmVudEVtaXR0ZXIsIGVtaXRQcm9taXNlRXZlbnQgfSBmcm9tICcuLi8uLi9zaGFyZWQvZXZlbnRzJztcbmltcG9ydCB7IGNoYW5nZUNhc2VUb1VuZGVyc2NvcmUsIGlzRW1wdHlBcnJheSwgaXNOaWwsIGlzTm90TmlsLCB0b0Jvb2xlYW4gfSBmcm9tICcuLi8uLi9zaGFyZWQvZnVuY3Rpb25zJztcbmltcG9ydCB7IHdhaXRGb3IsIHdhaXRGb3JGYWxzZSwgV2FpdEZvck9wdGlvbnMsIHdhaXRGb3JUcnVlIH0gZnJvbSAnLi4vLi4vc2hhcmVkL29ic2VydmFibGVzJztcbmltcG9ydCB7IFNob3dUb2FzdE9wdGlvbnMsIFRvYXN0cyB9IGZyb20gJy4uLy4uL3NoYXJlZC90b2FzdC90b2FzdHMnO1xuaW1wb3J0IHsgQWxlcnRzIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2FsZXJ0cyc7XG5pbXBvcnQgeyBDZGtDb2x1bW5EZWYgfSBmcm9tICdAYW5ndWxhci9jZGsvdGFibGUnO1xuaW1wb3J0IHsgTG9hZFJlc3VsdCB9IGZyb20gJy4uLy4uL3NoYXJlZC9zZXJ2aWNlcy9lbnRpdHktc2VydmljZS5jbGFzcyc7XG5pbXBvcnQgeyBGb3JtRXJyb3JUcmFuc2xhdG9yLCBGb3JtRXJyb3JUcmFuc2xhdG9yT3B0aW9ucywgSUZvcm1Db250cm9sUGF0aFRyYW5zbGF0b3IgfSBmcm9tICcuLi8uLi9zaGFyZWQvdmFsaWRhdG9yL2Zvcm0tZXJyb3ItYWRhcHRlci5jbGFzcyc7XG5pbXBvcnQge1xuICBDZWxsVmFsdWVDaGFuZ2VMaXN0ZW5lcixcbiAgREVGQVVMVF9QQUdFX1NJWkUsXG4gIERFRkFVTFRfUEFHRV9TSVpFX09QVElPTlMsXG4gIERFRkFVTFRfUkVRVUlSRURfQ09MVU1OUyxcbiAgUkVTRVJWRURfRU5EX0NPTFVNTlMsXG4gIFJFU0VSVkVEX1NUQVJUX0NPTFVNTlMsXG4gIFNhdmVBY3Rpb25UeXBlLFxuICBTRVRUSU5HU19ESVNQTEFZX0NPTFVNTlMsXG4gIFNFVFRJTkdTX1BBR0VfU0laRSxcbiAgU0VUVElOR1NfU09SVEVEX0NPTFVNTlxufSBmcm9tICcuL3RhYmxlLm1vZGVsJztcbmltcG9ydCB7IEFzeW5jVGFibGVFbGVtZW50IH0gZnJvbSAnQGUtaXMvbmd4LW1hdGVyaWFsLXRhYmxlJztcbmltcG9ydCB7IEVudGl0aWVzQXN5bmNUYWJsZURhdGFTb3VyY2UgfSBmcm9tICcuL2VudGl0aWVzLWFzeW5jLXRhYmxlLWRhdGFzb3VyY2UuY2xhc3MnO1xuXG4vLyBAZHluYW1pY1xuLy8gbm9pbnNwZWN0aW9uIER1cGxpY2F0ZWRDb2RlXG5ARGlyZWN0aXZlKClcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvZGlyZWN0aXZlLWNsYXNzLXN1ZmZpeFxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEFwcEFzeW5jVGFibGU8VCBleHRlbmRzIElFbnRpdHk8VCwgSUQ+LFxuICBGID0gYW55LFxuICBJRCA9IG51bWJlcj5cbiAgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdCwgSUFwcEZvcm0sIElGb3JtQ29udHJvbFBhdGhUcmFuc2xhdG9yIHtcblxuICBwcml2YXRlIF9pbml0aWFsaXplZCA9IGZhbHNlO1xuICBwcml2YXRlIF9zdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIHByaXZhdGUgX2RhdGFTb3VyY2VMb2FkaW5nU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgcHJpdmF0ZSBfY2VsbFZhbHVlQ2hhbmdlc0RlZnM6IHtcbiAgICBba2V5OiBzdHJpbmddOiBDZWxsVmFsdWVDaGFuZ2VMaXN0ZW5lcjtcbiAgfSA9IHt9O1xuXG4gIHByb3RlY3RlZCBfZW5hYmxlZCA9IHRydWU7XG4gIHByb3RlY3RlZCBfYXV0b2NvbXBsZXRlQ29uZmlnSG9sZGVyOiBNYXRBdXRvY29tcGxldGVDb25maWdIb2xkZXI7XG4gIHByb3RlY3RlZCBhbGxvd1Jvd0RldGFpbCA9IHRydWU7XG4gIHByb3RlY3RlZCByb3V0ZTogQWN0aXZhdGVkUm91dGU7XG4gIHByb3RlY3RlZCByb3V0ZXI6IFJvdXRlcjtcbiAgcHJvdGVjdGVkIGxvY2F0aW9uOiBMb2NhdGlvbjtcbiAgcHJvdGVjdGVkIHNldHRpbmdzOiBMb2NhbFNldHRpbmdzU2VydmljZTtcbiAgcHJvdGVjdGVkIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZTtcbiAgcHJvdGVjdGVkIG1vZGFsQ3RybDogTW9kYWxDb250cm9sbGVyO1xuICBwcm90ZWN0ZWQgYWxlcnRDdHJsOiBBbGVydENvbnRyb2xsZXI7XG4gIHByb3RlY3RlZCB0b2FzdENvbnRyb2xsZXI6IFRvYXN0Q29udHJvbGxlcjtcbiAgcHJvdGVjdGVkIHByZXZpb3VzbHlFZGl0ZWRSb3dJZDogbnVtYmVyO1xuICBwcm90ZWN0ZWQgZm9ybUVycm9yQWRhcHRlcjogRm9ybUVycm9yVHJhbnNsYXRvcjtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGRlc3Ryb3lTdWJqZWN0ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBleGNsdWRlc0NvbHVtbnM6IHN0cmluZ1tdID0gW107XG4gIGRpc3BsYXllZENvbHVtbnM6IHN0cmluZ1tdO1xuICB0b3RhbFJvd0NvdW50OiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgdmlzaWJsZVJvd0NvdW50OiBudW1iZXI7XG4gIGVycm9yVHJhbnNsYXRvck9wdGlvbnM6IEZvcm1FcnJvclRyYW5zbGF0b3JPcHRpb25zO1xuXG4gIHJlYWRvbmx5IHJlYWR5U3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuICByZWFkb25seSBsb2FkaW5nU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4odHJ1ZSk7XG4gIHJlYWRvbmx5IHNhdmluZ1N1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgcmVhZG9ubHkgdG91Y2hlZFN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgcmVhZG9ubHkgZGlydHlTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG4gIHJlYWRvbmx5IGVycm9yU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPih1bmRlZmluZWQpO1xuXG4gIGdldCBlcnJvcigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmVycm9yU3ViamVjdC52YWx1ZTtcbiAgfVxuXG4gIHNldCBlcnJvcihlcnJvcjogc3RyaW5nKSB7XG4gICAgdGhpcy5zZXRFcnJvcihlcnJvcik7XG4gIH1cblxuICBzZWxlY3Rpb24gPSBuZXcgU2VsZWN0aW9uTW9kZWw8QXN5bmNUYWJsZUVsZW1lbnQ8VD4+KHRydWUsIFtdKTtcbiAgYXV0b2NvbXBsZXRlRmllbGRzOiB7IFtrZXk6IHN0cmluZ106IE1hdEF1dG9jb21wbGV0ZUZpZWxkQ29uZmlnIH07XG4gIHJlYWRvbmx5IG1vYmlsZTogYm9vbGVhbjtcblxuICAvLyBUYWJsZSBvcHRpb25zXG4gIEBJbnB1dCgpIHNldHRpbmdzSWQ6IHN0cmluZztcbiAgQElucHV0KCkgZGVidWc6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGkxOG5Db2x1bW5QcmVmaXggPSAnQ09NTU9OLic7XG4gIEBJbnB1dCgpIGkxOG5Db2x1bW5TdWZmaXg6IHN0cmluZztcbiAgQElucHV0KCkgYXV0b0xvYWQgPSB0cnVlO1xuICBASW5wdXQoKSByZWFkT25seTogYm9vbGVhbjtcbiAgQElucHV0KCkgaW5saW5lRWRpdGlvbjogYm9vbGVhbjtcbiAgQElucHV0KCkgZm9jdXNGaXJzdENvbHVtbiA9IGZhbHNlO1xuICBASW5wdXQoKSBjb25maXJtQmVmb3JlRGVsZXRlID0gZmFsc2U7XG4gIEBJbnB1dCgpIGNvbmZpcm1CZWZvcmVDYW5jZWwgPSBmYWxzZTtcbiAgQElucHV0KCkgdW5kb2FibGVEZWxldGlvbiA9IGZhbHNlO1xuICBASW5wdXQoKSBzYXZlQmVmb3JlRGVsZXRlOiBib29sZWFuO1xuICBASW5wdXQoKSBrZWVwRWRpdGVkUm93T25TYXZlOiBib29sZWFuO1xuICBASW5wdXQoKSBzYXZlQmVmb3JlU29ydDogYm9vbGVhbjtcbiAgQElucHV0KCkgc2F2ZUJlZm9yZUZpbHRlcjogYm9vbGVhbjtcbiAgQElucHV0KCkgcHJvcGFnYXRlUm93RXJyb3IgPSBmYWxzZTtcblxuICBASW5wdXQoKSBkZWZhdWx0U29ydEJ5OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGRlZmF1bHRTb3J0RGlyZWN0aW9uOiBTb3J0RGlyZWN0aW9uO1xuICBASW5wdXQoKSBkZWZhdWx0UGFnZVNpemUgPSBERUZBVUxUX1BBR0VfU0laRTtcbiAgQElucHV0KCkgZGVmYXVsdFBhZ2VTaXplT3B0aW9ucyA9IERFRkFVTFRfUEFHRV9TSVpFX09QVElPTlM7XG5cbiAgLy8gRm9jdXMgbWFuYWdlclxuICBASW5wdXQoKSBmb2N1c0NvbHVtbjogc3RyaW5nO1xuXG4gIGdldCBmaXJzdFVzZXJDb2x1bW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zW1JFU0VSVkVEX1NUQVJUX0NPTFVNTlMubGVuZ3RoXTtcbiAgfVxuXG4gIGdldCBsYXN0VXNlckNvbHVtbigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmRpc3BsYXllZENvbHVtbnNbdGhpcy5kaXNwbGF5ZWRDb2x1bW5zLmxlbmd0aCAtIFJFU0VSVkVEX0VORF9DT0xVTU5TLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgQElucHV0KCkgc2V0IGRhdGFTb3VyY2UodmFsdWU6IEVudGl0aWVzQXN5bmNUYWJsZURhdGFTb3VyY2U8VCwgRiwgSUQ+KSB7XG4gICAgdGhpcy5zZXREYXRhc291cmNlKHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkYXRhU291cmNlKCk6IEVudGl0aWVzQXN5bmNUYWJsZURhdGFTb3VyY2U8VCwgRiwgSUQ+IHtcbiAgICByZXR1cm4gdGhpcy5fZGF0YVNvdXJjZTtcbiAgfVxuXG4gIEBJbnB1dCgpIHNldCBmaWx0ZXIodmFsdWU6IEYpIHtcbiAgICB0aGlzLnNldEZpbHRlcih2YWx1ZSk7XG4gIH1cblxuICBnZXQgZmlsdGVyKCk6IEYge1xuICAgIHJldHVybiB0aGlzLl9maWx0ZXI7XG4gIH1cblxuICBnZXQgZW1wdHkoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubG9hZGluZyB8fCB0aGlzLnRvdGFsUm93Q291bnQgPT09IDA7XG4gIH1cblxuICBAT3V0cHV0KCkgb25SZWZyZXNoID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBvbk9wZW5Sb3cgPSBuZXcgRXZlbnRFbWl0dGVyPEFzeW5jVGFibGVFbGVtZW50PFQ+PigpO1xuICBAT3V0cHV0KCkgb25OZXdSb3cgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgpIG9uU3RhcnRFZGl0aW5nUm93ID0gbmV3IEV2ZW50RW1pdHRlcjxBc3luY1RhYmxlRWxlbWVudDxUPj4oKTtcbiAgQE91dHB1dCgpIG9uQ29uZmlybUVkaXRDcmVhdGVSb3cgPSBuZXcgRXZlbnRFbWl0dGVyPEFzeW5jVGFibGVFbGVtZW50PFQ+PigpO1xuICBAT3V0cHV0KCkgb25DYW5jZWxPckRlbGV0ZVJvdyA9IG5ldyBFdmVudEVtaXR0ZXI8QXN5bmNUYWJsZUVsZW1lbnQ8VD4+KCk7XG4gIEBPdXRwdXQoKSBvbkJlZm9yZURlbGV0ZVJvd3MgPSBjcmVhdGVQcm9taXNlRXZlbnRFbWl0dGVyPGJvb2xlYW4sIHsgcm93czogQXN5bmNUYWJsZUVsZW1lbnQ8VD5bXSB9PigpO1xuICBAT3V0cHV0KCkgb25CZWZvcmVDYW5jZWxSb3dzID0gY3JlYXRlUHJvbWlzZUV2ZW50RW1pdHRlcjxib29sZWFuLCB7IHJvd3M6IEFzeW5jVGFibGVFbGVtZW50PFQ+W10gfT4oKTtcbiAgQE91dHB1dCgpIG9uQmVmb3JlU2F2ZSA9IGNyZWF0ZVByb21pc2VFdmVudEVtaXR0ZXI8eyBjb25maXJtZWQ6IGJvb2xlYW47IHNhdmU6IGJvb2xlYW4gfSwgeyBhY3Rpb246IFNhdmVBY3Rpb25UeXBlOyB2YWxpZDogYm9vbGVhbiB9PigpO1xuICBAT3V0cHV0KCkgb25BZnRlckRlbGV0ZWRSb3dzID0gbmV3IEV2ZW50RW1pdHRlcjxBc3luY1RhYmxlRWxlbWVudDxUPltdPigpO1xuICBAT3V0cHV0KCkgb25Tb3J0ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBvbkRpcnR5ID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuICBAT3V0cHV0KCkgb25FcnJvciA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIGdldCBkaXJ0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5kaXJ0eVN1YmplY3QudmFsdWU7XG4gIH1cblxuICBnZXQgdmFsaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YVNvdXJjZS5nZXRSb3dzKCkuZXZlcnkocm93ID0+IHJvdy5lZGl0aW5nID8gcm93LnZhbGlkIDogdHJ1ZSk7XG4gIH1cblxuICBnZXQgaW52YWxpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhU291cmNlLmdldFJvd3MoKS5zb21lKHJvdyA9PiByb3cuZWRpdGluZyA/IHJvdy5pbnZhbGlkIDogZmFsc2UpO1xuICB9XG5cbiAgZ2V0IHBlbmRpbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YVNvdXJjZS5nZXRSb3dzKCkuc29tZShyb3cgPT4gcm93LmVkaXRpbmcgPyByb3cucGVuZGluZyA6IGZhbHNlKTtcbiAgfVxuXG4gIGdldCB0b3VjaGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnRvdWNoZWRTdWJqZWN0LnZhbHVlO1xuICB9XG5cbiAgZ2V0IHVudG91Y2hlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIXRoaXMudG91Y2hlZFN1YmplY3QudmFsdWU7XG4gIH1cblxuICBkaXNhYmxlKG9wdHM/OiB7IG9ubHlTZWxmPzogYm9vbGVhbjsgZW1pdEV2ZW50PzogYm9vbGVhbiB9KSB7XG4gICAgaWYgKHRoaXMuc29ydCkgdGhpcy5zb3J0LmRpc2FibGVkID0gdHJ1ZTtcbiAgICB0aGlzLl9lbmFibGVkID0gZmFsc2U7XG4gICAgaWYgKCFvcHRzIHx8IG9wdHMuZW1pdEV2ZW50ICE9IGZhbHNlKSB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgZW5hYmxlKG9wdHM/OiB7IG9ubHlTZWxmPzogYm9vbGVhbjsgZW1pdEV2ZW50PzogYm9vbGVhbiB9KSB7XG4gICAgaWYgKHRoaXMuc29ydCkgdGhpcy5zb3J0LmRpc2FibGVkID0gZmFsc2U7XG4gICAgdGhpcy5fZW5hYmxlZCA9IHRydWU7XG4gICAgaWYgKCFvcHRzIHx8IG9wdHMuZW1pdEV2ZW50ICE9IGZhbHNlKSB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgZ2V0IGVuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2VuYWJsZWQ7XG4gIH1cblxuICAvLyBGSVhNRTogbmVlZCB0byBoaWRkZW4gYnV0dG9ucyAoaW4gSFRNTCksIGV0Yy4gd2hlbiBkaXNhYmxlZFxuICBASW5wdXQoKSBzZXQgZGlzYWJsZWQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICBpZiAodmFsdWUgIT09ICF0aGlzLl9lbmFibGVkKSB7XG4gICAgICBpZiAodmFsdWUpIHRoaXMuZGlzYWJsZSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICBlbHNlIHRoaXMuZW5hYmxlKHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICB9XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLl9lbmFibGVkO1xuICB9XG5cbiAgbWFya0FzRGlydHkob3B0cz86IHsgb25seVNlbGY/OiBib29sZWFuOyBlbWl0RXZlbnQ/OiBib29sZWFuIH0pIHtcbiAgICBpZiAodGhpcy5kaXJ0eVN1YmplY3QudmFsdWUgIT09IHRydWUpIHtcbiAgICAgIHRoaXMuZGlydHlTdWJqZWN0Lm5leHQodHJ1ZSk7XG4gICAgICBpZiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSB7XG4gICAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbWFya0FzUHJpc3RpbmUob3B0cz86IHsgb25seVNlbGY/OiBib29sZWFuOyBlbWl0RXZlbnQ/OiBib29sZWFuIH0pIHtcbiAgICBpZiAodGhpcy5kaXJ0eVN1YmplY3QudmFsdWUgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLmRpcnR5U3ViamVjdC5uZXh0KGZhbHNlKTtcbiAgICAgIGlmICghb3B0cyB8fCBvcHRzLmVtaXRFdmVudCAhPT0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBtYXJrQXNVbnRvdWNoZWQob3B0cz86IHsgb25seVNlbGY/OiBib29sZWFuOyBlbWl0RXZlbnQ/OiBib29sZWFuIH0pIHtcbiAgICBsZXQgbmVlZEVtaXRFdmVudCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLnRvdWNoZWRTdWJqZWN0LnZhbHVlKSB7XG4gICAgICB0aGlzLnRvdWNoZWRTdWJqZWN0Lm5leHQoZmFsc2UpO1xuICAgICAgbmVlZEVtaXRFdmVudCA9IHRydWU7XG4gICAgfVxuICAgIGlmICh0aGlzLmRpcnR5IHx8IHRoaXMuZGF0YVNvdXJjZS5oYXNTb21lRWRpdGluZ1JvdygpKSB7XG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiB0aGlzLmRhdGFTb3VyY2UuZ2V0RWRpdGluZ1Jvd3MoKSkge1xuXG4gICAgICAgIC8vIENhbmNlbCB0aGUgY3VycmVudCBlZGl0aW5nIHJvdyBvbmx5IGlmIGVkaXRpbmcgYW5kIGlmIGl0IHdhcyBub3QgcHJldmlvdXNseSBzYXZlZFxuICAgICAgICBhd2FpdCB0aGlzLmRhdGFTb3VyY2UuY2FuY2VsT3JEZWxldGUocm93KTtcblxuICAgICAgICAvLyBNYXJrIHJvdyBhcyBwcmlzdGluZVxuICAgICAgICBhd2FpdCB0aGlzLmNoZWNrSWZSb3dQcmlzdGluZShyb3csIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgIH1cbiAgICAgIG5lZWRFbWl0RXZlbnQgPSB0cnVlO1xuICAgIH1cbiAgICB0aGlzLnByZXZpb3VzbHlFZGl0ZWRSb3dJZCA9IHVuZGVmaW5lZDtcbiAgICBpZiAobmVlZEVtaXRFdmVudCAmJiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSkgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVwcmVjYXRlZCBwcmVmZXIgdG8gdXNlIG1hcmtBbGxBc1RvdWNoZWQoKVxuICAgKiBAcGFyYW0gb3B0c1xuICAgKi9cbiAgbWFya0FzVG91Y2hlZChvcHRzPzogeyBvbmx5U2VsZj86IGJvb2xlYW47IGVtaXRFdmVudD86IGJvb2xlYW4gfSkge1xuICAgIGNvbnNvbGUud2FybignVE9ETzogUmVwbGFjZSB0aGlzIGNhbGwgYnkgbWFya0FsbEFzVG91Y2hlZCgpIC0gYmVjYXVzZSBvZiBjaGFuZ2VzIGluIG5neC1jb21wb25lbnRzID49IDAuMTYuMCcpO1xuICAgIGlmICh0aGlzLmRhdGFTb3VyY2UuaGFzU29tZUVkaXRpbmdSb3coKSkge1xuICAgICAgdGhpcy5kYXRhU291cmNlLmdldEVkaXRpbmdSb3dzKCkuZm9yRWFjaChyb3cgPT4gcm93LnZhbGlkYXRvcj8ubWFya0FsbEFzVG91Y2hlZCgpKTtcbiAgICAgIGlmICghb3B0cyB8fCBvcHRzLmVtaXRFdmVudCAhPT0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBtYXJrQWxsQXNUb3VjaGVkKG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICh0aGlzLnRvdWNoZWRTdWJqZWN0LnZhbHVlICE9PSB0cnVlKSB7XG4gICAgICB0aGlzLnRvdWNoZWRTdWJqZWN0Lm5leHQodHJ1ZSk7XG4gICAgICBpZiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgICBpZiAodGhpcy5kYXRhU291cmNlLmhhc1NvbWVFZGl0aW5nUm93KCkpIHtcbiAgICAgIHRoaXMuZGF0YVNvdXJjZS5nZXRFZGl0aW5nUm93cygpLmZvckVhY2gocm93ID0+IHJvdy52YWxpZGF0b3I/Lm1hcmtBbGxBc1RvdWNoZWQoKSk7XG4gICAgfVxuICB9XG5cbiAgbWFya0FzU2F2aW5nKG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICh0aGlzLnNhdmluZ1N1YmplY3QudmFsdWUgIT09IHRydWUpIHtcbiAgICAgIHRoaXMuZm9jdXNDb2x1bW4gPSB1bmRlZmluZWQ7IC8vIHVuc2VsZWN0IGZvY3VzIGNvbHVtblxuICAgICAgdGhpcy5zYXZpbmdTdWJqZWN0Lm5leHQodHJ1ZSk7XG4gICAgICBpZiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxuXG4gIG1hcmtBc1NhdmVkKG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICh0aGlzLnNhdmluZ1N1YmplY3QudmFsdWUgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLnNhdmluZ1N1YmplY3QubmV4dChmYWxzZSk7XG4gICAgICBpZiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxuXG4gIG1hcmtBc0xvYWRpbmcob3B0cz86IHsgZW1pdEV2ZW50PzogYm9vbGVhbiB9KSB7XG4gICAgdGhpcy5zZXRMb2FkaW5nKHRydWUsIG9wdHMpO1xuICB9XG5cbiAgbWFya0FzTG9hZGVkKG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW4gfSkge1xuICAgIHRoaXMuc2V0TG9hZGluZyhmYWxzZSwgb3B0cyk7XG4gIH1cblxuICBtYXJrQXNSZWFkeShvcHRzPzogeyBlbWl0RXZlbnQ/OiBib29sZWFuIH0pIHtcbiAgICBpZiAodGhpcy5yZWFkeVN1YmplY3QudmFsdWUgIT09IHRydWUpIHtcbiAgICAgIHRoaXMucmVhZHlTdWJqZWN0Lm5leHQodHJ1ZSk7XG5cbiAgICAgIC8vIElmIHN1YmNsYXNzZXMgaW1wbGVtZW50cyBPblJlYWR5XG4gICAgICBpZiAodHlwZW9mIHRoaXNbJ25nT25SZWFkeSddID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICh0aGlzIGFzIGFueSBhcyBPblJlYWR5KS5uZ09uUmVhZHkoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBnZXQgbG9hZGluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5sb2FkaW5nU3ViamVjdC52YWx1ZTtcbiAgfVxuXG4gIGdldCBsb2FkZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLmxvYWRpbmdTdWJqZWN0LnZhbHVlO1xuICB9XG5cbiAgZW5hYmxlU29ydCgpIHtcbiAgICBpZiAodGhpcy5zb3J0KSB0aGlzLnNvcnQuZGlzYWJsZWQgPSBmYWxzZTtcbiAgfVxuXG4gIGRpc2FibGVTb3J0KCkge1xuICAgIGlmICh0aGlzLnNvcnQpIHRoaXMuc29ydC5kaXNhYmxlZCA9IHRydWU7XG4gIH1cblxuICBzZXQgcGFnZVNpemUodmFsdWU6IG51bWJlcikge1xuICAgIHRoaXMuZGVmYXVsdFBhZ2VTaXplID0gdmFsdWU7XG4gICAgaWYgKHRoaXMucGFnaW5hdG9yKSB7XG4gICAgICB0aGlzLnBhZ2luYXRvci5wYWdlU2l6ZSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIGdldCBwYWdlU2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnBhZ2luYXRvciAmJiB0aGlzLnBhZ2luYXRvci5wYWdlU2l6ZSB8fCB0aGlzLmRlZmF1bHRQYWdlU2l6ZSB8fCBERUZBVUxUX1BBR0VfU0laRTtcbiAgfVxuXG4gIGdldCBwYWdlT2Zmc2V0KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucGFnaW5hdG9yICYmIHRoaXMucGFnaW5hdG9yLnBhZ2VJbmRleCAqIHRoaXMucGFnaW5hdG9yLnBhZ2VTaXplIHx8IDA7XG4gIH1cblxuICBnZXQgc29ydEFjdGl2ZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNvcnQgJiYgdGhpcy5zb3J0LmFjdGl2ZTtcbiAgfVxuXG4gIGdldCBzb3J0RGlyZWN0aW9uKCk6ICdhc2MnIHwgJ2Rlc2MnIHtcbiAgICByZXR1cm4gdGhpcy5zb3J0ICYmIHRoaXMuc29ydC5kaXJlY3Rpb24gJiYgKHRoaXMuc29ydC5kaXJlY3Rpb24gPT09ICdkZXNjJyA/ICdkZXNjJyA6ICdhc2MnKSB8fCB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIF9wYWdpbmF0b3I6IE1hdFBhZ2luYXRvciB8IG51bGwgPSBudWxsO1xuXG4gIEBJbnB1dCgpIHNldCBwYWdpbmF0b3IodmFsdWU6IE1hdFBhZ2luYXRvcikge1xuICAgIHRoaXMuX3BhZ2luYXRvciA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IHBhZ2luYXRvcigpOiBNYXRQYWdpbmF0b3Ige1xuICAgIHJldHVybiB0aGlzLl9wYWdpbmF0b3IgfHwgdGhpcy5jaGlsZFBhZ2luYXRvcjtcbiAgfVxuXG4gIGdldCBkZXN0cm95ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZGVzdHJveVN1YmplY3Q/LmNsb3NlZCAhPT0gZmFsc2U7XG4gIH1cblxuICBAVmlld0NoaWxkKE1hdFRhYmxlLCB7IHN0YXRpYzogZmFsc2UgfSkgdGFibGU6IE1hdFRhYmxlPFQ+O1xuICBAVmlld0NoaWxkKE1hdFBhZ2luYXRvciwgeyBzdGF0aWM6IGZhbHNlIH0pIGNoaWxkUGFnaW5hdG9yOiBNYXRQYWdpbmF0b3I7XG4gIEBWaWV3Q2hpbGQoTWF0U29ydCwgeyBzdGF0aWM6IGZhbHNlIH0pIHNvcnQ6IE1hdFNvcnQ7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBwcm90ZWN0ZWQgY29sdW1uczogc3RyaW5nW10sXG4gICAgcHJvdGVjdGVkIF9kYXRhU291cmNlPzogRW50aXRpZXNBc3luY1RhYmxlRGF0YVNvdXJjZTxULCBGLCBJRD4sXG4gICAgcHJpdmF0ZSBfZmlsdGVyPzogRlxuICApIHtcbiAgICB0aGlzLnJvdXRlID0gaW5qZWN0b3IuZ2V0KEFjdGl2YXRlZFJvdXRlKTtcbiAgICB0aGlzLnJvdXRlciA9IGluamVjdG9yLmdldChSb3V0ZXIpO1xuICAgIHRoaXMubG9jYXRpb24gPSBpbmplY3Rvci5nZXQoTG9jYXRpb24pO1xuICAgIHRoaXMuc2V0dGluZ3MgPSBpbmplY3Rvci5nZXQoTG9jYWxTZXR0aW5nc1NlcnZpY2UpO1xuICAgIHRoaXMudHJhbnNsYXRlID0gaW5qZWN0b3IuZ2V0KFRyYW5zbGF0ZVNlcnZpY2UpO1xuICAgIHRoaXMubW9kYWxDdHJsID0gaW5qZWN0b3IuZ2V0KE1vZGFsQ29udHJvbGxlcik7XG4gICAgdGhpcy5hbGVydEN0cmwgPSBpbmplY3Rvci5nZXQoQWxlcnRDb250cm9sbGVyKTtcbiAgICB0aGlzLnRvYXN0Q29udHJvbGxlciA9IGluamVjdG9yLmdldChUb2FzdENvbnRyb2xsZXIpO1xuICAgIHRoaXMuZm9ybUVycm9yQWRhcHRlciA9IGluamVjdG9yLmdldChGb3JtRXJyb3JUcmFuc2xhdG9yKTtcbiAgICB0aGlzLm1vYmlsZSA9IHRoaXMuc2V0dGluZ3MubW9iaWxlO1xuXG4gICAgLy8gQXV0b2NvbXBsZXRlIGZpZWxkc1xuICAgIHRoaXMuX2F1dG9jb21wbGV0ZUNvbmZpZ0hvbGRlciA9IG5ldyBNYXRBdXRvY29tcGxldGVDb25maWdIb2xkZXIoe1xuICAgICAgZ2V0VXNlckF0dHJpYnV0ZXM6IChhLCBiKSA9PiB0aGlzLnNldHRpbmdzLmdldEZpZWxkRGlzcGxheUF0dHJpYnV0ZXMoYSwgYilcbiAgICB9KTtcbiAgICB0aGlzLmF1dG9jb21wbGV0ZUZpZWxkcyA9IHRoaXMuX2F1dG9jb21wbGV0ZUNvbmZpZ0hvbGRlci5maWVsZHM7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICBpZiAodGhpcy5faW5pdGlhbGl6ZWQpIHJldHVybjsgLy8gSW5pdCBvbmx5IG9uY2VcbiAgICB0aGlzLl9pbml0aWFsaXplZCA9IHRydWU7XG5cbiAgICAvLyBTZXQgZGVmYXVsdHNcbiAgICB0aGlzLnJlYWRPbmx5ID0gdG9Cb29sZWFuKHRoaXMucmVhZE9ubHksIHRoaXMuZGF0YVNvdXJjZT8uY29uZmlnLnJlYWRPbmx5IHx8IGZhbHNlKTsgLy8gcmVhZC93cml0ZSBieSBkZWZhdWx0XG4gICAgdGhpcy5pbmxpbmVFZGl0aW9uID0gIXRoaXMucmVhZE9ubHkgJiYgdG9Cb29sZWFuKHRoaXMuaW5saW5lRWRpdGlvbiwgZmFsc2UpOyAvLyBmb3JjZSB0byBmYWxzZSB3aGVuIHJlYWRvbmx5XG4gICAgdGhpcy5zYXZlQmVmb3JlRGVsZXRlID0gdG9Cb29sZWFuKHRoaXMuc2F2ZUJlZm9yZURlbGV0ZSwgIXRoaXMucmVhZE9ubHkpOyAvLyBmb3JjZSB0byBmYWxzZSB3aGVuIHJlYWRvbmx5XG4gICAgdGhpcy5zYXZlQmVmb3JlU29ydCA9IHRvQm9vbGVhbih0aGlzLnNhdmVCZWZvcmVTb3J0LCAhdGhpcy5yZWFkT25seSk7IC8vIGZvcmNlIHRvIGZhbHNlIHdoZW4gcmVhZG9ubHlcbiAgICB0aGlzLnNhdmVCZWZvcmVGaWx0ZXIgPSB0b0Jvb2xlYW4odGhpcy5zYXZlQmVmb3JlRmlsdGVyLCAhdGhpcy5yZWFkT25seSk7IC8vIGZvcmNlIHRvIGZhbHNlIHdoZW4gcmVhZG9ubHlcbiAgICB0aGlzLmtlZXBFZGl0ZWRSb3dPblNhdmUgPSB0b0Jvb2xlYW4odGhpcy5rZWVwRWRpdGVkUm93T25TYXZlLCB0aGlzLmlubGluZUVkaXRpb24pO1xuICAgIHRoaXMuZXJyb3JUcmFuc2xhdG9yT3B0aW9ucyA9IHRoaXMuZXJyb3JUcmFuc2xhdG9yT3B0aW9ucyB8fCB7IHNlcGFyYXRvcjogJywgJywgY29udHJvbFBhdGhUcmFuc2xhdG9yOiB0aGlzIH07IC8vIENhbiBiZSBvdmVycmlkZSBpbiBzdWJjbGFzc2VzIGNvbnN0cnVjdG9yc1xuXG4gICAgLy8gQ2hlY2sgYXNrIHVzZXIgY29uZmlybWF0aW9uIGlzIHBvc3NpYmxlXG4gICAgaWYgKHRoaXMuY29uZmlybUJlZm9yZURlbGV0ZSAmJiAhdGhpcy5hbGVydEN0cmwpIHRocm93IEVycm9yKCdNaXNzaW5nIFxcJ2FsZXJ0Q3RybFxcJyBvciBcXCdpbmplY3RvclxcJyBpbiBjb21wb25lbnRcXCdzIGNvbnN0cnVjdG9yLicpO1xuXG4gICAgLy8gRGVmaW5lZCB1bmlxdWUgaWQgZm9yIHNldHRpbmdzIGZvciB0aGUgcGFnZVxuICAgIHRoaXMuc2V0dGluZ3NJZCA9IHRoaXMuc2V0dGluZ3NJZCB8fCB0aGlzLmdlbmVyYXRlVGFibGVJZCgpO1xuXG4gICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5nZXREaXNwbGF5Q29sdW1ucygpO1xuXG4gICAgLy8gTG9hZCB0aGUgc29ydGVkIGNvbHVtbnMsIGZyb20gc2V0dGluZ3NcbiAgICB7XG4gICAgICBjb25zdCBzb3J0ZWRDb2x1bW4gPSB0aGlzLmdldFNvcnRlZENvbHVtbigpO1xuICAgICAgdGhpcy5kZWZhdWx0U29ydEJ5ID0gc29ydGVkQ29sdW1uLmlkO1xuICAgICAgdGhpcy5kZWZhdWx0U29ydERpcmVjdGlvbiA9IHNvcnRlZENvbHVtbi5zdGFydDtcbiAgICB9XG5cbiAgICB0aGlzLmRlZmF1bHRQYWdlU2l6ZSA9IHRoaXMuZ2V0UGFnZVNpemUoKTtcblxuICAgIC8vIFByb3BhZ2F0ZSBlcnJvciB0byBldmVudCBlbWl0dGVyXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbih0aGlzLmVycm9yU3ViamVjdFxuICAgICAgLnN1YnNjcmliZSh2YWx1ZSA9PiB0aGlzLm9uRXJyb3IuZW1pdCh2YWx1ZSkpKTtcblxuICAgIC8vIFByb3BhZ2F0ZSBkaXJ0eSB0byBldmVudCBlbWl0dGVyXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbih0aGlzLmRpcnR5U3ViamVjdFxuICAgICAgLnN1YnNjcmliZSh2YWx1ZSA9PiB0aGlzLm9uRGlydHkuZW1pdCh2YWx1ZSkpKTtcblxuICAgIC8vIFByb3BhZ2F0ZSByb3cgZGlydHkgc3RhdGUgdG8gdGFibGVcbiAgICB0aGlzLnJlZ2lzdGVyU3Vic2NyaXB0aW9uKFxuICAgICAgdGhpcy5vblN0YXJ0RWRpdGluZ1Jvd1xuICAgICAgICAucGlwZShcbiAgICAgICAgICBmaWx0ZXIocm93ID0+IHJvdz8udmFsaWRhdG9yICYmIHRydWUpLFxuICAgICAgICAgIG1lcmdlTWFwKHJvdyA9PiByb3cudmFsaWRhdG9yLnZhbHVlQ2hhbmdlc1xuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgIGZpbHRlcihyb3cgPT4gcm93LmRpcnR5KSxcbiAgICAgICAgICAgICAgZmlyc3QoKSxcbiAgICAgICAgICAgICAgLy8gREVCVUdcbiAgICAgICAgICAgICAgLy90YXAoKCkgPT4gY29uc29sZS5kZWJ1ZyhcIlByb3BhZ2F0ZSByb3cncyBkaXJ0eSB0byB0YWJsZS4uLlwiKSlcblxuICAgICAgICAgICAgICAvLyBTdG9wIGlmIG5leHQgYW5vdGhlciByb3csIG9yIGRlc3Ryb3lpbmdcbiAgICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMub25TdGFydEVkaXRpbmdSb3cpLFxuICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5kZXN0cm95U3ViamVjdClcbiAgICAgICAgICAgICkpXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLm1hcmtBc0RpcnR5KCkpXG4gICAgKTtcblxuICAgIC8vIENhbGwgZGF0YXNvdXJjZSByZWZyZXNoLCBvbiBlYWNoIHJlZnJlc2ggZXZlbnRzXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbihcbiAgICAgIHRoaXMub25SZWZyZXNoXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHN0YXJ0V2l0aDxhbnksIGFueT4oKHRoaXMuYXV0b0xvYWQgPyB7fSA6ICdza2lwJykgYXMgYW55KSxcbiAgICAgICAgICBzd2l0Y2hNYXAoXG4gICAgICAgICAgICAoZXZlbnQ6IGFueSkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLmRpcnR5U3ViamVjdC5uZXh0KGZhbHNlKTtcbiAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb24uY2xlYXIoKTtcbiAgICAgICAgICAgICAgaWYgKGV2ZW50ID09PSAnc2tpcCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2YodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoIXRoaXMuX2RhdGFTb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kZWJ1ZykgY29uc29sZS5kZWJ1ZygnW3RhYmxlXSBTa2lwcGluZyBkYXRhIGxvYWQ6IG5vIGRhdGFTb3VyY2UgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgIHJldHVybiBvZih1bmRlZmluZWQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmICh0aGlzLmRlYnVnKSBjb25zb2xlLmRlYnVnKCdbdGFibGVdIENhbGxpbmcgZGF0YVNvdXJjZS53YXRjaEFsbCgpLi4uJyk7XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRhU291cmNlLndhdGNoQWxsKFxuICAgICAgICAgICAgICAgIHRoaXMucGFnZU9mZnNldCxcbiAgICAgICAgICAgICAgICB0aGlzLnBhZ2VTaXplLFxuICAgICAgICAgICAgICAgIHRoaXMuc29ydEFjdGl2ZSxcbiAgICAgICAgICAgICAgICB0aGlzLnNvcnREaXJlY3Rpb24sXG4gICAgICAgICAgICAgICAgdGhpcy5fZmlsdGVyXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICBjYXRjaEVycm9yKGVyciA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5kZWJ1ZykgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICAgICAgdGhpcy5zZXRFcnJvcihlcnIgJiYgZXJyLm1lc3NhZ2UgfHwgZXJyKTtcbiAgICAgICAgICAgIHJldHVybiBvZih1bmRlZmluZWQpOyAvLyBDb250aW51ZVxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZShyZXMgPT4gdGhpcy51cGRhdGVWaWV3KHJlcyBhcyBMb2FkUmVzdWx0PFQ+IHwgdW5kZWZpbmVkKSkpO1xuXG4gICAgLy8gTGlzdGVuIGRhdGFTb3VyY2UgbG9hZGluZyBldmVudHNcbiAgICBpZiAodGhpcy5fZGF0YVNvdXJjZSkgdGhpcy5saXN0ZW5EYXRhc291cmNlTG9hZGluZyh0aGlzLl9kYXRhU291cmNlKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICAvLyBEZXRlY3Qgd2hlbiBwYXJlbnQgbmdPbkluaXQoKSBub3QgY2FsbFxuICAgIGlmICh0aGlzLmRlYnVnICYmICF0aGlzLmRpc3BsYXllZENvbHVtbnMpIGNvbnNvbGUud2FybihgW3RhYmxlXSBNaXNzaW5nICdkaXNwbGF5ZWRDb2x1bW5zJy4gRGlkIHlvdSBjYWxsIHBhcmVudCBuZ09uSW5pdCgpIGluIGNvbXBvbmVudCAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gP2ApO1xuXG4gICAgLy8gU3RhcnQgbGlzdGVuaW5nIHNvcnQgYW5kIHBhZ2luYXRvciBldmVudHNcbiAgICAvLyBub2luc3BlY3Rpb24gSlNJZ25vcmVkUHJvbWlzZUZyb21DYWxsXG4gICAgdGhpcy5saXN0ZW5Tb3J0QW5kUGFnaW5hdGlvbkV2ZW50cygpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5fc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG5cbiAgICAvLyBVbnN1YnNjcmliZSBjb2x1bW4gdmFsdWUgY2hhbmdlc1xuICAgIE9iamVjdC5rZXlzKHRoaXMuX2NlbGxWYWx1ZUNoYW5nZXNEZWZzKS5mb3JFYWNoKGNvbCA9PiB0aGlzLnN0b3BDZWxsVmFsdWVDaGFuZ2VzKGNvbCwgdHJ1ZSkpO1xuICAgIHRoaXMuX2NlbGxWYWx1ZUNoYW5nZXNEZWZzID0ge307XG5cbiAgICB0aGlzLnJlYWR5U3ViamVjdC51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMubG9hZGluZ1N1YmplY3QudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnNhdmluZ1N1YmplY3QudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLmVycm9yU3ViamVjdC51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuZGlydHlTdWJqZWN0LnVuc3Vic2NyaWJlKCk7XG5cbiAgICB0aGlzLm9uUmVmcmVzaC51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMub25PcGVuUm93LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5vbk5ld1Jvdy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMub25TdGFydEVkaXRpbmdSb3cudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLm9uQ29uZmlybUVkaXRDcmVhdGVSb3cudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLm9uQ2FuY2VsT3JEZWxldGVSb3cudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLm9uQmVmb3JlRGVsZXRlUm93cy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMub25CZWZvcmVDYW5jZWxSb3dzLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5vbkJlZm9yZVNhdmUudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLm9uQWZ0ZXJEZWxldGVkUm93cy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMub25Tb3J0LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5vbkRpcnR5LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5vbkVycm9yLnVuc3Vic2NyaWJlKCk7XG5cbiAgICB0aGlzLmRlc3Ryb3lTdWJqZWN0Lm5leHQoKTtcbiAgICB0aGlzLmRlc3Ryb3lTdWJqZWN0LnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBhc3luYyB1cGRhdGVWaWV3KHJlczogTG9hZFJlc3VsdDxUPiB8IHVuZGVmaW5lZCwgb3B0cz86IHtcbiAgICBlbWl0RXZlbnQ/OiBib29sZWFuO1xuICB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFyZXMpIHJldHVybjsgLy8gU2tpcCAoZS5nIGVycm9yKVxuICAgIGlmIChyZXMgJiYgcmVzLmRhdGEpIHtcbiAgICAgIHRoaXMudmlzaWJsZVJvd0NvdW50ID0gcmVzLmRhdGEubGVuZ3RoO1xuICAgICAgdGhpcy50b3RhbFJvd0NvdW50ID0gaXNOb3ROaWwocmVzLnRvdGFsKSA/IHJlcy50b3RhbCA6ICgodGhpcy5wYWdpbmF0b3IgJiYgdGhpcy5wYWdpbmF0b3IucGFnZUluZGV4ICogKHRoaXMucGFnaW5hdG9yLnBhZ2VTaXplIHx8IERFRkFVTFRfUEFHRV9TSVpFKSB8fCAwKSArIHRoaXMudmlzaWJsZVJvd0NvdW50KTtcbiAgICAgIGlmICh0aGlzLmRlYnVnKSBjb25zb2xlLmRlYnVnKGBbdGFibGVdICR7cmVzLmRhdGEubGVuZ3RofSByb3dzIGxvYWRlZGApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvL2lmICh0aGlzLmRlYnVnKSBjb25zb2xlLmRlYnVnKCdbdGFibGVdIE5PIHJvd3MgbG9hZGVkJyk7XG4gICAgICB0aGlzLnRvdGFsUm93Q291bnQgPSAwO1xuICAgICAgdGhpcy52aXNpYmxlUm93Q291bnQgPSAwO1xuICAgIH1cblxuICAgIGlmICghb3B0cyB8fCBvcHRzLmVtaXRFdmVudCAhPT0gZmFsc2UpIHtcbiAgICAgIGF3YWl0IHRoaXMubWFya0FzVW50b3VjaGVkKHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgIHRoaXMubWFya0FzUHJpc3RpbmUoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgdGhpcy5tYXJrQXNMb2FkZWQoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH1cblxuICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBzZXREYXRhc291cmNlKGRhdGFzb3VyY2U6IEVudGl0aWVzQXN5bmNUYWJsZURhdGFTb3VyY2U8VCwgRiwgSUQ+KSB7XG4gICAgaWYgKHRoaXMuX2RhdGFTb3VyY2UpIHRocm93IG5ldyBFcnJvcignW3RhYmxlXSBkYXRhU291cmNlIGFscmVhZHkgc2V0ICEnKTtcbiAgICBpZiAoZGF0YXNvdXJjZSAmJiB0aGlzLl9kYXRhU291cmNlICE9PSBkYXRhc291cmNlKSB7XG4gICAgICB0aGlzLl9kYXRhU291cmNlID0gZGF0YXNvdXJjZTtcbiAgICAgIGlmICh0aGlzLl9pbml0aWFsaXplZCkgdGhpcy5saXN0ZW5EYXRhc291cmNlTG9hZGluZyhkYXRhc291cmNlKTtcbiAgICB9XG4gIH1cblxuICByZXNldERhdGFTb3VyY2UoKSB7XG4gICAgaWYgKHRoaXMuX2RhdGFTb3VyY2VMb2FkaW5nU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLl9kYXRhU291cmNlTG9hZGluZ1N1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5fc3Vic2NyaXB0aW9uLnJlbW92ZSh0aGlzLl9kYXRhU291cmNlTG9hZGluZ1N1YnNjcmlwdGlvbik7XG4gICAgfVxuICAgIC8vdGhpcy5fZGF0YVNvdXJjZT8uY2xvc2UoKTtcbiAgICB0aGlzLl9kYXRhU291cmNlID0gbnVsbDtcbiAgfVxuXG4gIGFkZENvbHVtbkRlZihjb2x1bW46IENka0NvbHVtbkRlZikge1xuICAgIHRoaXMudGFibGUuYWRkQ29sdW1uRGVmKGNvbHVtbik7XG4gIH1cblxuICByZW1vdmVDb2x1bW5EZWYoY29sdW1uOiBDZGtDb2x1bW5EZWYpIHtcbiAgICB0aGlzLnRhYmxlLnJlbW92ZUNvbHVtbkRlZihjb2x1bW4pO1xuICB9XG5cbiAgc2V0RmlsdGVyKGZpbHRlcjogRiwgb3B0cz86IHsgZW1pdEV2ZW50PzogYm9vbGVhbjsgfSkge1xuICAgIG9wdHMgPSBvcHRzIHx8IHsgZW1pdEV2ZW50OiB0cnVlIH07XG5cbiAgICBpZiAodGhpcy5zYXZlQmVmb3JlRmlsdGVyKSB7XG5cbiAgICAgIC8vIGlmIGEgZGlydHkgdGFibGUgaXMgdG8gYmUgc2F2ZWQgYmVmb3JlIGZpbHRlclxuICAgICAgaWYgKHRoaXMuZGlydHkpIHtcblxuICAgICAgICAvLyBTYXZlXG4gICAgICAgIHRoaXMuc2F2ZUJlZm9yZUFjdGlvbignZmlsdGVyJykudGhlbihzYXZlZCA9PiB7XG4gICAgICAgICAgLy8gQXBwbHkgZmlsdGVyIG9ubHkgaWYgdXNlciBkaWRuJ3QgY2FuY2VsIHRoZSBzYXZlIG9yIHRoZSBzYXZlIGlzIG9rXG4gICAgICAgICAgaWYgKHNhdmVkKSB7XG4gICAgICAgICAgICB0aGlzLmFwcGx5RmlsdGVyKGZpbHRlciwgb3B0cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gYXBwbHkgZmlsdGVyIG9uIG5vbi1kaXJ0eSB0YWJsZVxuICAgICAgICB0aGlzLmFwcGx5RmlsdGVyKGZpbHRlciwgb3B0cyk7XG4gICAgICB9XG5cbiAgICB9IGVsc2Uge1xuXG4gICAgICAvLyBhcHBseSBmaWx0ZXIgZGlyZWN0bHlcbiAgICAgIHRoaXMuYXBwbHlGaWx0ZXIoZmlsdGVyLCBvcHRzKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjb25maXJtQW5kQWRkKGV2ZW50PzogRXZlbnQsIHJvdz86IEFzeW5jVGFibGVFbGVtZW50PFQ+KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKCFhd2FpdCB0aGlzLmNvbmZpcm1FZGl0Q3JlYXRlKGV2ZW50LCByb3cpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIEFkZCByb3dcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5hZGRSb3coZXZlbnQpO1xuICB9XG5cbiAgYXN5bmMgY29uZmlybUFuZEJhY2t3YXJkKGV2ZW50PzogRXZlbnQsIHJvdz86IEFzeW5jVGFibGVFbGVtZW50PFQ+KTogUHJvbWlzZTxib29sZWFuPiB7XG5cbiAgICAvLyBEZWxldGluZyBlZGl0ZWQgcm93LCBpZiBlbXB0eSBhbmQgbm90IGRpcnR5XG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZS5oYXNTb21lRWRpdGluZ1JvdygpKSB7XG4gICAgICBmb3IgKGNvbnN0IGVkaXRpbmdSb3cgb2YgdGhpcy5kYXRhU291cmNlLmdldEVkaXRpbmdSb3dzKCkuZmlsdGVyKHJvdyA9PiByb3cuaWQgPT09IC0xICYmIHJvdy5pbnZhbGlkICYmICFyb3cuZGlydHkpKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZGVsZXRlTmV3Um93KGV2ZW50LCBlZGl0aW5nUm93KTtcbiAgICAgIH1cblxuICAgICAgLy8gV2FpdCBkZWxldGlvbiBpcyBkb25lLCB0aGVuIGVkaXQgcHJldmlvdXMgcm93IChieSBpZCwgYmVjYXVzZSBvZiByZWxvYWRpbmcpXG4gICAgICBhd2FpdCB0aGlzLndhaXRJZGxlKCk7XG4gICAgICBhd2FpdCB0aGlzLmVkaXRSb3dCeUlkKGV2ZW50LCByb3cuaWQsIHsgZm9jdXNDb2x1bW46IHRoaXMubGFzdFVzZXJDb2x1bW4gfSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBFZGl0IHByZXZpb3VzIHJvd1xuICAgIGF3YWl0IHRoaXMuZWRpdFJvdyhldmVudCwgcm93LCB7IGZvY3VzQ29sdW1uOiB0aGlzLmxhc3RVc2VyQ29sdW1uIH0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgYXN5bmMgY29uZmlybUFuZEZvcndhcmQoZXZlbnQ/OiBFdmVudCwgcm93PzogQXN5bmNUYWJsZUVsZW1lbnQ8VD4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoIXRoaXMuaW5saW5lRWRpdGlvbikgcmV0dXJuIGZhbHNlO1xuXG4gICAgYXdhaXQgdGhpcy5jb25maXJtRWRpdENyZWF0ZShldmVudCwgcm93KTtcblxuICAgIC8vIEVkaXQgbmV4dCByb3dcbiAgICBhd2FpdCB0aGlzLmVkaXRSb3dCeUlkKGV2ZW50LCByb3cuaWQgKyAxLCB7IGZvY3VzQ29sdW1uOiB0aGlzLmZpcnN0VXNlckNvbHVtbiB9KTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maXJtIHRoZSBjcmVhdGlvbiBvZiB0aGUgZ2l2ZW4gcm93LCBvciBpZiBub3Qgc3BlY2lmaWVkIHRoZSBjdXJyZW50bHkgZWRpdGVkIHJvd1xuICAgKlxuICAgKiBAcGFyYW0gZXZlbnRcbiAgICogQHBhcmFtIHJvd1xuICAgKi9cbiAgYXN5bmMgY29uZmlybUVkaXRDcmVhdGUoZXZlbnQ/OiBFdmVudCwgcm93PzogQXN5bmNUYWJsZUVsZW1lbnQ8VD4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByb3cgPSByb3cgfHwgdGhpcy5kYXRhU291cmNlLmdldFNpbmdsZUVkaXRpbmdSb3coKTtcbiAgICBpZiAoIXJvdyB8fCAhcm93LmVkaXRpbmcpIHJldHVybiB0cnVlOyAvLyBubyByb3cgdG8gY29uZmlybVxuXG4gICAgLy8gU3RvcCBldmVudFxuICAgIGV2ZW50Py5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIC8vIENvbmZpcm1hdGlvbiBlZGl0aW9uIG9yIGNyZWF0aW9uXG4gICAgY29uc3QgY29uZmlybWVkID0gYXdhaXQgcm93LmNvbmZpcm1FZGl0Q3JlYXRlKCk7XG5cbiAgICBpZiAoY29uZmlybWVkKSB7XG4gICAgICAvLyBNYXJrIHRhYmxlIGFzIGRpcnR5IChpZiByb3cgaXMgZGlydHkpXG4gICAgICBpZiAocm93LmRpcnR5KSB7XG4gICAgICAgIHRoaXMubWFya0FzRGlydHkoeyBlbWl0RXZlbnQ6IGZhbHNlIC8qIGJlY2F1c2Ugb2YgcmVzZXRFcnJvcigpICovIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyBDbGVhciBlcnJvclxuICAgICAgdGhpcy5yZXNldEVycm9yKCk7XG5cbiAgICAgIC8vIEVtaXQgdGhlIGNvbmZpcm0gZXZlbnRcbiAgICAgIHRoaXMub25Db25maXJtRWRpdENyZWF0ZVJvdy5uZXh0KHJvdyk7XG5cbiAgICAgIHJldHVybiB0cnVlOyAvLyBDb250aW51ZVxuICAgIH1cblxuICAgIGlmIChyb3cudmFsaWRhdG9yKSB7XG4gICAgICAvLyBJZiBwZW5kaW5nOiBXYWl0IGVuZCBvZiB2YWxpZGF0aW9uXG4gICAgICAvLyBUT0RPOiByZW1vdmUgd2hlbiB1c2luZyBhc3luYyBpc1ZhbGlkKCkgZnVuY3Rpb25cbiAgICAgIGlmIChyb3cucGVuZGluZykge1xuICAgICAgICBhd2FpdCBBcHBGb3JtVXRpbHMud2FpdFdoaWxlUGVuZGluZyhyb3cudmFsaWRhdG9yKTtcbiAgICAgIH1cblxuICAgICAgLy8gTk9UIGNvbmZpcm1lZCA9IHJvdyBoYXMgZXJyb3JcbiAgICAgIGlmICh0aGlzLmRlYnVnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignW3RhYmxlXSBDYW5ub3QgY29uZmlybSByb3csIGJlY2F1c2UgaW52YWxpZCcpO1xuICAgICAgICBBcHBGb3JtVXRpbHMubG9nRm9ybUVycm9ycyhyb3cudmFsaWRhdG9yLCAnW3RhYmxlXSAnKTtcbiAgICAgIH1cblxuICAgICAgLy8gZml4OiBtYXJrIGFsbCBjb250cm9scyBhcyB0b3VjaGVkIHRvIHNob3cgZXJyb3JzXG4gICAgICByb3cudmFsaWRhdG9yLm1hcmtBbGxBc1RvdWNoZWQoKTtcblxuICAgICAgLy8gQ29tcHV0ZSByb3cgZXJyb3IsIGFuZCBwcm9wYWdhdGUgdG8gdGFibGUncyBlcnJvclxuICAgICAgaWYgKHRoaXMucHJvcGFnYXRlUm93RXJyb3IpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmdldFJvd0Vycm9yKHJvdyk7XG4gICAgICAgIHRoaXMuc2V0RXJyb3IoZXJyb3IpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdCBjb25maXJtZWRcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBhc3luYyBjYW5jZWxPckRlbGV0ZShldmVudDogRXZlbnQsIHJvdzogQXN5bmNUYWJsZUVsZW1lbnQ8VD4sIG9wdHM/OiB7IGludGVyYWN0aXZlPzogYm9vbGVhbjsga2VlcEVkaXRpbmc/OiBib29sZWFuOyB9KSB7XG4gICAgLy8gRGVsZXRlIG5ldyByb3dcbiAgICBpZiAocm93LmlkID09PSAtMSkge1xuICAgICAgYXdhaXQgdGhpcy5kZWxldGVOZXdSb3coZXZlbnQsIHJvdyk7XG4gICAgfVxuICAgIC8vIERlbGV0ZSBleGlzdGluZyAoYnV0IG5vdCBlZGl0aW5nKSByb3dcbiAgICBlbHNlIGlmICghcm93LmVkaXRpbmcpIHtcbiAgICAgIGF3YWl0IHRoaXMuZGVsZXRlRXhpc3RpbmdSb3coZXZlbnQsIHJvdywgb3B0cyk7XG4gICAgfVxuICAgIC8vIENhbmNlbCBleGlzdGluZyAoYW5kIGVkaXRpbmcpIHJvd1xuICAgIGVsc2Uge1xuICAgICAgYXdhaXQgdGhpcy5jYW5jZWxFeGlzdGluZ1JvdyhldmVudCwgcm93LCBvcHRzKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBhZGRSb3coZXZlbnQ/OiBFdmVudCwgaW5zZXJ0QXQ/OiBudW1iZXIsIG9wdHM/OiB7IGZvY3VzQ29sdW1uPzogc3RyaW5nOyBlZGl0aW5nPzogYm9vbGVhbiB9KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKHRoaXMuZGVidWcpIGNvbnNvbGUuZGVidWcoJ1t0YWJsZV0gQXNraW5nIGZvciBuZXcgcm93Li4uJyk7XG4gICAgaWYgKCF0aGlzLl9lbmFibGVkKSByZXR1cm4gZmFsc2U7XG5cbiAgICAvLyBVc2UgbW9kYWwgaWYgaW5saW5lIGVkaXRpb24gaXMgZGlzYWJsZWRcbiAgICBpZiAoIXRoaXMuaW5saW5lRWRpdGlvbikge1xuICAgICAgYXdhaXQgdGhpcy5vcGVuTmV3Um93RGV0YWlsKGV2ZW50KTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gZmluaXNoIGVkaXRlZCByb3cgZmlyc3RcbiAgICBpZiAoIWF3YWl0IHRoaXMuY29uZmlybUVkaXRDcmVhdGUoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIEFkZCBuZXcgcm93XG4gICAgY29uc3Qgcm93ID0gYXdhaXQgdGhpcy5hZGRSb3dUb1RhYmxlKGluc2VydEF0LCBvcHRzKTtcbiAgICByZXR1cm4gISFyb3c7XG4gIH1cblxuICBhc3luYyBzYXZlKG9wdHM/OiB7IGtlZXBFZGl0aW5nPzogYm9vbGVhbiB9KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgb3B0cyA9IHtcbiAgICAgIGtlZXBFZGl0aW5nOiB0aGlzLmtlZXBFZGl0ZWRSb3dPblNhdmUsXG4gICAgICAuLi5vcHRzXG4gICAgfTtcbiAgICBpZiAodGhpcy5yZWFkT25seSkge1xuICAgICAgdGhyb3cgeyBjb2RlOiBFcnJvckNvZGVzLlRBQkxFX1JFQURfT05MWSwgbWVzc2FnZTogJ0VSUk9SLlRBQkxFX1JFQURfT05MWScgfTtcbiAgICB9XG5cbiAgICB0aGlzLnJlc2V0RXJyb3IoKTtcblxuICAgIC8vIEtlZXAgZWRpdGVkIHJvdyBpZCAoc2hvdWxkIGJlIGRvbmUgQkVGT1JFIGNvbmZpcm1FZGl0Q3JlYXRlKCkgKVxuICAgIGNvbnN0IGVkaXRlZFJvdyA9IHRoaXMuZGF0YVNvdXJjZS5nZXRTaW5nbGVFZGl0aW5nUm93KCk7XG4gICAgdGhpcy5wcmV2aW91c2x5RWRpdGVkUm93SWQgPSBvcHRzLmtlZXBFZGl0aW5nID8gKChlZGl0ZWRSb3c/LmVkaXRpbmcgPyBlZGl0ZWRSb3cuaWQgOiB1bmRlZmluZWQpIHx8IHRoaXMuc2luZ2xlU2VsZWN0ZWRSb3c/LmlkKSA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBwcmV2aW91c2x5RWRpdGVkRGF0YSA9IG9wdHMua2VlcEVkaXRpbmcgPyAoaXNOb3ROaWwodGhpcy5wcmV2aW91c2x5RWRpdGVkUm93SWQpICYmIGVkaXRlZFJvdz8uY3VycmVudERhdGEgfHwgdGhpcy5zaW5nbGVTZWxlY3RlZFJvdz8uY3VycmVudERhdGEpIDogdW5kZWZpbmVkO1xuXG4gICAgaWYgKCFhd2FpdCB0aGlzLmNvbmZpcm1FZGl0Q3JlYXRlKCkpIHtcbiAgICAgIHRocm93IHsgY29kZTogRXJyb3JDb2Rlcy5UQUJMRV9JTlZBTElEX1JPV19FUlJPUiwgbWVzc2FnZTogJ0VSUk9SLlRBQkxFX0lOVkFMSURfUk9XX0VSUk9SJyB9O1xuICAgIH1cblxuICAgIC8vIE1hcmsgYXMgc2F2aW5nXG4gICAgdGhpcy5tYXJrQXNTYXZpbmcoKTtcblxuICAgIHRyeSB7XG5cbiAgICAgIC8vIENhbGxpbmcgc2VydmljZSBzYXZlKClcbiAgICAgIGlmICh0aGlzLmRlYnVnKSBjb25zb2xlLmRlYnVnKCdbdGFibGVdIENhbGxpbmcgZGF0YVNvdXJjZS5zYXZlKCkuLi4nKTtcbiAgICAgIGNvbnN0IGlzT0sgPSBhd2FpdCB0aGlzLl9kYXRhU291cmNlLnNhdmUoKTtcblxuICAgICAgaWYgKGlzT0spIHRoaXMubWFya0FzUHJpc3RpbmUoKTtcblxuICAgICAgcmV0dXJuIGlzT0s7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLnNldEVycm9yKGVyciAmJiBlcnIubWVzc2FnZSB8fCBlcnIpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLm1hcmtBc1NhdmVkKCk7XG5cbiAgICAgIC8vIFJlc3RvcmUgcHJldmlvdXMgcm93XG4gICAgICBpZiAoaXNOb3ROaWwodGhpcy5wcmV2aW91c2x5RWRpdGVkUm93SWQpKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2VsZWN0Um93QnlJZE9yRGF0YSh0aGlzLnByZXZpb3VzbHlFZGl0ZWRSb3dJZCwgcHJldmlvdXNseUVkaXRlZERhdGEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGNhbmNlbChldmVudD86IEV2ZW50LCBvcHRzPzogeyBpbnRlcmFjdGl2ZT86IGJvb2xlYW47IH0pIHtcblxuICAgIC8vIENoZWNrIGNvbmZpcm1hdGlvblxuICAgIGlmICgoIW9wdHMgfHwgb3B0cy5pbnRlcmFjdGl2ZSAhPT0gZmFsc2UpICYmIHRoaXMuZGlydHkgJiYgKHRoaXMuY29uZmlybUJlZm9yZUNhbmNlbCB8fCB0aGlzLm9uQmVmb3JlQ2FuY2VsUm93cy5vYnNlcnZlcnMubGVuZ3RoID4gMCkpIHtcbiAgICAgIGV2ZW50Py5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIGlmICghYXdhaXQgdGhpcy5jYW5DYW5jZWxSb3dzKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMub25SZWZyZXNoLmVtaXQoKTtcbiAgfVxuXG4gIGFzeW5jIGR1cGxpY2F0ZVJvdyhldmVudD86IEV2ZW50LCByb3c/OiBBc3luY1RhYmxlRWxlbWVudDxUPiwgb3B0cz86IHtcbiAgICBza2lwUHJvcGVydGllcz86IHN0cmluZ1tdO1xuICB9KSB7XG4gICAgZXZlbnQ/LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgcm93ID0gcm93IHx8IHRoaXMuc2luZ2xlU2VsZWN0ZWRSb3c7XG4gICAgaWYgKCFyb3cgfHwgIWF3YWl0IHRoaXMuY29uZmlybUVkaXRDcmVhdGUoZXZlbnQsIHJvdykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBuZXdSb3cgPSBhd2FpdCB0aGlzLmFkZFJvd1RvVGFibGUocm93LmlkICsgMSk7XG4gICAgaWYgKCFuZXdSb3cpIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGFkZCBuZXcgcm93IHRvIHRhYmxlJyk7XG4gICAgY29uc3QganNvbiA9IHsgLi4ucm93LmN1cnJlbnREYXRhLCBpZDogbnVsbCB9O1xuXG4gICAgLy8gUmVzZXQgc29tZSBwcm9wZXJ0aWVzIChlLmcuIHJhbmtPcmRlciwgZXRjKVxuICAgIGlmIChvcHRzICYmIG9wdHMuc2tpcFByb3BlcnRpZXMpIHtcbiAgICAgIGNvbnN0IG5ld0RhdGEgPSBuZXdSb3cuY3VycmVudERhdGE7XG4gICAgICBvcHRzLnNraXBQcm9wZXJ0aWVzLmZvckVhY2goa2V5ID0+IGpzb25ba2V5XSA9IG5ld0RhdGFba2V5XSk7XG4gICAgfVxuXG4gICAgaWYgKG5ld1Jvdy52YWxpZGF0b3IpIHtcbiAgICAgIG5ld1Jvdy52YWxpZGF0b3IucGF0Y2hWYWx1ZShqc29uKTtcbiAgICAgIG5ld1Jvdy52YWxpZGF0b3IubWFya0FzRGlydHkoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG5ld1Jvdy5jdXJyZW50RGF0YT8uZnJvbU9iamVjdCkge1xuICAgICAgICBuZXdSb3cuY3VycmVudERhdGEuZnJvbU9iamVjdChqc29uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld1Jvdy5jdXJyZW50RGF0YSA9IGpzb247XG4gICAgICB9XG4gICAgICB0aGlzLm1hcmtBc0RpcnR5KCk7XG4gICAgfVxuXG4gICAgLy8gc2VsZWN0XG4gICAgYXdhaXQgdGhpcy5jbGlja1Jvdyh1bmRlZmluZWQsIG5ld1Jvdyk7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgbnVtYmVyIG9mIHNlbGVjdGVkIGVsZW1lbnRzIG1hdGNoZXMgdGhlIHRvdGFsIG51bWJlciBvZiByb3dzLiAqL1xuICBpc0FsbFNlbGVjdGVkKCkge1xuICAgIC8vIERFQlVHXG4gICAgLy9jb25zb2xlLmRlYnVnKCdpc0FsbFNlbGVjdGVkLiBsZW5ndGhzJywgdGhpcy5zZWxlY3Rpb24uc2VsZWN0ZWQubGVuZ3RoLCB0aGlzLnRvdGFsUm93Q291bnQpO1xuXG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0aW9uLnNlbGVjdGVkLmxlbmd0aCA9PT0gdGhpcy50b3RhbFJvd0NvdW50IHx8XG4gICAgICB0aGlzLnNlbGVjdGlvbi5zZWxlY3RlZC5sZW5ndGggPT09IHRoaXMudmlzaWJsZVJvd0NvdW50O1xuICB9XG5cbiAgLyoqIFNlbGVjdHMgYWxsIHJvd3MgaWYgdGhleSBhcmUgbm90IGFsbCBzZWxlY3RlZDsgb3RoZXJ3aXNlIGNsZWFyIHNlbGVjdGlvbi4gKi9cbiAgYXN5bmMgbWFzdGVyVG9nZ2xlKCkge1xuXG4gICAgaWYgKHRoaXMubG9hZGluZykgcmV0dXJuO1xuICAgIGlmICh0aGlzLmlzQWxsU2VsZWN0ZWQoKSkge1xuICAgICAgdGhpcy5zZWxlY3Rpb24uY2xlYXIoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgcm93cyA9IHRoaXMuX2RhdGFTb3VyY2UuZ2V0Um93cygpO1xuICAgICAgcm93cy5mb3JFYWNoKHJvdyA9PiB0aGlzLnNlbGVjdGlvbi5zZWxlY3Qocm93KSk7XG4gICAgfVxuICB9XG5cbiAgZGVsZXRlU2VsZWN0aW9uKGV2ZW50OiBFdmVudCwgb3B0cz86IHtpbnRlcmFjdGl2ZT86IGJvb2xlYW59KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICByZXR1cm4gdGhpcy5kZWxldGVSb3dzKGV2ZW50LCB0aGlzLnNlbGVjdGlvbi5zZWxlY3RlZCwgb3B0cyk7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqIEBwYXJhbSByb3dcbiAgICogQHBhcmFtIG9wdHMgVXNlIGludGVyYWN0aXZlPWZhbHNlIHRvIGF2b2lkIHVzZXIgaW50ZXJhY3Rpb24gKGUuZy4gdXNlciBjb25maXJtYXRpb24pXG4gICAqICBBbmQgdG8gZm9yY2UgZGVsZXRpb24gZXZlbiBpZiB0YWJsZSBpcyBidXN5XG4gICAqL1xuICBhc3luYyBkZWxldGVSb3coZXZlbnQ6IEV2ZW50IHwgbnVsbCwgcm93OiBBc3luY1RhYmxlRWxlbWVudDxUPiwgb3B0cz86IHsgaW50ZXJhY3RpdmU/OiBib29sZWFuOyB9KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgZGVsZXRlQ291bnQgPSBhd2FpdCB0aGlzLmRlbGV0ZVJvd3MoZXZlbnQsIFtyb3ddLCBvcHRzKTtcbiAgICByZXR1cm4gZGVsZXRlQ291bnQgPT09IDE7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqIEBwYXJhbSByb3dzXG4gICAqIEBwYXJhbSBvcHRzIFVzZSBpbnRlcmFjdGl2ZT1mYWxzZSB0byBhdm9pZCB1c2VyIGludGVyYWN0aW9uIChlLmcuIHVzZXIgY29uZmlybWF0aW9uKVxuICAgKiAgICBBbmQgdG8gZm9yY2UgZGVsZXRpb24gZXZlbiBpZiB0YWJsZSBpcyBidXN5XG4gICAqL1xuICBhc3luYyBkZWxldGVSb3dzKGV2ZW50OiBFdmVudCB8IG51bGwsIHJvd3M6IEFzeW5jVGFibGVFbGVtZW50PFQ+W10sIG9wdHM/OiB7IGludGVyYWN0aXZlPzogYm9vbGVhbjsgfSk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IHsgY29kZTogRXJyb3JDb2Rlcy5UQUJMRV9SRUFEX09OTFksIG1lc3NhZ2U6ICdFUlJPUi5UQUJMRV9SRUFEX09OTFknIH07XG4gICAgfVxuICAgIGlmIChldmVudD8uZGVmYXVsdFByZXZlbnRlZCkgcmV0dXJuIDA7IC8vIFNLaXBcbiAgICBldmVudD8ucHJldmVudERlZmF1bHQoKTtcblxuICAgIGlmICghdGhpcy5fZW5hYmxlZCB8fCBpc0VtcHR5QXJyYXkocm93cykpIHJldHVybiAwOyAvLyBTa2lwIGlzIGRpc2FibGVkLCBvciBubyByb3dzIHRvIGRlbGV0ZVxuXG4gICAgaWYgKHRoaXMubG9hZGluZyAmJiAoIW9wdHMgfHwgb3B0cy5pbnRlcmFjdGl2ZSAhPT0gZmFsc2UpKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1thcHAtdGFibGVdIFNraXAgZGVsZXRlUm93cygpIGJlY2F1c2UgdGFibGUgaXMgYnVzeSAobG9hZGluZykuIFVzZSBvcHRzLmludGVyYWN0aXZlID0gZmFsc2UgdG8gZm9yY2UgZGVsZXRpb24nKTtcbiAgICAgIHJldHVybiAwOyAvLyBTa2lwIGlmIGxvYWRpbmdcbiAgICB9XG5cbiAgICAvLyBNYWtlIHN1cmUgdG8ga2VlcCBuZXdseSBjcmVhdGVkIHJvd1xuICAgIGNvbnN0IGVkaXRlZFJvdyA9IHRoaXMuZGF0YVNvdXJjZS5nZXRTaW5nbGVFZGl0aW5nUm93KCk7XG4gICAgaWYgKGVkaXRlZFJvdz8uaWQgPT09IC0xICYmIGVkaXRlZFJvdy5lZGl0aW5nICYmICFyb3dzLmluY2x1ZGVzKGVkaXRlZFJvdykpIHtcbiAgICAgIGNvbnN0IGNvbmZpcm1lZCA9IGF3YWl0IHRoaXMuY29uZmlybUVkaXRDcmVhdGUoKTtcbiAgICAgIGlmICghY29uZmlybWVkKSByZXR1cm4gMDsgLy8gQ2Fubm90IGRlbGV0ZSAoZS5nLiBlZGl0ZWQgcm93IGlzIGludmFsaWQpXG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgaXQgY2FuIGRlbGV0ZVxuICAgIGNvbnN0IGNhbkRlbGV0ZSA9IGF3YWl0IHRoaXMuY2FuRGVsZXRlUm93cyhyb3dzLCBvcHRzKTtcbiAgICBpZiAoIWNhbkRlbGV0ZSkgcmV0dXJuIDA7IC8vIENhbm5vdCBkZWxldGVcblxuICAgIC8vIFJldmVyc2Ugcm93IG9yZGVyIChvbiBhIGNvcHkpXG4gICAgLy8gVGhpcyBpcyBhIHdvcmthcm91bmQsIG5lZWQgYmVjYXVzZSByb3cuZGVsZXRlKCkgaGFzIGFzeW5jIGV4ZWN1dGlvblxuICAgIC8vIGFuZCBpbmRleCBjYWNoZSBpcyB1cGRhdGVkIHdpdGggYSBkZWxheVxuICAgIGxldCB0ZW1wUm93cyA9IHJvd3Muc2xpY2UoKVxuICAgICAgLnNvcnQoKGEsIGIpID0+IGEuaWQgPiBiLmlkID8gLTEgOiAxKTtcblxuICAgIGxldCBkZWxldGVkUm93czogQXN5bmNUYWJsZUVsZW1lbnQ8VD5bXSA9IFtdO1xuXG4gICAgLy8gSWYgZGF0YSBuZWVkIHRvIGJlIHNhdmVkIGZpcnN0XG4gICAgaWYgKHRoaXMuc2F2ZUJlZm9yZURlbGV0ZSkge1xuICAgICAgLy8gRXhjbHVkZSBpbnZhbGlkIHJvd3MgKGJlY2F1c2Ugb2Ygc2F2ZSgpIHdpbGwgZmFpbCwgd2hlbiBleGlzdHMgc29tZSBpbnZhbGlkIHJvd3MpXG4gICAgICB0ZW1wUm93cyA9IHRlbXBSb3dzLmZpbHRlcihyb3cgPT4ge1xuICAgICAgICAvLyBEZWxldGUgdGhlIHJvdyA6XG4gICAgICAgIC8vIC0gaWYgbmV3bHkgY3JlYXRlZCByb3cgKGlkID0gLTEpLFxuICAgICAgICAvLyAtIG9yIGlmIGludmFsaWQgYW5kIG5vdCBlZGl0aW5nICg9IG5vdCBjYW5jZWxsYWJsZSlcbiAgICAgICAgaWYgKHJvdy5pZCA9PT0gLTEgfHwgKCFyb3cuZWRpdGluZyAmJiByb3cuaW52YWxpZCAvKmRvIG5vdCB1c2UgIXZhbGlkIGJlY2F1c2UgaWYgcm93IGlzIGRpc2FibGVkLCBpdCB3aWxsIGJlIGFsd2F5cyAhdmFsaWQgKi8pKSB7XG4gICAgICAgICAgaWYgKHRoaXMuZGVidWcpIGNvbnNvbGUuZGVidWcoYFt0YWJsZV0gRGVsZXRlIHJvdyAjJHtyb3cuaWR9YCk7XG4gICAgICAgICAgcm93LmRlbGV0ZSgpO1xuICAgICAgICAgIHRoaXMudmlzaWJsZVJvd0NvdW50LS07XG4gICAgICAgICAgdGhpcy50b3RhbFJvd0NvdW50LS07XG4gICAgICAgICAgZGVsZXRlZFJvd3MucHVzaChyb3cpO1xuICAgICAgICAgIHJldHVybiBmYWxzZTsgLy8gRXhjbHVkZSBmcm9tIHRoZSBsaXN0IHRvIGRlbGV0ZSB1c2luZyB0aGUgc2VydmljZVxuICAgICAgICB9XG4gICAgICAgIC8vIENhbmNlbCB0aGUgcm93IChhbmQgbWFyayBhcyBwcmlzdGluZSksIHdoZW4gbm90IHZhbGlkIGJ1dCBpbiBlZGl0aW9uXG4gICAgICAgIGVsc2UgaWYgKHJvdy5lZGl0aW5nICYmICFyb3cudmFsaWQpIHtcbiAgICAgICAgICByb3cuY2FuY2VsKCk7XG4gICAgICAgICAgLy8gTWFyayByb3cgYXMgcHJpc3RpbmUgKGlmIHBvc3NpYmxlKVxuICAgICAgICAgIHRoaXMuY2hlY2tJZlJvd1ByaXN0aW5lKHJvdywgeyBlbWl0RXZlbnQ6IGZhbHNlLCBvbmx5U2VsZjogdHJ1ZSAvKmF2b2lkIHByb3BhZ2F0aW9uIHRvIHRhYmxlKi8gfSk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7IC8vIEtlZXAgdGhlIHJvdy4gdGhlIHJvdyB3aWxsIGJlIGRlbGV0ZWQgYWZ0ZXIgdGhlIHNhdmVcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIEFwcGx5IHNhdmUsIG9ubHkgaWYgdGhlcmUgaXMgc3RpbGwgc29tZSByb3dzIHRvIGRlbGV0ZVxuICAgICAgLy8gV0FSTjogSWYgbm8gbW9yZSByb3dzIChlLmcuIGJlY2F1c2UgYWxsIGhhcyBiZWVuIGNhbmNlbGxlZCkgdGhlbiBjb250aW51ZSBhbnl3YXkgdG8gY2xlYXIgZWRpdGVkUm93IGFuZCBzZWxlY3Rpb24gKGlzc3VlIElNQUdJTkUtNjY5KVxuICAgICAgaWYgKGRlbGV0ZWRSb3dzLmxlbmd0aCB8fCB0ZW1wUm93cy5sZW5ndGgpIHtcblxuICAgICAgICAvLyBTYXZlIGRhdGEgKGUuZy4gd2hlbiB1c2luZyBtZW1vcnkgc2VydmljZSlcbiAgICAgICAgY29uc3Qgc2F2ZWQgPSBhd2FpdCB0aGlzLnNhdmVCZWZvcmVBY3Rpb24oJ2RlbGV0ZScpO1xuICAgICAgICBpZiAoIXNhdmVkKSB7XG4gICAgICAgICAgLy8gU3RvcCBpZiBzYXZlIGNhbmNlbGxlZCBvciBzYXZlIGZhaWxlZFxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRyeSB7XG5cbiAgICAgIC8vIEFwcGx5IGRlbGV0aW9uIG9uIGRhdGFzb3VyY2VcbiAgICAgIC8vIElmIG5vIG1vcmUgcm93cyB0byBkZWxldGUsIGNvbnRpbnVlIGFueXdheSB0byBjbGVhciBlZGl0ZWRSb3cgYW5kIHNlbGVjdGlvbiAoaXNzdWUgSU1BR0lORS02NjkpXG4gICAgICBpZiAodGVtcFJvd3MubGVuZ3RoKSB7XG4gICAgICAgIGlmICh0aGlzLmRlYnVnKSBjb25zb2xlLmRlYnVnKGBbdGFibGVdIERlbGV0ZSAke3RlbXBSb3dzLmxlbmd0aH0gcm93cy4uLmApO1xuICAgICAgICBhd2FpdCB0aGlzLl9kYXRhU291cmNlLmRlbGV0ZUFsbCh0ZW1wUm93cyk7XG4gICAgICB9XG5cbiAgICAgIC8vIERPIG5vdCB1cGRhdGUgbWFudWFsbHksIGJlY2F1c2Ugd2F0Y2hBTGwoKS5zdWJzY3JpYmUoKSB3aWxsIHVwZGF0ZSB0aGlzIGNvdW50XG4gICAgICAvL3RoaXMudG90YWxSb3dDb3VudCAtPSBkZWxldGVDb3VudDtcbiAgICAgIC8vdGhpcy52aXNpYmxlUm93Q291bnQgLT0gZGVsZXRlQ291bnQ7XG5cbiAgICAgIHRoaXMuc2VsZWN0aW9uLmNsZWFyKCk7XG4gICAgICB0aGlzLm1hcmtBc0RpcnR5KHsgZW1pdEV2ZW50OiBmYWxzZSAvKm1hcmtGb3JDaGVjaygpIGlzIGNhbGxlZCBqdXN0IGFmdGVyKi8gfSk7XG4gICAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuXG4gICAgICB0aGlzLm9uQWZ0ZXJEZWxldGVkUm93cy5uZXh0KHJvd3MpO1xuXG4gICAgICByZXR1cm4gcm93cy5sZW5ndGg7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLnNldEVycm9yKGVyciAmJiBlcnIubWVzc2FnZSB8fCBlcnIpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNlbGVjdFJvd0J5SWQoaWQ6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmIChpZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gZmFsc2U7XG4gICAgYXdhaXQgdGhpcy53YWl0SWRsZSgpO1xuICAgIGNvbnN0IHJvdyA9IHRoaXMuZGF0YVNvdXJjZS5nZXRSb3coaWQpO1xuICAgIGlmICghcm93KSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRoaXMuY2xpY2tSb3cobnVsbCwgcm93KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcnkgdG8gc2VsZWN0IHJvdyBieSBkYXRhLiBXaWxsIHVzZSBkYXRhRXF1YWxzKCkgKHRoYXQgY2FsbCBFbnRpdHlVdGlscy5lcXVhbHMoKSkgdG8gZmluZCBzYW1lIHJvdydzIGRhdGFcbiAgICogQHBhcmFtIGRhdGFcbiAgICovXG4gIGFzeW5jIHNlbGVjdFJvd0J5RGF0YShkYXRhOiBUKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKGRhdGEgPT09IHVuZGVmaW5lZCkgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy53YWl0SWRsZSgpO1xuICAgIGNvbnN0IHJvdyA9IHRoaXMuZGF0YVNvdXJjZS5nZXRSb3dzKClcbiAgICAgIC5maW5kKHJvdyA9PiB0aGlzLmVxdWFscyhyb3cuY3VycmVudERhdGEsIGRhdGEpKTtcbiAgICBpZiAoIXJvdykgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0aGlzLmNsaWNrUm93KG51bGwsIHJvdyk7XG4gIH1cblxuICBhc3luYyBjbGlja1JvdyhldmVudDogRXZlbnQgfCB1bmRlZmluZWQsIHJvdzogQXN5bmNUYWJsZUVsZW1lbnQ8VD4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5sb2FkaW5nKSB7XG4gICAgICAvLyBXYWl0IHdoaWxlIGxvYWRpbmcsIGFuZCBsb29wXG4gICAgICBpZiAodGhpcy5kZWJ1ZykgY29uc29sZS5kZWJ1ZygnW3RhYmxlXSBXYWl0aW5nIGJlZm9yZSBhcHBseSBjbGlja1JvdygpIChkYXRhc291cmNlIGlzIGJ1c3kpLi4uJyk7XG4gICAgICBhd2FpdCB0aGlzLndhaXRJZGxlKHsgdGltZW91dDogMjAwMCB9KTtcbiAgICB9XG5cbiAgICAvLyBERUJVR1xuICAgIC8vY29uc29sZS5kZWJ1ZyhcIlt0YWJsZV0gRGV0ZWN0IGNsaWNrIG9uIHJvd1wiKTtcblxuICAgIGlmIChyb3cuaWQgPT09IC0xIHx8IHJvdy5lZGl0aW5nKSByZXR1cm4gdHJ1ZTsgLy8gQWxyZWFkeSBpbiBlZGl0aW9uXG4gICAgaWYgKGV2ZW50Py5kZWZhdWx0UHJldmVudGVkKSByZXR1cm4gZmFsc2U7IC8vIENhbmNlbGxlZCBieSBldmVudFxuXG4gICAgLy8gT3BlbiB0aGUgZGV0YWlsIHBhZ2UgKGlmIG5vdCBpbmxpbmUgZWRpdGluZylcbiAgICBpZiAoIXRoaXMuaW5saW5lRWRpdGlvbikge1xuXG4gICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubWFya0FzTG9hZGluZygpO1xuICAgICAgdGhpcy5zZWxlY3Rpb24uY2xlYXIoKTtcblxuICAgICAgdGhpcy5vcGVuUm93KHJvdy5jdXJyZW50RGF0YS5pZCwgcm93KVxuICAgICAgICAudGhlbigoKSA9PiB0aGlzLm1hcmtBc0xvYWRlZCgpKVxuICAgICAgICAuY2F0Y2goKCkgPT4gdGhpcy5tYXJrQXNMb2FkZWQoKSk7XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIFN0YXJ0IGVkaXRpbmcgcm93XG4gICAgcmV0dXJuIHRoaXMuZWRpdFJvdyhldmVudCwgcm93LCB7IGZvY3VzQ29sdW1uOiB1bmRlZmluZWQgLypmb3JjZSB0byB1c2UgdGhlIGNsaWNrIHRhcmdldCovIH0pO1xuICB9XG5cbiAgYXN5bmMgbW92ZVJvdyhpZDogbnVtYmVyLCBkaXJlY3Rpb246IG51bWJlcikge1xuICAgIGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tb3ZlKGlkLCBkaXJlY3Rpb24pO1xuICB9XG5cbiAgcmVhZHkob3B0cz86IFdhaXRGb3JPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHdhaXRGb3JUcnVlKHRoaXMucmVhZHlTdWJqZWN0LCBvcHRzKTtcbiAgfVxuXG4gIHdhaXRJZGxlKG9wdHM/OiBXYWl0Rm9yT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB3YWl0Rm9yRmFsc2UodGhpcy5sb2FkaW5nU3ViamVjdCwgb3B0cyk7XG4gIH1cblxuICBhc3luYyBvcGVuU2VsZWN0Q29sdW1uc01vZGFsKGV2ZW50PzogRXZlbnQpOiBQcm9taXNlPGFueT4ge1xuICAgIGV2ZW50Py5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgLy8gQ29weSBjdXJyZW50IGNvbHVtbnMgKGRlZXAgY29weSlcbiAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5nZXRDdXJyZW50Q29sdW1ucygpO1xuXG4gICAgY29uc3QgaGFzVG9wTW9kYWwgPSAhIShhd2FpdCB0aGlzLm1vZGFsQ3RybC5nZXRUb3AoKSk7XG4gICAgY29uc3QgbW9kYWwgPSBhd2FpdCB0aGlzLm1vZGFsQ3RybC5jcmVhdGUoe1xuICAgICAgY29tcG9uZW50OiBUYWJsZVNlbGVjdENvbHVtbnNDb21wb25lbnQsXG4gICAgICBjb21wb25lbnRQcm9wczogeyBjb2x1bW5zIH0sXG4gICAgICBjc3NDbGFzczogaGFzVG9wTW9kYWwgJiYgJ3N0YWNrLW1vZGFsJ1xuICAgIH0pO1xuXG4gICAgLy8gT3BlbiB0aGUgbW9kYWxcbiAgICBhd2FpdCBtb2RhbC5wcmVzZW50KCk7XG5cbiAgICAvLyBPbiBkaXNtaXNzXG4gICAgY29uc3QgeyBkYXRhIH0gPSBhd2FpdCBtb2RhbC5vbkRpZERpc21pc3MoKTtcbiAgICBpZiAoIWRhdGEpIHJldHVybjsgLy8gQ0FOQ0VMTEVEXG5cbiAgICAvLyBBcHBseSBjb2x1bW5zXG4gICAgY29uc3QgdXNlckNvbHVtbnMgPSAoZGF0YSB8fCBbXSkuZmlsdGVyKGMgPT4gYy5jYW5IaWRlID09PSBmYWxzZSB8fCBjLnZpc2libGUpLm1hcChjID0+IGMubmFtZSkgfHwgW107XG4gICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zID0gUkVTRVJWRURfU1RBUlRfQ09MVU1OUy5jb25jYXQodXNlckNvbHVtbnMpLmNvbmNhdChSRVNFUlZFRF9FTkRfQ09MVU1OUyk7XG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcblxuICAgIC8vIFVwZGF0ZSB1c2VyIHNldHRpbmdzXG4gICAgYXdhaXQgdGhpcy5zZXR0aW5ncy5zYXZlUGFnZVNldHRpbmcodGhpcy5zZXR0aW5nc0lkLCB1c2VyQ29sdW1ucywgU0VUVElOR1NfRElTUExBWV9DT0xVTU5TKTtcbiAgfVxuXG4gIHRyYWNrQnlGbihpbmRleDogbnVtYmVyLCByb3c6IEFzeW5jVGFibGVFbGVtZW50PFQ+KSB7XG4gICAgcmV0dXJuIHJvdy5pZDtcbiAgfVxuXG4gIGRvUmVmcmVzaChldmVudD86IENvbXBsZXRhYmxlRXZlbnQpIHtcbiAgICB0aGlzLm9uUmVmcmVzaC5lbWl0KGV2ZW50KTtcblxuICAgIC8vIFdoZW4gdGFyZ2V0IHdhaXQgZm9yIGEgY29tcGxldGUgKGUuZy4gSW9uUmVmcmVzaGVyKVxuICAgIGlmIChldmVudD8udGFyZ2V0ICYmIGV2ZW50LnRhcmdldC5jb21wbGV0ZSkge1xuICAgICAgc2V0VGltZW91dChhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMud2FpdElkbGUoKTtcbiAgICAgICAgZXZlbnQudGFyZ2V0LmNvbXBsZXRlKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBnZXRDdXJyZW50Q29sdW1ucygpOiBDb2x1bW5JdGVtW10ge1xuICAgIGNvbnN0IGhpZGRlbkNvbHVtbnMgPSB0aGlzLmNvbHVtbnMuc2xpY2UoUkVTRVJWRURfU1RBUlRfQ09MVU1OUy5sZW5ndGgpXG4gICAgICAuZmlsdGVyKG5hbWUgPT4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zLmluZGV4T2YobmFtZSkgPT09IC0xKTtcbiAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zXG4gICAgICAuY29uY2F0KGhpZGRlbkNvbHVtbnMpXG4gICAgICAuZmlsdGVyKG5hbWUgPT4gIVJFU0VSVkVEX1NUQVJUX0NPTFVNTlMuaW5jbHVkZXMobmFtZSkgJiYgIVJFU0VSVkVEX0VORF9DT0xVTU5TLmluY2x1ZGVzKG5hbWUpXG4gICAgICAgICYmICF0aGlzLmV4Y2x1ZGVzQ29sdW1ucy5pbmNsdWRlcyhuYW1lKSlcbiAgICAgIC5tYXAobmFtZSA9PiAoe1xuICAgICAgICBuYW1lLFxuICAgICAgICBsYWJlbDogdGhpcy5nZXRJMThuQ29sdW1uTmFtZShuYW1lKSxcbiAgICAgICAgdmlzaWJsZTogdGhpcy5kaXNwbGF5ZWRDb2x1bW5zLmluZGV4T2YobmFtZSkgIT09IC0xLFxuICAgICAgICBjYW5IaWRlOiB0aGlzLmdldFJlcXVpcmVkQ29sdW1ucygpLmluZGV4T2YobmFtZSkgPT09IC0xXG4gICAgICB9KSk7XG4gIH1cblxuICBhc3luYyBlc2NhcGVFZGl0aW5nUm93KGV2ZW50PzogRXZlbnQsIHJvdz86IEFzeW5jVGFibGVFbGVtZW50PFQ+KSB7XG4gICAgcm93ID0gcm93IHx8IHRoaXMuZGF0YVNvdXJjZS5nZXRTaW5nbGVFZGl0aW5nUm93KCk7XG4gICAgaWYgKCFyb3cgfHwgIXJvdy5lZGl0aW5nKSByZXR1cm47XG5cbiAgICAvLyBERUJVR1xuICAgIC8vY29uc29sZS5kZWJ1ZygnW2FwcC10YWJsZV0gQ2FuY2VsIHRoZSByb3cgKGtleWRvd24uZXNjYXBlKScpO1xuXG4gICAgaWYgKGV2ZW50KSB7XG4gICAgICAvLyBBdm9pZCB0byBjYW5jZWwgdGhlIGVkaXRvclxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cblxuICAgIC8vIElmIG5ldyByb3cgKG5vIGlkKVxuICAgIGlmIChyb3cuaWQgPT09IC0xKSB7XG4gICAgICBpZiAocm93LnZhbGlkYXRvcikge1xuICAgICAgICAvLyBJZiBwZW5kaW5nOiBXYWl0IGVuZCBvZiB2YWxpZGF0aW9uLCB0aGVuIGxvb3BcbiAgICAgICAgaWYgKHJvdy5wZW5kaW5nKSB7XG4gICAgICAgICAgYXdhaXQgQXBwRm9ybVV0aWxzLndhaXRXaGlsZVBlbmRpbmcocm93LnZhbGlkYXRvcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSb3cgaXMgaW52YWxpZDogZGVsZXRlIHRoZSByb3dcbiAgICAgICAgaWYgKHJvdy5pbnZhbGlkKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5kZWxldGVOZXdSb3coZXZlbnQsIHJvdyk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8vIElmIHRoZSByb3cgZXhpc3RzIChoYXMgYW4gaWQpXG4gICAgZWxzZSB7XG4gICAgICAvLyBuZWVkIHRvIGNhbGwgY2FuY2VsIGZ1bmN0aW9uIChpZiBjb25maXJtYXRpb24gd2lsbCBiZSBjYWxsZWQgYmVmb3JlKVxuICAgICAgaWYgKHRoaXMuY29uZmlybUJlZm9yZUNhbmNlbCkge1xuICAgICAgICBhd2FpdCB0aGlzLmNhbmNlbEV4aXN0aW5nUm93KGV2ZW50LCByb3csIHsga2VlcEVkaXRpbmc6IGZhbHNlIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQnkgZGVmYXVsdCwgdHJ5IHRvIGNvbmZpcm0gdGhlIHJvd1xuICAgIGF3YWl0IHRoaXMuY29uZmlybUVkaXRDcmVhdGUoZXZlbnQsIHJvdyk7XG4gIH1cblxuICB0cmFuc2xhdGVDb250cm9sUGF0aChwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIC8vIENhbiBiZSBvdmVycmlkZGVuIGJ5IHN1YmNsYXNzZXMsIHRvIHJlc29sdmUgYWxsIGZpZWxkIG5hbWVcblxuICAgIC8vIFVzZSBjb2x1bW5zIGtleSwgaGFzIGRlZmF1bHQgbmFtZVxuICAgIGNvbnN0IGkxOG5Db2x1bW5LZXkgPSB0aGlzLmdldEkxOG5Db2x1bW5OYW1lKHBhdGgpO1xuICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZT8uaW5zdGFudChpMThuQ29sdW1uS2V5KSB8fCBpMThuQ29sdW1uS2V5O1xuICB9XG5cbiAgLyogLS0gcHJvdGVjdGVkIG1ldGhvZCAtLSAqL1xuXG5cbiAgcHJvdGVjdGVkIGFzeW5jIGVkaXRSb3coZXZlbnQ6IEV2ZW50IHwgdW5kZWZpbmVkLCByb3c6IEFzeW5jVGFibGVFbGVtZW50PFQ+LCBvcHRzPzogeyBmb2N1c0NvbHVtbj86IHN0cmluZyB9KTogUHJvbWlzZTxib29sZWFuPiB7XG5cbiAgICBpZiAoIXRoaXMuX2VuYWJsZWQgfHwgIXRoaXMuaW5saW5lRWRpdGlvbikgcmV0dXJuIGZhbHNlO1xuICAgIGlmICh0aGlzLmRhdGFTb3VyY2UuZ2V0RWRpdGluZ1Jvd3MoKS5pbmNsdWRlcyhyb3cpKSByZXR1cm4gdHJ1ZTsgLy8gQWxyZWFkeSB0aGUgZWRpdGVkIHJvd1xuICAgIGlmIChldmVudD8uZGVmYXVsdFByZXZlbnRlZCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYgKCFhd2FpdCB0aGlzLmNvbmZpcm1FZGl0Q3JlYXRlKCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXJvdy5lZGl0aW5nICYmICF0aGlzLmxvYWRpbmcpIHtcbiAgICAgIHRoaXMuZm9jdXNDb2x1bW4gPSBvcHRzICYmIG9wdHMuZm9jdXNDb2x1bW4gfHwgdGhpcy5mb2N1c0NvbHVtbjtcbiAgICAgIGF3YWl0IHRoaXMuX2RhdGFTb3VyY2Uuc3RhcnRFZGl0KHJvdyk7XG4gICAgfVxuICAgIHRoaXMub25TdGFydEVkaXRpbmdSb3cuZW1pdChyb3cpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyeSB0byBzZWxlY3Qgcm93LCBieSByb3cuaWQsIG9yIGJ5IGRhdGEuIFdJbGwgdXNlIEVudGl0eVV0aWxzLmVxdWFscygpXG4gICAqIEBwYXJhbSBpZFxuICAgKiBAcGFyYW0gZGF0YVxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgc2VsZWN0Um93QnlJZE9yRGF0YShpZDogbnVtYmVyLCBkYXRhPzogVCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGxldCBkb25lID0gZmFsc2U7XG4gICAgdHJ5IHtcblxuICAgICAgLy8gU2VsZWN0IGJ5IHJvdyBpZCAoaWYgTk9UIGEgbmV3IHJvdylcbiAgICAgIGlmIChpc05vdE5pbChpZCkgfHwgaWQgIT09IC0xKSB7XG4gICAgICAgIGRvbmUgPSBhd2FpdCB0aGlzLnNlbGVjdFJvd0J5SWQoaWQpO1xuICAgICAgICBpZiAoZG9uZSkgcmV0dXJuIHRydWU7XG4gICAgICAgIGNvbnNvbGUud2FybignW2FwcC10YWJsZV0gU2F2ZTogQ2Fubm90IHJlc2VsZWN0IHJvdyBieSByb3cuaWQ6ICcsIGlkKTtcbiAgICAgIH1cblxuICAgICAgLy8gVHJ5IGJ5IGRhdGFcbiAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgIGRvbmUgPSBhd2FpdCB0aGlzLnNlbGVjdFJvd0J5RGF0YShkYXRhKTtcbiAgICAgICAgaWYgKGRvbmUpIHJldHVybiB0cnVlO1xuICAgICAgICBjb25zb2xlLndhcm4oJ1thcHAtdGFibGVdIFNhdmU6IENhbm5vdCByZXNlbGVjdCByb3cgYnkgZGF0YTogJywgZGF0YSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIExvZywgYnV0IGNvbnRpbnVlXG4gICAgICBjb25zb2xlLmVycm9yKGVyciAmJiBlcnIubWVzc2FnZSB8fCBlcnIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiByZXR1cm4gdGhlIHNlbGVjdGVkIHJvdyBpZiB1bmlxdWUgaW4gc2VsZWN0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0IHNpbmdsZVNlbGVjdGVkUm93KCk6IEFzeW5jVGFibGVFbGVtZW50PFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3Rpb24uc2VsZWN0ZWQ/Lmxlbmd0aCA9PT0gMSA/IHRoaXMuc2VsZWN0aW9uLnNlbGVjdGVkWzBdIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGNhbkRlbGV0ZVJvd3Mocm93czogQXN5bmNUYWJsZUVsZW1lbnQ8VD5bXSwgb3B0cz86IHsgaW50ZXJhY3RpdmU/OiBib29sZWFuOyB9KTogUHJvbWlzZTxib29sZWFuPiB7XG5cbiAgICAvLyBDaGVjayB1c2luZyBlbWl0dGVyXG4gICAgaWYgKHRoaXMub25CZWZvcmVEZWxldGVSb3dzLm9ic2VydmVycy5sZW5ndGggPiAwKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjYW5EZWxldGUgPSBhd2FpdCBlbWl0UHJvbWlzZUV2ZW50KHRoaXMub25CZWZvcmVEZWxldGVSb3dzLCAnY2FuRGVsZXRlJywge1xuICAgICAgICAgIGRldGFpbDogeyByb3dzIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghY2FuRGVsZXRlKSByZXR1cm4gZmFsc2U7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgaWYgKGVyciA9PT0gJ0NBTkNFTExFRCcpIHJldHVybiBmYWxzZTsgLy8gVXNlciBjYW5jZWxcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igd2hpbGUgY2hlY2tpbmcgaWYgY2FuIGRlbGV0ZSByb3dzJywgZXJyKTtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFzayB1c2VyIGNvbmZpcm1hdGlvblxuICAgIGlmICh0aGlzLmNvbmZpcm1CZWZvcmVEZWxldGUgJiYgKCFvcHRzIHx8IG9wdHMuaW50ZXJhY3RpdmUgIT09IGZhbHNlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuYXNrRGVsZXRlQ29uZmlybWF0aW9uKG51bGwsIHJvd3MpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBjYW5DYW5jZWxSb3dzKHJvd3M/OiBBc3luY1RhYmxlRWxlbWVudDxUPltdLCBvcHRzPzogeyBpbnRlcmFjdGl2ZT86IGJvb2xlYW47IH0pOiBQcm9taXNlPGJvb2xlYW4+IHtcblxuICAgIC8vIEdldCBkaXJ0eSByb3dzXG4gICAgcm93cyA9IHJvd3MgfHwgdGhpcy5kYXRhU291cmNlLmdldFJvd3MoKS5maWx0ZXIocm93ID0+IHJvdy52YWxpZGF0b3I/LmRpcnR5KTtcblxuICAgIGlmIChpc0VtcHR5QXJyYXkocm93cykpIHJldHVybiB0cnVlOyAvLyBObyBkaXJ0eTogT0tcblxuICAgIC8vIENoZWNrIHVzaW5nIGVtaXR0ZXJcbiAgICBpZiAodGhpcy5vbkJlZm9yZUNhbmNlbFJvd3Mub2JzZXJ2ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGlzQ2FuY2VsID0gYXdhaXQgZW1pdFByb21pc2VFdmVudCh0aGlzLm9uQmVmb3JlQ2FuY2VsUm93cywgJ2NhbkNhbmNlbCcsIHtcbiAgICAgICAgICBkZXRhaWw6IHsgcm93cyB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIWlzQ2FuY2VsKSByZXR1cm4gZmFsc2U7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgaWYgKGVyciA9PT0gJ0NBTkNFTExFRCcpIHJldHVybiBmYWxzZTsgLy8gVXNlciBjYW5jZWxcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igd2hpbGUgY2hlY2tpbmcgaWYgY2FuIGNhbmNlbCByb3dzJywgZXJyKTtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFzayB1c2VyIGNvbmZpcm1hdGlvblxuICAgIGlmICh0aGlzLmNvbmZpcm1CZWZvcmVDYW5jZWwgJiYgKCFvcHRzIHx8IG9wdHMuaW50ZXJhY3RpdmUgIT09IGZhbHNlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuYXNrQ2FuY2VsQ29uZmlybWF0aW9uKG51bGwsIHJvd3MpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBzYXZlQmVmb3JlQWN0aW9uKHNhdmVBY3Rpb246IFNhdmVBY3Rpb25UeXBlKTogUHJvbWlzZTxib29sZWFuPiB7XG5cbiAgICBpZiAoIXRoaXMuZGlydHkpIHtcbiAgICAgIC8vIENvbnRpbnVlIHdpdGhvdXQgc2F2ZVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgbGV0IHNhdmU6IGJvb2xlYW47XG4gICAgc3dpdGNoIChzYXZlQWN0aW9uKSB7XG4gICAgICBjYXNlICdkZWxldGUnOlxuICAgICAgICBzYXZlID0gdGhpcy5zYXZlQmVmb3JlRGVsZXRlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2ZpbHRlcic6XG4gICAgICAgIHNhdmUgPSB0aGlzLnNhdmVCZWZvcmVGaWx0ZXI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnc29ydCc6XG4gICAgICAgIHNhdmUgPSB0aGlzLnNhdmVCZWZvcmVTb3J0O1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHNhdmUgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIERlZmF1bHQgYmVoYXZpb3JcbiAgICBsZXQgY29uZmlybWVkID0gdHJ1ZTtcblxuICAgIGlmIChzYXZlKSB7XG4gICAgICBpZiAodGhpcy5vbkJlZm9yZVNhdmUub2JzZXJ2ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgLy8gQXNrIGNvbmZpcm1hdGlvblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGVtaXRQcm9taXNlRXZlbnQodGhpcy5vbkJlZm9yZVNhdmUsICdiZWZvcmVTYXZlJywge1xuICAgICAgICAgICAgZGV0YWlsOiB7IGFjdGlvbjogc2F2ZUFjdGlvbiwgdmFsaWQ6IHRoaXMudmFsaWQgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGNvbmZpcm1lZCA9IHJlcy5jb25maXJtZWQ7XG4gICAgICAgICAgc2F2ZSA9IHJlcy5zYXZlO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoZXJyID09PSAnQ0FOQ0VMTEVEJykgcmV0dXJuIGZhbHNlOyAvLyBVc2VyIGNhbmNlbFxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHdoaWxlIGNoZWNraW5nIGlmIGNhbiBkZWxldGUgcm93cycsIGVycik7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG5cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY29uZmlybWVkKSB7XG4gICAgICBpZiAoc2F2ZSkge1xuICAgICAgICAvLyBVc2VyIGNvbmZpcm1lZCBzYXZlXG4gICAgICAgIGNvbnN0IHNhdmVkID0gYXdhaXQgdGhpcy5zYXZlKCk7XG4gICAgICAgIHRoaXMubWFya0FzRGlydHkoKTsgLy8gUmVzdG9yZSBkaXJ0eSBmbGFnXG4gICAgICAgIHJldHVybiBzYXZlZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlOyAvLyBObyBzYXZlIGJ1dCBjb250aW51ZSBhY3Rpb25cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7IC8vIFVzZXIgY2FuY2VsIHRoZSBhY3Rpb25cbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIGEgcm93IGRldGFpbCB2aWV3LiBCeSBkZWZhdWx0LCB3aWxsIHRvIG9wZW4gcm93IGRldGFpbCBwYWdlLlxuICAgKiBDYW4gYmUgb3ZlcnJpZGRlbiBieSBzdWJjbGFzc2VzLCBCVVQgcHJlZmVyIHRvIHN1YnNjcmliZSBvbiBvbk9wZW5Sb3dcbiAgICogQHBhcmFtIGlkXG4gICAqIEBwYXJhbSByb3dcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIG9wZW5Sb3coaWQ6IElELCByb3c6IEFzeW5jVGFibGVFbGVtZW50PFQ+KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKHRoaXMuYWxsb3dSb3dEZXRhaWwpIHtcbiAgICAgIGlmICh0aGlzLmRlYnVnICYmIHRoaXMuZGlydHkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdbdGFibGVdIE9wZW5pbmcgcm93IGRldGFpbHMsIGJ1dCB0YWJsZSBoYXMgdW5zYXZlZCBjaGFuZ2VzIScpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5vbk9wZW5Sb3cub2JzZXJ2ZXJzLmxlbmd0aCkge1xuICAgICAgICB0aGlzLm9uT3BlblJvdy5lbWl0KHJvdyk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBObyBJRCBkZWZpbmVkOiB1bmFibGUgdG8gb3BlbiBkZXRhaWxzXG4gICAgICBpZiAoaXNOaWwoaWQpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignW3RhYmxlXSBPcGVuaW5nIHJvdyBkZXRhaWxzLCBidXQgZGF0YSBoYXMgbm8gaWQhJyk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnLicsIGlkLnRvU3RyaW5nKCldLCB7XG4gICAgICAgIHJlbGF0aXZlVG86IHRoaXMucm91dGUsXG4gICAgICAgIHF1ZXJ5UGFyYW1zOiB7fVxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBvcGVuTmV3Um93RGV0YWlsKGV2ZW50PzogYW55KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKCF0aGlzLmFsbG93Um93RGV0YWlsKSByZXR1cm4gZmFsc2U7XG5cbiAgICBpZiAodGhpcy5vbk5ld1Jvdy5vYnNlcnZlcnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5vbk5ld1Jvdy5lbWl0KGV2ZW50KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJ25ldyddLCB7XG4gICAgICByZWxhdGl2ZVRvOiB0aGlzLnJvdXRlXG4gICAgfSk7XG4gIH1cblxuICAvLyBjYW4gYmUgb3ZlcnJpZGRlbiB0byBhZGQgbW9yZSByZXF1aXJlZCBjb2x1bW5zXG4gIHByb3RlY3RlZCBnZXRSZXF1aXJlZENvbHVtbnMoKSB7XG4gICAgcmV0dXJuIERFRkFVTFRfUkVRVUlSRURfQ09MVU1OUztcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRVc2VyQ29sdW1ucygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuc2V0dGluZ3MuZ2V0UGFnZVNldHRpbmdzKHRoaXMuc2V0dGluZ3NJZCwgU0VUVElOR1NfRElTUExBWV9DT0xVTU5TKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRTb3J0ZWRDb2x1bW4oKTogTWF0U29ydGFibGUge1xuICAgIGNvbnN0IGRhdGEgPSB0aGlzLnNldHRpbmdzLmdldFBhZ2VTZXR0aW5ncyh0aGlzLnNldHRpbmdzSWQsIFNFVFRJTkdTX1NPUlRFRF9DT0xVTU4pO1xuICAgIGNvbnN0IHBhcnRzID0gZGF0YSAmJiBkYXRhLnNwbGl0KCc6Jyk7XG4gICAgaWYgKHBhcnRzICYmIHBhcnRzLmxlbmd0aCA9PT0gMiAmJiB0aGlzLmNvbHVtbnMuaW5jbHVkZXMocGFydHNbMF0pKSB7XG4gICAgICByZXR1cm4geyBpZDogcGFydHNbMF0sIHN0YXJ0OiBwYXJ0c1sxXSA9PT0gJ2Rlc2MnID8gJ2Rlc2MnIDogJ2FzYycsIGRpc2FibGVDbGVhcjogZmFsc2UgfTtcbiAgICB9XG4gICAgaWYgKHRoaXMuZGVmYXVsdFNvcnRCeSkge1xuICAgICAgcmV0dXJuIHsgaWQ6IHRoaXMuZGVmYXVsdFNvcnRCeSwgc3RhcnQ6IHRoaXMuZGVmYXVsdFNvcnREaXJlY3Rpb24gfHwgJ2FzYycsIGRpc2FibGVDbGVhcjogZmFsc2UgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgaWQ6ICdpZCcsIHN0YXJ0OiAnYXNjJywgZGlzYWJsZUNsZWFyOiBmYWxzZSB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFBhZ2VTaXplKCk6IG51bWJlciB7XG4gICAgY29uc3QgcGFnZVNpemUgPSB0aGlzLnNldHRpbmdzLmdldFBhZ2VTZXR0aW5nczxudW1iZXI+KHRoaXMuc2V0dGluZ3NJZCwgU0VUVElOR1NfUEFHRV9TSVpFKTtcbiAgICByZXR1cm4gcGFnZVNpemUgfHwgdGhpcy5kZWZhdWx0UGFnZVNpemU7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0RGlzcGxheUNvbHVtbnMoKTogc3RyaW5nW10ge1xuICAgIGxldCB1c2VyQ29sdW1ucyA9IHRoaXMuZ2V0VXNlckNvbHVtbnMoKTtcblxuICAgIC8vIE5vIHVzZXIgb3ZlcnJpZGVcbiAgICBpZiAoIXVzZXJDb2x1bW5zKSB7XG4gICAgICAvLyBSZXR1cm4gZGVmYXVsdCwgd2l0aG91dCBjb2x1bW5zIHRvIGhpZGVcbiAgICAgIHJldHVybiB0aGlzLmNvbHVtbnMuZmlsdGVyKGNvbHVtbiA9PiAhdGhpcy5leGNsdWRlc0NvbHVtbnMuaW5jbHVkZXMoY29sdW1uKSk7XG4gICAgfVxuXG4gICAgLy8gR2V0IGZpeGVkIHN0YXJ0IGNvbHVtbnNcbiAgICBjb25zdCBmaXhlZFN0YXJ0Q29sdW1ucyA9IHRoaXMuY29sdW1ucy5maWx0ZXIoYyA9PiBSRVNFUlZFRF9TVEFSVF9DT0xVTU5TLmluY2x1ZGVzKGMpKTtcblxuICAgIC8vIFJlbW92ZSBlbmQgY29sdW1uc1xuICAgIGNvbnN0IGZpeGVkRW5kQ29sdW1ucyA9IHRoaXMuY29sdW1ucy5maWx0ZXIoYyA9PiBSRVNFUlZFRF9FTkRfQ09MVU1OUy5pbmNsdWRlcyhjKSk7XG5cbiAgICAvLyBSZW1vdmUgZml4ZWQgY29sdW1ucyBmcm9tIHVzZXIgY29sdW1uc1xuICAgIHVzZXJDb2x1bW5zID0gdXNlckNvbHVtbnMuZmlsdGVyKGMgPT4gIWZpeGVkU3RhcnRDb2x1bW5zLmluY2x1ZGVzKGMpICYmICFmaXhlZEVuZENvbHVtbnMuaW5jbHVkZXMoYykgJiYgdGhpcy5jb2x1bW5zLmluY2x1ZGVzKGMpKTtcblxuICAgIC8vIEFkZCByZXF1aXJlZCBjb2x1bW5zIGlmIG1pc3NpbmdcbiAgICB1c2VyQ29sdW1ucy5wdXNoKC4uLnRoaXMuZ2V0UmVxdWlyZWRDb2x1bW5zKCkuZmlsdGVyKGMgPT4gIWZpeGVkU3RhcnRDb2x1bW5zLmluY2x1ZGVzKGMpICYmICFmaXhlZEVuZENvbHVtbnMuaW5jbHVkZXMoYykgJiYgIXVzZXJDb2x1bW5zLmluY2x1ZGVzKGMpKSk7XG5cbiAgICByZXR1cm4gZml4ZWRTdGFydENvbHVtbnNcbiAgICAgIC5jb25jYXQodXNlckNvbHVtbnMpXG4gICAgICAuY29uY2F0KGZpeGVkRW5kQ29sdW1ucylcbiAgICAgIC8vIFJlbW92ZSBjb2x1bW5zIHRvIGhpZGVcbiAgICAgIC5maWx0ZXIoY29sdW1uID0+ICF0aGlzLmV4Y2x1ZGVzQ29sdW1ucy5pbmNsdWRlcyhjb2x1bW4pKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNvbXB1dGUgZGlzcGxheSBjb2x1bW5zXG4gICAqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIHByb3RlY3RlZCB1cGRhdGVDb2x1bW5zKCkge1xuICAgIHRoaXMuZGlzcGxheWVkQ29sdW1ucyA9IHRoaXMuZ2V0RGlzcGxheUNvbHVtbnMoKTtcbiAgICBpZiAoIXRoaXMubG9hZGluZykgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHByb3RlY3RlZCByZWdpc3RlclN1YnNjcmlwdGlvbihzdWI6IFN1YnNjcmlwdGlvbikge1xuICAgIHRoaXMuX3N1YnNjcmlwdGlvbi5hZGQoc3ViKTtcbiAgfVxuXG4gIHByb3RlY3RlZCB1bnJlZ2lzdGVyU3Vic2NyaXB0aW9uKHN1YjogU3Vic2NyaXB0aW9uKSB7XG4gICAgdGhpcy5fc3Vic2NyaXB0aW9uLnJlbW92ZShzdWIpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJlZ2lzdGVyQXV0b2NvbXBsZXRlRmllbGQ8RSA9IGFueSwgRUYgPSBhbnk+KGZpZWxkTmFtZTogc3RyaW5nLCBvcHRpb25zPzogTWF0QXV0b2NvbXBsZXRlRmllbGRBZGRPcHRpb25zPEUsIEVGPik6IE1hdEF1dG9jb21wbGV0ZUZpZWxkQ29uZmlnPEUsIEVGPiB7XG4gICAgcmV0dXJuIHRoaXMuX2F1dG9jb21wbGV0ZUNvbmZpZ0hvbGRlci5hZGQoZmllbGROYW1lLCBvcHRpb25zKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRJMThuQ29sdW1uTmFtZShjb2x1bW5OYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gKHRoaXMuaTE4bkNvbHVtblByZWZpeCB8fCAnJykgKyBjaGFuZ2VDYXNlVG9VbmRlcnNjb3JlKGNvbHVtbk5hbWUpLnRvVXBwZXJDYXNlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2VuZXJhdGVUYWJsZUlkKCkge1xuICAgIC8vIG5vaW5zcGVjdGlvbiBKU05vbkFTQ0lJTmFtZXNcbiAgICBjb25zdCBpZCA9IHRoaXMubG9jYXRpb24ucGF0aCh0cnVlKVxuICAgICAgICAucmVwbGFjZSgvWz9dLiokL2csICcnKVxuICAgICAgICAucmVwbGFjZSgvXFwvXFxkKy9nLCAnX2lkJylcbiAgICAgICsgJ18nXG4gICAgICAvLyBHZXQgYSBjb21wb25lbnQgdW5pcXVlIG5hbWUgLSBTZWUgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjAxMTQ2ODIvaG93LXRvLWFjY2Vzcy1jb21wb25lbnRzLXVuaXF1ZS1lbmNhcHN1bGF0aW9uLWlkLWluLWFuZ3VsYXItOVxuICAgICAgKyAodGhpcy5jb25zdHJ1Y3RvclsnybVjbXAnXT8uaWQgfHwgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICAvL2lmICh0aGlzLmRlYnVnKSBjb25zb2xlLmRlYnVnKFwiW3RhYmxlXSBpZCA9IFwiICsgaWQpO1xuICAgIHJldHVybiBpZDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBhZGRSb3dUb1RhYmxlKGluc2VydEF0PzogbnVtYmVyLCBvcHRzPzogeyBmb2N1c0NvbHVtbj86IHN0cmluZzsgZWRpdGluZz86IGJvb2xlYW47IGVtaXRFdmVudD86IGJvb2xlYW47IH0pOiBQcm9taXNlPEFzeW5jVGFibGVFbGVtZW50PFQ+IHwgdW5kZWZpbmVkPiB7XG4gICAgLy8gVHJ5IHRvIGZpbmlzaCBlZGl0ZWQgcm93IGZpcnN0XG4gICAgaWYgKCFhd2FpdCB0aGlzLmNvbmZpcm1FZGl0Q3JlYXRlKCkpIHtcbiAgICAgIGNvbnNvbGUud2FybignW3RhYmxlXSBDYW5ub3QgYWRkIG5ldyByb3csIGJlY2F1c2UgdGhlIHByZXZpb3VzIGVkaXRlZCByb3cgY2Fubm90IGJlIGNvbmZpcm1lZCcpO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBlZGl0aW5nID0gdGhpcy5pbmxpbmVFZGl0aW9uICYmICghb3B0cyB8fCBvcHRzLmVkaXRpbmcgIT09IGZhbHNlKTsgLy8gdHJ1ZSBieSBkZWZhdWx0LCBpZiBpbmxpbmVFZGl0aW9uXG5cbiAgICBjb25zdCByb3cgPSBhd2FpdCB0aGlzLl9kYXRhU291cmNlLmNyZWF0ZU5ldyhpbnNlcnRBdCwgeyBlZGl0aW5nIH0pO1xuICAgIGlmICghcm93KSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgaWYgKHJvdy5lZGl0aW5nKSB7XG4gICAgICAvLyBVcGRhdGUgZm9jdXNlZCBjb2x1bW5cbiAgICAgIHRoaXMuZm9jdXNGaXJzdENvbHVtbiA9IHRydWU7XG4gICAgICB0aGlzLmZvY3VzQ29sdW1uID0gb3B0cz8uZm9jdXNDb2x1bW4gfHwgdGhpcy5maXJzdFVzZXJDb2x1bW47XG5cbiAgICAgIC8vIEVtaXQgc3RhcnQgZWRpdGluZyBldmVudFxuICAgICAgdGhpcy5vblN0YXJ0RWRpdGluZ1Jvdy5lbWl0KHJvdyk7XG4gICAgfVxuXG4gICAgdGhpcy50b3RhbFJvd0NvdW50Kys7XG4gICAgdGhpcy52aXNpYmxlUm93Q291bnQrKztcblxuICAgIHRoaXMubWFya0FzRGlydHkoeyBlbWl0RXZlbnQ6IGZhbHNlIC8qbWFya0ZvckNoZWNrKCkgaXMgY2FsbGVkIGp1c3QgYWZ0ZXIqLyB9KTtcblxuICAgIC8vIEVtaXQgZXZlbnRcbiAgICBpZiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSB0aGlzLm1hcmtGb3JDaGVjaygpO1xuXG4gICAgcmV0dXJuIHJvdztcbiAgfVxuXG4gIHByb3RlY3RlZCByZWdpc3RlckNlbGxWYWx1ZUNoYW5nZXMobmFtZTogc3RyaW5nLCBmb3JtUGF0aD86IHN0cmluZywgZW1pdEluaXRpYWxWYWx1ZT86IGJvb2xlYW4pOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIGZvcm1QYXRoID0gZm9ybVBhdGggfHwgbmFtZTtcbiAgICBlbWl0SW5pdGlhbFZhbHVlID0gZW1pdEluaXRpYWxWYWx1ZSB8fCBmYWxzZTtcbiAgICBsZXQgZGVmID0gdGhpcy5fY2VsbFZhbHVlQ2hhbmdlc0RlZnNbbmFtZV07XG4gICAgaWYgKGRlZiAmJiAoZGVmLmZvcm1QYXRoICE9PSBmb3JtUGF0aCB8fCBkZWYuZW1pdEluaXRpYWxWYWx1ZSAhPT0gZW1pdEluaXRpYWxWYWx1ZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdBbHJlYWR5IHJlZ2lzdGVyIGEgY2VsbCB2YWx1ZSBjaGFuZ2UgZm9yIHRoaXMgbmFtZSwgd2l0aCBkaWZmZXJlbnQgXFwnZm9ybVBhdGhcXCcgb3IgXFwnZW1pdEluaXRpYWxWYWx1ZVxcJy4gUGxlYXNlIHVzZSBzYW1lIGFyZ3VtZW50cy4nKTtcbiAgICB9XG5cbiAgICAvLyBOb3QgZXhpc3RzOiByZWdpc3RlciBuZXcgZGVmaW5pdGlvblxuICAgIGlmICghZGVmKSB7XG4gICAgICBpZiAodGhpcy5kZWJ1ZykgY29uc29sZS5kZWJ1ZyhgW3RhYmxlXSBOZXcgbGlzdGVuZXIgeyR7bmFtZX19IGZvciB2YWx1ZSBjaGFuZ2VzIG9uIHBhdGggJHtmb3JtUGF0aH1gKTtcbiAgICAgIGRlZiA9IHtcbiAgICAgICAgc3ViamVjdDogbmV3IFN1YmplY3Q8YW55PigpLFxuICAgICAgICBzdWJzY3JpcHRpb246IG51bGwsXG4gICAgICAgIGZvcm1QYXRoLFxuICAgICAgICBlbWl0SW5pdGlhbFZhbHVlXG4gICAgICB9O1xuICAgICAgdGhpcy5fY2VsbFZhbHVlQ2hhbmdlc0RlZnNbbmFtZV0gPSBkZWY7XG5cbiAgICAgIC8vIFN0YXJ0IHRoZSBsaXN0ZW5lciwgd2hlbiBlZGl0aW5nIHN0YXJ0c1xuICAgICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbihcbiAgICAgICAgdGhpcy5vblN0YXJ0RWRpdGluZ1Jvdy5zdWJzY3JpYmUocm93ID0+IHRoaXMuc3RhcnRDZWxsVmFsdWVDaGFuZ2VzKG5hbWUsIHJvdykpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGVmLnN1YmplY3Q7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0U2hvd0NvbHVtbihjb2x1bW5OYW1lOiBzdHJpbmcsIHNob3c6IGJvb2xlYW4sIG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICghdGhpcy5leGNsdWRlc0NvbHVtbnMuaW5jbHVkZXMoY29sdW1uTmFtZSkgIT09IHNob3cpIHtcbiAgICAgIGlmICghc2hvdykge1xuICAgICAgICB0aGlzLmV4Y2x1ZGVzQ29sdW1ucy5wdXNoKGNvbHVtbk5hbWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmV4Y2x1ZGVzQ29sdW1ucy5maW5kSW5kZXgodmFsdWUgPT4gdmFsdWUgPT09IGNvbHVtbk5hbWUpO1xuICAgICAgICBpZiAoaW5kZXggPj0gMCkgdGhpcy5leGNsdWRlc0NvbHVtbnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVjb21wdXRlIGRpc3BsYXkgY29sdW1uc1xuICAgICAgaWYgKHRoaXMuZGlzcGxheWVkQ29sdW1ucyAmJiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSkge1xuICAgICAgICB0aGlzLnVwZGF0ZUNvbHVtbnMoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0U2hvd0NvbHVtbihjb2x1bW5OYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIXRoaXMuZXhjbHVkZXNDb2x1bW5zLmluY2x1ZGVzKGNvbHVtbk5hbWUpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHN0YXJ0c1dpdGhVcHBlckNhc2UoaW5wdXQ6IHN0cmluZywgc2VhcmNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaW5wdXQgJiYgaW5wdXQudG9VcHBlckNhc2UoKS5zdGFydHNXaXRoKHNlYXJjaCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWFya0ZvckNoZWNrKCkge1xuICAgIC8vIFNob3VsZCBiZSBvdmVycmlkZGVuIGJ5IHN1YmNsYXNzZXMsIGRlcGVuZGluZyBvbiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneVxuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGFza0RlbGV0ZUNvbmZpcm1hdGlvbihldmVudD86IEV2ZW50LCByb3dzPzogQXN5bmNUYWJsZUVsZW1lbnQ8VD5bXSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmICh0aGlzLnVuZG9hYmxlRGVsZXRpb24pIHtcbiAgICAgIC8vIFNwZWNpYWwgbWVzc2FnZSwgZm9yIHVuZG9hYmxlIGRlbGV0aW9uXG4gICAgICByZXR1cm4gQWxlcnRzLmFza0NvbmZpcm1hdGlvbihyb3dzPy5sZW5ndGggPT09IDEgPyAnQ09ORklSTS5ERUxFVEVfUk9XJyA6ICdDT05GSVJNLkRFTEVURV9ST1dTJywgdGhpcy5hbGVydEN0cmwsIHRoaXMudHJhbnNsYXRlLCBldmVudCk7XG4gICAgfVxuICAgIC8vIEltbWVkaWF0ZSBkZWxldGlvbiBhY3Rpb25cbiAgICByZXR1cm4gQWxlcnRzLmFza0FjdGlvbkNvbmZpcm1hdGlvbih0aGlzLmFsZXJ0Q3RybCwgdGhpcy50cmFuc2xhdGUsIHRydWUsIGV2ZW50KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBhc2tDYW5jZWxDb25maXJtYXRpb24oZXZlbnQ/OiBFdmVudCwgcm93cz86IEFzeW5jVGFibGVFbGVtZW50PFQ+W10pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gQWxlcnRzLmFza0NvbmZpcm1hdGlvbihyb3dzPy5sZW5ndGggPT09IDEgPyAnQ09ORklSTS5DQU5DRUxfUk9XJyA6ICdDT05GSVJNLkNBTkNFTF9ST1dTJywgdGhpcy5hbGVydEN0cmwsIHRoaXMudHJhbnNsYXRlLCBldmVudCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgYXNrUmVzdG9yZUNvbmZpcm1hdGlvbihldmVudD86IEV2ZW50KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIEFsZXJ0cy5hc2tBY3Rpb25Db25maXJtYXRpb24odGhpcy5hbGVydEN0cmwsIHRoaXMudHJhbnNsYXRlLCBmYWxzZSwgZXZlbnQpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHNob3dUb2FzdChvcHRzOiBTaG93VG9hc3RPcHRpb25zKSB7XG4gICAgaWYgKCF0aGlzLnRvYXN0Q29udHJvbGxlcikgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHRvYXN0Q29udHJvbGxlciBpbiBjb21wb25lbnRcXCdzIGNvbnN0cnVjdG9yJyk7XG4gICAgcmV0dXJuIFRvYXN0cy5zaG93KHRoaXMudG9hc3RDb250cm9sbGVyLCB0aGlzLnRyYW5zbGF0ZSwgb3B0cyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVzZXRFcnJvcihvcHRzPzogeyBlbWl0RXZlbnQ/OiBib29sZWFuOyB9KSB7XG4gICAgdGhpcy5zZXRFcnJvcih1bmRlZmluZWQsIG9wdHMpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFJvd0Vycm9yKHJvdz86IEFzeW5jVGFibGVFbGVtZW50PFQ+LCBvcHRzPzogRm9ybUVycm9yVHJhbnNsYXRvck9wdGlvbnMpOiBzdHJpbmcge1xuICAgIHJvdyA9IHJvdyB8fCB0aGlzLmRhdGFTb3VyY2UuZ2V0U2luZ2xlRWRpdGluZ1JvdygpO1xuICAgIGlmICghcm93IHx8ICF0aGlzLmZvcm1FcnJvckFkYXB0ZXIpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gdGhpcy5mb3JtRXJyb3JBZGFwdGVyLnRyYW5zbGF0ZUZvcm1FcnJvcnMocm93LnZhbGlkYXRvciwge1xuICAgICAgLi4udGhpcy5lcnJvclRyYW5zbGF0b3JPcHRpb25zLFxuICAgICAgLi4ub3B0c1xuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldEVycm9yKHZhbHVlOiBzdHJpbmcsIG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW47IH0pIHtcbiAgICBpZiAodGhpcy5lcnJvclN1YmplY3QudmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICB0aGlzLmVycm9yU3ViamVjdC5uZXh0KHZhbHVlKTtcbiAgICAgIGlmICghb3B0cyB8fCBvcHRzLmVtaXRFdmVudCAhPT0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29tcGFyZSBkYXRhIGVxdWFsaXR5IChkZWZhdWx0IGJ5IGlkKVxuICAgKiBDYW4gYmUgb3ZlcnJpZGRlbiB0byBhZGQgYWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIGNvbXBhcmVcbiAgICpcbiAgICogQHBhcmFtIGQxXG4gICAqIEBwYXJhbSBkMlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgZXF1YWxzKGQxOiBULCBkMjogVCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBFbnRpdHlVdGlscy5lcXVhbHMoZDEsIGQyLCAnaWQnKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBtYXJrUm93QXNEaXJ0eShyb3c/OiBBc3luY1RhYmxlRWxlbWVudDxUPiwgb3B0cz86IHsgb25seVNlbGY/OiBib29sZWFuOyBlbWl0RVZlbnQ/OiBib29sZWFuOyB9KSB7XG4gICAgcm93ID0gcm93IHx8IHRoaXMuZGF0YVNvdXJjZS5nZXRTaW5nbGVFZGl0aW5nUm93KCk7XG4gICAgaWYgKHJvdykgcm93LnZhbGlkYXRvcj8ubWFya0FzRGlydHkob3B0cyk7XG4gICAgdGhpcy5tYXJrQXNEaXJ0eShvcHRzKTtcbiAgfVxuXG4gIC8qIC0tIHByaXZhdGUgbWV0aG9kIC0tICovXG5cbiAgcHJpdmF0ZSBhc3luYyBsaXN0ZW5Tb3J0QW5kUGFnaW5hdGlvbkV2ZW50cygpIHtcblxuICAgIGlmICghdGhpcy50YWJsZSkge1xuXG4gICAgICAvLyBERUJVRyBvbmx5IC0tIGFsZXJ0IHVzZXIgdGhhdCB0YWJsZSBub3QgZm91bmQgaW4gdGVtcGxhdGVcbiAgICAgIGlmICh0aGlzLmRlYnVnKSB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4gIXRoaXMudGFibGUgJiYgY29uc29sZS53YXJuKGBbdGFibGVdIE1pc3NpbmcgPG1hdC10YWJsZT4gaW4gdGhlIEhUTUwgdGVtcGxhdGUgKGFmdGVyIHdhaXRpbmcgNTAwbXMpISBDb21wb25lbnQ6ICR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfWApLCA1MDApO1xuICAgICAgfVxuXG4gICAgICAvLyBNYWtlIHN1cmUgdG8gd2FpdCB0aGUgdGFibGVcbiAgICAgIGF3YWl0IHdhaXRGb3IoKCkgPT4gISF0aGlzLnRhYmxlLCB7IHN0b3A6IHRoaXMuZGVzdHJveVN1YmplY3QsIHN0b3BFcnJvcjogZmFsc2UvKmF2b2lkIGVycm9yIHdoZW4gZGVzdG9yeWluZyB0aGUgdGFibGUqLyB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnJlZ2lzdGVyU3Vic2NyaXB0aW9uKFxuICAgICAgbWVyZ2UoXG4gICAgICAgIC8vIExpc3RlbiBzb3J0IGV2ZW50c1xuICAgICAgICB0aGlzLnNvcnQgJiYgdGhpcy5zb3J0LnNvcnRDaGFuZ2VcbiAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgIGZpbHRlcigoKSA9PiAhdGhpcy5zb3J0LmRpc2FibGVkKSxcbiAgICAgICAgICAgIG1lcmdlTWFwKGFzeW5jICgpID0+IHRoaXMuc2F2ZUJlZm9yZUFjdGlvbignc29ydCcpKSxcbiAgICAgICAgICAgIGZpbHRlcihyZXMgPT4gcmVzID09PSB0cnVlKSxcbiAgICAgICAgICAgIC8vIFNhdmUgc29ydCBpbiBzZXR0aW5nc1xuICAgICAgICAgICAgdGFwKCgpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBbdGhpcy5zb3J0LmFjdGl2ZSwgdGhpcy5zb3J0LmRpcmVjdGlvbiB8fCAnYXNjJ10uam9pbignOicpO1xuICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnNhdmVQYWdlU2V0dGluZyh0aGlzLnNldHRpbmdzSWQsIHZhbHVlLCBTRVRUSU5HU19TT1JURURfQ09MVU1OKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKVxuICAgICAgICB8fCBFTVBUWSxcblxuICAgICAgICAvLyBMaXN0ZW4gcGFnaW5hdG9yIGV2ZW50c1xuICAgICAgICB0aGlzLnBhZ2luYXRvciAmJiB0aGlzLnBhZ2luYXRvci5wYWdlXG4gICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICBtZXJnZU1hcCgoXykgPT4gdGhpcy5zYXZlQmVmb3JlQWN0aW9uKCdzb3J0JykpLFxuICAgICAgICAgICAgZmlsdGVyKHNhdmVkID0+IHNhdmVkID09PSB0cnVlKSxcbiAgICAgICAgICAgIC8vIFNhdmUgcGFnZSBzaXplIGluIHNldHRpbmdzXG4gICAgICAgICAgICB0YXAoKCkgPT4gdGhpcy5zZXR0aW5ncy5zYXZlUGFnZVNldHRpbmcodGhpcy5zZXR0aW5nc0lkLCB0aGlzLnBhZ2luYXRvci5wYWdlU2l6ZSwgU0VUVElOR1NfUEFHRV9TSVpFKSlcbiAgICAgICAgICApIHx8IEVNUFRZXG4gICAgICApXG4gICAgICAgIC8vIFJlZnJlc2ggb24gYW55IHNvcnQgb3IgcGFnaW5hdG9yIGV2ZW50c1xuICAgICAgICAuc3Vic2NyaWJlKHZhbHVlID0+IHtcbiAgICAgICAgICB0aGlzLm9uU29ydC5lbWl0KHZhbHVlKTtcbiAgICAgICAgICB0aGlzLm9uUmVmcmVzaC5lbWl0KHZhbHVlKTtcbiAgICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gSWYgdGhlIHVzZXIgY2hhbmdlcyB0aGUgc29ydCBvcmRlciwgcmVzZXQgYmFjayB0byB0aGUgZmlyc3QgcGFnZS5cbiAgICBpZiAodGhpcy5zb3J0ICYmIHRoaXMucGFnaW5hdG9yKSB7XG4gICAgICB0aGlzLnJlZ2lzdGVyU3Vic2NyaXB0aW9uKFxuICAgICAgICB0aGlzLnNvcnQuc29ydENoYW5nZVxuICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgZmlsdGVyKCgpID0+ICF0aGlzLnNvcnQuZGlzYWJsZWQpXG4gICAgICAgICAgKVxuICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5wYWdpbmF0b3IucGFnZUluZGV4ID0gMClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBlZGl0Um93QnlJZChldmVudDogRXZlbnQgfCB1bmRlZmluZWQsIGlkOiBudW1iZXIsIG9wdHM/OiB7IGZvY3VzQ29sdW1uPzogc3RyaW5nIH0pIHtcbiAgICBpZiAoaWQgPCAwKSByZXR1cm47XG4gICAgaWYgKGlkID49IHRoaXMudmlzaWJsZVJvd0NvdW50KSB7XG4gICAgICBhd2FpdCB0aGlzLmFkZFJvdyhldmVudCwgdW5kZWZpbmVkLCB7IC4uLm9wdHMsIGVkaXRpbmc6IHRydWUgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJvdyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5nZXRSb3coaWQpO1xuICAgICAgYXdhaXQgdGhpcy5lZGl0Um93KGV2ZW50LCByb3csIG9wdHMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2V0TG9hZGluZyh2YWx1ZTogYm9vbGVhbiwgb3B0cz86IHsgZW1pdEV2ZW50PzogYm9vbGVhbiB9KSB7XG4gICAgaWYgKHRoaXMubG9hZGluZ1N1YmplY3QudmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQodmFsdWUpO1xuXG4gICAgICBpZiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSB7XG4gICAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkZWxldGVOZXdSb3coZXZlbnQ6IEV2ZW50IHwgdW5kZWZpbmVkLCByb3c6IEFzeW5jVGFibGVFbGVtZW50PFQ+KSB7Ly8gTWFrZSBzdXJlIHJvdyB3aWxsIGJlIGNhbmNlbGxlZCwgYW5kIE5PVCBkZWxldGVkXG4gICAgaWYgKHJvdy5pZCAhPT0gLTEpIHRocm93IG5ldyBFcnJvcignUm93IG11c3QgaGF2ZSBpZCA9IC0xJyk7XG4gICAgZXZlbnQ/LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgdGhpcy5zZWxlY3Rpb24uY2xlYXIoKTtcbiAgICBhd2FpdCB0aGlzLl9kYXRhU291cmNlLmNhbmNlbE9yRGVsZXRlKHJvdyk7XG4gICAgdGhpcy5vbkNhbmNlbE9yRGVsZXRlUm93Lm5leHQocm93KTtcbiAgICB0aGlzLnJlc2V0RXJyb3IoKTtcbiAgICB0aGlzLnRvdGFsUm93Q291bnQtLTtcbiAgICB0aGlzLnZpc2libGVSb3dDb3VudC0tO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkZWxldGVFeGlzdGluZ1JvdyhldmVudDogRXZlbnQgfCBudWxsLCByb3c6IEFzeW5jVGFibGVFbGVtZW50PFQ+LCBvcHRzPzogeyBpbnRlcmFjdGl2ZT86IGJvb2xlYW47IH0pIHtcbiAgICAvLyBNYWtlIHN1cmUgcm93IHdpbGwgYmUgY2FuY2VsbGVkLCBhbmQgTk9UIGRlbGV0ZWRcbiAgICBpZiAocm93LmlkID09PSAtMSkgdGhyb3cgbmV3IEVycm9yKCdSb3cgbXVzdCBoYXZlIGFuIGlkJyk7XG5cbiAgICBpZiAoZXZlbnQ/LmRlZmF1bHRQcmV2ZW50ZWQpIHJldHVybiAwOyAvLyBTS2lwXG4gICAgZXZlbnQ/LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBhd2FpdCB0aGlzLmRlbGV0ZVJvdyhudWxsLCByb3csIG9wdHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjYW5jZWxFeGlzdGluZ1JvdyhldmVudDogRXZlbnQgfCB1bmRlZmluZWQsIHJvdzogQXN5bmNUYWJsZUVsZW1lbnQ8VD4sIG9wdHM/OiB7IGludGVyYWN0aXZlPzogYm9vbGVhbjsga2VlcEVkaXRpbmc/OiBib29sZWFuOyB9KSB7XG4gICAgLy8gTWFrZSBzdXJlIHJvdyB3aWxsIGJlIGNhbmNlbGxlZCwgYW5kIE5PVCBkZWxldGVkXG4gICAgaWYgKHJvdy5pZCA9PT0gLTEgfHwgIXJvdy5lZGl0aW5nKSB0aHJvdyBuZXcgRXJyb3IoJ1JvdyBjYW5ub3QgYmUgY2FuY2VsaW5nLCBidXQgb25seSBkZWxldGluZycpO1xuXG4gICAgY29uc3QgY29uZmlybWVkID0gKCFvcHRzIHx8IG9wdHMuaW50ZXJhY3RpdmUgIT09IGZhbHNlKTtcblxuICAgIC8vIEFzayB1c2VyIGNvbmZpcm1hdGlvbiwgaWYgY2FuY2VsXG4gICAgaWYgKCFjb25maXJtZWQgJiYgcm93LmRpcnR5ICYmICh0aGlzLmNvbmZpcm1CZWZvcmVDYW5jZWwgfHwgdGhpcy5vbkJlZm9yZUNhbmNlbFJvd3Mub2JzZXJ2ZXJzLmxlbmd0aCA+IDApKSB7XG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIGlmICghYXdhaXQgdGhpcy5jYW5DYW5jZWxSb3dzKFtyb3ddLCBvcHRzKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qga2VlcEVkaXRpbmcgPSByb3cuZWRpdGluZyAmJiAoIW9wdHMgfHwgb3B0cy5rZWVwRWRpdGluZyAhPT0gZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuX2RhdGFTb3VyY2UuY2FuY2VsT3JEZWxldGUocm93KTtcbiAgICB0aGlzLm9uQ2FuY2VsT3JEZWxldGVSb3cubmV4dChyb3cpO1xuXG4gICAgLy8gTWFyayByb3cgYXMgcHJpc3RpbmVcbiAgICBhd2FpdCB0aGlzLmNoZWNrSWZSb3dQcmlzdGluZShyb3cpO1xuXG4gICAgLy8gUmVzdG9yZSBlZGl0aW5nIHN0YXRlXG4gICAgaWYgKGtlZXBFZGl0aW5nKSB7XG4gICAgICBhd2FpdCB0aGlzLmVkaXRSb3codW5kZWZpbmVkLCByb3cpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2hlY2tJZlJvd1ByaXN0aW5lKHJvdzogQXN5bmNUYWJsZUVsZW1lbnQ8VD4sIG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW47IG9ubHlTZWxmPzogYm9vbGVhbiB9KSB7XG4gICAgLy8gTWFyayByb3cgYXMgcHJpc3RpbmVcbiAgICBjb25zdCBtYXJrUm93QXNQcmlzdGluZSA9IHRoaXMuZGF0YVNvdXJjZT8uY29uZmlnLnJlc3RvcmVPcmlnaW5hbERhdGFPbkNhbmNlbCA9PT0gdHJ1ZTtcbiAgICBpZiAobWFya1Jvd0FzUHJpc3RpbmUpIHtcbiAgICAgIHJvdy52YWxpZGF0b3I/Lm1hcmtBc1ByaXN0aW5lKCk7XG5cbiAgICAgIC8vIENoZWNrIGlmIHRhYmxlIGlzIG5vdyBwcmlzdGluZVxuICAgICAgaWYgKCFvcHRzIHx8IG9wdHMub25seVNlbGYgIT09IHRydWUpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5jaGVja0lmUHJpc3RpbmUob3B0cyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja0lmUHJpc3RpbmUob3B0cz86IHsgZW1pdEV2ZW50PzogYm9vbGVhbjsgfSkge1xuICAgIGlmICghdGhpcy5kaXJ0eSkgcmV0dXJuOyAvLyBBbHJlYWR5IHByaXN0aW5lXG5cbiAgICBjb25zdCByb3dzID0gdGhpcy5fZGF0YVNvdXJjZS5nZXRSb3dzKCk7XG4gICAgY29uc3QgcHJpc3RpbmUgPSAocm93cyB8fCBbXSkuZmluZEluZGV4KHJvdyA9PiByb3cuZGlydHkpID09PSAtMTtcbiAgICBpZiAocHJpc3RpbmUpIHRoaXMubWFya0FzUHJpc3RpbmUob3B0cyk7XG4gIH1cblxuICBwcml2YXRlIGFwcGx5RmlsdGVyKGZpbHRlcjogRiwgb3B0czogeyBlbWl0RXZlbnQ/OiBib29sZWFuOyB9KSB7XG4gICAgaWYgKHRoaXMuZGVidWcpIGNvbnNvbGUuZGVidWcoJ1t0YWJsZV0gQXBwbHlpbmcgZmlsdGVyJywgZmlsdGVyKTtcbiAgICB0aGlzLl9maWx0ZXIgPSBmaWx0ZXI7XG4gICAgaWYgKG9wdHMgJiYgb3B0cy5lbWl0RXZlbnQpIHtcbiAgICAgIGlmICh0aGlzLnBhZ2luYXRvciAmJiB0aGlzLnBhZ2luYXRvci5wYWdlSW5kZXggPiAwKSB7XG4gICAgICAgIHRoaXMucGFnaW5hdG9yLnBhZ2VJbmRleCA9IDA7XG4gICAgICB9XG4gICAgICB0aGlzLm9uUmVmcmVzaC5lbWl0KCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBsaXN0ZW5EYXRhc291cmNlTG9hZGluZyhkYXRhU291cmNlOiBFbnRpdGllc0FzeW5jVGFibGVEYXRhU291cmNlPFQsIEYsIElEPikge1xuICAgIGlmICghZGF0YVNvdXJjZSkgdGhyb3cgbmV3IEVycm9yKCdbdGFibGVdIGRhdGFTb3VyY2Ugbm90IHNldCAhJyk7XG5cbiAgICAvLyBDbGVhbmluZyBwcmV2aW91cyBzdWJzY3JpcHRpb24gb24gZGF0YXNvdXJjZVxuICAgIGlmIChpc05vdE5pbCh0aGlzLl9kYXRhU291cmNlTG9hZGluZ1N1YnNjcmlwdGlvbikpIHtcbiAgICAgIGlmICh0aGlzLmRlYnVnKSBjb25zb2xlLmRlYnVnKCdbdGFibGVdIE1hbnkgY2FsbCB0byBsaXN0ZW5EYXRhc291cmNlKCk6IENsZWFuaW5nIHByZXZpb3VzIHN1YnNjcmlwdGlvbnMuLi4nKTtcbiAgICAgIHRoaXMuX2RhdGFTb3VyY2VMb2FkaW5nU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLnVucmVnaXN0ZXJTdWJzY3JpcHRpb24odGhpcy5fZGF0YVNvdXJjZUxvYWRpbmdTdWJzY3JpcHRpb24pO1xuICAgIH1cblxuICAgIC8vIFByb3BhZ2UgbG9hZGluZyB0byB0YWJsZVxuICAgIHRoaXMuX2RhdGFTb3VyY2VMb2FkaW5nU3Vic2NyaXB0aW9uID0gdGhpcy5fZGF0YVNvdXJjZS5sb2FkaW5nU3ViamVjdFxuICAgICAgLnBpcGUoXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG5cbiAgICAgICAgLy8gSWYgY2hhbmdlZCB0byBUcnVlOiBwcm9wYWdhdGUgYXMgc29vbiBhcyBwb3NzaWJsZVxuICAgICAgICB0YXAoKGxvYWRpbmcpID0+IGxvYWRpbmcgJiYgdGhpcy5zZXRMb2FkaW5nKHRydWUpKSxcblxuICAgICAgICAvLyBJZiBjaGFuZ2VkIHRvIEZhbHNlOiB3YWl0IDI1MG1zIGJlZm9yZSBwcm9wYWdhdGUgKHRvIG1ha2Ugc3VyZSB0aGUgc3Bpbm5lciBoYXMgYmVlbiBkaXNwbGF5ZWQpXG4gICAgICAgIGRlYm91bmNlVGltZSgyNTApLFxuICAgICAgICB0YXAobG9hZGluZyA9PiAhbG9hZGluZyAmJiB0aGlzLnNldExvYWRpbmcoZmFsc2UpKVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgpO1xuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24odGhpcy5fZGF0YVNvdXJjZUxvYWRpbmdTdWJzY3JpcHRpb24pO1xuICB9XG5cblxuICBwcml2YXRlIHN0YXJ0Q2VsbFZhbHVlQ2hhbmdlcyhuYW1lOiBzdHJpbmcsIHJvdzogQXN5bmNUYWJsZUVsZW1lbnQ8VD4pIHtcbiAgICBjb25zdCBkZWYgPSB0aGlzLl9jZWxsVmFsdWVDaGFuZ2VzRGVmc1tuYW1lXTtcbiAgICBpZiAoIWRlZikge1xuICAgICAgY29uc29sZS53YXJuKCdbdGFibGVdIExpc3RlbmVyIHdpdGggbmFtZSB7JyArIG5hbWUgKyAnfSBub3QgcmVnaXN0ZXJlZCEgUGxlYXNlIGNhbGwgcmVnaXN0ZXJDZWxsVmFsdWVDaGFuZ2VzKCkgYmVmb3JlOycpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBTdG9wIHByZXZpb3VzIHN1YnNjcmlwdGlvblxuICAgIGlmIChkZWYuc3Vic2NyaXB0aW9uKSB7XG4gICAgICBkZWYuc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICBkZWYuc3Vic2NyaXB0aW9uID0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMuZGVidWcpIGNvbnNvbGUuZGVidWcoYFt0YWJsZV0gU3RhcnQgdmFsdWVzIGNoYW5nZXMgb24gcm93IHBhdGggeyR7ZGVmLmZvcm1QYXRofX1gKTtcbiAgICB9XG5cbiAgICAvLyBMaXN0ZW4gdmFsdWUgY2hhbmdlcywgYW5kIHJlZGlyZWN0IHRvIGV2ZW50IGVtaXR0ZXJcbiAgICBjb25zdCBjb250cm9sID0gcm93LnZhbGlkYXRvciAmJiBBcHBGb3JtVXRpbHMuZ2V0Q29udHJvbEZyb21QYXRoKHJvdy52YWxpZGF0b3IsIGRlZi5mb3JtUGF0aCk7XG4gICAgaWYgKCFjb250cm9sKSB7XG4gICAgICBjb25zb2xlLndhcm4oYFt0YWJsZV0gQ291bGQgbm90IGxpc3RlbiBjZWxsIGNoYW5nZXM6IG5vIHZhbGlkYXRvciBvciBpbnZhbGlkIGZvcm0gcGF0aCB7JHtkZWYuZm9ybVBhdGh9fWApO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWYuc3Vic2NyaXB0aW9uID0gY29udHJvbC52YWx1ZUNoYW5nZXNcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgLy8gZG9uJ3QgZW1pdCBpZiBjb250cm9sIGlzIGRpc2FibGVkXG4gICAgICAgICAgZmlsdGVyKCgpID0+IGNvbnRyb2wuZW5hYmxlZClcbiAgICAgICAgKVxuICAgICAgICAuc3Vic2NyaWJlKCh2YWx1ZSkgPT4gZGVmLnN1YmplY3QubmV4dCh2YWx1ZSkpO1xuXG4gICAgICAvLyBFbWl0IHRoZSBhY3R1YWwgdmFsdWVcbiAgICAgIGlmIChkZWYuZW1pdEluaXRpYWxWYWx1ZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgZGVmLnN1YmplY3QubmV4dChjb250cm9sLnZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN0b3BDZWxsVmFsdWVDaGFuZ2VzKG5hbWU6IHN0cmluZywgZGVzdHJveT86IGJvb2xlYW4pIHtcbiAgICBjb25zdCBkZWYgPSB0aGlzLl9jZWxsVmFsdWVDaGFuZ2VzRGVmc1tuYW1lXTtcbiAgICBpZiAoIWRlZikgcmV0dXJuO1xuICAgIGlmIChkZWYuc3Vic2NyaXB0aW9uKSB7XG4gICAgICBpZiAodGhpcy5kZWJ1ZykgY29uc29sZS5kZWJ1ZygnW3RhYmxlXSBTdG9wIHZhbHVlIGNoYW5nZXMgb24gcm93IHBhdGggeycgKyBkZWYuZm9ybVBhdGggKyAnfScpO1xuICAgICAgZGVmLnN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgZGVmLnN1YnNjcmlwdGlvbiA9IG51bGw7XG4gICAgfVxuICAgIGlmIChkZXN0cm95ICYmIGRlZi5zdWJqZWN0KSB7XG4gICAgICBkZWYuc3ViamVjdC5jb21wbGV0ZSgpO1xuICAgICAgZGVmLnN1YmplY3QudW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cbn1cblxuIl19
|