ngx-dynamic-entity 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +129 -139
  2. package/esm2022/lib/field-types/array-field.component.mjs +112 -104
  3. package/esm2022/lib/field-types/boolean-field.component.mjs +62 -61
  4. package/esm2022/lib/field-types/checkbox-field.component.mjs +48 -47
  5. package/esm2022/lib/field-types/currency-field.component.mjs +54 -53
  6. package/esm2022/lib/field-types/date-field.component.mjs +46 -45
  7. package/esm2022/lib/field-types/dropdown-field.component.mjs +89 -87
  8. package/esm2022/lib/field-types/email-field.component.mjs +64 -63
  9. package/esm2022/lib/field-types/entity-ref-field.component.mjs +85 -71
  10. package/esm2022/lib/field-types/field-component.contract.mjs +2 -0
  11. package/esm2022/lib/field-types/file-field.component.mjs +88 -87
  12. package/esm2022/lib/field-types/group-field.component.mjs +50 -50
  13. package/esm2022/lib/field-types/image-field.component.mjs +92 -91
  14. package/esm2022/lib/field-types/month-year-field.component.mjs +80 -79
  15. package/esm2022/lib/field-types/multi-select-field.component.mjs +66 -65
  16. package/esm2022/lib/field-types/number-field.component.mjs +71 -75
  17. package/esm2022/lib/field-types/password-field.component.mjs +68 -67
  18. package/esm2022/lib/field-types/radio-field.component.mjs +66 -65
  19. package/esm2022/lib/field-types/text-field.component.mjs +81 -74
  20. package/esm2022/lib/field-types/textarea-field.component.mjs +48 -47
  21. package/esm2022/lib/form/dynamic-field/dynamic-field.component.mjs +53 -6
  22. package/esm2022/lib/form/dynamic-form.component.mjs +309 -20
  23. package/esm2022/lib/form/dynamic-record-form.component.mjs +36 -11
  24. package/esm2022/lib/providers/provide-field-types.mjs +1 -1
  25. package/esm2022/lib/providers/provide-ngx-dynamic-entity.mjs +8 -2
  26. package/esm2022/lib/services/cascade-data.service.mjs +2 -2
  27. package/esm2022/lib/services/entity-ref-cache.mjs +1 -1
  28. package/esm2022/lib/services/entity-ref-registry.service.mjs +2 -2
  29. package/esm2022/lib/services/entity-ref-selection.service.mjs +1 -1
  30. package/esm2022/lib/services/entity-reference.service.mjs +1 -1
  31. package/esm2022/lib/services/field-registry.service.mjs +1 -1
  32. package/esm2022/lib/services/file-upload.service.mjs +1 -1
  33. package/esm2022/lib/services/lookup-registry.service.mjs +2 -2
  34. package/esm2022/lib/services/rbac.service.mjs +1 -1
  35. package/esm2022/lib/services/validation-messages.service.mjs +56 -0
  36. package/esm2022/lib/services/validator-registry.service.mjs +35 -2
  37. package/esm2022/lib/tokens/injection-tokens.mjs +35 -6
  38. package/esm2022/public-api.mjs +23 -2
  39. package/fesm2022/ngx-dynamic-entity.mjs +1754 -1236
  40. package/fesm2022/ngx-dynamic-entity.mjs.map +1 -1
  41. package/lib/field-types/array-field.component.d.ts +7 -1
  42. package/lib/field-types/dropdown-field.component.d.ts +2 -1
  43. package/lib/field-types/entity-ref-field.component.d.ts +12 -2
  44. package/lib/field-types/field-component.contract.d.ts +49 -0
  45. package/lib/field-types/group-field.component.d.ts +1 -1
  46. package/lib/field-types/multi-select-field.component.d.ts +1 -1
  47. package/lib/field-types/number-field.component.d.ts +1 -0
  48. package/lib/field-types/radio-field.component.d.ts +1 -1
  49. package/lib/field-types/text-field.component.d.ts +10 -2
  50. package/lib/form/dynamic-field/dynamic-field.component.d.ts +39 -4
  51. package/lib/form/dynamic-form.component.d.ts +155 -8
  52. package/lib/form/dynamic-record-form.component.d.ts +13 -2
  53. package/lib/providers/provide-ngx-dynamic-entity.d.ts +25 -3
  54. package/lib/services/cascade-data.service.d.ts +1 -1
  55. package/lib/services/entity-ref-registry.service.d.ts +1 -1
  56. package/lib/services/lookup-registry.service.d.ts +1 -1
  57. package/lib/services/validation-messages.service.d.ts +43 -0
  58. package/lib/services/validator-registry.service.d.ts +13 -1
  59. package/lib/tokens/injection-tokens.d.ts +42 -7
  60. package/package.json +17 -18
  61. package/public-api.d.ts +12 -0
  62. package/styles.css +579 -0
@@ -1,10 +1,10 @@
1
- import { Component, Input, Output, EventEmitter, signal, computed, inject, HostListener, } from '@angular/core';
1
+ import { Component, Input, Output, EventEmitter, signal, computed, inject, isDevMode, ViewChild, ViewChildren, HostListener, } from '@angular/core';
2
2
  import { NgComponentOutlet } from '@angular/common';
3
3
  import { FormArray, FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
4
4
  import { debounceTime } from 'rxjs/operators';
5
- import { applyAutoPatch, applyPatchOnTrue, evaluateFieldVisibility, findTab, getTabData, getTabPath, getValueByPath, normalizeArrayStructures, normalizeConfigOptions, resolveLabel, setTabData, setValueByPath, } from '@dynamic-entity/core';
5
+ import { applyAutoPatch, applyPatchOnTrue, migrateRecord, evaluateFieldVisibility, findTab, getTabData, getTabPath, getValueByPath, normalizeArrayStructures, normalizeConfigOptions, resolveLabel, setTabData, setValueByPath, } from '@dynamic-entity/core';
6
6
  import { DynamicFieldComponent } from './dynamic-field/dynamic-field.component';
7
- import { COMMON_MODULES_REGISTRY } from '../tokens/injection-tokens';
7
+ import { COMMON_MODULES_REGISTRY, RECORD_MIGRATIONS } from '../tokens/injection-tokens';
8
8
  import { ValidatorRegistryService } from '../services/validator-registry.service';
9
9
  import { HookRegistryService } from '../services/hook-registry.service';
10
10
  import { RbacService } from '../services/rbac.service';
@@ -20,7 +20,26 @@ import * as i1 from "@angular/forms";
20
20
  */
21
21
  export class DynamicFormComponent {
22
22
  // ─── Inputs ───────────────────────────────────────────────────────────────
23
- config;
23
+ /**
24
+ * The schema to render.
25
+ *
26
+ * An accessor pair rather than a plain field: `ngOnChanges` normalises the option shape,
27
+ * and that result is kept here instead of being written back over the input. Reassigning
28
+ * an `@Input` works, but it mutates what the parent handed us — and a parent using OnPush
29
+ * or signals would never observe the replacement anyway.
30
+ *
31
+ * Reads of `this.config` get the normalised copy once it exists, so every internal caller
32
+ * is unaffected.
33
+ */
34
+ set config(value) {
35
+ this.rawConfig = value;
36
+ this.normalizedConfig = undefined; // re-normalised in ngOnChanges
37
+ }
38
+ get config() {
39
+ return this.normalizedConfig ?? this.rawConfig;
40
+ }
41
+ rawConfig;
42
+ normalizedConfig;
24
43
  rules;
25
44
  initialData;
26
45
  /** Session-original values for `VALUE_CHANGED` rules. Captured from the first build when omitted. */
@@ -54,6 +73,11 @@ export class DynamicFormComponent {
54
73
  formReset = new EventEmitter();
55
74
  /** The visible tab changed. Lets a host track it without reaching into this component. */
56
75
  activeTabChange = new EventEmitter();
76
+ /**
77
+ * Emitted when a `beforeSave` hook aborted the save — by returning false or throwing.
78
+ * `formSubmit` does not fire in that case.
79
+ */
80
+ saveRejected = new EventEmitter();
57
81
  // ─── Services ─────────────────────────────────────────────────────────────
58
82
  fb = inject(FormBuilder);
59
83
  validatorRegistry = inject(ValidatorRegistryService);
@@ -62,6 +86,7 @@ export class DynamicFormComponent {
62
86
  rulesEvaluation = inject(RulesEvaluationService);
63
87
  entityRefSelection = inject(EntityRefSelectionService);
64
88
  commonModulesRegistry = inject(COMMON_MODULES_REGISTRY, { optional: true });
89
+ migrations = inject(RECORD_MIGRATIONS, { optional: true }) ?? [];
65
90
  Object = Object;
66
91
  // ─── Signals (local reactive state) ───────────────────────────────────────
67
92
  activeTab = signal('');
@@ -72,6 +97,10 @@ export class DynamicFormComponent {
72
97
  sessionBaseline = signal({});
73
98
  /** Critical fields the user has explicitly unlocked for editing. */
74
99
  unlockedFields = signal(new Set());
100
+ /** The active tab's field panel, focused after a tab switch. */
101
+ formPanel;
102
+ /** The hosted field components, so an external control-state change can reach them. */
103
+ fieldHosts;
75
104
  // ─── Form ─────────────────────────────────────────────────────────────────
76
105
  form;
77
106
  valueSub;
@@ -144,11 +173,72 @@ export class DynamicFormComponent {
144
173
  const hiddenFields = this.ruleResult().hiddenFields;
145
174
  return rawFields.filter(field => evaluateFieldVisibility(field, currentValues) && !hiddenFields.includes(field.id));
146
175
  }
176
+ /**
177
+ * Entity-level permissions for the current roles.
178
+ *
179
+ * Cached rather than recomputed: this is read from the template several times per change
180
+ * detection pass, and a fresh object each time is both wasted allocation and a new
181
+ * identity for anything comparing by reference. Invalidated in `ngOnChanges` when
182
+ * `config` or `userRoles` change, which are its only inputs.
183
+ */
147
184
  get permissions() {
148
- return this.rbacService.getPermissions(this.config, this.userRoles);
185
+ return (this.permissionsCache ??= this.rbacService.getPermissions(this.config, this.userRoles));
186
+ }
187
+ permissionsCache = null;
188
+ /**
189
+ * Whether the current roles may see this record at all.
190
+ *
191
+ * `permissions.view` used to be computed and thrown away — a user whose roles failed it
192
+ * still received the complete form with every value in the DOM. It is honoured now.
193
+ *
194
+ * As with masking, this is presentational: it stops the browser rendering data, it does
195
+ * not stop the data reaching the browser. Authorize on the server.
196
+ */
197
+ get canView() {
198
+ return this.permissions.canView;
199
+ }
200
+ /**
201
+ * Whether the current roles may delete this record.
202
+ *
203
+ * The library ships no delete affordance, so this is surfaced for the consumer to gate
204
+ * their own — exposed rather than dropped, because a permission the schema declares
205
+ * should be answerable.
206
+ */
207
+ get canDelete() {
208
+ return this.permissions.canDelete;
149
209
  }
150
210
  get canSubmit() {
151
- return this.permissions.canEdit && !this.readonly;
211
+ return this.canView && this.permissions.canEdit && !this.readonly;
212
+ }
213
+ /**
214
+ * Errors raised by `validation` rules, keyed by the target they point at.
215
+ *
216
+ * A rule can declare the record invalid independently of Angular's validators, so form
217
+ * validity alone is not the whole picture. `DynamicRecordFormComponent.saveSection()`
218
+ * has always honoured these; `submit()` did not, which meant the same rule blocked one
219
+ * save path and merely painted a banner on the other — and anything wiring
220
+ * `(formSubmit)` to persistence wrote records the rules engine had already rejected.
221
+ */
222
+ get ruleValidationErrors() {
223
+ return this.ruleResult().validationErrors;
224
+ }
225
+ /** True when a `validation` rule is currently blocking submission. */
226
+ get hasRuleErrors() {
227
+ return Object.keys(this.ruleValidationErrors).length > 0;
228
+ }
229
+ /**
230
+ * True while an async validator is still running.
231
+ *
232
+ * Angular reports a control with an outstanding async check as `pending`, and `invalid` is
233
+ * false until it settles — so without this a form could be submitted in the gap before a
234
+ * uniqueness check came back.
235
+ */
236
+ get isValidating() {
237
+ return this.form.pending;
238
+ }
239
+ /** Single source of truth for both the submit guard and the button's disabled state. */
240
+ get submitBlocked() {
241
+ return this.form.invalid || this.form.pending || this.hasRuleErrors;
152
242
  }
153
243
  ngOnInit() {
154
244
  this.selectionSub = this.entityRefSelection.selection$.subscribe(({ fieldId, option }) => {
@@ -156,12 +246,18 @@ export class DynamicFormComponent {
156
246
  });
157
247
  }
158
248
  ngOnChanges(changes) {
159
- if (changes['config'] && this.config) {
249
+ if (changes['config'] || changes['userRoles']) {
250
+ this.permissionsCache = null;
251
+ }
252
+ if (changes['config'] && this.rawConfig) {
160
253
  // Configs arrive as plain JSON from storage or an API, where TypeScript cannot enforce
161
254
  // the option shape. Normalise here, at the library boundary, so everything downstream
162
255
  // can rely on an option being a LocalizedText. Returns the same object when it already
163
256
  // is, so a well-formed config costs nothing.
164
- this.config = normalizeConfigOptions(this.config);
257
+ // Kept in a field of our own rather than written back to the @Input. Reassigning an
258
+ // input works, but it surprises a parent that holds the same object — and a parent
259
+ // using OnPush or signals would not see the replacement anyway.
260
+ this.normalizedConfig = normalizeConfigOptions(this.config);
165
261
  }
166
262
  if (changes['config'] || changes['initialData']) {
167
263
  this.buildForm();
@@ -175,9 +271,12 @@ export class DynamicFormComponent {
175
271
  this.selectionSub?.unsubscribe();
176
272
  }
177
273
  setActiveTab(tabId) {
178
- if (this.activeTab() !== tabId)
274
+ const changed = this.activeTab() !== tabId;
275
+ if (changed)
179
276
  this.activeTabChange.emit(tabId);
180
277
  this.activeTab.set(tabId);
278
+ if (changed)
279
+ this.focusActivePanel();
181
280
  const parent = findTab(this.tabs, tabId);
182
281
  if (parent?.children?.length) {
183
282
  this.activeSubTab.set(parent.children[0].id);
@@ -187,7 +286,10 @@ export class DynamicFormComponent {
187
286
  }
188
287
  }
189
288
  setActiveSubTab(subTabId) {
289
+ const changed = this.activeSubTab() !== subTabId;
190
290
  this.activeSubTab.set(subTabId);
291
+ if (changed)
292
+ this.focusActivePanel();
191
293
  }
192
294
  getFieldSpan(field) {
193
295
  const span = field.colSpan ?? 12;
@@ -249,13 +351,14 @@ export class DynamicFormComponent {
249
351
  buildTabControls(this.config.tabs || [], group);
250
352
  this.form = this.fb.group(group);
251
353
  if (this.initialData) {
252
- this.patchForm(this.initialData);
354
+ this.patchForm(this.upgradeRecord(this.initialData));
253
355
  }
254
356
  const initialFlattened = this.flattenFormValues();
255
357
  this.formValues.set(initialFlattened);
256
358
  this.previousValues = { ...initialFlattened };
257
359
  this.sessionBaseline.set({ ...initialFlattened });
258
360
  this.unlockedFields.set(new Set());
361
+ this.syncHiddenFieldState(initialFlattened);
259
362
  if (this.preview) {
260
363
  // Show what an array field looks like rather than an empty slot, then freeze.
261
364
  for (const field of this.allFields()) {
@@ -276,6 +379,7 @@ export class DynamicFormComponent {
276
379
  const flattened = this.flattenFormValues();
277
380
  this.formValues.set(flattened);
278
381
  this.runPatchOnTrue(flattened);
382
+ this.syncHiddenFieldState(flattened);
279
383
  this.previousValues = { ...flattened };
280
384
  this.formChange.emit(this.extractRecord());
281
385
  });
@@ -293,7 +397,8 @@ export class DynamicFormComponent {
293
397
  }
294
398
  else {
295
399
  const validators = this.validatorRegistry.resolveFromConfig(field.validators);
296
- group[field.id] = this.fb.control({ value: field.defaultValue ?? null, disabled: field.disabled ?? false }, validators);
400
+ const asyncValidators = this.validatorRegistry.resolveAsyncFromConfig(field.validators);
401
+ group[field.id] = this.fb.control({ value: field.defaultValue ?? null, disabled: field.disabled ?? false }, validators, asyncValidators);
297
402
  }
298
403
  }
299
404
  /** One row of an `array` field: a FormGroup when the field declares columns, else a bare control. */
@@ -324,10 +429,41 @@ export class DynamicFormComponent {
324
429
  group.patchValue(item);
325
430
  return group;
326
431
  }
432
+ /**
433
+ * Mark every control touched, then re-check the field components.
434
+ *
435
+ * They are OnPush and `touched` is flipped from outside their own template, so the second
436
+ * half is what makes the error messages actually appear.
437
+ */
438
+ markAllTouched() {
439
+ this.form.markAllAsTouched();
440
+ this.fieldHosts?.forEach(host => host.refresh());
441
+ }
442
+ /**
443
+ * Bring a record up to the config's `version` before it reaches the form.
444
+ *
445
+ * Done here because this is the one place a record enters the renderer, so a consumer
446
+ * cannot forget it. Migration is a no-op unless the consumer registered steps *and* the
447
+ * record is behind — an unstamped record is deliberately left alone (see `migrateRecord`).
448
+ *
449
+ * A missing or broken step throws from core. That is not swallowed: rendering a
450
+ * half-understood record would write it back in a shape matching neither schema.
451
+ */
452
+ upgradeRecord(data) {
453
+ if (!this.migrations.length || !this.config)
454
+ return data;
455
+ const result = migrateRecord(data, this.config, this.migrations);
456
+ if (result.applied.length && isDevMode()) {
457
+ console.info(`[ngx-dynamic-entity] Migrated a "${this.config.entity}" record from config version ` +
458
+ `${result.from} to ${result.to} (steps: ${result.applied.join(', ')}).`);
459
+ }
460
+ return result.record;
461
+ }
327
462
  patchForm(data) {
328
463
  if (!data || !this.form)
329
464
  return;
330
465
  const fieldsById = new Map(this.allFields().map(f => [f.id, f]));
466
+ const patchedFieldIds = new Set();
331
467
  const walkTabs = (tabs) => {
332
468
  for (const tab of tabs) {
333
469
  const tabData = getTabData(tab.id, data, this.config);
@@ -352,13 +488,57 @@ export class DynamicFormComponent {
352
488
  else {
353
489
  ctrl.patchValue(val, { emitEvent: false });
354
490
  }
491
+ patchedFieldIds.add(field.id);
355
492
  }
356
493
  if (tab.children)
357
494
  walkTabs(tab.children);
358
495
  }
359
496
  };
360
497
  walkTabs(this.config.tabs || []);
498
+ this.warnUnconsumedInitialData(data, fieldsById, patchedFieldIds);
361
499
  }
500
+ /**
501
+ * A record is nested by tab id (`{ tabId: { fieldId: value } }`) unless the tab sets
502
+ * `flatData: true`. Handing a flat record to a nested tab finds nothing, so the fields
503
+ * stay empty — with no error and no clue. That silent miss is the most expensive way to
504
+ * lose an hour with this library, so name it in dev builds.
505
+ *
506
+ * Only top-level keys that match a known field id are reported: anything else is assumed
507
+ * to be the consumer's own record metadata (ids, timestamps, `_configVersion`) and is not
508
+ * our business.
509
+ */
510
+ warnUnconsumedInitialData(data, fieldsById, patchedFieldIds) {
511
+ if (!isDevMode() || !this.config)
512
+ return;
513
+ const tabIds = new Set();
514
+ const collectTabIds = (tabs) => {
515
+ for (const tab of tabs) {
516
+ tabIds.add(tab.id);
517
+ if (tab.children)
518
+ collectTabIds(tab.children);
519
+ }
520
+ };
521
+ collectTabIds(this.config.tabs || []);
522
+ const unconsumed = Object.keys(data).filter(key => !tabIds.has(key) && // a tab id at the root is the nested container, not a stray field
523
+ data[key] !== undefined &&
524
+ fieldsById.has(key) &&
525
+ !patchedFieldIds.has(key) &&
526
+ !this.warnedUnconsumedKeys.has(key));
527
+ if (!unconsumed.length)
528
+ return;
529
+ for (const key of unconsumed)
530
+ this.warnedUnconsumedKeys.add(key);
531
+ const shown = unconsumed.slice(0, 5).join(', ');
532
+ const more = unconsumed.length > 5 ? ` (+${unconsumed.length - 5} more)` : '';
533
+ const plural = unconsumed.length === 1;
534
+ console.warn(`[ngx-dynamic-entity] initialData has top-level ${plural ? 'key' : 'keys'} matching ` +
535
+ `${plural ? 'a field that was' : 'fields that were'} not populated: ${shown}${more}. ` +
536
+ `A record is nested by tab id ({ tabId: { fieldId: value } }) unless the tab sets ` +
537
+ `flatData: true. Either nest the value under its tab id, or set flatData: true on ` +
538
+ `the tab holding ${plural ? 'that field' : 'those fields'}.`);
539
+ }
540
+ /** Warn once per key per form instance — patchForm re-runs on every initialData change. */
541
+ warnedUnconsumedKeys = new Set();
362
542
  /** Assemble full nested record from per-tab FormGroups, respecting flatData, refererField & arrays. */
363
543
  extractRecord() {
364
544
  if (!this.form || !this.config)
@@ -428,6 +608,10 @@ export class DynamicFormComponent {
428
608
  const control = this.resolveTargetControl(autoPatch, targetId);
429
609
  control?.patchValue(value);
430
610
  }
611
+ // Readonly targets interpolate `control.value` under OnPush. `detectChanges` on the
612
+ // hosted component flushes that write immediately — `markForCheck` waits for a later
613
+ // tick that a Playwright selection never schedules.
614
+ this.fieldHosts?.forEach(host => host.refresh());
431
615
  }
432
616
  /**
433
617
  * `patchOnTrue` — when a boolean/checkbox field transitions to `true`,
@@ -457,6 +641,57 @@ export class DynamicFormComponent {
457
641
  return this.getControl(targetId, autoPatch.targetTab);
458
642
  }
459
643
  // ─── Helpers ──────────────────────────────────────────────────────────────
644
+ /**
645
+ * The fields the render filter operates on — a tab's own fields, at every tab depth.
646
+ * Deliberately not `allFields()`: `group` and `array` children are shown or hidden with
647
+ * their parent, and toggling a child's state independently would fight the parent's.
648
+ */
649
+ tabFields() {
650
+ const out = [];
651
+ const walk = (tabs) => {
652
+ for (const tab of tabs ?? []) {
653
+ out.push(...(tab.fields ?? []));
654
+ walk(tab.children);
655
+ }
656
+ };
657
+ walk(this.config?.tabs);
658
+ return out;
659
+ }
660
+ /**
661
+ * Keep a hidden field's control out of form validity.
662
+ *
663
+ * A field hidden by a rule or a `showWhen` condition is filtered out of the render, but
664
+ * its validators stay attached — so a hidden *required* field holds `form.invalid` true
665
+ * forever, permanently disabling Save with nothing on screen to explain why.
666
+ *
667
+ * Disabling is the fix rather than stripping validators: Angular excludes disabled
668
+ * controls from validity, and the field's own validators survive intact for when it
669
+ * comes back. Values are untouched — `flattenFormValues` and `extractRecord` both read
670
+ * `control.value`, which a disabled control still carries, so rule evaluation and the
671
+ * emitted record see exactly what they saw before. That also keeps this from feeding
672
+ * back on itself: hiding a field cannot change the values the rules are evaluated over.
673
+ *
674
+ * The visibility predicate is the same one `fieldsForActiveTab` filters with, so what is
675
+ * rendered and what counts toward validity cannot drift apart.
676
+ */
677
+ syncHiddenFieldState(values) {
678
+ if (this.preview)
679
+ return; // preview freezes the whole form on purpose
680
+ const hiddenByRule = new Set(this.ruleResult().hiddenFields);
681
+ for (const field of this.tabFields()) {
682
+ const ctrl = this.getControl(field.id);
683
+ if (!ctrl)
684
+ continue;
685
+ const hidden = hiddenByRule.has(field.id) || !evaluateFieldVisibility(field, values);
686
+ if (hidden) {
687
+ if (ctrl.enabled)
688
+ ctrl.disable({ emitEvent: false });
689
+ }
690
+ else if (ctrl.disabled && !field.disabled) {
691
+ ctrl.enable({ emitEvent: false });
692
+ }
693
+ }
694
+ }
460
695
  /** Every field in the config, including `group`/`array` children. */
461
696
  allFields() {
462
697
  const out = [];
@@ -522,24 +757,70 @@ export class DynamicFormComponent {
522
757
  };
523
758
  return findInGroup(this.form);
524
759
  }
760
+ /**
761
+ * Move focus into the newly shown panel.
762
+ *
763
+ * Activating a tab replaces everything below it while focus stays on the tab button, so a
764
+ * screen-reader or keyboard user is given no indication that the content changed and must
765
+ * tab back through the strip to reach it. Deferred a frame because the panel's contents
766
+ * are rendered by the change detection this call is part of.
767
+ */
768
+ focusActivePanel() {
769
+ if (typeof requestAnimationFrame !== 'function')
770
+ return;
771
+ requestAnimationFrame(() => this.formPanel?.nativeElement?.focus?.());
772
+ }
773
+ /** Accessible name for the field panel — it is the tabpanel for the active tab. */
774
+ get activeTabLabel() {
775
+ const tab = this.activeSubTabConfig ?? this.activeTabConfig;
776
+ return tab ? this.resolveTabLabel(tab) : '';
777
+ }
778
+ /**
779
+ * Why a referenced field is flagged.
780
+ *
781
+ * `hasDrift` was written by the builder and read by nothing at runtime, so a field whose
782
+ * source definition had changed since it was linked looked entirely normal to the person
783
+ * filling the form in.
784
+ */
785
+ driftHint(field) {
786
+ const source = field.referencedEntityKey
787
+ ? `"${field.referencedEntityKey}"`
788
+ : 'its source entity';
789
+ return `This field is linked to ${source} and its definition there has changed since it was linked.`;
790
+ }
525
791
  resolveTabLabel(tab) {
526
792
  return resolveLabel(tab.label, this.language);
527
793
  }
528
794
  async submit() {
529
- if (!this.canSubmit || this.form.invalid) {
530
- this.form.markAllAsTouched();
795
+ if (!this.canSubmit || this.submitBlocked) {
796
+ this.markAllTouched();
531
797
  return;
532
798
  }
533
799
  const rawData = this.extractRecord();
534
800
  let processedData = rawData;
535
- const hookKey = `${this.config?.entity}:beforeSave`;
536
- if (this.hookRegistry.has(hookKey)) {
537
- processedData = await this.hookRegistry.run(hookKey, processedData);
538
- }
539
801
  this.isSaving.set(true);
540
802
  try {
803
+ // beforeSave can now abort the save: returning false, or throwing, stops it. Previously
804
+ // its return value simply replaced the payload and the submit proceeded regardless, so
805
+ // a hook that wanted to veto — a server-side check, a confirmation — had no way to.
806
+ const hookKey = `${this.config?.entity}:beforeSave`;
807
+ if (this.hookRegistry.has(hookKey)) {
808
+ const result = await this.hookRegistry.run(hookKey, processedData);
809
+ if (result === false) {
810
+ this.saveRejected.emit({ reason: 'beforeSave returned false' });
811
+ return;
812
+ }
813
+ // Anything else is the payload to submit; `undefined` means "unchanged".
814
+ if (result !== undefined && result !== true)
815
+ processedData = result;
816
+ }
541
817
  this.formSubmit.emit(processedData);
542
818
  }
819
+ catch (err) {
820
+ // A hook that throws aborts the save and reports why, rather than the error escaping
821
+ // into an unhandled rejection with the form left looking as though it saved.
822
+ this.saveRejected.emit({ reason: err instanceof Error ? err.message : String(err), error: err });
823
+ }
543
824
  finally {
544
825
  this.isSaving.set(false);
545
826
  }
@@ -555,11 +836,11 @@ export class DynamicFormComponent {
555
836
  this.formReset.emit();
556
837
  }
557
838
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
558
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: DynamicFormComponent, isStandalone: true, selector: "ngx-dynamic-form", inputs: { config: "config", rules: "rules", initialData: "initialData", originalData: "originalData", userRoles: "userRoles", language: "language", readonly: "readonly", readOnlyFields: "readOnlyFields", showInfoBanners: "showInfoBanners", loading: "loading", error: "error", changeDebounceMs: "changeDebounceMs", preview: "preview" }, outputs: { formSubmit: "formSubmit", formChange: "formChange", formReset: "formReset", activeTabChange: "activeTabChange" }, host: { listeners: { "window:keydown": "handleKeyboardEvent($event)" } }, providers: [EntityRefSelectionService], usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"submit()\" class=\"ngx-form\" novalidate>\r\n\r\n <!-- Error message banner -->\r\n @if (error) {\r\n <div class=\"ngx-form__error-banner\" role=\"alert\" data-testid=\"form-error\">{{ error }}</div>\r\n }\r\n\r\n <!-- Rules Info Banners -->\r\n @for (infoKey of showInfoBanners ? Object.keys(ruleResult().infoBanners) : []; track infoKey) {\r\n <div class=\"ngx-form__info-banner\" role=\"status\" [attr.data-testid]=\"'info-banner-' + infoKey\">\r\n \u2139\uFE0F {{ ruleResult().infoBanners[infoKey] }}\r\n </div>\r\n }\r\n\r\n <!-- Rules Validation Errors & Warnings -->\r\n @for (errKey of Object.keys(ruleResult().validationErrors); track errKey) {\r\n <div class=\"ngx-form__error-banner\" role=\"alert\" [attr.data-testid]=\"'rule-error-' + errKey\">\r\n \u26A0\uFE0F {{ ruleResult().validationErrors[errKey] }}\r\n </div>\r\n }\r\n @for (warnKey of Object.keys(ruleResult().validationWarnings); track warnKey) {\r\n <div class=\"ngx-form__warning-banner\" role=\"status\" [attr.data-testid]=\"'rule-warning-' + warnKey\">\r\n \u26A1 {{ ruleResult().validationWarnings[warnKey] }}\r\n </div>\r\n }\r\n\r\n <!-- Deferred VALUE_CHANGED notice for criticalField edits (vs session baseline) -->\r\n @if (changedCriticalFields().length > 0) {\r\n <div class=\"ngx-form__warning-banner\" role=\"status\" data-testid=\"critical-change-banner\">\r\n \uD83D\uDD12 Critical field changed:\r\n @for (field of changedCriticalFields(); track field.id) {\r\n <span>{{ resolveFieldLabel(field) }}{{ $last ? '' : ', ' }}</span>\r\n }\r\n \u2014 this differs from the value at the start of this session.\r\n </div>\r\n }\r\n\r\n <!-- Primary Tab bar \u2014 only if visible tabs defined -->\r\n @if (visibleTabs.length > 0) {\r\n <div class=\"ngx-form__tabs\" role=\"tablist\" data-testid=\"tab-strip\">\r\n @for (tab of visibleTabs; track tab.id) {\r\n <button\r\n type=\"button\"\r\n class=\"ngx-form__tab\"\r\n [attr.data-testid]=\"'tab-' + tab.id\"\r\n [class.ngx-form__tab--active]=\"activeTab() === tab.id\"\r\n (click)=\"setActiveTab(tab.id)\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"activeTab() === tab.id\"\r\n >\r\n {{ resolveTabLabel(tab) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Sub-tab bar \u2014 only if active tab has sub-tabs -->\r\n @if (visibleSubTabs.length > 0) {\r\n <div class=\"ngx-form__tabs ngx-form__tabs--sub\" role=\"tablist\" data-testid=\"subtab-strip\" style=\"margin-top: -12px; margin-bottom: 12px; font-size: 13px;\">\r\n @for (subTab of visibleSubTabs; track subTab.id) {\r\n <button\r\n type=\"button\"\r\n class=\"ngx-form__tab ngx-form__tab--sub\"\r\n [attr.data-testid]=\"'subtab-' + subTab.id\"\r\n [class.ngx-form__tab--active]=\"(activeSubTabConfig?.id) === subTab.id\"\r\n (click)=\"setActiveSubTab(subTab.id)\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"(activeSubTabConfig?.id) === subTab.id\"\r\n >\r\n {{ resolveTabLabel(subTab) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Module tab component OR Fields for active tab -->\r\n @if (activeTabModuleComponent) {\r\n <div class=\"ngx-form__module-panel\" data-testid=\"module-panel\">\r\n <ng-container *ngComponentOutlet=\"activeTabModuleComponent; inputs: (activeSubTabConfig || activeTabConfig)?.moduleInputs\"></ng-container>\r\n </div>\r\n } @else {\r\n <!-- Fields for active tab (Responsive 12-column grid) -->\r\n <div class=\"ngx-form__panel\" data-testid=\"form-panel\">\r\n @for (field of fieldsForActiveTab; track field.id) {\r\n <div\r\n class=\"ngx-form__field-slot\"\r\n [style.gridColumn]=\"getFieldSpan(field)\"\r\n [attr.id]=\"'field-container-' + field.id\"\r\n >\r\n <ngx-dynamic-field\r\n [field]=\"field\"\r\n [control]=\"getControl(field.id, (activeSubTabConfig || activeTabConfig)?.id)!\"\r\n [config]=\"config\"\r\n [currentTabId]=\"(activeSubTabConfig || activeTabConfig)?.id\"\r\n [language]=\"language\"\r\n [readonly]=\"isFieldReadonly(field)\"\r\n [userRoles]=\"userRoles\"\r\n />\r\n @if (field.criticalField && !readonly) {\r\n <button\r\n type=\"button\"\r\n class=\"ngx-form__lock\"\r\n [attr.data-testid]=\"'lock-' + field.id\"\r\n [attr.aria-pressed]=\"!isFieldLocked(field)\"\r\n [attr.aria-label]=\"\r\n (isFieldLocked(field) ? 'Unlock ' : 'Lock ') + resolveFieldLabel(field)\r\n \"\r\n [title]=\"\r\n isFieldLocked(field)\r\n ? 'Critical field \u2014 click to unlock for editing'\r\n : 'Critical field \u2014 click to lock'\r\n \"\r\n (click)=\"toggleFieldLock(field)\"\r\n >\r\n {{ isFieldLocked(field) ? '\uD83D\uDD12' : '\uD83D\uDD13' }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Submit button \u2014 gated by RBAC and isSaving lock -->\r\n @if (!readonly && permissions.canEdit) {\r\n <div class=\"ngx-form__actions\" data-testid=\"form-actions\">\r\n <button\r\n type=\"button\"\r\n class=\"ngx-form__reset\"\r\n data-testid=\"form-reset\"\r\n (click)=\"reset()\"\r\n [disabled]=\"isSaving()\"\r\n >\r\n Reset\r\n </button>\r\n <button\r\n type=\"submit\"\r\n class=\"ngx-form__submit\"\r\n data-testid=\"form-submit\"\r\n [disabled]=\"form.invalid\"\r\n title=\"Shortcut: Ctrl+S\"\r\n >\r\n @if (isSaving() || loading) {\r\n Saving\u2026\r\n } @else {\r\n Save\r\n }\r\n </button>\r\n </div>\r\n }\r\n\r\n</form>\r\n", styles: [".ngx-form__panel{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:16px 20px;align-items:start}.ngx-form__field-slot{display:flex;align-items:flex-start;gap:6px;min-width:0}.ngx-form__field-slot ngx-dynamic-field{flex:1;min-width:0}.ngx-form__lock{flex:0 0 auto;margin-top:22px;background:none;border:1px solid transparent;border-radius:6px;cursor:pointer;font-size:14px;line-height:1;padding:4px 6px}.ngx-form__lock:hover{border-color:#d1d5db;background:#f9fafb}@media (max-width: 768px){.ngx-form__panel{grid-template-columns:1fr}.ngx-form__field-slot{grid-column:span 12!important}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DynamicFieldComponent, selector: "ngx-dynamic-field", inputs: ["field", "control", "config", "currentTabId", "language", "readonly", "userRoles"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }] });
839
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: DynamicFormComponent, isStandalone: true, selector: "ngx-dynamic-form", inputs: { config: "config", rules: "rules", initialData: "initialData", originalData: "originalData", userRoles: "userRoles", language: "language", readonly: "readonly", readOnlyFields: "readOnlyFields", showInfoBanners: "showInfoBanners", loading: "loading", error: "error", changeDebounceMs: "changeDebounceMs", preview: "preview" }, outputs: { formSubmit: "formSubmit", formChange: "formChange", formReset: "formReset", activeTabChange: "activeTabChange", saveRejected: "saveRejected" }, host: { listeners: { "window:keydown": "handleKeyboardEvent($event)" } }, providers: [EntityRefSelectionService], viewQueries: [{ propertyName: "formPanel", first: true, predicate: ["formPanel"], descendants: true }, { propertyName: "fieldHosts", predicate: DynamicFieldComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (canView) {\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\" class=\"ngx-form\" novalidate>\n\n <!-- Error message banner -->\n @if (error) {\n <div class=\"ngx-form__error-banner\" role=\"alert\" data-testid=\"form-error\">{{ error }}</div>\n }\n\n <!-- Rules Info Banners -->\n @for (infoKey of showInfoBanners ? Object.keys(ruleResult().infoBanners) : []; track infoKey) {\n <div class=\"ngx-form__info-banner\" role=\"status\" [attr.data-testid]=\"'info-banner-' + infoKey\">\n \u2139\uFE0F {{ ruleResult().infoBanners[infoKey] }}\n </div>\n }\n\n <!-- Rules Validation Errors & Warnings -->\n @for (errKey of Object.keys(ruleResult().validationErrors); track errKey) {\n <div class=\"ngx-form__error-banner\" role=\"alert\" [attr.data-testid]=\"'rule-error-' + errKey\">\n \u26A0\uFE0F {{ ruleResult().validationErrors[errKey] }}\n </div>\n }\n @for (warnKey of Object.keys(ruleResult().validationWarnings); track warnKey) {\n <div class=\"ngx-form__warning-banner\" role=\"status\" [attr.data-testid]=\"'rule-warning-' + warnKey\">\n \u26A1 {{ ruleResult().validationWarnings[warnKey] }}\n </div>\n }\n\n <!-- Deferred VALUE_CHANGED notice for criticalField edits (vs session baseline) -->\n @if (changedCriticalFields().length > 0) {\n <div class=\"ngx-form__warning-banner\" role=\"status\" data-testid=\"critical-change-banner\">\n \uD83D\uDD12 Critical field changed:\n @for (field of changedCriticalFields(); track field.id) {\n <span>{{ resolveFieldLabel(field) }}{{ $last ? '' : ', ' }}</span>\n }\n \u2014 this differs from the value at the start of this session.\n </div>\n }\n\n <!-- Primary Tab bar \u2014 only if visible tabs defined -->\n @if (visibleTabs.length > 0) {\n <div class=\"ngx-form__tabs\" role=\"tablist\" data-testid=\"tab-strip\">\n @for (tab of visibleTabs; track tab.id) {\n <button\n type=\"button\"\n class=\"ngx-form__tab\"\n [attr.data-testid]=\"'tab-' + tab.id\"\n [class.ngx-form__tab--active]=\"activeTab() === tab.id\"\n (click)=\"setActiveTab(tab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === tab.id\"\n >\n {{ resolveTabLabel(tab) }}\n </button>\n }\n </div>\n }\n\n <!-- Sub-tab bar \u2014 only if active tab has sub-tabs -->\n @if (visibleSubTabs.length > 0) {\n <div class=\"ngx-form__tabs ngx-form__tabs--sub\" role=\"tablist\" data-testid=\"subtab-strip\" style=\"margin-top: -12px; margin-bottom: 12px; font-size: 13px;\">\n @for (subTab of visibleSubTabs; track subTab.id) {\n <button\n type=\"button\"\n class=\"ngx-form__tab ngx-form__tab--sub\"\n [attr.data-testid]=\"'subtab-' + subTab.id\"\n [class.ngx-form__tab--active]=\"(activeSubTabConfig?.id) === subTab.id\"\n (click)=\"setActiveSubTab(subTab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"(activeSubTabConfig?.id) === subTab.id\"\n >\n {{ resolveTabLabel(subTab) }}\n </button>\n }\n </div>\n }\n\n <!--\n One tabpanel per tab, wrapping both branches. Focus moves here on a tab switch, and a\n module tab is still a tab \u2014 putting the panel semantics on only the fields branch left\n a module tab with nowhere for focus to land.\n -->\n <div\n role=\"tabpanel\"\n tabindex=\"-1\"\n #formPanel\n class=\"ngx-form__tabpanel\"\n [attr.aria-label]=\"activeTabLabel\"\n >\n @if (activeTabModuleComponent) {\n <div class=\"ngx-form__module-panel\" data-testid=\"module-panel\">\n <ng-container *ngComponentOutlet=\"activeTabModuleComponent; inputs: (activeSubTabConfig || activeTabConfig)?.moduleInputs\"></ng-container>\n </div>\n } @else {\n <!-- Fields for active tab (Responsive 12-column grid) -->\n <div class=\"ngx-form__panel\" data-testid=\"form-panel\">\n @for (field of fieldsForActiveTab; track field.id) {\n <div\n class=\"ngx-form__field-slot\"\n [style.gridColumn]=\"getFieldSpan(field)\"\n [attr.id]=\"'field-container-' + field.id\"\n >\n <ngx-dynamic-field\n [field]=\"field\"\n [control]=\"getControl(field.id, (activeSubTabConfig || activeTabConfig)?.id)!\"\n [config]=\"config\"\n [currentTabId]=\"(activeSubTabConfig || activeTabConfig)?.id\"\n [language]=\"language\"\n [readonly]=\"isFieldReadonly(field)\"\n [userRoles]=\"userRoles\"\n />\n @if (field.hasDrift) {\n <!--\n Drift was previously visible only in the builder, so a referenced field whose\n source had changed looked completely normal to the person filling the form in.\n role=\"status\" rather than \"alert\": it is information, not an error.\n -->\n <span\n class=\"ngx-field__drift\"\n role=\"status\"\n [attr.data-testid]=\"'field-' + field.id + '-drift'\"\n [title]=\"driftHint(field)\"\n >\u26A0 {{ driftHint(field) }}</span>\n }\n @if (field.criticalField && !readonly) {\n <button\n type=\"button\"\n class=\"ngx-form__lock\"\n [attr.data-testid]=\"'lock-' + field.id\"\n [attr.aria-pressed]=\"!isFieldLocked(field)\"\n [attr.aria-label]=\"\n (isFieldLocked(field) ? 'Unlock ' : 'Lock ') + resolveFieldLabel(field)\n \"\n [title]=\"\n isFieldLocked(field)\n ? 'Critical field \u2014 click to unlock for editing'\n : 'Critical field \u2014 click to lock'\n \"\n (click)=\"toggleFieldLock(field)\"\n >\n {{ isFieldLocked(field) ? '\uD83D\uDD12' : '\uD83D\uDD13' }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Submit button \u2014 gated by RBAC and isSaving lock -->\n @if (!readonly && permissions.canEdit) {\n <div class=\"ngx-form__actions\" data-testid=\"form-actions\">\n <button\n type=\"button\"\n class=\"ngx-form__reset\"\n data-testid=\"form-reset\"\n (click)=\"reset()\"\n [disabled]=\"isSaving()\"\n >\n Reset\n </button>\n <button\n type=\"submit\"\n class=\"ngx-form__submit\"\n data-testid=\"form-submit\"\n [disabled]=\"submitBlocked\"\n title=\"Shortcut: Ctrl+S\"\n >\n @if (isSaving() || loading) {\n Saving\u2026\n } @else {\n Save\n }\n </button>\n </div>\n }\n\n </form>\n} @else {\n <!-- permissions.view denied: render nothing of the record.\n Presentational only \u2014 the server must not send data this user may not see. -->\n <div class=\"ngx-form__denied\" role=\"status\" data-testid=\"form-access-denied\">\n You do not have permission to view this record.\n </div>\n}\n", styles: [".ngx-form__panel{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:16px 20px;align-items:start}.ngx-form__field-slot{display:flex;align-items:flex-start;gap:6px;min-width:0}.ngx-form__field-slot ngx-dynamic-field{flex:1;min-width:0}.ngx-form__lock{flex:0 0 auto;margin-top:22px;background:none;border:1px solid transparent;border-radius:6px;cursor:pointer;font-size:14px;line-height:1;padding:4px 6px}.ngx-form__lock:hover{border-color:#d1d5db;background:#f9fafb}@media (max-width: 768px){.ngx-form__panel{grid-template-columns:1fr}.ngx-form__field-slot{grid-column:span 12!important}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DynamicFieldComponent, selector: "ngx-dynamic-field", inputs: ["field", "control", "config", "currentTabId", "language", "readonly", "userRoles"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }] });
559
840
  }
560
841
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DynamicFormComponent, decorators: [{
561
842
  type: Component,
562
- args: [{ selector: 'ngx-dynamic-form', standalone: true, imports: [ReactiveFormsModule, DynamicFieldComponent, NgComponentOutlet], providers: [EntityRefSelectionService], template: "<form [formGroup]=\"form\" (ngSubmit)=\"submit()\" class=\"ngx-form\" novalidate>\r\n\r\n <!-- Error message banner -->\r\n @if (error) {\r\n <div class=\"ngx-form__error-banner\" role=\"alert\" data-testid=\"form-error\">{{ error }}</div>\r\n }\r\n\r\n <!-- Rules Info Banners -->\r\n @for (infoKey of showInfoBanners ? Object.keys(ruleResult().infoBanners) : []; track infoKey) {\r\n <div class=\"ngx-form__info-banner\" role=\"status\" [attr.data-testid]=\"'info-banner-' + infoKey\">\r\n \u2139\uFE0F {{ ruleResult().infoBanners[infoKey] }}\r\n </div>\r\n }\r\n\r\n <!-- Rules Validation Errors & Warnings -->\r\n @for (errKey of Object.keys(ruleResult().validationErrors); track errKey) {\r\n <div class=\"ngx-form__error-banner\" role=\"alert\" [attr.data-testid]=\"'rule-error-' + errKey\">\r\n \u26A0\uFE0F {{ ruleResult().validationErrors[errKey] }}\r\n </div>\r\n }\r\n @for (warnKey of Object.keys(ruleResult().validationWarnings); track warnKey) {\r\n <div class=\"ngx-form__warning-banner\" role=\"status\" [attr.data-testid]=\"'rule-warning-' + warnKey\">\r\n \u26A1 {{ ruleResult().validationWarnings[warnKey] }}\r\n </div>\r\n }\r\n\r\n <!-- Deferred VALUE_CHANGED notice for criticalField edits (vs session baseline) -->\r\n @if (changedCriticalFields().length > 0) {\r\n <div class=\"ngx-form__warning-banner\" role=\"status\" data-testid=\"critical-change-banner\">\r\n \uD83D\uDD12 Critical field changed:\r\n @for (field of changedCriticalFields(); track field.id) {\r\n <span>{{ resolveFieldLabel(field) }}{{ $last ? '' : ', ' }}</span>\r\n }\r\n \u2014 this differs from the value at the start of this session.\r\n </div>\r\n }\r\n\r\n <!-- Primary Tab bar \u2014 only if visible tabs defined -->\r\n @if (visibleTabs.length > 0) {\r\n <div class=\"ngx-form__tabs\" role=\"tablist\" data-testid=\"tab-strip\">\r\n @for (tab of visibleTabs; track tab.id) {\r\n <button\r\n type=\"button\"\r\n class=\"ngx-form__tab\"\r\n [attr.data-testid]=\"'tab-' + tab.id\"\r\n [class.ngx-form__tab--active]=\"activeTab() === tab.id\"\r\n (click)=\"setActiveTab(tab.id)\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"activeTab() === tab.id\"\r\n >\r\n {{ resolveTabLabel(tab) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Sub-tab bar \u2014 only if active tab has sub-tabs -->\r\n @if (visibleSubTabs.length > 0) {\r\n <div class=\"ngx-form__tabs ngx-form__tabs--sub\" role=\"tablist\" data-testid=\"subtab-strip\" style=\"margin-top: -12px; margin-bottom: 12px; font-size: 13px;\">\r\n @for (subTab of visibleSubTabs; track subTab.id) {\r\n <button\r\n type=\"button\"\r\n class=\"ngx-form__tab ngx-form__tab--sub\"\r\n [attr.data-testid]=\"'subtab-' + subTab.id\"\r\n [class.ngx-form__tab--active]=\"(activeSubTabConfig?.id) === subTab.id\"\r\n (click)=\"setActiveSubTab(subTab.id)\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"(activeSubTabConfig?.id) === subTab.id\"\r\n >\r\n {{ resolveTabLabel(subTab) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Module tab component OR Fields for active tab -->\r\n @if (activeTabModuleComponent) {\r\n <div class=\"ngx-form__module-panel\" data-testid=\"module-panel\">\r\n <ng-container *ngComponentOutlet=\"activeTabModuleComponent; inputs: (activeSubTabConfig || activeTabConfig)?.moduleInputs\"></ng-container>\r\n </div>\r\n } @else {\r\n <!-- Fields for active tab (Responsive 12-column grid) -->\r\n <div class=\"ngx-form__panel\" data-testid=\"form-panel\">\r\n @for (field of fieldsForActiveTab; track field.id) {\r\n <div\r\n class=\"ngx-form__field-slot\"\r\n [style.gridColumn]=\"getFieldSpan(field)\"\r\n [attr.id]=\"'field-container-' + field.id\"\r\n >\r\n <ngx-dynamic-field\r\n [field]=\"field\"\r\n [control]=\"getControl(field.id, (activeSubTabConfig || activeTabConfig)?.id)!\"\r\n [config]=\"config\"\r\n [currentTabId]=\"(activeSubTabConfig || activeTabConfig)?.id\"\r\n [language]=\"language\"\r\n [readonly]=\"isFieldReadonly(field)\"\r\n [userRoles]=\"userRoles\"\r\n />\r\n @if (field.criticalField && !readonly) {\r\n <button\r\n type=\"button\"\r\n class=\"ngx-form__lock\"\r\n [attr.data-testid]=\"'lock-' + field.id\"\r\n [attr.aria-pressed]=\"!isFieldLocked(field)\"\r\n [attr.aria-label]=\"\r\n (isFieldLocked(field) ? 'Unlock ' : 'Lock ') + resolveFieldLabel(field)\r\n \"\r\n [title]=\"\r\n isFieldLocked(field)\r\n ? 'Critical field \u2014 click to unlock for editing'\r\n : 'Critical field \u2014 click to lock'\r\n \"\r\n (click)=\"toggleFieldLock(field)\"\r\n >\r\n {{ isFieldLocked(field) ? '\uD83D\uDD12' : '\uD83D\uDD13' }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Submit button \u2014 gated by RBAC and isSaving lock -->\r\n @if (!readonly && permissions.canEdit) {\r\n <div class=\"ngx-form__actions\" data-testid=\"form-actions\">\r\n <button\r\n type=\"button\"\r\n class=\"ngx-form__reset\"\r\n data-testid=\"form-reset\"\r\n (click)=\"reset()\"\r\n [disabled]=\"isSaving()\"\r\n >\r\n Reset\r\n </button>\r\n <button\r\n type=\"submit\"\r\n class=\"ngx-form__submit\"\r\n data-testid=\"form-submit\"\r\n [disabled]=\"form.invalid\"\r\n title=\"Shortcut: Ctrl+S\"\r\n >\r\n @if (isSaving() || loading) {\r\n Saving\u2026\r\n } @else {\r\n Save\r\n }\r\n </button>\r\n </div>\r\n }\r\n\r\n</form>\r\n", styles: [".ngx-form__panel{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:16px 20px;align-items:start}.ngx-form__field-slot{display:flex;align-items:flex-start;gap:6px;min-width:0}.ngx-form__field-slot ngx-dynamic-field{flex:1;min-width:0}.ngx-form__lock{flex:0 0 auto;margin-top:22px;background:none;border:1px solid transparent;border-radius:6px;cursor:pointer;font-size:14px;line-height:1;padding:4px 6px}.ngx-form__lock:hover{border-color:#d1d5db;background:#f9fafb}@media (max-width: 768px){.ngx-form__panel{grid-template-columns:1fr}.ngx-form__field-slot{grid-column:span 12!important}}\n"] }]
843
+ args: [{ selector: 'ngx-dynamic-form', standalone: true, imports: [ReactiveFormsModule, DynamicFieldComponent, NgComponentOutlet], providers: [EntityRefSelectionService], template: "@if (canView) {\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\" class=\"ngx-form\" novalidate>\n\n <!-- Error message banner -->\n @if (error) {\n <div class=\"ngx-form__error-banner\" role=\"alert\" data-testid=\"form-error\">{{ error }}</div>\n }\n\n <!-- Rules Info Banners -->\n @for (infoKey of showInfoBanners ? Object.keys(ruleResult().infoBanners) : []; track infoKey) {\n <div class=\"ngx-form__info-banner\" role=\"status\" [attr.data-testid]=\"'info-banner-' + infoKey\">\n \u2139\uFE0F {{ ruleResult().infoBanners[infoKey] }}\n </div>\n }\n\n <!-- Rules Validation Errors & Warnings -->\n @for (errKey of Object.keys(ruleResult().validationErrors); track errKey) {\n <div class=\"ngx-form__error-banner\" role=\"alert\" [attr.data-testid]=\"'rule-error-' + errKey\">\n \u26A0\uFE0F {{ ruleResult().validationErrors[errKey] }}\n </div>\n }\n @for (warnKey of Object.keys(ruleResult().validationWarnings); track warnKey) {\n <div class=\"ngx-form__warning-banner\" role=\"status\" [attr.data-testid]=\"'rule-warning-' + warnKey\">\n \u26A1 {{ ruleResult().validationWarnings[warnKey] }}\n </div>\n }\n\n <!-- Deferred VALUE_CHANGED notice for criticalField edits (vs session baseline) -->\n @if (changedCriticalFields().length > 0) {\n <div class=\"ngx-form__warning-banner\" role=\"status\" data-testid=\"critical-change-banner\">\n \uD83D\uDD12 Critical field changed:\n @for (field of changedCriticalFields(); track field.id) {\n <span>{{ resolveFieldLabel(field) }}{{ $last ? '' : ', ' }}</span>\n }\n \u2014 this differs from the value at the start of this session.\n </div>\n }\n\n <!-- Primary Tab bar \u2014 only if visible tabs defined -->\n @if (visibleTabs.length > 0) {\n <div class=\"ngx-form__tabs\" role=\"tablist\" data-testid=\"tab-strip\">\n @for (tab of visibleTabs; track tab.id) {\n <button\n type=\"button\"\n class=\"ngx-form__tab\"\n [attr.data-testid]=\"'tab-' + tab.id\"\n [class.ngx-form__tab--active]=\"activeTab() === tab.id\"\n (click)=\"setActiveTab(tab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === tab.id\"\n >\n {{ resolveTabLabel(tab) }}\n </button>\n }\n </div>\n }\n\n <!-- Sub-tab bar \u2014 only if active tab has sub-tabs -->\n @if (visibleSubTabs.length > 0) {\n <div class=\"ngx-form__tabs ngx-form__tabs--sub\" role=\"tablist\" data-testid=\"subtab-strip\" style=\"margin-top: -12px; margin-bottom: 12px; font-size: 13px;\">\n @for (subTab of visibleSubTabs; track subTab.id) {\n <button\n type=\"button\"\n class=\"ngx-form__tab ngx-form__tab--sub\"\n [attr.data-testid]=\"'subtab-' + subTab.id\"\n [class.ngx-form__tab--active]=\"(activeSubTabConfig?.id) === subTab.id\"\n (click)=\"setActiveSubTab(subTab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"(activeSubTabConfig?.id) === subTab.id\"\n >\n {{ resolveTabLabel(subTab) }}\n </button>\n }\n </div>\n }\n\n <!--\n One tabpanel per tab, wrapping both branches. Focus moves here on a tab switch, and a\n module tab is still a tab \u2014 putting the panel semantics on only the fields branch left\n a module tab with nowhere for focus to land.\n -->\n <div\n role=\"tabpanel\"\n tabindex=\"-1\"\n #formPanel\n class=\"ngx-form__tabpanel\"\n [attr.aria-label]=\"activeTabLabel\"\n >\n @if (activeTabModuleComponent) {\n <div class=\"ngx-form__module-panel\" data-testid=\"module-panel\">\n <ng-container *ngComponentOutlet=\"activeTabModuleComponent; inputs: (activeSubTabConfig || activeTabConfig)?.moduleInputs\"></ng-container>\n </div>\n } @else {\n <!-- Fields for active tab (Responsive 12-column grid) -->\n <div class=\"ngx-form__panel\" data-testid=\"form-panel\">\n @for (field of fieldsForActiveTab; track field.id) {\n <div\n class=\"ngx-form__field-slot\"\n [style.gridColumn]=\"getFieldSpan(field)\"\n [attr.id]=\"'field-container-' + field.id\"\n >\n <ngx-dynamic-field\n [field]=\"field\"\n [control]=\"getControl(field.id, (activeSubTabConfig || activeTabConfig)?.id)!\"\n [config]=\"config\"\n [currentTabId]=\"(activeSubTabConfig || activeTabConfig)?.id\"\n [language]=\"language\"\n [readonly]=\"isFieldReadonly(field)\"\n [userRoles]=\"userRoles\"\n />\n @if (field.hasDrift) {\n <!--\n Drift was previously visible only in the builder, so a referenced field whose\n source had changed looked completely normal to the person filling the form in.\n role=\"status\" rather than \"alert\": it is information, not an error.\n -->\n <span\n class=\"ngx-field__drift\"\n role=\"status\"\n [attr.data-testid]=\"'field-' + field.id + '-drift'\"\n [title]=\"driftHint(field)\"\n >\u26A0 {{ driftHint(field) }}</span>\n }\n @if (field.criticalField && !readonly) {\n <button\n type=\"button\"\n class=\"ngx-form__lock\"\n [attr.data-testid]=\"'lock-' + field.id\"\n [attr.aria-pressed]=\"!isFieldLocked(field)\"\n [attr.aria-label]=\"\n (isFieldLocked(field) ? 'Unlock ' : 'Lock ') + resolveFieldLabel(field)\n \"\n [title]=\"\n isFieldLocked(field)\n ? 'Critical field \u2014 click to unlock for editing'\n : 'Critical field \u2014 click to lock'\n \"\n (click)=\"toggleFieldLock(field)\"\n >\n {{ isFieldLocked(field) ? '\uD83D\uDD12' : '\uD83D\uDD13' }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Submit button \u2014 gated by RBAC and isSaving lock -->\n @if (!readonly && permissions.canEdit) {\n <div class=\"ngx-form__actions\" data-testid=\"form-actions\">\n <button\n type=\"button\"\n class=\"ngx-form__reset\"\n data-testid=\"form-reset\"\n (click)=\"reset()\"\n [disabled]=\"isSaving()\"\n >\n Reset\n </button>\n <button\n type=\"submit\"\n class=\"ngx-form__submit\"\n data-testid=\"form-submit\"\n [disabled]=\"submitBlocked\"\n title=\"Shortcut: Ctrl+S\"\n >\n @if (isSaving() || loading) {\n Saving\u2026\n } @else {\n Save\n }\n </button>\n </div>\n }\n\n </form>\n} @else {\n <!-- permissions.view denied: render nothing of the record.\n Presentational only \u2014 the server must not send data this user may not see. -->\n <div class=\"ngx-form__denied\" role=\"status\" data-testid=\"form-access-denied\">\n You do not have permission to view this record.\n </div>\n}\n", styles: [".ngx-form__panel{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:16px 20px;align-items:start}.ngx-form__field-slot{display:flex;align-items:flex-start;gap:6px;min-width:0}.ngx-form__field-slot ngx-dynamic-field{flex:1;min-width:0}.ngx-form__lock{flex:0 0 auto;margin-top:22px;background:none;border:1px solid transparent;border-radius:6px;cursor:pointer;font-size:14px;line-height:1;padding:4px 6px}.ngx-form__lock:hover{border-color:#d1d5db;background:#f9fafb}@media (max-width: 768px){.ngx-form__panel{grid-template-columns:1fr}.ngx-form__field-slot{grid-column:span 12!important}}\n"] }]
563
844
  }], propDecorators: { config: [{
564
845
  type: Input
565
846
  }], rules: [{
@@ -594,8 +875,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
594
875
  type: Output
595
876
  }], activeTabChange: [{
596
877
  type: Output
878
+ }], saveRejected: [{
879
+ type: Output
880
+ }], formPanel: [{
881
+ type: ViewChild,
882
+ args: ['formPanel']
883
+ }], fieldHosts: [{
884
+ type: ViewChildren,
885
+ args: [DynamicFieldComponent]
597
886
  }], handleKeyboardEvent: [{
598
887
  type: HostListener,
599
888
  args: ['window:keydown', ['$event']]
600
889
  }] } });
601
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZm9ybS9keW5hbWljLWZvcm0uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vc3JjL2xpYi9mb3JtL2R5bmFtaWMtZm9ybS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUtaLE1BQU0sRUFDTixRQUFRLEVBQ1IsTUFBTSxFQUNOLFlBQVksR0FDYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQW1CLFNBQVMsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFekcsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBUTlDLE9BQU8sRUFDTCxjQUFjLEVBQ2QsZ0JBQWdCLEVBQ2hCLHVCQUF1QixFQUN2QixPQUFPLEVBQ1AsVUFBVSxFQUNWLFVBQVUsRUFDVixjQUFjLEVBQ2Qsd0JBQXdCLEVBQ3hCLHNCQUFzQixFQUN0QixZQUFZLEVBQ1osVUFBVSxFQUNWLGNBQWMsR0FDZixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3JFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFB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UUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsXHJcbiAgSW5wdXQsXHJcbiAgT3V0cHV0LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBPbkNoYW5nZXMsXHJcbiAgT25EZXN0cm95LFxyXG4gIE9uSW5pdCxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIHNpZ25hbCxcclxuICBjb21wdXRlZCxcclxuICBpbmplY3QsXHJcbiAgSG9zdExpc3RlbmVyLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBOZ0NvbXBvbmVudE91dGxldCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybUFycmF5LCBGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZGVib3VuY2VUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgdHlwZSB7XHJcbiAgQXV0b1BhdGNoQ29uZmlnLFxyXG4gIEVudGl0eUZvcm1Db25maWcsXHJcbiAgRm9ybVJ1bGUsXHJcbiAgTmVzdGVkRmllbGRDb25maWcsXHJcbiAgTmVzdGVkVGFiQ29uZmlnLFxyXG59IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHtcclxuICBhcHBseUF1dG9QYXRjaCxcclxuICBhcHBseVBhdGNoT25UcnVlLFxyXG4gIGV2YWx1YXRlRmllbGRWaXNpYmlsaXR5LFxyXG4gIGZpbmRUYWIsXHJcbiAgZ2V0VGFiRGF0YSxcclxuICBnZXRUYWJQYXRoLFxyXG4gIGdldFZhbHVlQnlQYXRoLFxyXG4gIG5vcm1hbGl6ZUFycmF5U3RydWN0dXJlcyxcclxuICBub3JtYWxpemVDb25maWdPcHRpb25zLFxyXG4gIHJlc29sdmVMYWJlbCxcclxuICBzZXRUYWJEYXRhLFxyXG4gIHNldFZhbHVlQnlQYXRoLFxyXG59IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHsgRHluYW1pY0ZpZWxkQ29tcG9uZW50IH0gZnJvbSAnLi9keW5hbWljLWZpZWxkL2R5bmFtaWMtZmllbGQuY29tcG9uZW50JztcclxuaW1wb3J0IHsgQ09NTU9OX01PRFVMRVNfUkVHSVNUUlkgfSBmcm9tICcuLi90b2tlbnMvaW5qZWN0aW9uLXRva2Vucyc7XHJcbmltcG9ydCB7IFZhbGlkYXRvclJlZ2lzdHJ5U2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL3ZhbGlkYXRvci1yZWdpc3RyeS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgSG9va1JlZ2lzdHJ5U2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2hvb2stcmVnaXN0cnkuc2VydmljZSc7XHJcbmltcG9ydCB7IFJiYWNTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvcmJhYy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgUnVsZXNFdmFsdWF0aW9uU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL3J1bGVzLWV2YWx1YXRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IEVudGl0eVJlZlNlbGVjdGlvblNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9lbnRpdHktcmVmLXNlbGVjdGlvbi5zZXJ2aWNlJztcclxuXHJcbi8qKlxyXG4gKiBEeW5hbWljRm9ybUNvbXBvbmVudCDigJQgdGhlIG1haW4gZm9ybSBjb21wb25lbnQuXHJcbiAqIFJlbmRlcnMgYSByZWFjdGl2ZSBmb3JtIGZyb20gRW50aXR5Rm9ybUNvbmZpZyB3aXRoIHRhYiBzdXBwb3J0LCByZXNwb25zaXZlIDEyLWNvbCBncmlkLFxyXG4gKiBydWxlcyBldmFsdWF0aW9uLCBjb25kaXRpb25hbCB2aXNpYmlsaXR5LCBhdXRvUGF0Y2gvcGF0Y2hPblRydWUsIGNyaXRpY2FsRmllbGQgbG9ja2luZyxcclxuICoga2V5Ym9hcmQgc2hvcnRjdXRzIChDdHJsK1MsIEVzYyksIGFuZCBSQkFDLWdhdGVkIHN1Ym1pc3Npb24uXHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ25neC1keW5hbWljLWZvcm0nLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW1JlYWN0aXZlRm9ybXNNb2R1bGUsIER5bmFtaWNGaWVsZENvbXBvbmVudCwgTmdDb21wb25lbnRPdXRsZXRdLFxyXG4gIC8vIFNjb3BlZCBwZXIgZm9ybSBpbnN0YW5jZTogZW50aXR5LXJlZiBzZWxlY3Rpb25zIG11c3Qgbm90IGxlYWsgYmV0d2VlbiBjb25jdXJyZW50IGZvcm1zLlxyXG4gIHByb3ZpZGVyczogW0VudGl0eVJlZlNlbGVjdGlvblNlcnZpY2VdLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9keW5hbWljLWZvcm0uY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlczogW1xyXG4gICAgYFxyXG4gICAgICAubmd4LWZvcm1fX3BhbmVsIHtcclxuICAgICAgICBkaXNwbGF5OiBncmlkO1xyXG4gICAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogcmVwZWF0KDEyLCBtaW5tYXgoMCwgMWZyKSk7XHJcbiAgICAgICAgZ2FwOiAxNnB4IDIwcHg7XHJcbiAgICAgICAgYWxpZ24taXRlbXM6IHN0YXJ0O1xyXG4gICAgICB9XHJcbiAgICAgIC5uZ3gtZm9ybV9fZmllbGQtc2xvdCB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICAgICAgICBnYXA6IDZweDtcclxuICAgICAgICBtaW4td2lkdGg6IDA7XHJcbiAgICAgIH1cclxuICAgICAgLm5neC1mb3JtX19maWVsZC1zbG90IG5neC1keW5hbWljLWZpZWxkIHtcclxuICAgICAgICBmbGV4OiAxO1xyXG4gICAgICAgIG1pbi13aWR0aDogMDtcclxuICAgICAgfVxyXG4gICAgICAubmd4LWZvcm1fX2xvY2sge1xyXG4gICAgICAgIGZsZXg6IDAgMCBhdXRvO1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDIycHg7XHJcbiAgICAgICAgYmFja2dyb3VuZDogbm9uZTtcclxuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCB0cmFuc3BhcmVudDtcclxuICAgICAgICBib3JkZXItcmFkaXVzOiA2cHg7XHJcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICAgIGZvbnQtc2l6ZTogMTRweDtcclxuICAgICAgICBsaW5lLWhlaWdodDogMTtcclxuICAgICAgICBwYWRkaW5nOiA0cHggNnB4O1xyXG4gICAgICB9XHJcbiAgICAgIC5uZ3gtZm9ybV9fbG9jazpob3ZlciB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjZDFkNWRiO1xyXG4gICAgICAgIGJhY2tncm91bmQ6ICNmOWZhZmI7XHJcbiAgICAgIH1cclxuICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDc2OHB4KSB7XHJcbiAgICAgICAgLm5neC1mb3JtX19wYW5lbCB7XHJcbiAgICAgICAgICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDFmcjtcclxuICAgICAgICB9XHJcbiAgICAgICAgLm5neC1mb3JtX19maWVsZC1zbG90IHtcclxuICAgICAgICAgIGdyaWQtY29sdW1uOiBzcGFuIDEyICFpbXBvcnRhbnQ7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICBgLFxyXG4gIF0sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBEeW5hbWljRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xyXG4gIC8vIOKUgOKUgOKUgCBJbnB1dHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcbiAgQElucHV0KCkgY29uZmlnITogRW50aXR5Rm9ybUNvbmZpZztcclxuICBASW5wdXQoKSBydWxlcz86IEZvcm1SdWxlW107XHJcbiAgQElucHV0KCkgaW5pdGlhbERhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xyXG4gIC8qKiBTZXNzaW9uLW9yaWdpbmFsIHZhbHVlcyBmb3IgYFZBTFVFX0NIQU5HRURgIHJ1bGVzLiBDYXB0dXJlZCBmcm9tIHRoZSBmaXJzdCBidWlsZCB3aGVuIG9taXR0ZWQuICovXHJcbiAgQElucHV0KCkgb3JpZ2luYWxEYXRhPzogUmVjb3JkPHN0cmluZywgYW55PjtcclxuICBASW5wdXQoKSB1c2VyUm9sZXM6IHN0cmluZ1tdID0gW107XHJcbiAgQElucHV0KCkgbGFuZ3VhZ2U6IHN0cmluZyA9ICdlbic7XHJcbiAgQElucHV0KCkgcmVhZG9ubHk6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAvKiogRmllbGQgaWRzIGZvcmNlZCByZWFkLW9ubHkgd2hpbGUgdGhlIHJlc3Qgb2YgdGhlIGZvcm0gc3RheXMgZWRpdGFibGUuICovXHJcbiAgQElucHV0KCkgcmVhZE9ubHlGaWVsZHM6IHN0cmluZ1tdID0gW107XHJcbiAgLyoqXHJcbiAgICogUmVuZGVyIHJ1bGUgYGluZm9gIGJhbm5lcnMgaW5saW5lLiBUaGUgcmVjb3JkIGVkaXRvciBzZXRzIHRoaXMgZmFsc2UgYW5kIHJlbmRlcnMgaXRzXHJcbiAgICogb3duIGRpc21pc3NpYmxlIHZlcnNpb25zLCBzbyB0aGUgdHdvIGRvIG5vdCBkb3VibGUgdXAuXHJcbiAgICovXHJcbiAgQElucHV0KCkgc2hvd0luZm9CYW5uZXJzOiBib29sZWFuID0gdHJ1ZTtcclxuICBASW5wdXQoKSBsb2FkaW5nOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgZXJyb3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gIC8qKlxyXG4gICAqIE1pbGxpc2Vjb25kcyB0byBkZWJvdW5jZSBgZm9ybUNoYW5nZWAuIFRoZSByZWZlcmVuY2UgZGVib3VuY2VzIGF0IDMwMG1zIHNvIGEgY29uc3VtZXJcclxuICAgKiByZS1yZW5kZXJpbmcgb24gZXZlcnkgdmFsdWUgY2hhbmdlIGlzIG5vdCBkcml2ZW4gcGVyIGtleXN0cm9rZS4gWmVybyBlbWl0c1xyXG4gICAqIHN5bmNocm9ub3VzbHksIHdoaWNoIHRoZSByZWNvcmQgZWRpdG9yIHJlbGllcyBvbiBmb3IgaXRzIG93biBib29ra2VlcGluZy5cclxuICAgKi9cclxuICBASW5wdXQoKSBjaGFuZ2VEZWJvdW5jZU1zOiBudW1iZXIgPSAwO1xyXG4gIC8qKlxyXG4gICAqIFByZXZpZXcgbW9kZTogc2VlZCBvbmUgZW1wdHkgcm93IHBlciBgYXJyYXlgIGZpZWxkIHNvIHRoZSBzdHJ1Y3R1cmUgaXMgdmlzaWJsZSwgdGhlblxyXG4gICAqIGRpc2FibGUgdGhlIGZvcm0uIFVzZWQgYnkgdGhlIGJ1aWxkZXIncyBsaXZlIHByZXZpZXcuXHJcbiAgICovXHJcbiAgQElucHV0KCkgcHJldmlldzogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvLyDilIDilIDilIAgT3V0cHV0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuICBAT3V0cHV0KCkgZm9ybVN1Ym1pdCA9IG5ldyBFdmVudEVtaXR0ZXI8UmVjb3JkPHN0cmluZywgYW55Pj4oKTtcclxuICBAT3V0cHV0KCkgZm9ybUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8UmVjb3JkPHN0cmluZywgYW55Pj4oKTtcclxuICBAT3V0cHV0KCkgZm9ybVJlc2V0ID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG4gIC8qKiBUaGUgdmlzaWJsZSB0YWIgY2hhbmdlZC4gTGV0cyBhIGhvc3QgdHJhY2sgaXQgd2l0aG91dCByZWFjaGluZyBpbnRvIHRoaXMgY29tcG9uZW50LiAqL1xyXG4gIEBPdXRwdXQoKSBhY3RpdmVUYWJDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuXHJcbiAgLy8g4pSA4pSA4pSAIFNlcnZpY2VzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG4gIHByaXZhdGUgcmVhZG9ubHkgZmIgPSBpbmplY3QoRm9ybUJ1aWxkZXIpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgdmFsaWRhdG9yUmVnaXN0cnkgPSBpbmplY3QoVmFsaWRhdG9yUmVnaXN0cnlTZXJ2aWNlKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IGhvb2tSZWdpc3RyeSA9IGluamVjdChIb29rUmVnaXN0cnlTZXJ2aWNlKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IHJiYWNTZXJ2aWNlID0gaW5qZWN0KFJiYWNTZXJ2aWNlKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IHJ1bGVzRXZhbHVhdGlvbiA9IGluamVjdChSdWxlc0V2YWx1YXRpb25TZXJ2aWNlKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IGVudGl0eVJlZlNlbGVjdGlvbiA9IGluamVjdChFbnRpdHlSZWZTZWxlY3Rpb25TZXJ2aWNlKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IGNvbW1vbk1vZHVsZXNSZWdpc3RyeSA9IGluamVjdChDT01NT05fTU9EVUxFU19SRUdJU1RSWSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcclxuXHJcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IE9iamVjdCA9IE9iamVjdDtcclxuXHJcbiAgLy8g4pSA4pSA4pSAIFNpZ25hbHMgKGxvY2FsIHJlYWN0aXZlIHN0YXRlKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuICByZWFkb25seSBhY3RpdmVUYWIgPSBzaWduYWw8c3RyaW5nPignJyk7XHJcbiAgcmVhZG9ubHkgYWN0aXZlU3ViVGFiID0gc2lnbmFsPHN0cmluZz4oJycpO1xyXG4gIHJlYWRvbmx5IGlzU2F2aW5nID0gc2lnbmFsKGZhbHNlKTtcclxuICByZWFkb25seSBmb3JtVmFsdWVzID0gc2lnbmFsPFJlY29yZDxzdHJpbmcsIGFueT4+KHt9KTtcclxuICAvKiogQmFzZWxpbmUgY2FwdHVyZWQgYXQgZmlyc3QgYnVpbGQsIHVzZWQgd2hlbiBgb3JpZ2luYWxEYXRhYCBpcyBub3Qgc3VwcGxpZWQuICovXHJcbiAgcmVhZG9ubHkgc2Vzc2lvbkJhc2VsaW5lID0gc2lnbmFsPFJlY29yZDxzdHJpbmcsIGFueT4+KHt9KTtcclxuICAvKiogQ3JpdGljYWwgZmllbGRzIHRoZSB1c2VyIGhhcyBleHBsaWNpdGx5IHVubG9ja2VkIGZvciBlZGl0aW5nLiAqL1xyXG4gIHJlYWRvbmx5IHVubG9ja2VkRmllbGRzID0gc2lnbmFsPFJlYWRvbmx5U2V0PHN0cmluZz4+KG5ldyBTZXQ8c3RyaW5nPigpKTtcclxuXHJcbiAgLy8g4pSA4pSA4pSAIEZvcm0g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcbiAgZm9ybSE6IEZvcm1Hcm91cDtcclxuXHJcbiAgcHJpdmF0ZSB2YWx1ZVN1Yj86IFN1YnNjcmlwdGlvbjtcclxuICBwcml2YXRlIHNlbGVjdGlvblN1Yj86IFN1YnNjcmlwdGlvbjtcclxuICAvKiogUHJldmlvdXMgdmFsdWVzLCBmb3IgZGV0ZWN0aW5nIGBwYXRjaE9uVHJ1ZWAgZmFsc2XihpJ0cnVlIHRyYW5zaXRpb25zLiAqL1xyXG4gIHByaXZhdGUgcHJldmlvdXNWYWx1ZXM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcclxuXHJcbiAgLy8g4pSA4pSA4pSAIEtleWJvYXJkIFNob3J0Y3V0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bicsIFsnJGV2ZW50J10pXHJcbiAgaGFuZGxlS2V5Ym9hcmRFdmVudChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xyXG4gICAgaWYgKChldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXkpICYmIGV2ZW50LmtleS50b0xvd2VyQ2FzZSgpID09PSAncycpIHtcclxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgaWYgKCF0aGlzLnJlYWRvbmx5ICYmIHRoaXMuY2FuU3VibWl0ICYmIHRoaXMuZm9ybT8udmFsaWQpIHtcclxuICAgICAgICB0aGlzLnN1Ym1pdCgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgQ29tcHV0ZWQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcbiAgcmVhZG9ubHkgcnVsZVJlc3VsdCA9IGNvbXB1dGVkKCgpID0+XHJcbiAgICB0aGlzLnJ1bGVzRXZhbHVhdGlvbi5ldmFsdWF0ZSh0aGlzLnJ1bGVzLCB0aGlzLmZvcm1WYWx1ZXMoKSwgdGhpcy5iYXNlbGluZSgpKSxcclxuICApO1xyXG5cclxuICAvKipcclxuICAgKiBDcml0aWNhbCBmaWVsZHMgd2hvc2UgdmFsdWUgZGlmZmVycyBmcm9tIHRoZSBzZXNzaW9uIGJhc2VsaW5lLlxyXG4gICAqIFRoZXNlIGRyaXZlIHRoZSBkZWZlcnJlZCBgVkFMVUVfQ0hBTkdFRGAgYmFubmVyIOKAlCBhIGNyaXRpY2FsIGVkaXQgaXMgYW5ub3VuY2VkIG9uY2UsXHJcbiAgICogYWdhaW5zdCB0aGUgdmFsdWUgdGhlIHJlY29yZCBoYWQgd2hlbiB0aGUgc2Vzc2lvbiBzdGFydGVkLCBub3QgcGVyIGtleXN0cm9rZS5cclxuICAgKi9cclxuICByZWFkb25seSBjaGFuZ2VkQ3JpdGljYWxGaWVsZHMgPSBjb21wdXRlZDxOZXN0ZWRGaWVsZENvbmZpZ1tdPigoKSA9PiB7XHJcbiAgICBjb25zdCBiYXNlbGluZSA9IHRoaXMuYmFzZWxpbmUoKTtcclxuICAgIGlmICghYmFzZWxpbmUgfHwgT2JqZWN0LmtleXMoYmFzZWxpbmUpLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdO1xyXG4gICAgY29uc3QgdmFsdWVzID0gdGhpcy5mb3JtVmFsdWVzKCk7XHJcbiAgICByZXR1cm4gdGhpcy5hbGxGaWVsZHMoKS5maWx0ZXIoXHJcbiAgICAgIGYgPT4gZi5jcml0aWNhbEZpZWxkICYmICF0aGlzLnNhbWVWYWx1ZSh2YWx1ZXNbZi5pZF0sIGJhc2VsaW5lW2YuaWRdKSxcclxuICAgICk7XHJcbiAgfSk7XHJcblxyXG4gIGdldCB0YWJzKCk6IE5lc3RlZFRhYkNvbmZpZ1tdIHtcclxuICAgIHJldHVybiB0aGlzLmNvbmZpZz8udGFicyB8fCBbXTtcclxuICB9XHJcblxyXG4gIGdldCB2aXNpYmxlVGFicygpOiBOZXN0ZWRUYWJDb25maWdbXSB7XHJcbiAgICBjb25zdCBoaWRkZW4gPSB0aGlzLnJ1bGVSZXN1bHQoKS5oaWRkZW5UYWJzO1xyXG4gICAgcmV0dXJuIHRoaXMudGFicy5maWx0ZXIodGFiID0+IHRhYi52aXNpYmlsaXR5ICE9PSBmYWxzZSAmJiAhaGlkZGVuLmluY2x1ZGVzKHRhYi5pZCkpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGFjdGl2ZVRhYkNvbmZpZygpOiBOZXN0ZWRUYWJDb25maWcgfCBudWxsIHtcclxuICAgIGNvbnN0IHRhYklkID0gdGhpcy5hY3RpdmVUYWIoKTtcclxuICAgIGlmICghdGFiSWQpIHJldHVybiB0aGlzLnZpc2libGVUYWJzWzBdID8/IG51bGw7XHJcbiAgICByZXR1cm4gZmluZFRhYih0aGlzLnRhYnMsIHRhYklkKTtcclxuICB9XHJcblxyXG4gIGdldCB2aXNpYmxlU3ViVGFicygpOiBOZXN0ZWRUYWJDb25maWdbXSB7XHJcbiAgICBjb25zdCBhY3RpdmUgPSB0aGlzLmFjdGl2ZVRhYkNvbmZpZztcclxuICAgIGlmICghYWN0aXZlPy5jaGlsZHJlbiB8fCBhY3RpdmUuY2hpbGRyZW4ubGVuZ3RoID09PSAwKSByZXR1cm4gW107XHJcbiAgICBjb25zdCBoaWRkZW4gPSB0aGlzLnJ1bGVSZXN1bHQoKS5oaWRkZW5UYWJzO1xyXG4gICAgcmV0dXJuIGFjdGl2ZS5jaGlsZHJlbi5maWx0ZXIodGFiID0+IHRhYi52aXNpYmlsaXR5ICE9PSBmYWxzZSAmJiAhaGlkZGVuLmluY2x1ZGVzKHRhYi5pZCkpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGFjdGl2ZVN1YlRhYkNvbmZpZygpOiBOZXN0ZWRUYWJDb25maWcgfCBudWxsIHtcclxuICAgIGNvbnN0IHN1YlRhYnMgPSB0aGlzLnZpc2libGVTdWJUYWJzO1xyXG4gICAgaWYgKCFzdWJUYWJzLmxlbmd0aCkgcmV0dXJuIG51bGw7XHJcbiAgICBjb25zdCBzdWJJZCA9IHRoaXMuYWN0aXZlU3ViVGFiKCk7XHJcbiAgICByZXR1cm4gc3ViVGFicy5maW5kKHMgPT4gcy5pZCA9PT0gc3ViSWQpID8/IHN1YlRhYnNbMF07XHJcbiAgfVxyXG5cclxuICBnZXQgYWN0aXZlVGFiTW9kdWxlQ29tcG9uZW50KCk6IGFueSB8IG51bGwge1xyXG4gICAgY29uc3QgYWN0aXZlID0gdGhpcy5hY3RpdmVTdWJUYWJDb25maWcgPz8gdGhpcy5hY3RpdmVUYWJDb25maWc7XHJcbiAgICBpZiAoIWFjdGl2ZT8ubW9kdWxlTmFtZSB8fCAhdGhpcy5jb21tb25Nb2R1bGVzUmVnaXN0cnkpIHJldHVybiBudWxsO1xyXG4gICAgY29uc3QgZW50cnkgPSB0aGlzLmNvbW1vbk1vZHVsZXNSZWdpc3RyeS5maW5kKFxyXG4gICAgICBtID0+IG0uaWQgPT09IGFjdGl2ZS5tb2R1bGVOYW1lIHx8IG0uY29tcG9uZW50ID09PSBhY3RpdmUubW9kdWxlTmFtZSxcclxuICAgICk7XHJcbiAgICByZXR1cm4gZW50cnkgPyBlbnRyeS5jb21wb25lbnQgOiBudWxsO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGZpZWxkc0ZvckFjdGl2ZVRhYigpOiBOZXN0ZWRGaWVsZENvbmZpZ1tdIHtcclxuICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuYWN0aXZlU3ViVGFiQ29uZmlnID8/IHRoaXMuYWN0aXZlVGFiQ29uZmlnO1xyXG4gICAgaWYgKGFjdGl2ZT8ubW9kdWxlTmFtZSkgcmV0dXJuIFtdO1xyXG4gICAgY29uc3QgcmF3RmllbGRzID0gYWN0aXZlID8gKGFjdGl2ZS5maWVsZHMgfHwgW10pIDogKCh0aGlzLmNvbmZpZz8udGFicyB8fCBbXSkuZmxhdE1hcCh0ID0+IHQuZmllbGRzIHx8IFtdKSk7XHJcbiAgICBjb25zdCBjdXJyZW50VmFsdWVzID0gdGhpcy5mb3JtVmFsdWVzKCk7XHJcbiAgICBjb25zdCBoaWRkZW5GaWVsZHMgPSB0aGlzLnJ1bGVSZXN1bHQoKS5oaWRkZW5GaWVsZHM7XHJcblxyXG4gICAgcmV0dXJuIHJhd0ZpZWxkcy5maWx0ZXIoXHJcbiAgICAgIGZpZWxkID0+IGV2YWx1YXRlRmllbGRWaXNpYmlsaXR5KGZpZWxkLCBjdXJyZW50VmFsdWVzKSAmJiAhaGlkZGVuRmllbGRzLmluY2x1ZGVzKGZpZWxkLmlkKSxcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBnZXQgcGVybWlzc2lvbnMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5yYmFjU2VydmljZS5nZXRQZXJtaXNzaW9ucyh0aGlzLmNvbmZpZywgdGhpcy51c2VyUm9sZXMpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGNhblN1Ym1pdCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLnBlcm1pc3Npb25zLmNhbkVkaXQgJiYgIXRoaXMucmVhZG9ubHk7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuc2VsZWN0aW9uU3ViID0gdGhpcy5lbnRpdHlSZWZTZWxlY3Rpb24uc2VsZWN0aW9uJC5zdWJzY3JpYmUoKHsgZmllbGRJZCwgb3B0aW9uIH0pID0+IHtcclxuICAgICAgdGhpcy5ydW5BdXRvUGF0Y2goZmllbGRJZCwgb3B0aW9uPy5yZWNvcmQpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgICBpZiAoY2hhbmdlc1snY29uZmlnJ10gJiYgdGhpcy5jb25maWcpIHtcclxuICAgICAgLy8gQ29uZmlncyBhcnJpdmUgYXMgcGxhaW4gSlNPTiBmcm9tIHN0b3JhZ2Ugb3IgYW4gQVBJLCB3aGVyZSBUeXBlU2NyaXB0IGNhbm5vdCBlbmZvcmNlXHJcbiAgICAgIC8vIHRoZSBvcHRpb24gc2hhcGUuIE5vcm1hbGlzZSBoZXJlLCBhdCB0aGUgbGlicmFyeSBib3VuZGFyeSwgc28gZXZlcnl0aGluZyBkb3duc3RyZWFtXHJcbiAgICAgIC8vIGNhbiByZWx5IG9uIGFuIG9wdGlvbiBiZWluZyBhIExvY2FsaXplZFRleHQuIFJldHVybnMgdGhlIHNhbWUgb2JqZWN0IHdoZW4gaXQgYWxyZWFkeVxyXG4gICAgICAvLyBpcywgc28gYSB3ZWxsLWZvcm1lZCBjb25maWcgY29zdHMgbm90aGluZy5cclxuICAgICAgdGhpcy5jb25maWcgPSBub3JtYWxpemVDb25maWdPcHRpb25zKHRoaXMuY29uZmlnKTtcclxuICAgIH1cclxuICAgIGlmIChjaGFuZ2VzWydjb25maWcnXSB8fCBjaGFuZ2VzWydpbml0aWFsRGF0YSddKSB7XHJcbiAgICAgIHRoaXMuYnVpbGRGb3JtKCk7XHJcbiAgICAgIGlmICh0aGlzLnZpc2libGVUYWJzLmxlbmd0aCA+IDAgJiYgIXRoaXMuYWN0aXZlVGFiKCkpIHtcclxuICAgICAgICB0aGlzLnNldEFjdGl2ZVRhYih0aGlzLnZpc2libGVUYWJzWzBdLmlkKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLnZhbHVlU3ViPy51bnN1YnNjcmliZSgpO1xyXG4gICAgdGhpcy5zZWxlY3Rpb25TdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgfVxyXG5cclxuICBzZXRBY3RpdmVUYWIodGFiSWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuYWN0aXZlVGFiKCkgIT09IHRhYklkKSB0aGlzLmFjdGl2ZVRhYkNoYW5nZS5lbWl0KHRhYklkKTtcclxuICAgIHRoaXMuYWN0aXZlVGFiLnNldCh0YWJJZCk7XHJcbiAgICBjb25zdCBwYXJlbnQgPSBmaW5kVGFiKHRoaXMudGFicywgdGFiSWQpO1xyXG4gICAgaWYgKHBhcmVudD8uY2hpbGRyZW4/Lmxlbmd0aCkge1xyXG4gICAgICB0aGlzLmFjdGl2ZVN1YlRhYi5zZXQocGFyZW50LmNoaWxkcmVuWzBdLmlkKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuYWN0aXZlU3ViVGFiLnNldCgnJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzZXRBY3RpdmVTdWJUYWIoc3ViVGFiSWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5hY3RpdmVTdWJUYWIuc2V0KHN1YlRhYklkKTtcclxuICB9XHJcblxyXG4gIGdldEZpZWxkU3BhbihmaWVsZDogTmVzdGVkRmllbGRDb25maWcpOiBzdHJpbmcge1xyXG4gICAgY29uc3Qgc3BhbiA9IGZpZWxkLmNvbFNwYW4gPz8gMTI7XHJcbiAgICByZXR1cm4gYHNwYW4gJHtNYXRoLm1pbigxMiwgTWF0aC5tYXgoMSwgc3BhbikpfWA7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgY3JpdGljYWxGaWVsZCBsb2NraW5nIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICAvKiogQSBjcml0aWNhbCBmaWVsZCBzdGF5cyByZWFkLW9ubHkgdW50aWwgdGhlIHVzZXIgZGVsaWJlcmF0ZWx5IHVubG9ja3MgaXQuICovXHJcbiAgaXNGaWVsZExvY2tlZChmaWVsZDogTmVzdGVkRmllbGRDb25maWcpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAhIWZpZWxkLmNyaXRpY2FsRmllbGQgJiYgIXRoaXMudW5sb2NrZWRGaWVsZHMoKS5oYXMoZmllbGQuaWQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogV2hldGhlciB0aGlzIGZpZWxkIHJlbmRlcnMgcmVhZC1vbmx5LCBmcm9tIGFueSBvZiB0aGUgZm91ciByZWFzb25zOiB0aGUgd2hvbGUgZm9ybSxcclxuICAgKiB0aGUgZmllbGQncyBvd24gZmxhZywgYSBjYWxsZXItc3VwcGxpZWQgYHJlYWRPbmx5RmllbGRzYCBlbnRyeSwgb3IgYSBjcml0aWNhbEZpZWxkIGxvY2suXHJcbiAgICovXHJcbiAgaXNGaWVsZFJlYWRvbmx5KGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgdGhpcy5yZWFkb25seSB8fFxyXG4gICAgICAhIWZpZWxkLnJlYWRvbmx5IHx8XHJcbiAgICAgIHRoaXMucmVhZE9ubHlGaWVsZHMuaW5jbHVkZXMoZmllbGQuaWQpIHx8XHJcbiAgICAgIHRoaXMuaXNGaWVsZExvY2tlZChmaWVsZClcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICB0b2dnbGVGaWVsZExvY2soZmllbGQ6IE5lc3RlZEZpZWxkQ29uZmlnKTogdm9pZCB7XHJcbiAgICBpZiAoIWZpZWxkLmNyaXRpY2FsRmllbGQgfHwgdGhpcy5yZWFkb25seSkgcmV0dXJuO1xyXG4gICAgY29uc3QgbmV4dCA9IG5ldyBTZXQodGhpcy51bmxvY2tlZEZpZWxkcygpKTtcclxuICAgIGlmIChuZXh0LmhhcyhmaWVsZC5pZCkpIG5leHQuZGVsZXRlKGZpZWxkLmlkKTtcclxuICAgIGVsc2UgbmV4dC5hZGQoZmllbGQuaWQpO1xyXG4gICAgdGhpcy51bmxvY2tlZEZpZWxkcy5zZXQobmV4dCk7XHJcbiAgfVxyXG5cclxuICByZXNvbHZlRmllbGRMYWJlbChmaWVsZDogTmVzdGVkRmllbGRDb25maWcpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHJlc29sdmVMYWJlbChmaWVsZC5sYWJlbCwgdGhpcy5sYW5ndWFnZSk7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgRm9ybSBjb25zdHJ1Y3Rpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIHByaXZhdGUgYnVpbGRGb3JtKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmNvbmZpZykgcmV0dXJuO1xyXG4gICAgY29uc3QgZ3JvdXA6IFJlY29yZDxzdHJpbmcsIEFic3RyYWN0Q29udHJvbD4gPSB7fTtcclxuXHJcbiAgICBjb25zdCBidWlsZFRhYkNvbnRyb2xzID0gKHRhYnM6IE5lc3RlZFRhYkNvbmZpZ1tdLCBwYXJlbnRHcm91cDogUmVjb3JkPHN0cmluZywgQWJzdHJhY3RDb250cm9sPikgPT4ge1xyXG4gICAgICBmb3IgKGNvbnN0IHRhYiBvZiB0YWJzKSB7XHJcbiAgICAgICAgaWYgKHRhYi5mbGF0RGF0YSkge1xyXG4gICAgICAgICAgZm9yIChjb25zdCBmaWVsZCBvZiB0YWIuZmllbGRzIHx8IFtdKSB7XHJcbiAgICAgICAgICAgIHRoaXMuYnVpbGRGaWVsZENvbnRyb2woZmllbGQsIHBhcmVudEdyb3VwKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmICh0YWIuY2hpbGRyZW4pIGJ1aWxkVGFiQ29udHJvbHModGFiLmNoaWxkcmVuLCBwYXJlbnRHcm91cCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnN0IHRhYkdyb3VwOiBSZWNvcmQ8c3RyaW5nLCBBYnN0cmFjdENvbnRyb2w+ID0ge307XHJcbiAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRhYi5maWVsZHMgfHwgW10pIHtcclxuICAgICAgICAgICAgdGhpcy5idWlsZEZpZWxkQ29udHJvbChmaWVsZCwgdGFiR3JvdXApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKHRhYi5jaGlsZHJlbikgYnVpbGRUYWJDb250cm9scyh0YWIuY2hpbGRyZW4sIHRhYkdyb3VwKTtcclxuICAgICAgICAgIHBhcmVudEdyb3VwW3RhYi5pZF0gPSB0aGlzLmZiLmdyb3VwKHRhYkdyb3VwKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgYnVpbGRUYWJDb250cm9scyh0aGlzLmNvbmZpZy50YWJzIHx8IFtdLCBncm91cCk7XHJcbiAgICB0aGlzLmZvcm0gPSB0aGlzLmZiLmdyb3VwKGdyb3VwKTtcclxuXHJcbiAgICBpZiAodGhpcy5pbml0aWFsRGF0YSkge1xyXG4gICAgICB0aGlzLnBhdGNoRm9ybSh0aGlzLmluaXRpYWxEYXRhKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBpbml0aWFsRmxhdHRlbmVkID0gdGhpcy5mbGF0dGVuRm9ybVZhbHVlcygpO1xyXG4gICAgdGhpcy5mb3JtVmFsdWVzLnNldChpbml0aWFsRmxhdHRlbmVkKTtcclxuICAgIHRoaXMucHJldmlvdXNWYWx1ZXMgPSB7IC4uLmluaXRpYWxGbGF0dGVuZWQgfTtcclxuICAgIHRoaXMuc2Vzc2lvbkJhc2VsaW5lLnNldCh7IC4uLmluaXRpYWxGbGF0dGVuZWQgfSk7XHJcbiAgICB0aGlzLnVubG9ja2VkRmllbGRzLnNldChuZXcgU2V0PHN0cmluZz4oKSk7XHJcblxyXG4gICAgaWYgKHRoaXMucHJldmlldykge1xyXG4gICAgICAvLyBTaG93IHdoYXQgYW4gYXJyYXkgZmllbGQgbG9va3MgbGlrZSByYXRoZXIgdGhhbiBhbiBlbXB0eSBzbG90LCB0aGVuIGZyZWV6ZS5cclxuICAgICAgZm9yIChjb25zdCBmaWVsZCBvZiB0aGlzLmFsbEZpZWxkcygpKSB7XHJcbiAgICAgICAgaWYgKGZpZWxkLnR5cGUgIT09ICdhcnJheScpIGNvbnRpbnVlO1xyXG4gICAgICAgIGNvbnN0IGFycmF5ID0gdGhpcy5nZXRBcnJheUNvbnRyb2woZmllbGQuaWQpO1xyXG4gICAgICAgIGlmIChhcnJheSAmJiBhcnJheS5sZW5ndGggPT09IDApIGFycmF5LnB1c2godGhpcy5idWlsZEFycmF5Um93KGZpZWxkLCB1bmRlZmluZWQpKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmZvcm0uZGlzYWJsZSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmVidWlsZGluZyBtdXN0IG5vdCBzdGFjayBzdWJzY3JpcHRpb25zIG9uIHN1Y2Nlc3NpdmUgY29uZmlnL2RhdGEgY2hhbmdlcy5cclxuICAgIHRoaXMudmFsdWVTdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgICBjb25zdCBjaGFuZ2VzJCA9IHRoaXMuY2hhbmdlRGVib3VuY2VNcyA+IDBcclxuICAgICAgPyB0aGlzLmZvcm0udmFsdWVDaGFuZ2VzLnBpcGUoZGVib3VuY2VUaW1lKHRoaXMuY2hhbmdlRGVib3VuY2VNcykpXHJcbiAgICAgIDogdGhpcy5mb3JtLnZhbHVlQ2hhbmdlcztcclxuICAgIHRoaXMudmFsdWVTdWIgPSBjaGFuZ2VzJC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICBjb25zdCBmbGF0dGVuZWQgPSB0aGlzLmZsYXR0ZW5Gb3JtVmFsdWVzKCk7XHJcbiAgICAgIHRoaXMuZm9ybVZhbHVlcy5zZXQoZmxhdHRlbmVkKTtcclxuICAgICAgdGhpcy5ydW5QYXRjaE9uVHJ1ZShmbGF0dGVuZWQpO1xyXG4gICAgICB0aGlzLnByZXZpb3VzVmFsdWVzID0geyAuLi5mbGF0dGVuZWQgfTtcclxuICAgICAgdGhpcy5mb3JtQ2hhbmdlLmVtaXQodGhpcy5leHRyYWN0UmVjb3JkKCkpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGJ1aWxkRmllbGRDb250cm9sKGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZywgZ3JvdXA6IFJlY29yZDxzdHJpbmcsIEFic3RyYWN0Q29udHJvbD4pOiB2b2lkIHtcclxuICAgIGlmIChmaWVsZC50eXBlID09PSAnZ3JvdXAnKSB7XHJcbiAgICAgIGNvbnN0IHN1Ykdyb3VwOiBSZWNvcmQ8c3RyaW5nLCBBYnN0cmFjdENvbnRyb2w+ID0ge307XHJcbiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgZmllbGQuY2hpbGRyZW4gfHwgW10pIHtcclxuICAgICAgICB0aGlzLmJ1aWxkRmllbGRDb250cm9sKGNoaWxkLCBzdWJHcm91cCk7XHJcbiAgICAgIH1cclxuICAgICAgZ3JvdXBbZmllbGQuaWRdID0gdGhpcy5mYi5ncm91cChzdWJHcm91cCk7XHJcbiAgICB9IGVsc2UgaWYgKGZpZWxkLnR5cGUgPT09ICdhcnJheScpIHtcclxuICAgICAgZ3JvdXBbZmllbGQuaWRdID0gdGhpcy5mYi5hcnJheShbXSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zdCB2YWxpZGF0b3JzID0gdGhpcy52YWxpZGF0b3JSZWdpc3RyeS5yZXNvbHZlRnJvbUNvbmZpZyhmaWVsZC52YWxpZGF0b3JzKTtcclxuICAgICAgZ3JvdXBbZmllbGQuaWRdID0gdGhpcy5mYi5jb250cm9sKFxyXG4gICAgICAgIHsgdmFsdWU6IGZpZWxkLmRlZmF1bHRWYWx1ZSA/PyBudWxsLCBkaXNhYmxlZDogZmllbGQuZGlzYWJsZWQgPz8gZmFsc2UgfSxcclxuICAgICAgICB2YWxpZGF0b3JzLFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIE9uZSByb3cgb2YgYW4gYGFycmF5YCBmaWVsZDogYSBGb3JtR3JvdXAgd2hlbiB0aGUgZmllbGQgZGVjbGFyZXMgY29sdW1ucywgZWxzZSBhIGJhcmUgY29udHJvbC4gKi9cclxuICAvKipcclxuICAgKiBUaGUgYEZvcm1BcnJheWAgYmVoaW5kIGFuIGBhcnJheWAgZmllbGQsIGZvciBjYWxsZXJzIHRoYXQgbWFuYWdlIHJvd3MgdGhlbXNlbHZlcyDigJRcclxuICAgKiB0aGUgcmVjb3JkIGVkaXRvcidzIGlubGluZSByb3cgZHJhd2VyLlxyXG4gICAqL1xyXG4gIGdldEFycmF5Q29udHJvbChmaWVsZElkOiBzdHJpbmcsIHRhYklkPzogc3RyaW5nKTogRm9ybUFycmF5IHwgbnVsbCB7XHJcbiAgICBjb25zdCBjdHJsID0gdGhpcy5nZXRDb250cm9sKGZpZWxkSWQsIHRhYklkKTtcclxuICAgIHJldHVybiBjdHJsIGluc3RhbmNlb2YgRm9ybUFycmF5ID8gY3RybCA6IG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBCdWlsZCBvbmUgZGV0YWNoZWQgcm93IGZvciBhbiBgYXJyYXlgIGZpZWxkLCB3aXRoIHRoZSBmaWVsZCdzIG93biB2YWxpZGF0b3JzIGFwcGxpZWQuXHJcbiAgICogRXhwb3NlZCBzbyBhIHJvdyBjYW4gYmUgZWRpdGVkIG91dHNpZGUgdGhlIGZvcm0gYW5kIHB1c2hlZCBvbiBzYXZlLlxyXG4gICAqL1xyXG4gIGNyZWF0ZUFycmF5Um93KGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZywgdmFsdWU/OiB1bmtub3duKTogQWJzdHJhY3RDb250cm9sIHtcclxuICAgIHJldHVybiB0aGlzLmJ1aWxkQXJyYXlSb3coZmllbGQsIHZhbHVlKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYnVpbGRBcnJheVJvdyhmaWVsZDogTmVzdGVkRmllbGRDb25maWcgfCB1bmRlZmluZWQsIGl0ZW06IHVua25vd24pOiBBYnN0cmFjdENvbnRyb2wge1xyXG4gICAgaWYgKCFmaWVsZD8uY2hpbGRyZW4/Lmxlbmd0aCkgcmV0dXJuIHRoaXMuZmIuY29udHJvbChpdGVtKTtcclxuXHJcbiAgICBjb25zdCByb3dHcm91cDogUmVjb3JkPHN0cmluZywgQWJzdHJhY3RDb250cm9sPiA9IHt9O1xyXG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBmaWVsZC5jaGlsZHJlbikge1xyXG4gICAgICB0aGlzLmJ1aWxkRmllbGRDb250cm9sKGNoaWxkLCByb3dHcm91cCk7XHJcbiAgICB9XHJcbiAgICBjb25zdCBncm91cCA9IHRoaXMuZmIuZ3JvdXAocm93R3JvdXApO1xyXG4gICAgaWYgKGl0ZW0gJiYgdHlwZW9mIGl0ZW0gPT09ICdvYmplY3QnKSBncm91cC5wYXRjaFZhbHVlKGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pO1xyXG4gICAgcmV0dXJuIGdyb3VwO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBwYXRjaEZvcm0oZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xyXG4gICAgaWYgKCFkYXRhIHx8ICF0aGlzLmZvcm0pIHJldHVybjtcclxuICAgIGNvbnN0IGZpZWxkc0J5SWQgPSBuZXcgTWFwKHRoaXMuYWxsRmllbGRzKCkubWFwKGYgPT4gW2YuaWQsIGZdKSk7XHJcblxyXG4gICAgY29uc3Qgd2Fsa1RhYnMgPSAodGFiczogTmVzdGVkVGFiQ29uZmlnW10pID0+IHtcclxuICAgICAgZm9yIChjb25zdCB0YWIgb2YgdGFicykge1xyXG4gICAgICAgIGNvbnN0IHRhYkRhdGEgPSBnZXRUYWJEYXRhKHRhYi5pZCwgZGF0YSwgdGhpcy5jb25maWcpO1xyXG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgb2YgdGFiLmZpZWxkcyB8fCBbXSkge1xyXG4gICAgICAgICAgbGV0IHZhbCA9IHRhYkRhdGEgJiYgdHlwZW9mIHRhYkRhdGEgPT09ICdvYmplY3QnID8gdGFiRGF0YVtmaWVsZC5pZF0gOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgICBpZiAoZmllbGQucmVmZXJlckZpZWxkKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHJlZlZhbCA9IGdldFZhbHVlQnlQYXRoKGRhdGEsIGZpZWxkLnJlZmVyZXJGaWVsZCk7XHJcbiAgICAgICAgICAgIGlmIChyZWZWYWwgIT09IHVuZGVmaW5lZCkgdmFsID0gcmVmVmFsO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKHZhbCA9PT0gdW5kZWZpbmVkKSBjb250aW51ZTtcclxuXHJcbiAgICAgICAgICBjb25zdCBjdHJsID0gdGhpcy5nZXRDb250cm9sKGZpZWxkLmlkLCB0YWIuaWQpO1xyXG4gICAgICAgICAgaWYgKCFjdHJsKSBjb250aW51ZTtcclxuXHJcbiAgICAgICAgICBpZiAoY3RybCBpbnN0YW5jZW9mIEZvcm1BcnJheSAmJiBBcnJheS5pc0FycmF5KHZhbCkpIHtcclxuICAgICAgICAgICAgY3RybC5jbGVhcigpO1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdmFsKSB7XHJcbiAgICAgICAgICAgICAgY3RybC5wdXNoKHRoaXMuYnVpbGRBcnJheVJvdyhmaWVsZHNCeUlkLmdldChmaWVsZC5pZCksIGl0ZW0pKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY3RybC5wYXRjaFZhbHVlKHZhbCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGFiLmNoaWxkcmVuKSB3YWxrVGFicyh0YWIuY2hpbGRyZW4pO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIHdhbGtUYWJzKHRoaXMuY29uZmlnLnRhYnMgfHwgW10pO1xyXG4gIH1cclxuXHJcbiAgLyoqIEFzc2VtYmxlIGZ1bGwgbmVzdGVkIHJlY29yZCBmcm9tIHBlci10YWIgRm9ybUdyb3VwcywgcmVzcGVjdGluZyBmbGF0RGF0YSwgcmVmZXJlckZpZWxkICYgYXJyYXlzLiAqL1xyXG4gIGV4dHJhY3RSZWNvcmQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XHJcbiAgICBpZiAoIXRoaXMuZm9ybSB8fCAhdGhpcy5jb25maWcpIHJldHVybiB7fTtcclxuICAgIGxldCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcclxuXHJcbiAgICBjb25zdCB3YWxrVGFicyA9ICh0YWJzOiBOZXN0ZWRUYWJDb25maWdbXSkgPT4ge1xyXG4gICAgICBmb3IgKGNvbnN0IHRhYiBvZiB0YWJzKSB7XHJcbiAgICAgICAgY29uc3QgZmllbGRWYWxCYWc6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XHJcbiAgICAgICAgZm9yIChjb25zdCBmaWVsZCBvZiB0YWIuZmllbGRzIHx8IFtdKSB7XHJcbiAgICAgICAgICBjb25zdCBjdHJsID0gdGhpcy5nZXRDb250cm9sKGZpZWxkLmlkLCB0YWIuaWQpO1xyXG4gICAgICAgICAgaWYgKGN0cmwpIHtcclxuICAgICAgICAgICAgZmllbGRWYWxCYWdbZmllbGQuaWRdID0gY3RybC52YWx1ZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHNldFRhYkRhdGEocmVjb3JkLCB0YWIuaWQsIGZpZWxkVmFsQmFnLCB0aGlzLmNvbmZpZyk7XHJcblxyXG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgb2YgdGFiLmZpZWxkcyB8fCBbXSkge1xyXG4gICAgICAgICAgaWYgKGZpZWxkLnJlZmVyZXJGaWVsZCkge1xyXG4gICAgICAgICAgICBjb25zdCBjdHJsID0gdGhpcy5nZXRDb250cm9sKGZpZWxkLmlkLCB0YWIuaWQpO1xyXG4gICAgICAgICAgICBpZiAoY3RybCkge1xyXG4gICAgICAgICAgICAgIHNldFZhbHVlQnlQYXRoKHJlY29yZCwgZmllbGQucmVmZXJlckZpZWxkLCBjdHJsLnZhbHVlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRhYi5jaGlsZHJlbikgd2Fsa1RhYnModGFiLmNoaWxkcmVuKTtcclxuICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgICB3YWxrVGFicyh0aGlzLmNvbmZpZy50YWJzIHx8IFtdKTtcclxuICAgIHJlY29yZCA9IG5vcm1hbGl6ZUFycmF5U3RydWN0dXJlcyhyZWNvcmQsIHRoaXMuY29uZmlnKTtcclxuICAgIHJldHVybiByZWNvcmQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZsYXR0ZW5Gb3JtVmFsdWVzKCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xyXG4gICAgY29uc3Qgb3V0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XHJcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRoaXMuYWxsRmllbGRzKCkpIHtcclxuICAgICAgY29uc3QgY3RybCA9IHRoaXMuZ2V0Q29udHJvbChmaWVsZC5pZCk7XHJcbiAgICAgIGlmIChjdHJsKSBvdXRbZmllbGQuaWRdID0gY3RybC52YWx1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiBvdXQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldFRhYkdyb3VwKHRhYklkOiBzdHJpbmcpOiBGb3JtR3JvdXAgfCBudWxsIHtcclxuICAgIGNvbnN0IHBhdGggPSBnZXRUYWJQYXRoKHRoaXMuY29uZmlnPy50YWJzLCB0YWJJZCk7XHJcbiAgICBpZiAoIXBhdGggfHwgcGF0aC5sZW5ndGggPT09IDApIHJldHVybiB0aGlzLmZvcm07XHJcbiAgICBsZXQgY3VycjogQWJzdHJhY3RDb250cm9sIHwgbnVsbCA9IHRoaXMuZm9ybTtcclxuICAgIGZvciAoY29uc3QgcCBvZiBwYXRoKSB7XHJcbiAgICAgIGlmICghY3VyciB8fCAhKGN1cnIgaW5zdGFuY2VvZiBGb3JtR3JvdXApKSByZXR1cm4gbnVsbDtcclxuICAgICAgY3VyciA9IGN1cnIuZ2V0KHApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGN1cnIgaW5zdGFuY2VvZiBGb3JtR3JvdXAgPyBjdXJyIDogbnVsbDtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBhdXRvUGF0Y2ggLyBwYXRjaE9uVHJ1ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgLyoqXHJcbiAgICogYGF1dG9QYXRjaGAg4oCUIGNvcHkgbWFwcGVkIGZpZWxkcyBvdXQgb2YgdGhlIHJlY29yZCB0aGUgdXNlciBqdXN0IHNlbGVjdGVkIGluIGFuXHJcbiAgICogZW50aXR5LXJlZiBmaWVsZCBpbnRvIHRoZSBjb25maWd1cmVkIHRhcmdldCB0YWIncyBjb250cm9scy5cclxuICAgKi9cclxuICBwcml2YXRlIHJ1bkF1dG9QYXRjaChmaWVsZElkOiBzdHJpbmcsIHJlY29yZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQpOiB2b2lkIHtcclxuICAgIGlmICghcmVjb3JkKSByZXR1cm47XHJcbiAgICBjb25zdCBmaWVsZCA9IHRoaXMuYWxsRmllbGRzKCkuZmluZChmID0+IGYuaWQgPT09IGZpZWxkSWQpO1xyXG4gICAgY29uc3QgYXV0b1BhdGNoID0gZmllbGQ/LmF1dG9QYXRjaDtcclxuICAgIGlmICghYXV0b1BhdGNoKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgcGF0Y2ggPSBhcHBseUF1dG9QYXRjaChhdXRvUGF0Y2gsIHJlY29yZCk7XHJcbiAgICBmb3IgKGNvbnN0IFt0YXJnZXRJZCwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHBhdGNoKSkge1xyXG4gICAgICBjb25zdCBjb250cm9sID0gdGhpcy5yZXNvbHZlVGFyZ2V0Q29udHJvbChhdXRvUGF0Y2gsIHRhcmdldElkKTtcclxuICAgICAgY29udHJvbD8ucGF0Y2hWYWx1ZSh2YWx1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBgcGF0Y2hPblRydWVgIOKAlCB3aGVuIGEgYm9vbGVhbi9jaGVja2JveCBmaWVsZCB0cmFuc2l0aW9ucyB0byBgdHJ1ZWAsXHJcbiAgICogY29weSBgZnJvbWAg4oaSIGB0b2Agd2l0aGluIHRoZSBjdXJyZW50IHJlY29yZC5cclxuICAgKi9cclxuICBwcml2YXRlIHJ1blBhdGNoT25UcnVlKHZhbHVlczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xyXG4gICAgZm9yIChjb25zdCBmaWVsZCBvZiB0aGlzLmFsbEZpZWxkcygpKSB7XHJcbiAgICAgIGNvbnN0IG1hcHBpbmdzID0gZmllbGQucGF0Y2hPblRydWU7XHJcbiAgICAgIGlmICghbWFwcGluZ3M/Lmxlbmd0aCkgY29udGludWU7XHJcblxyXG4gICAgICBjb25zdCB3YXNUcnVlID0gdGhpcy5wcmV2aW91c1ZhbHVlc1tmaWVsZC5pZF0gPT09IHRydWU7XHJcbiAgICAgIGNvbnN0IGlzVHJ1ZSA9IHZhbHVlc1tmaWVsZC5pZF0gPT09IHRydWU7XHJcbiAgICAgIGlmICghaXNUcnVlIHx8IHdhc1RydWUpIGNvbnRpbnVlO1xyXG5cclxuICAgICAgY29uc3QgcGF0Y2ggPSBhcHBseVBhdGNoT25UcnVlKG1hcHBpbmdzLCB2YWx1ZXMpO1xyXG4gICAgICBmb3IgKGNvbnN0IFt0YXJnZXRJZCwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHBhdGNoKSkge1xyXG4gICAgICAgIHRoaXMuZ2V0Q29udHJvbCh0YXJnZXRJZCk/LnBhdGNoVmFsdWUodmFsdWUsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIFByZWZlciBhIGNvbnRyb2wgZGVjbGFyZWQgb24gdGhlIGNvbmZpZ3VyZWQgdGFyZ2V0IHRhYjsgZmFsbCBiYWNrIHRvIGEgdG9wLWxldmVsIGNvbnRyb2wuICovXHJcbiAgcHJpdmF0ZSByZXNvbHZlVGFyZ2V0Q29udHJvbChhdXRvUGF0Y2g6IEF1dG9QYXRjaENvbmZpZywgdGFyZ2V0SWQ6IHN0cmluZyk6IEFic3RyYWN0Q29udHJvbCB8IG51bGwge1xyXG4gICAgY29uc3QgdGFiID0gZmluZFRhYih0aGlzLnRhYnMsIGF1dG9QYXRjaC50YXJnZXRUYWIpO1xyXG4gICAgY29uc3QgaW5UYXJnZXRUYWIgPSAodGFiPy5maWVsZHMgPz8gW10pLnNvbWUoZiA9PiBmLmlkID09PSB0YXJnZXRJZCk7XHJcbiAgICBpZiAodGFiICYmICFpblRhcmdldFRhYikgcmV0dXJuIG51bGw7XHJcbiAgICByZXR1cm4gdGhpcy5nZXRDb250cm9sKHRhcmdldElkLCBhdXRvUGF0Y2gudGFyZ2V0VGFiKTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBIZWxwZXJzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICAvKiogRXZlcnkgZmllbGQgaW4gdGhlIGNvbmZpZywgaW5jbHVkaW5nIGBncm91cGAvYGFycmF5YCBjaGlsZHJlbi4gKi9cclxuICBwcml2YXRlIGFsbEZpZWxkcygpOiBOZXN0ZWRGaWVsZENvbmZpZ1tdIHtcclxuICAgIGNvbnN0IG91dDogTmVzdGVkRmllbGRDb25maWdbXSA9IFtdO1xyXG4gICAgY29uc3Qgd2Fsa0ZpZWxkcyA9IChmaWVsZHM6IE5lc3RlZEZpZWxkQ29uZmlnW10gfCB1bmRlZmluZWQpID0+IHtcclxuICAgICAgZm9yIChjb25zdCBmIG9mIGZpZWxkcyA/PyBbXSkge1xyXG4gICAgICAgIG91dC5wdXNoKGYpO1xyXG4gICAgICAgIGlmIChmLmNoaWxkcmVuPy5sZW5ndGgpIHdhbGtGaWVsZHMoZi5jaGlsZHJlbik7XHJcbiAgICAgIH1cclxuICAgIH07XHJcbiAgICBjb25zdCB3YWxrVGFicyA9ICh0YWJzOiBOZXN0ZWRUYWJDb25maWdbXSB8IHVuZGVmaW5lZCkgPT4ge1xyXG4gICAgICBmb3IgKGNvbnN0IHQgb2YgdGFicyA/PyBbXSkge1xyXG4gICAgICAgIHdhbGtGaWVsZHModC5maWVsZHMpO1xyXG4gICAgICAgIHdhbGtUYWJzKHQuY2hpbGRyZW4pO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG4gICAgd2Fsa1RhYnModGhpcy5jb25maWc/LnRhYnMpO1xyXG4gICAgcmV0dXJuIG91dDtcclxuICB9XHJcblxyXG4gIC8qKiBBbiBlbXB0eSBgb3JpZ2luYWxEYXRhYCBjb3VudHMgYXMgXCJub3Qgc3VwcGxpZWRcIiDigJQgZmFsbCBiYWNrIHRvIHRoZSBjYXB0dXJlZCBiYXNlbGluZS4gKi9cclxuICBwcml2YXRlIGJhc2VsaW5lKCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xyXG4gICAgY29uc3Qgc3VwcGxpZWQgPSB0aGlzLm9yaWdpbmFsRGF0YTtcclxuICAgIGlmIChzdXBwbGllZCAmJiBPYmplY3Qua2V5cyhzdXBwbGllZCkubGVuZ3RoID4gMCkgcmV0dXJuIHN1cHBsaWVkO1xyXG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbkJhc2VsaW5lKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNhbWVWYWx1ZShhOiB1bmtub3duLCBiOiB1bmtub3duKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoYSA9PT0gYikgcmV0dXJuIHRydWU7XHJcbiAgICBjb25zdCBhRW1wdHkgPSBhID09PSBudWxsIHx8IGEgPT09IHVuZGVmaW5lZCB8fCBhID09PSAnJztcclxuICAgIGNvbnN0IGJFbXB0eSA9IGIgPT09IG51bGwgfHwgYiA9PT0gdW5kZWZpbmVkIHx8IGIgPT09ICcnO1xyXG4gICAgaWYgKGFFbXB0eSAmJiBiRW1wdHkpIHJldHVybiB0cnVlO1xyXG4gICAgaWYgKHR5cGVvZiBhID09PSAnb2JqZWN0JyB8fCB0eXBlb2YgYiA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGEgPz8gbnVsbCkgPT09IEpTT04uc3RyaW5naWZ5KGIgPz8gbnVsbCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBnZXRDb250cm9sKGZpZWxkSWQ6IHN0cmluZywgY3VycmVudFRhYklkPzogc3RyaW5nKTogQWJzdHJhY3RDb250cm9sIHwgbnVsbCB7XHJcbiAgICBpZiAoIXRoaXMuZm9ybSkgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgaWYgKGN1cnJlbnRUYWJJZCkge1xyXG4gICAgICBjb25zdCB0YWJHcnAgPSB0aGlzLmdldFRhYkdyb3VwKGN1cnJlbnRUYWJJZCk7XHJcbiAgICAgIGNvbnN0IGN0cmwgPSB0YWJHcnA/LmdldChmaWVsZElkKTtcclxuICAgICAgaWYgKGN0cmwpIHJldHVybiBjdHJsO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHJvb3RDdHJsID0gdGhpcy5mb3JtLmdldChmaWVsZElkKTtcclxuICAgIGlmIChyb290Q3RybCkgcmV0dXJuIHJvb3RDdHJsO1xyXG5cclxuICAgIGNvbnN0IGZpbmRJbkdyb3VwID0gKGdyb3VwOiBGb3JtR3JvdXApOiBBYnN0cmFjdENvbnRyb2wgfCBudWxsID0+IHtcclxuICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoZ3JvdXAuY29udHJvbHMpKSB7XHJcbiAgICAgICAgY29uc3QgYyA9IGdyb3VwLmNvbnRyb2xzW2tleV07XHJcbiAgICAgICAgaWYgKGtleSA9PT0gZmllbGRJZCkgcmV0dXJuIGM7XHJcbiAgICAgICAgaWYgKGMgaW5zdGFuY2VvZiBGb3JtR3JvdXApIHtcclxuICAgICAgICAgIGNvbnN0IGZvdW5kID0gZmluZEluR3JvdXAoYyk7XHJcbiAgICAgICAgICBpZiAoZm91bmQpIHJldHVybiBmb3VuZDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9O1xyXG5cclxuICAgIHJldHVybiBmaW5kSW5Hcm91cCh0aGlzLmZvcm0pO1xyXG4gIH1cclxuXHJcbiAgcmVzb2x2ZVRhYkxhYmVsKHRhYjogTmVzdGVkVGFiQ29uZmlnKTogc3RyaW5nIHtcclxuICAgIHJldHVybiByZXNvbHZlTGFiZWwodGFiLmxhYmVsLCB0aGlzLmxhbmd1YWdlKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHN1Ym1pdCgpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICghdGhpcy5jYW5TdWJtaXQgfHwgdGhpcy5mb3JtLmludmFsaWQpIHtcclxuICAgICAgdGhpcy5mb3JtLm1hcmtBbGxBc1RvdWNoZWQoKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHJhd0RhdGEgPSB0aGlzLmV4dHJhY3RSZWNvcmQoKTtcclxuICAgIGxldCBwcm9jZXNzZWREYXRhID0gcmF3RGF0YTtcclxuXHJcbiAgICBjb25zdCBob29rS2V5ID0gYCR7dGhpcy5jb25maWc/LmVudGl0eX06YmVmb3JlU2F2ZWA7XHJcbiAgICBpZiAodGhpcy5ob29rUmVnaXN0cnkuaGFzKGhvb2tLZXkpKSB7XHJcbiAgICAgIHByb2Nlc3NlZERhdGEgPSBhd2FpdCB0aGlzLmhvb2tSZWdpc3RyeS5ydW4oaG9va0tleSwgcHJvY2Vzc2VkRGF0YSk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5pc1NhdmluZy5zZXQodHJ1ZSk7XHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLmZvcm1TdWJtaXQuZW1pdChwcm9jZXNzZWREYXRhKTtcclxuICAgIH0gZmluYWxseSB7XHJcbiAgICAgIHRoaXMuaXNTYXZpbmcuc2V0KGZhbHNlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJlc2V0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5mb3JtLnJlc2V0KCk7XHJcbiAgICBpZiAodGhpcy5pbml0aWFsRGF0YSkgdGhpcy5wYXRjaEZvcm0odGhpcy5pbml0aWFsRGF0YSk7XHJcbiAgICBjb25zdCB2YWx1ZXMgPSB0aGlzLmZsYXR0ZW5Gb3JtVmFsdWVzKCk7XHJcbiAgICB0aGlzLmZvcm1WYWx1ZXMuc2V0KHZhbHVlcyk7XHJcbiAgICB0aGlzLnByZXZpb3VzVmFsdWVzID0geyAuLi52YWx1ZXMgfTtcclxuICAgIHRoaXMudW5sb2NrZWRGaWVsZHMuc2V0KG5ldyBTZXQ8c3RyaW5nPigpKTtcclxuICAgIHRoaXMuZm9ybVJlc2V0LmVtaXQoKTtcclxuICB9XHJcbn1cclxuIiwiPGZvcm0gW2Zvcm1Hcm91cF09XCJmb3JtXCIgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCIgY2xhc3M9XCJuZ3gtZm9ybVwiIG5vdmFsaWRhdGU+XHJcblxyXG4gIDwhLS0gRXJyb3IgbWVzc2FnZSBiYW5uZXIgLS0+XHJcbiAgQGlmIChlcnJvcikge1xyXG4gICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX19lcnJvci1iYW5uZXJcIiByb2xlPVwiYWxlcnRcIiBkYXRhLXRlc3RpZD1cImZvcm0tZXJyb3JcIj57eyBlcnJvciB9fTwvZGl2PlxyXG4gIH1cclxuXHJcbiAgPCEtLSBSdWxlcyBJbmZvIEJhbm5lcnMgLS0+XHJcbiAgQGZvciAoaW5mb0tleSBvZiBzaG93SW5mb0Jhbm5lcnMgPyBPYmplY3Qua2V5cyhydWxlUmVzdWx0KCkuaW5mb0Jhbm5lcnMpIDogW107IHRyYWNrIGluZm9LZXkpIHtcclxuICAgIDxkaXYgY2xhc3M9XCJuZ3gtZm9ybV9faW5mby1iYW5uZXJcIiByb2xlPVwic3RhdHVzXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2luZm8tYmFubmVyLScgKyBpbmZvS2V5XCI+XHJcbiAgICAgIOKEue+4jyB7eyBydWxlUmVzdWx0KCkuaW5mb0Jhbm5lcnNbaW5mb0tleV0gfX1cclxuICAgIDwvZGl2PlxyXG4gIH1cclxuXHJcbiAgPCEtLSBSdWxlcyBWYWxpZGF0aW9uIEVycm9ycyAmIFdhcm5pbmdzIC0tPlxyXG4gIEBmb3IgKGVycktleSBvZiBPYmplY3Qua2V5cyhydWxlUmVzdWx0KCkudmFsaWRhdGlvbkVycm9ycyk7IHRyYWNrIGVycktleSkge1xyXG4gICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX19lcnJvci1iYW5uZXJcIiByb2xlPVwiYWxlcnRcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCIncnVsZS1lcnJvci0nICsgZXJyS2V5XCI+XHJcbiAgICAgIOKaoO+4jyB7eyBydWxlUmVzdWx0KCkudmFsaWRhdGlvbkVycm9yc1tlcnJLZXldIH19XHJcbiAgICA8L2Rpdj5cclxuICB9XHJcbiAgQGZvciAod2FybktleSBvZiBPYmplY3Qua2V5cyhydWxlUmVzdWx0KCkudmFsaWRhdGlvbldhcm5pbmdzKTsgdHJhY2sgd2FybktleSkge1xyXG4gICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX193YXJuaW5nLWJhbm5lclwiIHJvbGU9XCJzdGF0dXNcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCIncnVsZS13YXJuaW5nLScgKyB3YXJuS2V5XCI+XHJcbiAgICAgIOKaoSB7eyBydWxlUmVzdWx0KCkudmFsaWRhdGlvbldhcm5pbmdzW3dhcm5LZXldIH19XHJcbiAgICA8L2Rpdj5cclxuICB9XHJcblxyXG4gIDwhLS0gRGVmZXJyZWQgVkFMVUVfQ0hBTkdFRCBub3RpY2UgZm9yIGNyaXRpY2FsRmllbGQgZWRpdHMgKHZzIHNlc3Npb24gYmFzZWxpbmUpIC0tPlxyXG4gIEBpZiAoY2hhbmdlZENyaXRpY2FsRmllbGRzKCkubGVuZ3RoID4gMCkge1xyXG4gICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX193YXJuaW5nLWJhbm5lclwiIHJvbGU9XCJzdGF0dXNcIiBkYXRhLXRlc3RpZD1cImNyaXRpY2FsLWNoYW5nZS1iYW5uZXJcIj5cclxuICAgICAg8J+UkiBDcml0aWNhbCBmaWVsZCBjaGFuZ2VkOlxyXG4gICAgICBAZm9yIChmaWVsZCBvZiBjaGFuZ2VkQ3JpdGljYWxGaWVsZHMoKTsgdHJhY2sgZmllbGQuaWQpIHtcclxuICAgICAgICA8c3Bhbj57eyByZXNvbHZlRmllbGRMYWJlbChmaWVsZCkgfX17eyAkbGFzdCA/ICcnIDogJywgJyB9fTwvc3Bhbj5cclxuICAgICAgfVxyXG4gICAgICDigJQgdGhpcyBkaWZmZXJzIGZyb20gdGhlIHZhbHVlIGF0IHRoZSBzdGFydCBvZiB0aGlzIHNlc3Npb24uXHJcbiAgICA8L2Rpdj5cclxuICB9XHJcblxyXG4gIDwhLS0gUHJpbWFyeSBUYWIgYmFyIOKAlCBvbmx5IGlmIHZpc2libGUgdGFicyBkZWZpbmVkIC0tPlxyXG4gIEBpZiAodmlzaWJsZVRhYnMubGVuZ3RoID4gMCkge1xyXG4gICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX190YWJzXCIgcm9sZT1cInRhYmxpc3RcIiBkYXRhLXRlc3RpZD1cInRhYi1zdHJpcFwiPlxyXG4gICAgICBAZm9yICh0YWIgb2YgdmlzaWJsZVRhYnM7IHRyYWNrIHRhYi5pZCkge1xyXG4gICAgICAgIDxidXR0b25cclxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtZm9ybV9fdGFiXCJcclxuICAgICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIid0YWItJyArIHRhYi5pZFwiXHJcbiAgICAgICAgICBbY2xhc3Mubmd4LWZvcm1fX3RhYi0tYWN0aXZlXT1cImFjdGl2ZVRhYigpID09PSB0YWIuaWRcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cInNldEFjdGl2ZVRhYih0YWIuaWQpXCJcclxuICAgICAgICAgIHJvbGU9XCJ0YWJcIlxyXG4gICAgICAgICAgW2F0dHIuYXJpYS1zZWxlY3RlZF09XCJhY3RpdmVUYWIoKSA9PT0gdGFiLmlkXCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICB7eyByZXNvbHZlVGFiTGFiZWwodGFiKSB9fVxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICB9XHJcbiAgICA8L2Rpdj5cclxuICB9XHJcblxyXG4gIDwhLS0gU3ViLXRhYiBiYXIg4oCUIG9ubHkgaWYgYWN0aXZlIHRhYiBoYXMgc3ViLXRhYnMgLS0+XHJcbiAgQGlmICh2aXNpYmxlU3ViVGFicy5sZW5ndGggPiAwKSB7XHJcbiAgICA8ZGl2IGNsYXNzPVwibmd4LWZvcm1fX3RhYnMgbmd4LWZvcm1fX3RhYnMtLXN1YlwiIHJvbGU9XCJ0YWJsaXN0XCIgZGF0YS10ZXN0aWQ9XCJzdWJ0YWItc3RyaXBcIiBzdHlsZT1cIm1hcmdpbi10b3A6IC0xMnB4OyBtYXJnaW4tYm90dG9tOiAxMnB4OyBmb250LXNpemU6IDEzcHg7XCI+XHJcbiAgICAgIEBmb3IgKHN1YlRhYiBvZiB2aXNpYmxlU3ViVGFiczsgdHJhY2sgc3ViVGFiLmlkKSB7XHJcbiAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICBjbGFzcz1cIm5neC1mb3JtX190YWIgbmd4LWZvcm1fX3RhYi0tc3ViXCJcclxuICAgICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidzdWJ0YWItJyArIHN1YlRhYi5pZFwiXHJcbiAgICAgICAgICBbY2xhc3Mubmd4LWZvcm1fX3RhYi0tYWN0aXZlXT1cIihhY3RpdmVTdWJUYWJDb25maWc/LmlkKSA9PT0gc3ViVGFiLmlkXCJcclxuICAgICAgICAgIChjbGljayk9XCJzZXRBY3RpdmVTdWJUYWIoc3ViVGFiLmlkKVwiXHJcbiAgICAgICAgICByb2xlPVwidGFiXCJcclxuICAgICAgICAgIFthdHRyLmFyaWEtc2VsZWN0ZWRdPVwiKGFjdGl2ZVN1YlRhYkNvbmZpZz8uaWQpID09PSBzdWJUYWIuaWRcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIHt7IHJlc29sdmVUYWJMYWJlbChzdWJUYWIpIH19XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIH1cclxuICAgIDwvZGl2PlxyXG4gIH1cclxuXHJcbiAgPCEtLSBNb2R1bGUgdGFiIGNvbXBvbmVudCBPUiBGaWVsZHMgZm9yIGFjdGl2ZSB0YWIgLS0+XHJcbiAgQGlmIChhY3RpdmVUYWJNb2R1bGVDb21wb25lbnQpIHtcclxuICAgIDxkaXYgY2xhc3M9XCJuZ3gtZm9ybV9fbW9kdWxlLXBhbmVsXCIgZGF0YS10ZXN0aWQ9XCJtb2R1bGUtcGFuZWxcIj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdDb21wb25lbnRPdXRsZXQ9XCJhY3RpdmVUYWJNb2R1bGVDb21wb25lbnQ7IGlucHV0czogKGFjdGl2ZVN1YlRhYkNvbmZpZyB8fCBhY3RpdmVUYWJDb25maWcpPy5tb2R1bGVJbnB1dHNcIj48L25nLWNvbnRhaW5lcj5cclxuICAgIDwvZGl2PlxyXG4gIH0gQGVsc2Uge1xyXG4gICAgPCEtLSBGaWVsZHMgZm9yIGFjdGl2ZSB0YWIgKFJlc3BvbnNpdmUgMTItY29sdW1uIGdyaWQpIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX19wYW5lbFwiIGRhdGEtdGVzdGlkPVwiZm9ybS1wYW5lbFwiPlxyXG4gICAgICBAZm9yIChmaWVsZCBvZiBmaWVsZHNGb3JBY3RpdmVUYWI7IHRyYWNrIGZpZWxkLmlkKSB7XHJcbiAgICAgICAgPGRpdlxyXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtZm9ybV9fZmllbGQtc2xvdFwiXHJcbiAgICAgICAgICBbc3R5bGUuZ3JpZENvbHVtbl09XCJnZXRGaWVsZFNwYW4oZmllbGQpXCJcclxuICAgICAgICAgIFthdHRyLmlkXT1cIidmaWVsZC1jb250YWluZXItJyArIGZpZWxkLmlkXCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8bmd4LWR5bmFtaWMtZmllbGRcclxuICAgICAgICAgICAgW2ZpZWxkXT1cImZpZWxkXCJcclxuICAgICAgICAgICAgW2NvbnRyb2xdPVwiZ2V0Q29udHJvbChmaWVsZC5pZCwgKGFjdGl2ZVN1YlRhYkNvbmZpZyB8fCBhY3RpdmVUYWJDb25maWcpPy5pZCkhXCJcclxuICAgICAgICAgICAgW2NvbmZpZ109XCJjb25maWdcIlxyXG4gICAgICAgICAgICBbY3VycmVudFRhYklkXT1cIihhY3RpdmVTdWJUYWJDb25maWcgfHwgYWN0aXZlVGFiQ29uZmlnKT8uaWRcIlxyXG4gICAgICAgICAgICBbbGFuZ3VhZ2VdPVwibGFuZ3VhZ2VcIlxyXG4gICAgICAgICAgICBbcmVhZG9ubHldPVwiaXNGaWVsZFJlYWRvbmx5KGZpZWxkKVwiXHJcbiAgICAgICAgICAgIFt1c2VyUm9sZXNdPVwidXNlclJvbGVzXCJcclxuICAgICAgICAgIC8+XHJcbiAgICAgICAgICBAaWYgKGZpZWxkLmNyaXRpY2FsRmllbGQgJiYgIXJlYWRvbmx5KSB7XHJcbiAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cIm5neC1mb3JtX19sb2NrXCJcclxuICAgICAgICAgICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCInbG9jay0nICsgZmllbGQuaWRcIlxyXG4gICAgICAgICAgICAgIFthdHRyLmFyaWEtcHJlc3NlZF09XCIhaXNGaWVsZExvY2tlZChmaWVsZClcIlxyXG4gICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiXHJcbiAgICAgICAgICAgICAgICAoaXNGaWVsZExvY2tlZChmaWVsZCkgPyAnVW5sb2NrICcgOiAnTG9jayAnKSArIHJlc29sdmVGaWVsZExhYmVsKGZpZWxkKVxyXG4gICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgW3RpdGxlXT1cIlxyXG4gICAgICAgICAgICAgICAgaXNGaWVsZExvY2tlZChmaWVsZClcclxuICAgICAgICAgICAgICAgICAgPyAnQ3JpdGljYWwgZmllbGQg4oCUIGNsaWNrIHRvIHVubG9jayBmb3IgZWRpdGluZydcclxuICAgICAgICAgICAgICAgICAgOiAnQ3JpdGljYWwgZmllbGQg4oCUIGNsaWNrIHRvIGxvY2snXHJcbiAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlRmllbGRMb2NrKGZpZWxkKVwiXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICB7eyBpc0ZpZWxkTG9ja2VkKGZpZWxkKSA/ICfwn5SSJyA6ICfwn5STJyB9fVxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgIH1cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgfVxyXG4gICAgPC9kaXY+XHJcbiAgfVxyXG5cclxuICA8IS0tIFN1Ym1pdCBidXR0b24g4oCUIGdhdGVkIGJ5IFJCQUMgYW5kIGlzU2F2aW5nIGxvY2sgLS0+XHJcbiAgQGlmICghcmVhZG9ubHkgJiYgcGVybWlzc2lvbnMuY2FuRWRpdCkge1xyXG4gICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX19hY3Rpb25zXCIgZGF0YS10ZXN0aWQ9XCJmb3JtLWFjdGlvbnNcIj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgIGNsYXNzPVwibmd4LWZvcm1fX3Jlc2V0XCJcclxuICAgICAgICBkYXRhLXRlc3RpZD1cImZvcm0tcmVzZXRcIlxyXG4gICAgICAgIChjbGljayk9XCJyZXNldCgpXCJcclxuICAgICAgICBbZGlzYWJsZWRdPVwiaXNTYXZpbmcoKVwiXHJcbiAgICAgID5cclxuICAgICAgICBSZXNldFxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIHR5cGU9XCJzdWJtaXRcIlxyXG4gICAgICAgIGNsYXNzPVwibmd4LWZvcm1fX3N1Ym1pdFwiXHJcbiAgICAgICAgZGF0YS10ZXN0aWQ9XCJmb3JtLXN1Ym1pdFwiXHJcbiAgICAgICAgW2Rpc2FibGVkXT1cImZvcm0uaW52YWxpZFwiXHJcbiAgICAgICAgdGl0bGU9XCJTaG9ydGN1dDogQ3RybCtTXCJcclxuICAgICAgPlxyXG4gICAgICAgIEBpZiAoaXNTYXZpbmcoKSB8fCBsb2FkaW5nKSB7XHJcbiAgICAgICAgICBTYXZpbmfigKZcclxuICAgICAgICB9IEBlbHNlIHtcclxuICAgICAgICAgIFNhdmVcclxuICAgICAgICB9XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcbiAgfVxyXG5cclxuPC9mb3JtPlxyXG4iXX0=
890
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZm9ybS9keW5hbWljLWZvcm0uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vc3JjL2xpYi9mb3JtL2R5bmFtaWMtZm9ybS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUtaLE1BQU0sRUFDTixRQUFRLEVBQ1IsTUFBTSxFQUNOLFNBQVMsRUFFVCxTQUFTLEVBQ1QsWUFBWSxFQUVaLFlBQVksR0FDYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQW1CLFNBQVMsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFekcsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBUTlDLE9BQU8sRUFDTCxjQUFjLEVBQ2QsZ0JBQWdCLEVBQ2hCLGFBQWEsRUFDYix1QkFBdUIsRUFDdkIsT0FBTyxFQUNQLFVBQVUsRUFDVixVQUFVLEVBQ1YsY0FBYyxFQUNkLHdCQUF3QixFQUN4QixzQkFBc0IsRUFDdEIsWUFBWSxFQUNaLFVBQVUsRUFDVixjQUFjLEdBQ2YsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUNoRixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN4RixPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUNsRixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUN4RSxPQUFPLEVBQUUsV0FBVyxF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QVluQyxtQkFBbUI7c0JBRGxCLFlBQVk7dUJBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIEV2ZW50RW1pdHRlcixcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgc2lnbmFsLFxuICBjb21wdXRlZCxcbiAgaW5qZWN0LFxuICBpc0Rldk1vZGUsXG4gIEVsZW1lbnRSZWYsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0NoaWxkcmVuLFxuICBRdWVyeUxpc3QsXG4gIEhvc3RMaXN0ZW5lcixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZ0NvbXBvbmVudE91dGxldCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIEZvcm1BcnJheSwgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHR5cGUge1xuICBBdXRvUGF0Y2hDb25maWcsXG4gIEVudGl0eUZvcm1Db25maWcsXG4gIEZvcm1SdWxlLFxuICBOZXN0ZWRGaWVsZENvbmZpZyxcbiAgTmVzdGVkVGFiQ29uZmlnLFxufSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XG5pbXBvcnQge1xuICBhcHBseUF1dG9QYXRjaCxcbiAgYXBwbHlQYXRjaE9uVHJ1ZSxcbiAgbWlncmF0ZVJlY29yZCxcbiAgZXZhbHVhdGVGaWVsZFZpc2liaWxpdHksXG4gIGZpbmRUYWIsXG4gIGdldFRhYkRhdGEsXG4gIGdldFRhYlBhdGgsXG4gIGdldFZhbHVlQnlQYXRoLFxuICBub3JtYWxpemVBcnJheVN0cnVjdHVyZXMsXG4gIG5vcm1hbGl6ZUNvbmZpZ09wdGlvbnMsXG4gIHJlc29sdmVMYWJlbCxcbiAgc2V0VGFiRGF0YSxcbiAgc2V0VmFsdWVCeVBhdGgsXG59IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IER5bmFtaWNGaWVsZENvbXBvbmVudCB9IGZyb20gJy4vZHluYW1pYy1maWVsZC9keW5hbWljLWZpZWxkLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDT01NT05fTU9EVUxFU19SRUdJU1RSWSwgUkVDT1JEX01JR1JBVElPTlMgfSBmcm9tICcuLi90b2tlbnMvaW5qZWN0aW9uLXRva2Vucyc7XG5pbXBvcnQgeyBWYWxpZGF0b3JSZWdpc3RyeVNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy92YWxpZGF0b3ItcmVnaXN0cnkuc2VydmljZSc7XG5pbXBvcnQgeyBIb29rUmVnaXN0cnlTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvaG9vay1yZWdpc3RyeS5zZXJ2aWNlJztcbmltcG9ydCB7IFJiYWNTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvcmJhYy5zZXJ2aWNlJztcbmltcG9ydCB7IFJ1bGVzRXZhbHVhdGlvblNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9ydWxlcy1ldmFsdWF0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgRW50aXR5UmVmU2VsZWN0aW9uU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2VudGl0eS1yZWYtc2VsZWN0aW9uLnNlcnZpY2UnO1xuXG4vKipcbiAqIER5bmFtaWNGb3JtQ29tcG9uZW50IOKAlCB0aGUgbWFpbiBmb3JtIGNvbXBvbmVudC5cbiAqIFJlbmRlcnMgYSByZWFjdGl2ZSBmb3JtIGZyb20gRW50aXR5Rm9ybUNvbmZpZyB3aXRoIHRhYiBzdXBwb3J0LCByZXNwb25zaXZlIDEyLWNvbCBncmlkLFxuICogcnVsZXMgZXZhbHVhdGlvbiwgY29uZGl0aW9uYWwgdmlzaWJpbGl0eSwgYXV0b1BhdGNoL3BhdGNoT25UcnVlLCBjcml0aWNhbEZpZWxkIGxvY2tpbmcsXG4gKiBrZXlib2FyZCBzaG9ydGN1dHMgKEN0cmwrUywgRXNjKSwgYW5kIFJCQUMtZ2F0ZWQgc3VibWlzc2lvbi5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWR5bmFtaWMtZm9ybScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtSZWFjdGl2ZUZvcm1zTW9kdWxlLCBEeW5hbWljRmllbGRDb21wb25lbnQsIE5nQ29tcG9uZW50T3V0bGV0XSxcbiAgLy8gU2NvcGVkIHBlciBmb3JtIGluc3RhbmNlOiBlbnRpdHktcmVmIHNlbGVjdGlvbnMgbXVzdCBub3QgbGVhayBiZXR3ZWVuIGNvbmN1cnJlbnQgZm9ybXMuXG4gIHByb3ZpZGVyczogW0VudGl0eVJlZlNlbGVjdGlvblNlcnZpY2VdLFxuICB0ZW1wbGF0ZVVybDogJy4vZHluYW1pYy1mb3JtLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgLm5neC1mb3JtX19wYW5lbCB7XG4gICAgICAgIGRpc3BsYXk6IGdyaWQ7XG4gICAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogcmVwZWF0KDEyLCBtaW5tYXgoMCwgMWZyKSk7XG4gICAgICAgIGdhcDogMTZweCAyMHB4O1xuICAgICAgICBhbGlnbi1pdGVtczogc3RhcnQ7XG4gICAgICB9XG4gICAgICAubmd4LWZvcm1fX2ZpZWxkLXNsb3Qge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbiAgICAgICAgZ2FwOiA2cHg7XG4gICAgICAgIG1pbi13aWR0aDogMDtcbiAgICAgIH1cbiAgICAgIC5uZ3gtZm9ybV9fZmllbGQtc2xvdCBuZ3gtZHluYW1pYy1maWVsZCB7XG4gICAgICAgIGZsZXg6IDE7XG4gICAgICAgIG1pbi13aWR0aDogMDtcbiAgICAgIH1cbiAgICAgIC5uZ3gtZm9ybV9fbG9jayB7XG4gICAgICAgIGZsZXg6IDAgMCBhdXRvO1xuICAgICAgICBtYXJnaW4tdG9wOiAyMnB4O1xuICAgICAgICBiYWNrZ3JvdW5kOiBub25lO1xuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCB0cmFuc3BhcmVudDtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogNnB4O1xuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgICAgIGZvbnQtc2l6ZTogMTRweDtcbiAgICAgICAgbGluZS1oZWlnaHQ6IDE7XG4gICAgICAgIHBhZGRpbmc6IDRweCA2cHg7XG4gICAgICB9XG4gICAgICAubmd4LWZvcm1fX2xvY2s6aG92ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6ICNkMWQ1ZGI7XG4gICAgICAgIGJhY2tncm91bmQ6ICNmOWZhZmI7XG4gICAgICB9XG4gICAgICBAbWVkaWEgKG1heC13aWR0aDogNzY4cHgpIHtcbiAgICAgICAgLm5neC1mb3JtX19wYW5lbCB7XG4gICAgICAgICAgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiAxZnI7XG4gICAgICAgIH1cbiAgICAgICAgLm5neC1mb3JtX19maWVsZC1zbG90IHtcbiAgICAgICAgICBncmlkLWNvbHVtbjogc3BhbiAxMiAhaW1wb3J0YW50O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgRHluYW1pY0Zvcm1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgLy8g4pSA4pSA4pSAIElucHV0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLyoqXG4gICAqIFRoZSBzY2hlbWEgdG8gcmVuZGVyLlxuICAgKlxuICAgKiBBbiBhY2Nlc3NvciBwYWlyIHJhdGhlciB0aGFuIGEgcGxhaW4gZmllbGQ6IGBuZ09uQ2hhbmdlc2Agbm9ybWFsaXNlcyB0aGUgb3B0aW9uIHNoYXBlLFxuICAgKiBhbmQgdGhhdCByZXN1bHQgaXMga2VwdCBoZXJlIGluc3RlYWQgb2YgYmVpbmcgd3JpdHRlbiBiYWNrIG92ZXIgdGhlIGlucHV0LiBSZWFzc2lnbmluZ1xuICAgKiBhbiBgQElucHV0YCB3b3JrcywgYnV0IGl0IG11dGF0ZXMgd2hhdCB0aGUgcGFyZW50IGhhbmRlZCB1cyDigJQgYW5kIGEgcGFyZW50IHVzaW5nIE9uUHVzaFxuICAgKiBvciBzaWduYWxzIHdvdWxkIG5ldmVyIG9ic2VydmUgdGhlIHJlcGxhY2VtZW50IGFueXdheS5cbiAgICpcbiAgICogUmVhZHMgb2YgYHRoaXMuY29uZmlnYCBnZXQgdGhlIG5vcm1hbGlzZWQgY29weSBvbmNlIGl0IGV4aXN0cywgc28gZXZlcnkgaW50ZXJuYWwgY2FsbGVyXG4gICAqIGlzIHVuYWZmZWN0ZWQuXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgY29uZmlnKHZhbHVlOiBFbnRpdHlGb3JtQ29uZmlnKSB7XG4gICAgdGhpcy5yYXdDb25maWcgPSB2YWx1ZTtcbiAgICB0aGlzLm5vcm1hbGl6ZWRDb25maWcgPSB1bmRlZmluZWQ7IC8vIHJlLW5vcm1hbGlzZWQgaW4gbmdPbkNoYW5nZXNcbiAgfVxuICBnZXQgY29uZmlnKCk6IEVudGl0eUZvcm1Db25maWcge1xuICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZWRDb25maWcgPz8gdGhpcy5yYXdDb25maWc7XG4gIH1cbiAgcHJpdmF0ZSByYXdDb25maWchOiBFbnRpdHlGb3JtQ29uZmlnO1xuICBwcml2YXRlIG5vcm1hbGl6ZWRDb25maWc/OiBFbnRpdHlGb3JtQ29uZmlnO1xuICBASW5wdXQoKSBydWxlcz86IEZvcm1SdWxlW107XG4gIEBJbnB1dCgpIGluaXRpYWxEYXRhPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgLyoqIFNlc3Npb24tb3JpZ2luYWwgdmFsdWVzIGZvciBgVkFMVUVfQ0hBTkdFRGAgcnVsZXMuIENhcHR1cmVkIGZyb20gdGhlIGZpcnN0IGJ1aWxkIHdoZW4gb21pdHRlZC4gKi9cbiAgQElucHV0KCkgb3JpZ2luYWxEYXRhPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgQElucHV0KCkgdXNlclJvbGVzOiBzdHJpbmdbXSA9IFtdO1xuICBASW5wdXQoKSBsYW5ndWFnZTogc3RyaW5nID0gJ2VuJztcbiAgQElucHV0KCkgcmVhZG9ubHk6IGJvb2xlYW4gPSBmYWxzZTtcbiAgLyoqIEZpZWxkIGlkcyBmb3JjZWQgcmVhZC1vbmx5IHdoaWxlIHRoZSByZXN0IG9mIHRoZSBmb3JtIHN0YXlzIGVkaXRhYmxlLiAqL1xuICBASW5wdXQoKSByZWFkT25seUZpZWxkczogc3RyaW5nW10gPSBbXTtcbiAgLyoqXG4gICAqIFJlbmRlciBydWxlIGBpbmZvYCBiYW5uZXJzIGlubGluZS4gVGhlIHJlY29yZCBlZGl0b3Igc2V0cyB0aGlzIGZhbHNlIGFuZCByZW5kZXJzIGl0c1xuICAgKiBvd24gZGlzbWlzc2libGUgdmVyc2lvbnMsIHNvIHRoZSB0d28gZG8gbm90IGRvdWJsZSB1cC5cbiAgICovXG4gIEBJbnB1dCgpIHNob3dJbmZvQmFubmVyczogYm9vbGVhbiA9IHRydWU7XG4gIEBJbnB1dCgpIGxvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgZXJyb3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogTWlsbGlzZWNvbmRzIHRvIGRlYm91bmNlIGBmb3JtQ2hhbmdlYC4gVGhlIHJlZmVyZW5jZSBkZWJvdW5jZXMgYXQgMzAwbXMgc28gYSBjb25zdW1lclxuICAgKiByZS1yZW5kZXJpbmcgb24gZXZlcnkgdmFsdWUgY2hhbmdlIGlzIG5vdCBkcml2ZW4gcGVyIGtleXN0cm9rZS4gWmVybyBlbWl0c1xuICAgKiBzeW5jaHJvbm91c2x5LCB3aGljaCB0aGUgcmVjb3JkIGVkaXRvciByZWxpZXMgb24gZm9yIGl0cyBvd24gYm9va2tlZXBpbmcuXG4gICAqL1xuICBASW5wdXQoKSBjaGFuZ2VEZWJvdW5jZU1zOiBudW1iZXIgPSAwO1xuICAvKipcbiAgICogUHJldmlldyBtb2RlOiBzZWVkIG9uZSBlbXB0eSByb3cgcGVyIGBhcnJheWAgZmllbGQgc28gdGhlIHN0cnVjdHVyZSBpcyB2aXNpYmxlLCB0aGVuXG4gICAqIGRpc2FibGUgdGhlIGZvcm0uIFVzZWQgYnkgdGhlIGJ1aWxkZXIncyBsaXZlIHByZXZpZXcuXG4gICAqL1xuICBASW5wdXQoKSBwcmV2aWV3OiBib29sZWFuID0gZmFsc2U7XG5cbiAgLy8g4pSA4pSA4pSAIE91dHB1dHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIEBPdXRwdXQoKSBmb3JtU3VibWl0ID0gbmV3IEV2ZW50RW1pdHRlcjxSZWNvcmQ8c3RyaW5nLCBhbnk+PigpO1xuICBAT3V0cHV0KCkgZm9ybUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8UmVjb3JkPHN0cmluZywgYW55Pj4oKTtcbiAgQE91dHB1dCgpIGZvcm1SZXNldCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgLyoqIFRoZSB2aXNpYmxlIHRhYiBjaGFuZ2VkLiBMZXRzIGEgaG9zdCB0cmFjayBpdCB3aXRob3V0IHJlYWNoaW5nIGludG8gdGhpcyBjb21wb25lbnQuICovXG4gIEBPdXRwdXQoKSBhY3RpdmVUYWJDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIGBiZWZvcmVTYXZlYCBob29rIGFib3J0ZWQgdGhlIHNhdmUg4oCUIGJ5IHJldHVybmluZyBmYWxzZSBvciB0aHJvd2luZy5cbiAgICogYGZvcm1TdWJtaXRgIGRvZXMgbm90IGZpcmUgaW4gdGhhdCBjYXNlLlxuICAgKi9cbiAgQE91dHB1dCgpIHNhdmVSZWplY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyByZWFzb246IHN0cmluZzsgZXJyb3I/OiB1bmtub3duIH0+KCk7XG5cbiAgLy8g4pSA4pSA4pSAIFNlcnZpY2VzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICBwcml2YXRlIHJlYWRvbmx5IGZiID0gaW5qZWN0KEZvcm1CdWlsZGVyKTtcbiAgcHJpdmF0ZSByZWFkb25seSB2YWxpZGF0b3JSZWdpc3RyeSA9IGluamVjdChWYWxpZGF0b3JSZWdpc3RyeVNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGhvb2tSZWdpc3RyeSA9IGluamVjdChIb29rUmVnaXN0cnlTZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSByYmFjU2VydmljZSA9IGluamVjdChSYmFjU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcnVsZXNFdmFsdWF0aW9uID0gaW5qZWN0KFJ1bGVzRXZhbHVhdGlvblNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGVudGl0eVJlZlNlbGVjdGlvbiA9IGluamVjdChFbnRpdHlSZWZTZWxlY3Rpb25TZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBjb21tb25Nb2R1bGVzUmVnaXN0cnkgPSBpbmplY3QoQ09NTU9OX01PRFVMRVNfUkVHSVNUUlksIHsgb3B0aW9uYWw6IHRydWUgfSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWlncmF0aW9ucyA9IGluamVjdChSRUNPUkRfTUlHUkFUSU9OUywgeyBvcHRpb25hbDogdHJ1ZSB9KSA/PyBbXTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgT2JqZWN0ID0gT2JqZWN0O1xuXG4gIC8vIOKUgOKUgOKUgCBTaWduYWxzIChsb2NhbCByZWFjdGl2ZSBzdGF0ZSkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIHJlYWRvbmx5IGFjdGl2ZVRhYiA9IHNpZ25hbDxzdHJpbmc+KCcnKTtcbiAgcmVhZG9ubHkgYWN0aXZlU3ViVGFiID0gc2lnbmFsPHN0cmluZz4oJycpO1xuICByZWFkb25seSBpc1NhdmluZyA9IHNpZ25hbChmYWxzZSk7XG4gIHJlYWRvbmx5IGZvcm1WYWx1ZXMgPSBzaWduYWw8UmVjb3JkPHN0cmluZywgYW55Pj4oe30pO1xuICAvKiogQmFzZWxpbmUgY2FwdHVyZWQgYXQgZmlyc3QgYnVpbGQsIHVzZWQgd2hlbiBgb3JpZ2luYWxEYXRhYCBpcyBub3Qgc3VwcGxpZWQuICovXG4gIHJlYWRvbmx5IHNlc3Npb25CYXNlbGluZSA9IHNpZ25hbDxSZWNvcmQ8c3RyaW5nLCBhbnk+Pih7fSk7XG4gIC8qKiBDcml0aWNhbCBmaWVsZHMgdGhlIHVzZXIgaGFzIGV4cGxpY2l0bHkgdW5sb2NrZWQgZm9yIGVkaXRpbmcuICovXG4gIHJlYWRvbmx5IHVubG9ja2VkRmllbGRzID0gc2lnbmFsPFJlYWRvbmx5U2V0PHN0cmluZz4+KG5ldyBTZXQ8c3RyaW5nPigpKTtcblxuICAvKiogVGhlIGFjdGl2ZSB0YWIncyBmaWVsZCBwYW5lbCwgZm9jdXNlZCBhZnRlciBhIHRhYiBzd2l0Y2guICovXG4gIEBWaWV3Q2hpbGQoJ2Zvcm1QYW5lbCcpIHByaXZhdGUgZm9ybVBhbmVsPzogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG5cbiAgLyoqIFRoZSBob3N0ZWQgZmllbGQgY29tcG9uZW50cywgc28gYW4gZXh0ZXJuYWwgY29udHJvbC1zdGF0ZSBjaGFuZ2UgY2FuIHJlYWNoIHRoZW0uICovXG4gIEBWaWV3Q2hpbGRyZW4oRHluYW1pY0ZpZWxkQ29tcG9uZW50KSBwcml2YXRlIGZpZWxkSG9zdHM/OiBRdWVyeUxpc3Q8RHluYW1pY0ZpZWxkQ29tcG9uZW50PjtcblxuICAvLyDilIDilIDilIAgRm9ybSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgZm9ybSE6IEZvcm1Hcm91cDtcblxuICBwcml2YXRlIHZhbHVlU3ViPzogU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIHNlbGVjdGlvblN1Yj86IFN1YnNjcmlwdGlvbjtcbiAgLyoqIFByZXZpb3VzIHZhbHVlcywgZm9yIGRldGVjdGluZyBgcGF0Y2hPblRydWVgIGZhbHNl4oaSdHJ1ZSB0cmFuc2l0aW9ucy4gKi9cbiAgcHJpdmF0ZSBwcmV2aW91c1ZhbHVlczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuXG4gIC8vIOKUgOKUgOKUgCBLZXlib2FyZCBTaG9ydGN1dHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXlkb3duJywgWyckZXZlbnQnXSlcbiAgaGFuZGxlS2V5Ym9hcmRFdmVudChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICgoZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5KSAmJiBldmVudC5rZXkudG9Mb3dlckNhc2UoKSA9PT0gJ3MnKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgaWYgKCF0aGlzLnJlYWRvbmx5ICYmIHRoaXMuY2FuU3VibWl0ICYmIHRoaXMuZm9ybT8udmFsaWQpIHtcbiAgICAgICAgdGhpcy5zdWJtaXQoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyDilIDilIDilIAgQ29tcHV0ZWQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIHJlYWRvbmx5IHJ1bGVSZXN1bHQgPSBjb21wdXRlZCgoKSA9PlxuICAgIHRoaXMucnVsZXNFdmFsdWF0aW9uLmV2YWx1YXRlKHRoaXMucnVsZXMsIHRoaXMuZm9ybVZhbHVlcygpLCB0aGlzLmJhc2VsaW5lKCkpLFxuICApO1xuXG4gIC8qKlxuICAgKiBDcml0aWNhbCBmaWVsZHMgd2hvc2UgdmFsdWUgZGlmZmVycyBmcm9tIHRoZSBzZXNzaW9uIGJhc2VsaW5lLlxuICAgKiBUaGVzZSBkcml2ZSB0aGUgZGVmZXJyZWQgYFZBTFVFX0NIQU5HRURgIGJhbm5lciDigJQgYSBjcml0aWNhbCBlZGl0IGlzIGFubm91bmNlZCBvbmNlLFxuICAgKiBhZ2FpbnN0IHRoZSB2YWx1ZSB0aGUgcmVjb3JkIGhhZCB3aGVuIHRoZSBzZXNzaW9uIHN0YXJ0ZWQsIG5vdCBwZXIga2V5c3Ryb2tlLlxuICAgKi9cbiAgcmVhZG9ubHkgY2hhbmdlZENyaXRpY2FsRmllbGRzID0gY29tcHV0ZWQ8TmVzdGVkRmllbGRDb25maWdbXT4oKCkgPT4ge1xuICAgIGNvbnN0IGJhc2VsaW5lID0gdGhpcy5iYXNlbGluZSgpO1xuICAgIGlmICghYmFzZWxpbmUgfHwgT2JqZWN0LmtleXMoYmFzZWxpbmUpLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdO1xuICAgIGNvbnN0IHZhbHVlcyA9IHRoaXMuZm9ybVZhbHVlcygpO1xuICAgIHJldHVybiB0aGlzLmFsbEZpZWxkcygpLmZpbHRlcihcbiAgICAgIGYgPT4gZi5jcml0aWNhbEZpZWxkICYmICF0aGlzLnNhbWVWYWx1ZSh2YWx1ZXNbZi5pZF0sIGJhc2VsaW5lW2YuaWRdKSxcbiAgICApO1xuICB9KTtcblxuICBnZXQgdGFicygpOiBOZXN0ZWRUYWJDb25maWdbXSB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnPy50YWJzIHx8IFtdO1xuICB9XG5cbiAgZ2V0IHZpc2libGVUYWJzKCk6IE5lc3RlZFRhYkNvbmZpZ1tdIHtcbiAgICBjb25zdCBoaWRkZW4gPSB0aGlzLnJ1bGVSZXN1bHQoKS5oaWRkZW5UYWJzO1xuICAgIHJldHVybiB0aGlzLnRhYnMuZmlsdGVyKHRhYiA9PiB0YWIudmlzaWJpbGl0eSAhPT0gZmFsc2UgJiYgIWhpZGRlbi5pbmNsdWRlcyh0YWIuaWQpKTtcbiAgfVxuXG4gIGdldCBhY3RpdmVUYWJDb25maWcoKTogTmVzdGVkVGFiQ29uZmlnIHwgbnVsbCB7XG4gICAgY29uc3QgdGFiSWQgPSB0aGlzLmFjdGl2ZVRhYigpO1xuICAgIGlmICghdGFiSWQpIHJldHVybiB0aGlzLnZpc2libGVUYWJzWzBdID8/IG51bGw7XG4gICAgcmV0dXJuIGZpbmRUYWIodGhpcy50YWJzLCB0YWJJZCk7XG4gIH1cblxuICBnZXQgdmlzaWJsZVN1YlRhYnMoKTogTmVzdGVkVGFiQ29uZmlnW10ge1xuICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuYWN0aXZlVGFiQ29uZmlnO1xuICAgIGlmICghYWN0aXZlPy5jaGlsZHJlbiB8fCBhY3RpdmUuY2hpbGRyZW4ubGVuZ3RoID09PSAwKSByZXR1cm4gW107XG4gICAgY29uc3QgaGlkZGVuID0gdGhpcy5ydWxlUmVzdWx0KCkuaGlkZGVuVGFicztcbiAgICByZXR1cm4gYWN0aXZlLmNoaWxkcmVuLmZpbHRlcih0YWIgPT4gdGFiLnZpc2liaWxpdHkgIT09IGZhbHNlICYmICFoaWRkZW4uaW5jbHVkZXModGFiLmlkKSk7XG4gIH1cblxuICBnZXQgYWN0aXZlU3ViVGFiQ29uZmlnKCk6IE5lc3RlZFRhYkNvbmZpZyB8IG51bGwge1xuICAgIGNvbnN0IHN1YlRhYnMgPSB0aGlzLnZpc2libGVTdWJUYWJzO1xuICAgIGlmICghc3ViVGFicy5sZW5ndGgpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHN1YklkID0gdGhpcy5hY3RpdmVTdWJUYWIoKTtcbiAgICByZXR1cm4gc3ViVGFicy5maW5kKHMgPT4gcy5pZCA9PT0gc3ViSWQpID8/IHN1YlRhYnNbMF07XG4gIH1cblxuICBnZXQgYWN0aXZlVGFiTW9kdWxlQ29tcG9uZW50KCk6IGFueSB8IG51bGwge1xuICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuYWN0aXZlU3ViVGFiQ29uZmlnID8/IHRoaXMuYWN0aXZlVGFiQ29uZmlnO1xuICAgIGlmICghYWN0aXZlPy5tb2R1bGVOYW1lIHx8ICF0aGlzLmNvbW1vbk1vZHVsZXNSZWdpc3RyeSkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgZW50cnkgPSB0aGlzLmNvbW1vbk1vZHVsZXNSZWdpc3RyeS5maW5kKFxuICAgICAgbSA9PiBtLmlkID09PSBhY3RpdmUubW9kdWxlTmFtZSB8fCBtLmNvbXBvbmVudCA9PT0gYWN0aXZlLm1vZHVsZU5hbWUsXG4gICAgKTtcbiAgICByZXR1cm4gZW50cnkgPyBlbnRyeS5jb21wb25lbnQgOiBudWxsO1xuICB9XG5cbiAgZ2V0IGZpZWxkc0ZvckFjdGl2ZVRhYigpOiBOZXN0ZWRGaWVsZENvbmZpZ1tdIHtcbiAgICBjb25zdCBhY3RpdmUgPSB0aGlzLmFjdGl2ZVN1YlRhYkNvbmZpZyA/PyB0aGlzLmFjdGl2ZVRhYkNvbmZpZztcbiAgICBpZiAoYWN0aXZlPy5tb2R1bGVOYW1lKSByZXR1cm4gW107XG4gICAgY29uc3QgcmF3RmllbGRzID0gYWN0aXZlID8gKGFjdGl2ZS5maWVsZHMgfHwgW10pIDogKCh0aGlzLmNvbmZpZz8udGFicyB8fCBbXSkuZmxhdE1hcCh0ID0+IHQuZmllbGRzIHx8IFtdKSk7XG4gICAgY29uc3QgY3VycmVudFZhbHVlcyA9IHRoaXMuZm9ybVZhbHVlcygpO1xuICAgIGNvbnN0IGhpZGRlbkZpZWxkcyA9IHRoaXMucnVsZVJlc3VsdCgpLmhpZGRlbkZpZWxkcztcblxuICAgIHJldHVybiByYXdGaWVsZHMuZmlsdGVyKFxuICAgICAgZmllbGQgPT4gZXZhbHVhdGVGaWVsZFZpc2liaWxpdHkoZmllbGQsIGN1cnJlbnRWYWx1ZXMpICYmICFoaWRkZW5GaWVsZHMuaW5jbHVkZXMoZmllbGQuaWQpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogRW50aXR5LWxldmVsIHBlcm1pc3Npb25zIGZvciB0aGUgY3VycmVudCByb2xlcy5cbiAgICpcbiAgICogQ2FjaGVkIHJhdGhlciB0aGFuIHJlY29tcHV0ZWQ6IHRoaXMgaXMgcmVhZCBmcm9tIHRoZSB0ZW1wbGF0ZSBzZXZlcmFsIHRpbWVzIHBlciBjaGFuZ2VcbiAgICogZGV0ZWN0aW9uIHBhc3MsIGFuZCBhIGZyZXNoIG9iamVjdCBlYWNoIHRpbWUgaXMgYm90aCB3YXN0ZWQgYWxsb2NhdGlvbiBhbmQgYSBuZXdcbiAgICogaWRlbnRpdHkgZm9yIGFueXRoaW5nIGNvbXBhcmluZyBieSByZWZlcmVuY2UuIEludmFsaWRhdGVkIGluIGBuZ09uQ2hhbmdlc2Agd2hlblxuICAgKiBgY29uZmlnYCBvciBgdXNlclJvbGVzYCBjaGFuZ2UsIHdoaWNoIGFyZSBpdHMgb25seSBpbnB1dHMuXG4gICAqL1xuICBnZXQgcGVybWlzc2lvbnMoKTogUmV0dXJuVHlwZTxSYmFjU2VydmljZVsnZ2V0UGVybWlzc2lvbnMnXT4ge1xuICAgIHJldHVybiAodGhpcy5wZXJtaXNzaW9uc0NhY2hlID8/PSB0aGlzLnJiYWNTZXJ2aWNlLmdldFBlcm1pc3Npb25zKHRoaXMuY29uZmlnLCB0aGlzLnVzZXJSb2xlcykpO1xuICB9XG5cbiAgcHJpdmF0ZSBwZXJtaXNzaW9uc0NhY2hlOiBSZXR1cm5UeXBlPFJiYWNTZXJ2aWNlWydnZXRQZXJtaXNzaW9ucyddPiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBjdXJyZW50IHJvbGVzIG1heSBzZWUgdGhpcyByZWNvcmQgYXQgYWxsLlxuICAgKlxuICAgKiBgcGVybWlzc2lvbnMudmlld2AgdXNlZCB0byBiZSBjb21wdXRlZCBhbmQgdGhyb3duIGF3YXkg4oCUIGEgdXNlciB3aG9zZSByb2xlcyBmYWlsZWQgaXRcbiAgICogc3RpbGwgcmVjZWl2ZWQgdGhlIGNvbXBsZXRlIGZvcm0gd2l0aCBldmVyeSB2YWx1ZSBpbiB0aGUgRE9NLiBJdCBpcyBob25vdXJlZCBub3cuXG4gICAqXG4gICAqIEFzIHdpdGggbWFza2luZywgdGhpcyBpcyBwcmVzZW50YXRpb25hbDogaXQgc3RvcHMgdGhlIGJyb3dzZXIgcmVuZGVyaW5nIGRhdGEsIGl0IGRvZXNcbiAgICogbm90IHN0b3AgdGhlIGRhdGEgcmVhY2hpbmcgdGhlIGJyb3dzZXIuIEF1dGhvcml6ZSBvbiB0aGUgc2VydmVyLlxuICAgKi9cbiAgZ2V0IGNhblZpZXcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucGVybWlzc2lvbnMuY2FuVmlldztcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBjdXJyZW50IHJvbGVzIG1heSBkZWxldGUgdGhpcyByZWNvcmQuXG4gICAqXG4gICAqIFRoZSBsaWJyYXJ5IHNoaXBzIG5vIGRlbGV0ZSBhZmZvcmRhbmNlLCBzbyB0aGlzIGlzIHN1cmZhY2VkIGZvciB0aGUgY29uc3VtZXIgdG8gZ2F0ZVxuICAgKiB0aGVpciBvd24g4oCUIGV4cG9zZWQgcmF0aGVyIHRoYW4gZHJvcHBlZCwgYmVjYXVzZSBhIHBlcm1pc3Npb24gdGhlIHNjaGVtYSBkZWNsYXJlc1xuICAgKiBzaG91bGQgYmUgYW5zd2VyYWJsZS5cbiAgICovXG4gIGdldCBjYW5EZWxldGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucGVybWlzc2lvbnMuY2FuRGVsZXRlO1xuICB9XG5cbiAgZ2V0IGNhblN1Ym1pdCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jYW5WaWV3ICYmIHRoaXMucGVybWlzc2lvbnMuY2FuRWRpdCAmJiAhdGhpcy5yZWFkb25seTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFcnJvcnMgcmFpc2VkIGJ5IGB2YWxpZGF0aW9uYCBydWxlcywga2V5ZWQgYnkgdGhlIHRhcmdldCB0aGV5IHBvaW50IGF0LlxuICAgKlxuICAgKiBBIHJ1bGUgY2FuIGRlY2xhcmUgdGhlIHJlY29yZCBpbnZhbGlkIGluZGVwZW5kZW50bHkgb2YgQW5ndWxhcidzIHZhbGlkYXRvcnMsIHNvIGZvcm1cbiAgICogdmFsaWRpdHkgYWxvbmUgaXMgbm90IHRoZSB3aG9sZSBwaWN0dXJlLiBgRHluYW1pY1JlY29yZEZvcm1Db21wb25lbnQuc2F2ZVNlY3Rpb24oKWBcbiAgICogaGFzIGFsd2F5cyBob25vdXJlZCB0aGVzZTsgYHN1Ym1pdCgpYCBkaWQgbm90LCB3aGljaCBtZWFudCB0aGUgc2FtZSBydWxlIGJsb2NrZWQgb25lXG4gICAqIHNhdmUgcGF0aCBhbmQgbWVyZWx5IHBhaW50ZWQgYSBiYW5uZXIgb24gdGhlIG90aGVyIOKAlCBhbmQgYW55dGhpbmcgd2lyaW5nXG4gICAqIGAoZm9ybVN1Ym1pdClgIHRvIHBlcnNpc3RlbmNlIHdyb3RlIHJlY29yZHMgdGhlIHJ1bGVzIGVuZ2luZSBoYWQgYWxyZWFkeSByZWplY3RlZC5cbiAgICovXG4gIGdldCBydWxlVmFsaWRhdGlvbkVycm9ycygpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5ydWxlUmVzdWx0KCkudmFsaWRhdGlvbkVycm9ycztcbiAgfVxuXG4gIC8qKiBUcnVlIHdoZW4gYSBgdmFsaWRhdGlvbmAgcnVsZSBpcyBjdXJyZW50bHkgYmxvY2tpbmcgc3VibWlzc2lvbi4gKi9cbiAgZ2V0IGhhc1J1bGVFcnJvcnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMucnVsZVZhbGlkYXRpb25FcnJvcnMpLmxlbmd0aCA+IDA7XG4gIH1cblxuICAvKipcbiAgICogVHJ1ZSB3aGlsZSBhbiBhc3luYyB2YWxpZGF0b3IgaXMgc3RpbGwgcnVubmluZy5cbiAgICpcbiAgICogQW5ndWxhciByZXBvcnRzIGEgY29udHJvbCB3aXRoIGFuIG91dHN0YW5kaW5nIGFzeW5jIGNoZWNrIGFzIGBwZW5kaW5nYCwgYW5kIGBpbnZhbGlkYCBpc1xuICAgKiBmYWxzZSB1bnRpbCBpdCBzZXR0bGVzIOKAlCBzbyB3aXRob3V0IHRoaXMgYSBmb3JtIGNvdWxkIGJlIHN1Ym1pdHRlZCBpbiB0aGUgZ2FwIGJlZm9yZSBhXG4gICAqIHVuaXF1ZW5lc3MgY2hlY2sgY2FtZSBiYWNrLlxuICAgKi9cbiAgZ2V0IGlzVmFsaWRhdGluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5mb3JtLnBlbmRpbmc7XG4gIH1cblxuICAvKiogU2luZ2xlIHNvdXJjZSBvZiB0cnV0aCBmb3IgYm90aCB0aGUgc3VibWl0IGd1YXJkIGFuZCB0aGUgYnV0dG9uJ3MgZGlzYWJsZWQgc3RhdGUuICovXG4gIGdldCBzdWJtaXRCbG9ja2VkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmZvcm0uaW52YWxpZCB8fCB0aGlzLmZvcm0ucGVuZGluZyB8fCB0aGlzLmhhc1J1bGVFcnJvcnM7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGlvblN1YiA9IHRoaXMuZW50aXR5UmVmU2VsZWN0aW9uLnNlbGVjdGlvbiQuc3Vic2NyaWJlKCh7IGZpZWxkSWQsIG9wdGlvbiB9KSA9PiB7XG4gICAgICB0aGlzLnJ1bkF1dG9QYXRjaChmaWVsZElkLCBvcHRpb24/LnJlY29yZCk7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ2NvbmZpZyddIHx8IGNoYW5nZXNbJ3VzZXJSb2xlcyddKSB7XG4gICAgICB0aGlzLnBlcm1pc3Npb25zQ2FjaGUgPSBudWxsO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlc1snY29uZmlnJ10gJiYgdGhpcy5yYXdDb25maWcpIHtcbiAgICAgIC8vIENvbmZpZ3MgYXJyaXZlIGFzIHBsYWluIEpTT04gZnJvbSBzdG9yYWdlIG9yIGFuIEFQSSwgd2hlcmUgVHlwZVNjcmlwdCBjYW5ub3QgZW5mb3JjZVxuICAgICAgLy8gdGhlIG9wdGlvbiBzaGFwZS4gTm9ybWFsaXNlIGhlcmUsIGF0IHRoZSBsaWJyYXJ5IGJvdW5kYXJ5LCBzbyBldmVyeXRoaW5nIGRvd25zdHJlYW1cbiAgICAgIC8vIGNhbiByZWx5IG9uIGFuIG9wdGlvbiBiZWluZyBhIExvY2FsaXplZFRleHQuIFJldHVybnMgdGhlIHNhbWUgb2JqZWN0IHdoZW4gaXQgYWxyZWFkeVxuICAgICAgLy8gaXMsIHNvIGEgd2VsbC1mb3JtZWQgY29uZmlnIGNvc3RzIG5vdGhpbmcuXG4gICAgICAvLyBLZXB0IGluIGEgZmllbGQgb2Ygb3VyIG93biByYXRoZXIgdGhhbiB3cml0dGVuIGJhY2sgdG8gdGhlIEBJbnB1dC4gUmVhc3NpZ25pbmcgYW5cbiAgICAgIC8vIGlucHV0IHdvcmtzLCBidXQgaXQgc3VycHJpc2VzIGEgcGFyZW50IHRoYXQgaG9sZHMgdGhlIHNhbWUgb2JqZWN0IOKAlCBhbmQgYSBwYXJlbnRcbiAgICAgIC8vIHVzaW5nIE9uUHVzaCBvciBzaWduYWxzIHdvdWxkIG5vdCBzZWUgdGhlIHJlcGxhY2VtZW50IGFueXdheS5cbiAgICAgIHRoaXMubm9ybWFsaXplZENvbmZpZyA9IG5vcm1hbGl6ZUNvbmZpZ09wdGlvbnModGhpcy5jb25maWcpO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlc1snY29uZmlnJ10gfHwgY2hhbmdlc1snaW5pdGlhbERhdGEnXSkge1xuICAgICAgdGhpcy5idWlsZEZvcm0oKTtcbiAgICAgIGlmICh0aGlzLnZpc2libGVUYWJzLmxlbmd0aCA+IDAgJiYgIXRoaXMuYWN0aXZlVGFiKCkpIHtcbiAgICAgICAgdGhpcy5zZXRBY3RpdmVUYWIodGhpcy52aXNpYmxlVGFic1swXS5pZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZVN1Yj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnNlbGVjdGlvblN1Yj8udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHNldEFjdGl2ZVRhYih0YWJJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY2hhbmdlZCA9IHRoaXMuYWN0aXZlVGFiKCkgIT09IHRhYklkO1xuICAgIGlmIChjaGFuZ2VkKSB0aGlzLmFjdGl2ZVRhYkNoYW5nZS5lbWl0KHRhYklkKTtcbiAgICB0aGlzLmFjdGl2ZVRhYi5zZXQodGFiSWQpO1xuICAgIGlmIChjaGFuZ2VkKSB0aGlzLmZvY3VzQWN0aXZlUGFuZWwoKTtcbiAgICBjb25zdCBwYXJlbnQgPSBmaW5kVGFiKHRoaXMudGFicywgdGFiSWQpO1xuICAgIGlmIChwYXJlbnQ/LmNoaWxkcmVuPy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuYWN0aXZlU3ViVGFiLnNldChwYXJlbnQuY2hpbGRyZW5bMF0uaWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFjdGl2ZVN1YlRhYi5zZXQoJycpO1xuICAgIH1cbiAgfVxuXG4gIHNldEFjdGl2ZVN1YlRhYihzdWJUYWJJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY2hhbmdlZCA9IHRoaXMuYWN0aXZlU3ViVGFiKCkgIT09IHN1YlRhYklkO1xuICAgIHRoaXMuYWN0aXZlU3ViVGFiLnNldChzdWJUYWJJZCk7XG4gICAgaWYgKGNoYW5nZWQpIHRoaXMuZm9jdXNBY3RpdmVQYW5lbCgpO1xuICB9XG5cbiAgZ2V0RmllbGRTcGFuKGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZyk6IHN0cmluZyB7XG4gICAgY29uc3Qgc3BhbiA9IGZpZWxkLmNvbFNwYW4gPz8gMTI7XG4gICAgcmV0dXJuIGBzcGFuICR7TWF0aC5taW4oMTIsIE1hdGgubWF4KDEsIHNwYW4pKX1gO1xuICB9XG5cbiAgLy8g4pSA4pSA4pSAIGNyaXRpY2FsRmllbGQgbG9ja2luZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogQSBjcml0aWNhbCBmaWVsZCBzdGF5cyByZWFkLW9ubHkgdW50aWwgdGhlIHVzZXIgZGVsaWJlcmF0ZWx5IHVubG9ja3MgaXQuICovXG4gIGlzRmllbGRMb2NrZWQoZmllbGQ6IE5lc3RlZEZpZWxkQ29uZmlnKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhZmllbGQuY3JpdGljYWxGaWVsZCAmJiAhdGhpcy51bmxvY2tlZEZpZWxkcygpLmhhcyhmaWVsZC5pZCk7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIGZpZWxkIHJlbmRlcnMgcmVhZC1vbmx5LCBmcm9tIGFueSBvZiB0aGUgZm91ciByZWFzb25zOiB0aGUgd2hvbGUgZm9ybSxcbiAgICogdGhlIGZpZWxkJ3Mgb3duIGZsYWcsIGEgY2FsbGVyLXN1cHBsaWVkIGByZWFkT25seUZpZWxkc2AgZW50cnksIG9yIGEgY3JpdGljYWxGaWVsZCBsb2NrLlxuICAgKi9cbiAgaXNGaWVsZFJlYWRvbmx5KGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLnJlYWRvbmx5IHx8XG4gICAgICAhIWZpZWxkLnJlYWRvbmx5IHx8XG4gICAgICB0aGlzLnJlYWRPbmx5RmllbGRzLmluY2x1ZGVzKGZpZWxkLmlkKSB8fFxuICAgICAgdGhpcy5pc0ZpZWxkTG9ja2VkKGZpZWxkKVxuICAgICk7XG4gIH1cblxuICB0b2dnbGVGaWVsZExvY2soZmllbGQ6IE5lc3RlZEZpZWxkQ29uZmlnKTogdm9pZCB7XG4gICAgaWYgKCFmaWVsZC5jcml0aWNhbEZpZWxkIHx8IHRoaXMucmVhZG9ubHkpIHJldHVybjtcbiAgICBjb25zdCBuZXh0ID0gbmV3IFNldCh0aGlzLnVubG9ja2VkRmllbGRzKCkpO1xuICAgIGlmIChuZXh0LmhhcyhmaWVsZC5pZCkpIG5leHQuZGVsZXRlKGZpZWxkLmlkKTtcbiAgICBlbHNlIG5leHQuYWRkKGZpZWxkLmlkKTtcbiAgICB0aGlzLnVubG9ja2VkRmllbGRzLnNldChuZXh0KTtcbiAgfVxuXG4gIHJlc29sdmVGaWVsZExhYmVsKGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHJlc29sdmVMYWJlbChmaWVsZC5sYWJlbCwgdGhpcy5sYW5ndWFnZSk7XG4gIH1cblxuICAvLyDilIDilIDilIAgRm9ybSBjb25zdHJ1Y3Rpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJpdmF0ZSBidWlsZEZvcm0oKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZykgcmV0dXJuO1xuICAgIGNvbnN0IGdyb3VwOiBSZWNvcmQ8c3RyaW5nLCBBYnN0cmFjdENvbnRyb2w+ID0ge307XG5cbiAgICBjb25zdCBidWlsZFRhYkNvbnRyb2xzID0gKHRhYnM6IE5lc3RlZFRhYkNvbmZpZ1tdLCBwYXJlbnRHcm91cDogUmVjb3JkPHN0cmluZywgQWJzdHJhY3RDb250cm9sPikgPT4ge1xuICAgICAgZm9yIChjb25zdCB0YWIgb2YgdGFicykge1xuICAgICAgICBpZiAodGFiLmZsYXREYXRhKSB7XG4gICAgICAgICAgZm9yIChjb25zdCBmaWVsZCBvZiB0YWIuZmllbGRzIHx8IFtdKSB7XG4gICAgICAgICAgICB0aGlzLmJ1aWxkRmllbGRDb250cm9sKGZpZWxkLCBwYXJlbnRHcm91cCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0YWIuY2hpbGRyZW4pIGJ1aWxkVGFiQ29udHJvbHModGFiLmNoaWxkcmVuLCBwYXJlbnRHcm91cCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgdGFiR3JvdXA6IFJlY29yZDxzdHJpbmcsIEFic3RyYWN0Q29udHJvbD4gPSB7fTtcbiAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRhYi5maWVsZHMgfHwgW10pIHtcbiAgICAgICAgICAgIHRoaXMuYnVpbGRGaWVsZENvbnRyb2woZmllbGQsIHRhYkdyb3VwKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHRhYi5jaGlsZHJlbikgYnVpbGRUYWJDb250cm9scyh0YWIuY2hpbGRyZW4sIHRhYkdyb3VwKTtcbiAgICAgICAgICBwYXJlbnRHcm91cFt0YWIuaWRdID0gdGhpcy5mYi5ncm91cCh0YWJHcm91cCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgYnVpbGRUYWJDb250cm9scyh0aGlzLmNvbmZpZy50YWJzIHx8IFtdLCBncm91cCk7XG4gICAgdGhpcy5mb3JtID0gdGhpcy5mYi5ncm91cChncm91cCk7XG5cbiAgICBpZiAodGhpcy5pbml0aWFsRGF0YSkge1xuICAgICAgdGhpcy5wYXRjaEZvcm0odGhpcy51cGdyYWRlUmVjb3JkKHRoaXMuaW5pdGlhbERhdGEpKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbml0aWFsRmxhdHRlbmVkID0gdGhpcy5mbGF0dGVuRm9ybVZhbHVlcygpO1xuICAgIHRoaXMuZm9ybVZhbHVlcy5zZXQoaW5pdGlhbEZsYXR0ZW5lZCk7XG4gICAgdGhpcy5wcmV2aW91c1ZhbHVlcyA9IHsgLi4uaW5pdGlhbEZsYXR0ZW5lZCB9O1xuICAgIHRoaXMuc2Vzc2lvbkJhc2VsaW5lLnNldCh7IC4uLmluaXRpYWxGbGF0dGVuZWQgfSk7XG4gICAgdGhpcy51bmxvY2tlZEZpZWxkcy5zZXQobmV3IFNldDxzdHJpbmc+KCkpO1xuICAgIHRoaXMuc3luY0hpZGRlbkZpZWxkU3RhdGUoaW5pdGlhbEZsYXR0ZW5lZCk7XG5cbiAgICBpZiAodGhpcy5wcmV2aWV3KSB7XG4gICAgICAvLyBTaG93IHdoYXQgYW4gYXJyYXkgZmllbGQgbG9va3MgbGlrZSByYXRoZXIgdGhhbiBhbiBlbXB0eSBzbG90LCB0aGVuIGZyZWV6ZS5cbiAgICAgIGZvciAoY29uc3QgZmllbGQgb2YgdGhpcy5hbGxGaWVsZHMoKSkge1xuICAgICAgICBpZiAoZmllbGQudHlwZSAhPT0gJ2FycmF5JykgY29udGludWU7XG4gICAgICAgIGNvbnN0IGFycmF5ID0gdGhpcy5nZXRBcnJheUNvbnRyb2woZmllbGQuaWQpO1xuICAgICAgICBpZiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoID09PSAwKSBhcnJheS5wdXNoKHRoaXMuYnVpbGRBcnJheVJvdyhmaWVsZCwgdW5kZWZpbmVkKSk7XG4gICAgICB9XG4gICAgICB0aGlzLmZvcm0uZGlzYWJsZSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgfVxuXG4gICAgLy8gUmVidWlsZGluZyBtdXN0IG5vdCBzdGFjayBzdWJzY3JpcHRpb25zIG9uIHN1Y2Nlc3NpdmUgY29uZmlnL2RhdGEgY2hhbmdlcy5cbiAgICB0aGlzLnZhbHVlU3ViPy51bnN1YnNjcmliZSgpO1xuICAgIGNvbnN0IGNoYW5nZXMkID0gdGhpcy5jaGFuZ2VEZWJvdW5jZU1zID4gMFxuICAgICAgPyB0aGlzLmZvcm0udmFsdWVDaGFuZ2VzLnBpcGUoZGVib3VuY2VUaW1lKHRoaXMuY2hhbmdlRGVib3VuY2VNcykpXG4gICAgICA6IHRoaXMuZm9ybS52YWx1ZUNoYW5nZXM7XG4gICAgdGhpcy52YWx1ZVN1YiA9IGNoYW5nZXMkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICBjb25zdCBmbGF0dGVuZWQgPSB0aGlzLmZsYXR0ZW5Gb3JtVmFsdWVzKCk7XG4gICAgICB0aGlzLmZvcm1WYWx1ZXMuc2V0KGZsYXR0ZW5lZCk7XG4gICAgICB0aGlzLnJ1blBhdGNoT25UcnVlKGZsYXR0ZW5lZCk7XG4gICAgICB0aGlzLnN5bmNIaWRkZW5GaWVsZFN0YXRlKGZsYXR0ZW5lZCk7XG4gICAgICB0aGlzLnByZXZpb3VzVmFsdWVzID0geyAuLi5mbGF0dGVuZWQgfTtcbiAgICAgIHRoaXMuZm9ybUNoYW5nZS5lbWl0KHRoaXMuZXh0cmFjdFJlY29yZCgpKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRGaWVsZENvbnRyb2woZmllbGQ6IE5lc3RlZEZpZWxkQ29uZmlnLCBncm91cDogUmVjb3JkPHN0cmluZywgQWJzdHJhY3RDb250cm9sPik6IHZvaWQge1xuICAgIGlmIChmaWVsZC50eXBlID09PSAnZ3JvdXAnKSB7XG4gICAgICBjb25zdCBzdWJHcm91cDogUmVjb3JkPHN0cmluZywgQWJzdHJhY3RDb250cm9sPiA9IHt9O1xuICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBmaWVsZC5jaGlsZHJlbiB8fCBbXSkge1xuICAgICAgICB0aGlzLmJ1aWxkRmllbGRDb250cm9sKGNoaWxkLCBzdWJHcm91cCk7XG4gICAgICB9XG4gICAgICBncm91cFtmaWVsZC5pZF0gPSB0aGlzLmZiLmdyb3VwKHN1Ykdyb3VwKTtcbiAgICB9IGVsc2UgaWYgKGZpZWxkLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgIGdyb3VwW2ZpZWxkLmlkXSA9IHRoaXMuZmIuYXJyYXkoW10pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB2YWxpZGF0b3JzID0gdGhpcy52YWxpZGF0b3JSZWdpc3RyeS5yZXNvbHZlRnJvbUNvbmZpZyhmaWVsZC52YWxpZGF0b3JzKTtcbiAgICAgIGNvbnN0IGFzeW5jVmFsaWRhdG9ycyA9IHRoaXMudmFsaWRhdG9yUmVnaXN0cnkucmVzb2x2ZUFzeW5jRnJvbUNvbmZpZyhmaWVsZC52YWxpZGF0b3JzKTtcbiAgICAgIGdyb3VwW2ZpZWxkLmlkXSA9IHRoaXMuZmIuY29udHJvbChcbiAgICAgICAgeyB2YWx1ZTogZmllbGQuZGVmYXVsdFZhbHVlID8/IG51bGwsIGRpc2FibGVkOiBmaWVsZC5kaXNhYmxlZCA/PyBmYWxzZSB9LFxuICAgICAgICB2YWxpZGF0b3JzLFxuICAgICAgICBhc3luY1ZhbGlkYXRvcnMsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBPbmUgcm93IG9mIGFuIGBhcnJheWAgZmllbGQ6IGEgRm9ybUdyb3VwIHdoZW4gdGhlIGZpZWxkIGRlY2xhcmVzIGNvbHVtbnMsIGVsc2UgYSBiYXJlIGNvbnRyb2wuICovXG4gIC8qKlxuICAgKiBUaGUgYEZvcm1BcnJheWAgYmVoaW5kIGFuIGBhcnJheWAgZmllbGQsIGZvciBjYWxsZXJzIHRoYXQgbWFuYWdlIHJvd3MgdGhlbXNlbHZlcyDigJRcbiAgICogdGhlIHJlY29yZCBlZGl0b3IncyBpbmxpbmUgcm93IGRyYXdlci5cbiAgICovXG4gIGdldEFycmF5Q29udHJvbChmaWVsZElkOiBzdHJpbmcsIHRhYklkPzogc3RyaW5nKTogRm9ybUFycmF5IHwgbnVsbCB7XG4gICAgY29uc3QgY3RybCA9IHRoaXMuZ2V0Q29udHJvbChmaWVsZElkLCB0YWJJZCk7XG4gICAgcmV0dXJuIGN0cmwgaW5zdGFuY2VvZiBGb3JtQXJyYXkgPyBjdHJsIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBvbmUgZGV0YWNoZWQgcm93IGZvciBhbiBgYXJyYXlgIGZpZWxkLCB3aXRoIHRoZSBmaWVsZCdzIG93biB2YWxpZGF0b3JzIGFwcGxpZWQuXG4gICAqIEV4cG9zZWQgc28gYSByb3cgY2FuIGJlIGVkaXRlZCBvdXRzaWRlIHRoZSBmb3JtIGFuZCBwdXNoZWQgb24gc2F2ZS5cbiAgICovXG4gIGNyZWF0ZUFycmF5Um93KGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZywgdmFsdWU/OiB1bmtub3duKTogQWJzdHJhY3RDb250cm9sIHtcbiAgICByZXR1cm4gdGhpcy5idWlsZEFycmF5Um93KGZpZWxkLCB2YWx1ZSk7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkQXJyYXlSb3coZmllbGQ6IE5lc3RlZEZpZWxkQ29uZmlnIHwgdW5kZWZpbmVkLCBpdGVtOiB1bmtub3duKTogQWJzdHJhY3RDb250cm9sIHtcbiAgICBpZiAoIWZpZWxkPy5jaGlsZHJlbj8ubGVuZ3RoKSByZXR1cm4gdGhpcy5mYi5jb250cm9sKGl0ZW0pO1xuXG4gICAgY29uc3Qgcm93R3JvdXA6IFJlY29yZDxzdHJpbmcsIEFic3RyYWN0Q29udHJvbD4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGZpZWxkLmNoaWxkcmVuKSB7XG4gICAgICB0aGlzLmJ1aWxkRmllbGRDb250cm9sKGNoaWxkLCByb3dHcm91cCk7XG4gICAgfVxuICAgIGNvbnN0IGdyb3VwID0gdGhpcy5mYi5ncm91cChyb3dHcm91cCk7XG4gICAgaWYgKGl0ZW0gJiYgdHlwZW9mIGl0ZW0gPT09ICdvYmplY3QnKSBncm91cC5wYXRjaFZhbHVlKGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pO1xuICAgIHJldHVybiBncm91cDtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXJrIGV2ZXJ5IGNvbnRyb2wgdG91Y2hlZCwgdGhlbiByZS1jaGVjayB0aGUgZmllbGQgY29tcG9uZW50cy5cbiAgICpcbiAgICogVGhleSBhcmUgT25QdXNoIGFuZCBgdG91Y2hlZGAgaXMgZmxpcHBlZCBmcm9tIG91dHNpZGUgdGhlaXIgb3duIHRlbXBsYXRlLCBzbyB0aGUgc2Vjb25kXG4gICAqIGhhbGYgaXMgd2hhdCBtYWtlcyB0aGUgZXJyb3IgbWVzc2FnZXMgYWN0dWFsbHkgYXBwZWFyLlxuICAgKi9cbiAgcHJpdmF0ZSBtYXJrQWxsVG91Y2hlZCgpOiB2b2lkIHtcbiAgICB0aGlzLmZvcm0ubWFya0FsbEFzVG91Y2hlZCgpO1xuICAgIHRoaXMuZmllbGRIb3N0cz8uZm9yRWFjaChob3N0ID0+IGhvc3QucmVmcmVzaCgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCcmluZyBhIHJlY29yZCB1cCB0byB0aGUgY29uZmlnJ3MgYHZlcnNpb25gIGJlZm9yZSBpdCByZWFjaGVzIHRoZSBmb3JtLlxuICAgKlxuICAgKiBEb25lIGhlcmUgYmVjYXVzZSB0aGlzIGlzIHRoZSBvbmUgcGxhY2UgYSByZWNvcmQgZW50ZXJzIHRoZSByZW5kZXJlciwgc28gYSBjb25zdW1lclxuICAgKiBjYW5ub3QgZm9yZ2V0IGl0LiBNaWdyYXRpb24gaXMgYSBuby1vcCB1bmxlc3MgdGhlIGNvbnN1bWVyIHJlZ2lzdGVyZWQgc3RlcHMgKmFuZCogdGhlXG4gICAqIHJlY29yZCBpcyBiZWhpbmQg4oCUIGFuIHVuc3RhbXBlZCByZWNvcmQgaXMgZGVsaWJlcmF0ZWx5IGxlZnQgYWxvbmUgKHNlZSBgbWlncmF0ZVJlY29yZGApLlxuICAgKlxuICAgKiBBIG1pc3Npbmcgb3IgYnJva2VuIHN0ZXAgdGhyb3dzIGZyb20gY29yZS4gVGhhdCBpcyBub3Qgc3dhbGxvd2VkOiByZW5kZXJpbmcgYVxuICAgKiBoYWxmLXVuZGVyc3Rvb2QgcmVjb3JkIHdvdWxkIHdyaXRlIGl0IGJhY2sgaW4gYSBzaGFwZSBtYXRjaGluZyBuZWl0aGVyIHNjaGVtYS5cbiAgICovXG4gIHByaXZhdGUgdXBncmFkZVJlY29yZChkYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgaWYgKCF0aGlzLm1pZ3JhdGlvbnMubGVuZ3RoIHx8ICF0aGlzLmNvbmZpZykgcmV0dXJuIGRhdGE7XG5cbiAgICBjb25zdCByZXN1bHQgPSBtaWdyYXRlUmVjb3JkKGRhdGEsIHRoaXMuY29uZmlnLCB0aGlzLm1pZ3JhdGlvbnMpO1xuICAgIGlmIChyZXN1bHQuYXBwbGllZC5sZW5ndGggJiYgaXNEZXZNb2RlKCkpIHtcbiAgICAgIGNvbnNvbGUuaW5mbyhcbiAgICAgICAgYFtuZ3gtZHluYW1pYy1lbnRpdHldIE1pZ3JhdGVkIGEgXCIke3RoaXMuY29uZmlnLmVudGl0eX1cIiByZWNvcmQgZnJvbSBjb25maWcgdmVyc2lvbiBgICtcbiAgICAgICAgICBgJHtyZXN1bHQuZnJvbX0gdG8gJHtyZXN1bHQudG99IChzdGVwczogJHtyZXN1bHQuYXBwbGllZC5qb2luKCcsICcpfSkuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQucmVjb3JkO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXRjaEZvcm0oZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgIGlmICghZGF0YSB8fCAhdGhpcy5mb3JtKSByZXR1cm47XG4gICAgY29uc3QgZmllbGRzQnlJZCA9IG5ldyBNYXAodGhpcy5hbGxGaWVsZHMoKS5tYXAoZiA9PiBbZi5pZCwgZl0pKTtcbiAgICBjb25zdCBwYXRjaGVkRmllbGRJZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAgIGNvbnN0IHdhbGtUYWJzID0gKHRhYnM6IE5lc3RlZFRhYkNvbmZpZ1tdKSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IHRhYiBvZiB0YWJzKSB7XG4gICAgICAgIGNvbnN0IHRhYkRhdGEgPSBnZXRUYWJEYXRhKHRhYi5pZCwgZGF0YSwgdGhpcy5jb25maWcpO1xuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRhYi5maWVsZHMgfHwgW10pIHtcbiAgICAgICAgICBsZXQgdmFsID0gdGFiRGF0YSAmJiB0eXBlb2YgdGFiRGF0YSA9PT0gJ29iamVjdCcgPyB0YWJEYXRhW2ZpZWxkLmlkXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICBpZiAoZmllbGQucmVmZXJlckZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCByZWZWYWwgPSBnZXRWYWx1ZUJ5UGF0aChkYXRhLCBmaWVsZC5yZWZlcmVyRmllbGQpO1xuICAgICAgICAgICAgaWYgKHJlZlZhbCAhPT0gdW5kZWZpbmVkKSB2YWwgPSByZWZWYWw7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh2YWwgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG5cbiAgICAgICAgICBjb25zdCBjdHJsID0gdGhpcy5nZXRDb250cm9sKGZpZWxkLmlkLCB0YWIuaWQpO1xuICAgICAgICAgIGlmICghY3RybCkgY29udGludWU7XG5cbiAgICAgICAgICBpZiAoY3RybCBpbnN0YW5jZW9mIEZvcm1BcnJheSAmJiBBcnJheS5pc0FycmF5KHZhbCkpIHtcbiAgICAgICAgICAgIGN0cmwuY2xlYXIoKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiB2YWwpIHtcbiAgICAgICAgICAgICAgY3RybC5wdXNoKHRoaXMuYnVpbGRBcnJheVJvdyhmaWVsZHNCeUlkLmdldChmaWVsZC5pZCksIGl0ZW0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY3RybC5wYXRjaFZhbHVlKHZhbCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwYXRjaGVkRmllbGRJZHMuYWRkKGZpZWxkLmlkKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGFiLmNoaWxkcmVuKSB3YWxrVGFicyh0YWIuY2hpbGRyZW4pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB3YWxrVGFicyh0aGlzLmNvbmZpZy50YWJzIHx8IFtdKTtcbiAgICB0aGlzLndhcm5VbmNvbnN1bWVkSW5pdGlhbERhdGEoZGF0YSwgZmllbGRzQnlJZCwgcGF0Y2hlZEZpZWxkSWRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHJlY29yZCBpcyBuZXN0ZWQgYnkgdGFiIGlkIChgeyB0YWJJZDogeyBmaWVsZElkOiB2YWx1ZSB9IH1gKSB1bmxlc3MgdGhlIHRhYiBzZXRzXG4gICAqIGBmbGF0RGF0YTogdHJ1ZWAuIEhhbmRpbmcgYSBmbGF0IHJlY29yZCB0byBhIG5lc3RlZCB0YWIgZmluZHMgbm90aGluZywgc28gdGhlIGZpZWxkc1xuICAgKiBzdGF5IGVtcHR5IOKAlCB3aXRoIG5vIGVycm9yIGFuZCBubyBjbHVlLiBUaGF0IHNpbGVudCBtaXNzIGlzIHRoZSBtb3N0IGV4cGVuc2l2ZSB3YXkgdG9cbiAgICogbG9zZSBhbiBob3VyIHdpdGggdGhpcyBsaWJyYXJ5LCBzbyBuYW1lIGl0IGluIGRldiBidWlsZHMuXG4gICAqXG4gICAqIE9ubHkgdG9wLWxldmVsIGtleXMgdGhhdCBtYXRjaCBhIGtub3duIGZpZWxkIGlkIGFyZSByZXBvcnRlZDogYW55dGhpbmcgZWxzZSBpcyBhc3N1bWVkXG4gICAqIHRvIGJlIHRoZSBjb25zdW1lcidzIG93biByZWNvcmQgbWV0YWRhdGEgKGlkcywgdGltZXN0YW1wcywgYF9jb25maWdWZXJzaW9uYCkgYW5kIGlzIG5vdFxuICAgKiBvdXIgYnVzaW5lc3MuXG4gICAqL1xuICBwcml2YXRlIHdhcm5VbmNvbnN1bWVkSW5pdGlhbERhdGEoXG4gICAgZGF0YTogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBmaWVsZHNCeUlkOiBNYXA8c3RyaW5nLCBOZXN0ZWRGaWVsZENvbmZpZz4sXG4gICAgcGF0Y2hlZEZpZWxkSWRzOiBTZXQ8c3RyaW5nPixcbiAgKTogdm9pZCB7XG4gICAgaWYgKCFpc0Rldk1vZGUoKSB8fCAhdGhpcy5jb25maWcpIHJldHVybjtcblxuICAgIGNvbnN0IHRhYklkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IGNvbGxlY3RUYWJJZHMgPSAodGFiczogTmVzdGVkVGFiQ29uZmlnW10pID0+IHtcbiAgICAgIGZvciAoY29uc3QgdGFiIG9mIHRhYnMpIHtcbiAgICAgICAgdGFiSWRzLmFkZCh0YWIuaWQpO1xuICAgICAgICBpZiAodGFiLmNoaWxkcmVuKSBjb2xsZWN0VGFiSWRzKHRhYi5jaGlsZHJlbik7XG4gICAgICB9XG4gICAgfTtcbiAgICBjb2xsZWN0VGFiSWRzKHRoaXMuY29uZmlnLnRhYnMgfHwgW10pO1xuXG4gICAgY29uc3QgdW5jb25zdW1lZCA9IE9iamVjdC5rZXlzKGRhdGEpLmZpbHRlcihcbiAgICAgIGtleSA9PlxuICAgICAgICAhdGFiSWRzLmhhcyhrZXkpICYmIC8vIGEgdGFiIGlkIGF0IHRoZSByb290IGlzIHRoZSBuZXN0ZWQgY29udGFpbmVyLCBub3QgYSBzdHJheSBmaWVsZFxuICAgICAgICBkYXRhW2tleV0gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICBmaWVsZHNCeUlkLmhhcyhrZXkpICYmXG4gICAgICAgICFwYXRjaGVkRmllbGRJZHMuaGFzKGtleSkgJiZcbiAgICAgICAgIXRoaXMud2FybmVkVW5jb25zdW1lZEtleXMuaGFzKGtleSksXG4gICAgKTtcbiAgICBpZiAoIXVuY29uc3VtZWQubGVuZ3RoKSByZXR1cm47XG5cbiAgICBmb3IgKGNvbnN0IGtleSBvZiB1bmNvbnN1bWVkKSB0aGlzLndhcm5lZFVuY29uc3VtZWRLZXlzLmFkZChrZXkpO1xuXG4gICAgY29uc3Qgc2hvd24gPSB1bmNvbnN1bWVkLnNsaWNlKDAsIDUpLmpvaW4oJywgJyk7XG4gICAgY29uc3QgbW9yZSA9IHVuY29uc3VtZWQubGVuZ3RoID4gNSA/IGAgKCske3VuY29uc3VtZWQubGVuZ3RoIC0gNX0gbW9yZSlgIDogJyc7XG4gICAgY29uc3QgcGx1cmFsID0gdW5jb25zdW1lZC5sZW5ndGggPT09IDE7XG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYFtuZ3gtZHluYW1pYy1lbnRpdHldIGluaXRpYWxEYXRhIGhhcyB0b3AtbGV2ZWwgJHtwbHVyYWwgPyAna2V5JyA6ICdrZXlzJ30gbWF0Y2hpbmcgYCArXG4gICAgICAgIGAke3BsdXJhbCA/ICdhIGZpZWxkIHRoYXQgd2FzJyA6ICdmaWVsZHMgdGhhdCB3ZXJlJ30gbm90IHBvcHVsYXRlZDogJHtzaG93bn0ke21vcmV9LiBgICtcbiAgICAgICAgYEEgcmVjb3JkIGlzIG5lc3RlZCBieSB0YWIgaWQgKHsgdGFiSWQ6IHsgZmllbGRJZDogdmFsdWUgfSB9KSB1bmxlc3MgdGhlIHRhYiBzZXRzIGAgK1xuICAgICAgICBgZmxhdERhdGE6IHRydWUuIEVpdGhlciBuZXN0IHRoZSB2YWx1ZSB1bmRlciBpdHMgdGFiIGlkLCBvciBzZXQgZmxhdERhdGE6IHRydWUgb24gYCArXG4gICAgICAgIGB0aGUgdGFiIGhvbGRpbmcgJHtwbHVyYWwgPyAndGhhdCBmaWVsZCcgOiAndGhvc2UgZmllbGRzJ30uYCxcbiAgICApO1xuICB9XG5cbiAgLyoqIFdhcm4gb25jZSBwZXIga2V5IHBlciBmb3JtIGluc3RhbmNlIOKAlCBwYXRjaEZvcm0gcmUtcnVucyBvbiBldmVyeSBpbml0aWFsRGF0YSBjaGFuZ2UuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgd2FybmVkVW5jb25zdW1lZEtleXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAvKiogQXNzZW1ibGUgZnVsbCBuZXN0ZWQgcmVjb3JkIGZyb20gcGVyLXRhYiBGb3JtR3JvdXBzLCByZXNwZWN0aW5nIGZsYXREYXRhLCByZWZlcmVyRmllbGQgJiBhcnJheXMuICovXG4gIGV4dHJhY3RSZWNvcmQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgaWYgKCF0aGlzLmZvcm0gfHwgIXRoaXMuY29uZmlnKSByZXR1cm4ge307XG4gICAgbGV0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuXG4gICAgY29uc3Qgd2Fsa1RhYnMgPSAodGFiczogTmVzdGVkVGFiQ29uZmlnW10pID0+IHtcbiAgICAgIGZvciAoY29uc3QgdGFiIG9mIHRhYnMpIHtcbiAgICAgICAgY29uc3QgZmllbGRWYWxCYWc6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgb2YgdGFiLmZpZWxkcyB8fCBbXSkge1xuICAgICAgICAgIGNvbnN0IGN0cmwgPSB0aGlzLmdldENvbnRyb2woZmllbGQuaWQsIHRhYi5pZCk7XG4gICAgICAgICAgaWYgKGN0cmwpIHtcbiAgICAgICAgICAgIGZpZWxkVmFsQmFnW2ZpZWxkLmlkXSA9IGN0cmwudmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2V0VGFiRGF0YShyZWNvcmQsIHRhYi5pZCwgZmllbGRWYWxCYWcsIHRoaXMuY29uZmlnKTtcblxuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRhYi5maWVsZHMgfHwgW10pIHtcbiAgICAgICAgICBpZiAoZmllbGQucmVmZXJlckZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCBjdHJsID0gdGhpcy5nZXRDb250cm9sKGZpZWxkLmlkLCB0YWIuaWQpO1xuICAgICAgICAgICAgaWYgKGN0cmwpIHtcbiAgICAgICAgICAgICAgc2V0VmFsdWVCeVBhdGgocmVjb3JkLCBmaWVsZC5yZWZlcmVyRmllbGQsIGN0cmwudmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0YWIuY2hpbGRyZW4pIHdhbGtUYWJzKHRhYi5jaGlsZHJlbik7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHdhbGtUYWJzKHRoaXMuY29uZmlnLnRhYnMgfHwgW10pO1xuICAgIHJlY29yZCA9IG5vcm1hbGl6ZUFycmF5U3RydWN0dXJlcyhyZWNvcmQsIHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4gcmVjb3JkO1xuICB9XG5cbiAgcHJpdmF0ZSBmbGF0dGVuRm9ybVZhbHVlcygpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICBjb25zdCBvdXQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRoaXMuYWxsRmllbGRzKCkpIHtcbiAgICAgIGNvbnN0IGN0cmwgPSB0aGlzLmdldENvbnRyb2woZmllbGQuaWQpO1xuICAgICAgaWYgKGN0cmwpIG91dFtmaWVsZC5pZF0gPSBjdHJsLnZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUYWJHcm91cCh0YWJJZDogc3RyaW5nKTogRm9ybUdyb3VwIHwgbnVsbCB7XG4gICAgY29uc3QgcGF0aCA9IGdldFRhYlBhdGgodGhpcy5jb25maWc/LnRhYnMsIHRhYklkKTtcbiAgICBpZiAoIXBhdGggfHwgcGF0aC5sZW5ndGggPT09IDApIHJldHVybiB0aGlzLmZvcm07XG4gICAgbGV0IGN1cnI6IEFic3RyYWN0Q29udHJvbCB8IG51bGwgPSB0aGlzLmZvcm07XG4gICAgZm9yIChjb25zdCBwIG9mIHBhdGgpIHtcbiAgICAgIGlmICghY3VyciB8fCAhKGN1cnIgaW5zdGFuY2VvZiBGb3JtR3JvdXApKSByZXR1cm4gbnVsbDtcbiAgICAgIGN1cnIgPSBjdXJyLmdldChwKTtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnIgaW5zdGFuY2VvZiBGb3JtR3JvdXAgPyBjdXJyIDogbnVsbDtcbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBhdXRvUGF0Y2ggLyBwYXRjaE9uVHJ1ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogYGF1dG9QYXRjaGAg4oCUIGNvcHkgbWFwcGVkIGZpZWxkcyBvdXQgb2YgdGhlIHJlY29yZCB0aGUgdXNlciBqdXN0IHNlbGVjdGVkIGluIGFuXG4gICAqIGVudGl0eS1yZWYgZmllbGQgaW50byB0aGUgY29uZmlndXJlZCB0YXJnZXQgdGFiJ3MgY29udHJvbHMuXG4gICAqL1xuICBwcml2YXRlIHJ1bkF1dG9QYXRjaChmaWVsZElkOiBzdHJpbmcsIHJlY29yZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICBpZiAoIXJlY29yZCkgcmV0dXJuO1xuICAgIGNvbnN0IGZpZWxkID0gdGhpcy5hbGxGaWVsZHMoKS5maW5kKGYgPT4gZi5pZCA9PT0gZmllbGRJZCk7XG4gICAgY29uc3QgYXV0b1BhdGNoID0gZmllbGQ/LmF1dG9QYXRjaDtcbiAgICBpZiAoIWF1dG9QYXRjaCkgcmV0dXJuO1xuXG4gICAgY29uc3QgcGF0Y2ggPSBhcHBseUF1dG9QYXRjaChhdXRvUGF0Y2gsIHJlY29yZCk7XG4gICAgZm9yIChjb25zdCBbdGFyZ2V0SWQsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhwYXRjaCkpIHtcbiAgICAgIGNvbnN0IGNvbnRyb2wgPSB0aGlzLnJlc29sdmVUYXJnZXRDb250cm9sKGF1dG9QYXRjaCwgdGFyZ2V0SWQpO1xuICAgICAgY29udHJvbD8ucGF0Y2hWYWx1ZSh2YWx1ZSk7XG4gICAgfVxuICAgIC8vIFJlYWRvbmx5IHRhcmdldHMgaW50ZXJwb2xhdGUgYGNvbnRyb2wudmFsdWVgIHVuZGVyIE9uUHVzaC4gYGRldGVjdENoYW5nZXNgIG9uIHRoZVxuICAgIC8vIGhvc3RlZCBjb21wb25lbnQgZmx1c2hlcyB0aGF0IHdyaXRlIGltbWVkaWF0ZWx5IOKAlCBgbWFya0ZvckNoZWNrYCB3YWl0cyBmb3IgYSBsYXRlclxuICAgIC8vIHRpY2sgdGhhdCBhIFBsYXl3cmlnaHQgc2VsZWN0aW9uIG5ldmVyIHNjaGVkdWxlcy5cbiAgICB0aGlzLmZpZWxkSG9zdHM/LmZvckVhY2goaG9zdCA9PiBob3N0LnJlZnJlc2goKSk7XG4gIH1cblxuICAvKipcbiAgICogYHBhdGNoT25UcnVlYCDigJQgd2hlbiBhIGJvb2xlYW4vY2hlY2tib3ggZmllbGQgdHJhbnNpdGlvbnMgdG8gYHRydWVgLFxuICAgKiBjb3B5IGBmcm9tYCDihpIgYHRvYCB3aXRoaW4gdGhlIGN1cnJlbnQgcmVjb3JkLlxuICAgKi9cbiAgcHJpdmF0ZSBydW5QYXRjaE9uVHJ1ZSh2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRoaXMuYWxsRmllbGRzKCkpIHtcbiAgICAgIGNvbnN0IG1hcHBpbmdzID0gZmllbGQucGF0Y2hPblRydWU7XG4gICAgICBpZiAoIW1hcHBpbmdzPy5sZW5ndGgpIGNvbnRpbnVlO1xuXG4gICAgICBjb25zdCB3YXNUcnVlID0gdGhpcy5wcmV2aW91c1ZhbHVlc1tmaWVsZC5pZF0gPT09IHRydWU7XG4gICAgICBjb25zdCBpc1RydWUgPSB2YWx1ZXNbZmllbGQuaWRdID09PSB0cnVlO1xuICAgICAgaWYgKCFpc1RydWUgfHwgd2FzVHJ1ZSkgY29udGludWU7XG5cbiAgICAgIGNvbnN0IHBhdGNoID0gYXBwbHlQYXRjaE9uVHJ1ZShtYXBwaW5ncywgdmFsdWVzKTtcbiAgICAgIGZvciAoY29uc3QgW3RhcmdldElkLCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMocGF0Y2gpKSB7XG4gICAgICAgIHRoaXMuZ2V0Q29udHJvbCh0YXJnZXRJZCk/LnBhdGNoVmFsdWUodmFsdWUsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiogUHJlZmVyIGEgY29udHJvbCBkZWNsYXJlZCBvbiB0aGUgY29uZmlndXJlZCB0YXJnZXQgdGFiOyBmYWxsIGJhY2sgdG8gYSB0b3AtbGV2ZWwgY29udHJvbC4gKi9cbiAgcHJpdmF0ZSByZXNvbHZlVGFyZ2V0Q29udHJvbChhdXRvUGF0Y2g6IEF1dG9QYXRjaENvbmZpZywgdGFyZ2V0SWQ6IHN0cmluZyk6IEFic3RyYWN0Q29udHJvbCB8IG51bGwge1xuICAgIGNvbnN0IHRhYiA9IGZpbmRUYWIodGhpcy50YWJzLCBhdXRvUGF0Y2gudGFyZ2V0VGFiKTtcbiAgICBjb25zdCBpblRhcmdldFRhYiA9ICh0YWI/LmZpZWxkcyA/PyBbXSkuc29tZShmID0+IGYuaWQgPT09IHRhcmdldElkKTtcbiAgICBpZiAodGFiICYmICFpblRhcmdldFRhYikgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHRoaXMuZ2V0Q29udHJvbCh0YXJnZXRJZCwgYXV0b1BhdGNoLnRhcmdldFRhYik7XG4gIH1cblxuICAvLyDilIDilIDilIAgSGVscGVycyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogVGhlIGZpZWxkcyB0aGUgcmVuZGVyIGZpbHRlciBvcGVyYXRlcyBvbiDigJQgYSB0YWIncyBvd24gZmllbGRzLCBhdCBldmVyeSB0YWIgZGVwdGguXG4gICAqIERlbGliZXJhdGVseSBub3QgYGFsbEZpZWxkcygpYDogYGdyb3VwYCBhbmQgYGFycmF5YCBjaGlsZHJlbiBhcmUgc2hvd24gb3IgaGlkZGVuIHdpdGhcbiAgICogdGhlaXIgcGFyZW50LCBhbmQgdG9nZ2xpbmcgYSBjaGlsZCdzIHN0YXRlIGluZGVwZW5kZW50bHkgd291bGQgZmlnaHQgdGhlIHBhcmVudCdzLlxuICAgKi9cbiAgcHJpdmF0ZSB0YWJGaWVsZHMoKTogTmVzdGVkRmllbGRDb25maWdbXSB7XG4gICAgY29uc3Qgb3V0OiBOZXN0ZWRGaWVsZENvbmZpZ1tdID0gW107XG4gICAgY29uc3Qgd2FsayA9ICh0YWJzOiBOZXN0ZWRUYWJDb25maWdbXSB8IHVuZGVmaW5lZCkgPT4ge1xuICAgICAgZm9yIChjb25zdCB0YWIgb2YgdGFicyA/PyBbXSkge1xuICAgICAgICBvdXQucHVzaCguLi4odGFiLmZpZWxkcyA/PyBbXSkpO1xuICAgICAgICB3YWxrKHRhYi5jaGlsZHJlbik7XG4gICAgICB9XG4gICAgfTtcbiAgICB3YWxrKHRoaXMuY29uZmlnPy50YWJzKTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgLyoqXG4gICAqIEtlZXAgYSBoaWRkZW4gZmllbGQncyBjb250cm9sIG91dCBvZiBmb3JtIHZhbGlkaXR5LlxuICAgKlxuICAgKiBBIGZpZWxkIGhpZGRlbiBieSBhIHJ1bGUgb3IgYSBgc2hvd1doZW5gIGNvbmRpdGlvbiBpcyBmaWx0ZXJlZCBvdXQgb2YgdGhlIHJlbmRlciwgYnV0XG4gICAqIGl0cyB2YWxpZGF0b3JzIHN0YXkgYXR0YWNoZWQg4oCUIHNvIGEgaGlkZGVuICpyZXF1aXJlZCogZmllbGQgaG9sZHMgYGZvcm0uaW52YWxpZGAgdHJ1ZVxuICAgKiBmb3JldmVyLCBwZXJtYW5lbnRseSBkaXNhYmxpbmcgU2F2ZSB3aXRoIG5vdGhpbmcgb24gc2NyZWVuIHRvIGV4cGxhaW4gd2h5LlxuICAgKlxuICAgKiBEaXNhYmxpbmcgaXMgdGhlIGZpeCByYXRoZXIgdGhhbiBzdHJpcHBpbmcgdmFsaWRhdG9yczogQW5ndWxhciBleGNsdWRlcyBkaXNhYmxlZFxuICAgKiBjb250cm9scyBmcm9tIHZhbGlkaXR5LCBhbmQgdGhlIGZpZWxkJ3Mgb3duIHZhbGlkYXRvcnMgc3Vydml2ZSBpbnRhY3QgZm9yIHdoZW4gaXRcbiAgICogY29tZXMgYmFjay4gVmFsdWVzIGFyZSB1bnRvdWNoZWQg4oCUIGBmbGF0dGVuRm9ybVZhbHVlc2AgYW5kIGBleHRyYWN0UmVjb3JkYCBib3RoIHJlYWRcbiAgICogYGNvbnRyb2wudmFsdWVgLCB3aGljaCBhIGRpc2FibGVkIGNvbnRyb2wgc3RpbGwgY2Fycmllcywgc28gcnVsZSBldmFsdWF0aW9uIGFuZCB0aGVcbiAgICogZW1pdHRlZCByZWNvcmQgc2VlIGV4YWN0bHkgd2hhdCB0aGV5IHNhdyBiZWZvcmUuIFRoYXQgYWxzbyBrZWVwcyB0aGlzIGZyb20gZmVlZGluZ1xuICAgKiBiYWNrIG9uIGl0c2VsZjogaGlkaW5nIGEgZmllbGQgY2Fubm90IGNoYW5nZSB0aGUgdmFsdWVzIHRoZSBydWxlcyBhcmUgZXZhbHVhdGVkIG92ZXIuXG4gICAqXG4gICAqIFRoZSB2aXNpYmlsaXR5IHByZWRpY2F0ZSBpcyB0aGUgc2FtZSBvbmUgYGZpZWxkc0ZvckFjdGl2ZVRhYmAgZmlsdGVycyB3aXRoLCBzbyB3aGF0IGlzXG4gICAqIHJlbmRlcmVkIGFuZCB3aGF0IGNvdW50cyB0b3dhcmQgdmFsaWRpdHkgY2Fubm90IGRyaWZ0IGFwYXJ0LlxuICAgKi9cbiAgcHJpdmF0ZSBzeW5jSGlkZGVuRmllbGRTdGF0ZSh2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5wcmV2aWV3KSByZXR1cm47IC8vIHByZXZpZXcgZnJlZXplcyB0aGUgd2hvbGUgZm9ybSBvbiBwdXJwb3NlXG5cbiAgICBjb25zdCBoaWRkZW5CeVJ1bGUgPSBuZXcgU2V0KHRoaXMucnVsZVJlc3VsdCgpLmhpZGRlbkZpZWxkcyk7XG5cbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRoaXMudGFiRmllbGRzKCkpIHtcbiAgICAgIGNvbnN0IGN0cmwgPSB0aGlzLmdldENvbnRyb2woZmllbGQuaWQpO1xuICAgICAgaWYgKCFjdHJsKSBjb250aW51ZTtcblxuICAgICAgY29uc3QgaGlkZGVuID0gaGlkZGVuQnlSdWxlLmhhcyhmaWVsZC5pZCkgfHwgIWV2YWx1YXRlRmllbGRWaXNpYmlsaXR5KGZpZWxkLCB2YWx1ZXMpO1xuXG4gICAgICBpZiAoaGlkZGVuKSB7XG4gICAgICAgIGlmIChjdHJsLmVuYWJsZWQpIGN0cmwuZGlzYWJsZSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICB9IGVsc2UgaWYgKGN0cmwuZGlzYWJsZWQgJiYgIWZpZWxkLmRpc2FibGVkKSB7XG4gICAgICAgIGN0cmwuZW5hYmxlKHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiogRXZlcnkgZmllbGQgaW4gdGhlIGNvbmZpZywgaW5jbHVkaW5nIGBncm91cGAvYGFycmF5YCBjaGlsZHJlbi4gKi9cbiAgcHJpdmF0ZSBhbGxGaWVsZHMoKTogTmVzdGVkRmllbGRDb25maWdbXSB7XG4gICAgY29uc3Qgb3V0OiBOZXN0ZWRGaWVsZENvbmZpZ1tdID0gW107XG4gICAgY29uc3Qgd2Fsa0ZpZWxkcyA9IChmaWVsZHM6IE5lc3RlZEZpZWxkQ29uZmlnW10gfCB1bmRlZmluZWQpID0+IHtcbiAgICAgIGZvciAoY29uc3QgZiBvZiBmaWVsZHMgPz8gW10pIHtcbiAgICAgICAgb3V0LnB1c2goZik7XG4gICAgICAgIGlmIChmLmNoaWxkcmVuPy5sZW5ndGgpIHdhbGtGaWVsZHMoZi5jaGlsZHJlbik7XG4gICAgICB9XG4gICAgfTtcbiAgICBjb25zdCB3YWxrVGFicyA9ICh0YWJzOiBOZXN0ZWRUYWJDb25maWdbXSB8IHVuZGVmaW5lZCkgPT4ge1xuICAgICAgZm9yIChjb25zdCB0IG9mIHRhYnMgPz8gW10pIHtcbiAgICAgICAgd2Fsa0ZpZWxkcyh0LmZpZWxkcyk7XG4gICAgICAgIHdhbGtUYWJzKHQuY2hpbGRyZW4pO1xuICAgICAgfVxuICAgIH07XG4gICAgd2Fsa1RhYnModGhpcy5jb25maWc/LnRhYnMpO1xuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICAvKiogQW4gZW1wdHkgYG9yaWdpbmFsRGF0YWAgY291bnRzIGFzIFwibm90IHN1cHBsaWVkXCIg4oCUIGZhbGwgYmFjayB0byB0aGUgY2FwdHVyZWQgYmFzZWxpbmUuICovXG4gIHByaXZhdGUgYmFzZWxpbmUoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3Qgc3VwcGxpZWQgPSB0aGlzLm9yaWdpbmFsRGF0YTtcbiAgICBpZiAoc3VwcGxpZWQgJiYgT2JqZWN0LmtleXMoc3VwcGxpZWQpLmxlbmd0aCA+IDApIHJldHVybiBzdXBwbGllZDtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uQmFzZWxpbmUoKTtcbiAgfVxuXG4gIHByaXZhdGUgc2FtZVZhbHVlKGE6IHVua25vd24sIGI6IHVua25vd24pOiBib29sZWFuIHtcbiAgICBpZiAoYSA9PT0gYikgcmV0dXJuIHRydWU7XG4gICAgY29uc3QgYUVtcHR5ID0gYSA9PT0gbnVsbCB8fCBhID09PSB1bmRlZmluZWQgfHwgYSA9PT0gJyc7XG4gICAgY29uc3QgYkVtcHR5ID0gYiA9PT0gbnVsbCB8fCBiID09PSB1bmRlZmluZWQgfHwgYiA9PT0gJyc7XG4gICAgaWYgKGFFbXB0eSAmJiBiRW1wdHkpIHJldHVybiB0cnVlO1xuICAgIGlmICh0eXBlb2YgYSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIGIgPT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYSA/PyBudWxsKSA9PT0gSlNPTi5zdHJpbmdpZnkoYiA/PyBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZ2V0Q29udHJvbChmaWVsZElkOiBzdHJpbmcsIGN1cnJlbnRUYWJJZD86IHN0cmluZyk6IEFic3RyYWN0Q29udHJvbCB8IG51bGwge1xuICAgIGlmICghdGhpcy5mb3JtKSByZXR1cm4gbnVsbDtcblxuICAgIGlmIChjdXJyZW50VGFiSWQpIHtcbiAgICAgIGNvbnN0IHRhYkdycCA9IHRoaXMuZ2V0VGFiR3JvdXAoY3VycmVudFRhYklkKTtcbiAgICAgIGNvbnN0IGN0cmwgPSB0YWJHcnA/LmdldChmaWVsZElkKTtcbiAgICAgIGlmIChjdHJsKSByZXR1cm4gY3RybDtcbiAgICB9XG5cbiAgICBjb25zdCByb290Q3RybCA9IHRoaXMuZm9ybS5nZXQoZmllbGRJZCk7XG4gICAgaWYgKHJvb3RDdHJsKSByZXR1cm4gcm9vdEN0cmw7XG5cbiAgICBjb25zdCBmaW5kSW5Hcm91cCA9IChncm91cDogRm9ybUdyb3VwKTogQWJzdHJhY3RDb250cm9sIHwgbnVsbCA9PiB7XG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhncm91cC5jb250cm9scykpIHtcbiAgICAgICAgY29uc3QgYyA9IGdyb3VwLmNvbnRyb2xzW2tleV07XG4gICAgICAgIGlmIChrZXkgPT09IGZpZWxkSWQpIHJldHVybiBjO1xuICAgICAgICBpZiAoYyBpbnN0YW5jZW9mIEZvcm1Hcm91cCkge1xuICAgICAgICAgIGNvbnN0IGZvdW5kID0gZmluZEluR3JvdXAoYyk7XG4gICAgICAgICAgaWYgKGZvdW5kKSByZXR1cm4gZm91bmQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICByZXR1cm4gZmluZEluR3JvdXAodGhpcy5mb3JtKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3ZlIGZvY3VzIGludG8gdGhlIG5ld2x5IHNob3duIHBhbmVsLlxuICAgKlxuICAgKiBBY3RpdmF0aW5nIGEgdGFiIHJlcGxhY2VzIGV2ZXJ5dGhpbmcgYmVsb3cgaXQgd2hpbGUgZm9jdXMgc3RheXMgb24gdGhlIHRhYiBidXR0b24sIHNvIGFcbiAgICogc2NyZWVuLXJlYWRlciBvciBrZXlib2FyZCB1c2VyIGlzIGdpdmVuIG5vIGluZGljYXRpb24gdGhhdCB0aGUgY29udGVudCBjaGFuZ2VkIGFuZCBtdXN0XG4gICAqIHRhYiBiYWNrIHRocm91Z2ggdGhlIHN0cmlwIHRvIHJlYWNoIGl0LiBEZWZlcnJlZCBhIGZyYW1lIGJlY2F1c2UgdGhlIHBhbmVsJ3MgY29udGVudHNcbiAgICogYXJlIHJlbmRlcmVkIGJ5IHRoZSBjaGFuZ2UgZGV0ZWN0aW9uIHRoaXMgY2FsbCBpcyBwYXJ0IG9mLlxuICAgKi9cbiAgcHJpdmF0ZSBmb2N1c0FjdGl2ZVBhbmVsKCk6IHZvaWQge1xuICAgIGlmICh0eXBlb2YgcmVxdWVzdEFuaW1hdGlvbkZyYW1lICE9PSAnZnVuY3Rpb24nKSByZXR1cm47XG4gICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHRoaXMuZm9ybVBhbmVsPy5uYXRpdmVFbGVtZW50Py5mb2N1cz8uKCkpO1xuICB9XG5cbiAgLyoqIEFjY2Vzc2libGUgbmFtZSBmb3IgdGhlIGZpZWxkIHBhbmVsIOKAlCBpdCBpcyB0aGUgdGFicGFuZWwgZm9yIHRoZSBhY3RpdmUgdGFiLiAqL1xuICBnZXQgYWN0aXZlVGFiTGFiZWwoKTogc3RyaW5nIHtcbiAgICBjb25zdCB0YWIgPSB0aGlzLmFjdGl2ZVN1YlRhYkNvbmZpZyA/PyB0aGlzLmFjdGl2ZVRhYkNvbmZpZztcbiAgICByZXR1cm4gdGFiID8gdGhpcy5yZXNvbHZlVGFiTGFiZWwodGFiKSA6ICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoeSBhIHJlZmVyZW5jZWQgZmllbGQgaXMgZmxhZ2dlZC5cbiAgICpcbiAgICogYGhhc0RyaWZ0YCB3YXMgd3JpdHRlbiBieSB0aGUgYnVpbGRlciBhbmQgcmVhZCBieSBub3RoaW5nIGF0IHJ1bnRpbWUsIHNvIGEgZmllbGQgd2hvc2VcbiAgICogc291cmNlIGRlZmluaXRpb24gaGFkIGNoYW5nZWQgc2luY2UgaXQgd2FzIGxpbmtlZCBsb29rZWQgZW50aXJlbHkgbm9ybWFsIHRvIHRoZSBwZXJzb25cbiAgICogZmlsbGluZyB0aGUgZm9ybSBpbi5cbiAgICovXG4gIGRyaWZ0SGludChmaWVsZDogTmVzdGVkRmllbGRDb25maWcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHNvdXJjZSA9IGZpZWxkLnJlZmVyZW5jZWRFbnRpdHlLZXlcbiAgICAgID8gYFwiJHtmaWVsZC5yZWZlcmVuY2VkRW50aXR5S2V5fVwiYFxuICAgICAgOiAnaXRzIHNvdXJjZSBlbnRpdHknO1xuICAgIHJldHVybiBgVGhpcyBmaWVsZCBpcyBsaW5rZWQgdG8gJHtzb3VyY2V9IGFuZCBpdHMgZGVmaW5pdGlvbiB0aGVyZSBoYXMgY2hhbmdlZCBzaW5jZSBpdCB3YXMgbGlua2VkLmA7XG4gIH1cblxuICByZXNvbHZlVGFiTGFiZWwodGFiOiBOZXN0ZWRUYWJDb25maWcpOiBzdHJpbmcge1xuICAgIHJldHVybiByZXNvbHZlTGFiZWwodGFiLmxhYmVsLCB0aGlzLmxhbmd1YWdlKTtcbiAgfVxuXG4gIGFzeW5jIHN1Ym1pdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuY2FuU3VibWl0IHx8IHRoaXMuc3VibWl0QmxvY2tlZCkge1xuICAgICAgdGhpcy5tYXJrQWxsVG91Y2hlZCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJhd0RhdGEgPSB0aGlzLmV4dHJhY3RSZWNvcmQoKTtcbiAgICBsZXQgcHJvY2Vzc2VkRGF0YSA9IHJhd0RhdGE7XG5cbiAgICB0aGlzLmlzU2F2aW5nLnNldCh0cnVlKTtcbiAgICB0cnkge1xuICAgICAgLy8gYmVmb3JlU2F2ZSBjYW4gbm93IGFib3J0IHRoZSBzYXZlOiByZXR1cm5pbmcgZmFsc2UsIG9yIHRocm93aW5nLCBzdG9wcyBpdC4gUHJldmlvdXNseVxuICAgICAgLy8gaXRzIHJldHVybiB2YWx1ZSBzaW1wbHkgcmVwbGFjZWQgdGhlIHBheWxvYWQgYW5kIHRoZSBzdWJtaXQgcHJvY2VlZGVkIHJlZ2FyZGxlc3MsIHNvXG4gICAgICAvLyBhIGhvb2sgdGhhdCB3YW50ZWQgdG8gdmV0byDigJQgYSBzZXJ2ZXItc2lkZSBjaGVjaywgYSBjb25maXJtYXRpb24g4oCUIGhhZCBubyB3YXkgdG8uXG4gICAgICBjb25zdCBob29rS2V5ID0gYCR7dGhpcy5jb25maWc/LmVudGl0eX06YmVmb3JlU2F2ZWA7XG4gICAgICBpZiAodGhpcy5ob29rUmVnaXN0cnkuaGFzKGhvb2tLZXkpKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuaG9va1JlZ2lzdHJ5LnJ1bihob29rS2V5LCBwcm9jZXNzZWREYXRhKTtcbiAgICAgICAgaWYgKHJlc3VsdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICB0aGlzLnNhdmVSZWplY3RlZC5lbWl0KHsgcmVhc29uOiAnYmVmb3JlU2F2ZSByZXR1cm5lZCBmYWxzZScgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFueXRoaW5nIGVsc2UgaXMgdGhlIHBheWxvYWQgdG8gc3VibWl0OyBgdW5kZWZpbmVkYCBtZWFucyBcInVuY2hhbmdlZFwiLlxuICAgICAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQgJiYgcmVzdWx0ICE9PSB0cnVlKSBwcm9jZXNzZWREYXRhID0gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICB0aGlzLmZvcm1TdWJtaXQuZW1pdChwcm9jZXNzZWREYXRhKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIEEgaG9vayB0aGF0IHRocm93cyBhYm9ydHMgdGhlIHNhdmUgYW5kIHJlcG9ydHMgd2h5LCByYXRoZXIgdGhhbiB0aGUgZXJyb3IgZXNjYXBpbmdcbiAgICAgIC8vIGludG8gYW4gdW5oYW5kbGVkIHJlamVjdGlvbiB3aXRoIHRoZSBmb3JtIGxlZnQgbG9va2luZyBhcyB0aG91Z2ggaXQgc2F2ZWQuXG4gICAgICB0aGlzLnNhdmVSZWplY3RlZC5lbWl0KHsgcmVhc29uOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksIGVycm9yOiBlcnIgfSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuaXNTYXZpbmcuc2V0KGZhbHNlKTtcbiAgICB9XG4gIH1cblxuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLmZvcm0ucmVzZXQoKTtcbiAgICBpZiAodGhpcy5pbml0aWFsRGF0YSkgdGhpcy5wYXRjaEZvcm0odGhpcy5pbml0aWFsRGF0YSk7XG4gICAgY29uc3QgdmFsdWVzID0gdGhpcy5mbGF0dGVuRm9ybVZhbHVlcygpO1xuICAgIHRoaXMuZm9ybVZhbHVlcy5zZXQodmFsdWVzKTtcbiAgICB0aGlzLnByZXZpb3VzVmFsdWVzID0geyAuLi52YWx1ZXMgfTtcbiAgICB0aGlzLnVubG9ja2VkRmllbGRzLnNldChuZXcgU2V0PHN0cmluZz4oKSk7XG4gICAgdGhpcy5mb3JtUmVzZXQuZW1pdCgpO1xuICB9XG59XG4iLCJAaWYgKGNhblZpZXcpIHtcbiAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmb3JtXCIgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCIgY2xhc3M9XCJuZ3gtZm9ybVwiIG5vdmFsaWRhdGU+XG5cbiAgICA8IS0tIEVycm9yIG1lc3NhZ2UgYmFubmVyIC0tPlxuICAgIEBpZiAoZXJyb3IpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJuZ3gtZm9ybV9fZXJyb3ItYmFubmVyXCIgcm9sZT1cImFsZXJ0XCIgZGF0YS10ZXN0aWQ9XCJmb3JtLWVycm9yXCI+e3sgZXJyb3IgfX08L2Rpdj5cbiAgICB9XG5cbiAgICA8IS0tIFJ1bGVzIEluZm8gQmFubmVycyAtLT5cbiAgICBAZm9yIChpbmZvS2V5IG9mIHNob3dJbmZvQmFubmVycyA/IE9iamVjdC5rZXlzKHJ1bGVSZXN1bHQoKS5pbmZvQmFubmVycykgOiBbXTsgdHJhY2sgaW5mb0tleSkge1xuICAgICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX19pbmZvLWJhbm5lclwiIHJvbGU9XCJzdGF0dXNcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInaW5mby1iYW5uZXItJyArIGluZm9LZXlcIj5cbiAgICAgICAg4oS577iPIHt7IHJ1bGVSZXN1bHQoKS5pbmZvQmFubmVyc1tpbmZvS2V5XSB9fVxuICAgICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPCEtLSBSdWxlcyBWYWxpZGF0aW9uIEVycm9ycyAmIFdhcm5pbmdzIC0tPlxuICAgIEBmb3IgKGVycktleSBvZiBPYmplY3Qua2V5cyhydWxlUmVzdWx0KCkudmFsaWRhdGlvbkVycm9ycyk7IHRyYWNrIGVycktleSkge1xuICAgICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX19lcnJvci1iYW5uZXJcIiByb2xlPVwiYWxlcnRcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCIncnVsZS1lcnJvci0nICsgZXJyS2V5XCI+XG4gICAgICAgIOKaoO+4jyB7eyBydWxlUmVzdWx0KCkudmFsaWRhdGlvbkVycm9yc1tlcnJLZXldIH19XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gICAgQGZvciAod2FybktleSBvZiBPYmplY3Qua2V5cyhydWxlUmVzdWx0KCkudmFsaWRhdGlvbldhcm5pbmdzKTsgdHJhY2sgd2FybktleSkge1xuICAgICAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX193YXJuaW5nLWJhbm5lclwiIHJvbGU9XCJzdGF0dXNcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCIncnVsZS13YXJuaW5nLScgKyB3YXJuS2V5XCI+XG4gICAgICAgIOKaoSB7eyBydWxlUmVzdWx0KCkudmFsaWRhdGlvbldhcm5pbmdzW3dhcm5LZXldIH19XG4gICAgICA8L2Rpdj5cbiAgICB9XG5cbiAgICA8IS0tIERlZmVycmVkIFZBTFVFX0NIQU5HRUQgbm90aWNlIGZvciBjcml0aWNhbEZpZWxkIGVkaXRzICh2cyBzZXNzaW9uIGJhc2VsaW5lKSAtLT5cbiAgICBAaWYgKGNoYW5nZWRDcml0aWNhbEZpZWxkcygpLmxlbmd0aCA+IDApIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJuZ3gtZm9ybV9fd2FybmluZy1iYW5uZXJcIiByb2xlPVwic3RhdHVzXCIgZGF0YS10ZXN0aWQ9XCJjcml0aWNhbC1jaGFuZ2UtYmFubmVyXCI+XG4gICAgICAgIPCflJIgQ3JpdGljYWwgZmllbGQgY2hhbmdlZDpcbiAgICAgICAgQGZvciAoZmllbGQgb2YgY2hhbmdlZENyaXRpY2FsRmllbGRzKCk7IHRyYWNrIGZpZWxkLmlkKSB7XG4gICAgICAgICAgPHNwYW4+e3sgcmVzb2x2ZUZpZWxkTGFiZWwoZmllbGQpIH19e3sgJGxhc3QgPyAnJyA6ICcsICcgfX08L3NwYW4+XG4gICAgICAgIH1cbiAgICAgICAg4oCUIHRoaXMgZGlmZmVycyBmcm9tIHRoZSB2YWx1ZSBhdCB0aGUgc3RhcnQgb2YgdGhpcyBzZXNzaW9uLlxuICAgICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPCEtLSBQcmltYXJ5IFRhYiBiYXIg4oCUIG9ubHkgaWYgdmlzaWJsZSB0YWJzIGRlZmluZWQgLS0+XG4gICAgQGlmICh2aXNpYmxlVGFicy5sZW5ndGggPiAwKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwibmd4LWZvcm1fX3RhYnNcIiByb2xlPVwidGFibGlzdFwiIGRhdGEtdGVzdGlkPVwidGFiLXN0cmlwXCI+XG4gICAgICAgIEBmb3IgKHRhYiBvZiB2aXNpYmxlVGFiczsgdHJhY2sgdGFiLmlkKSB7XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBjbGFzcz1cIm5neC1mb3JtX190YWJcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ3RhYi0nICsgdGFiLmlkXCJcbiAgICAgICAgICAgIFtjbGFzcy5uZ3gtZm9ybV9fdGFiLS1hY3RpdmVdPVwiYWN0aXZlVGFiKCkgPT09IHRhYi5pZFwiXG4gICAgICAgICAgICAoY2xpY2spPVwic2V0QWN0aXZlVGFiKHRhYi5pZClcIlxuICAgICAgICAgICAgcm9sZT1cInRhYlwiXG4gICAgICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImFjdGl2ZVRhYigpID09PSB0YWIuaWRcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt7IHJlc29sdmVUYWJMYWJlbCh0YWIpIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIH1cblxuICAgIDwhLS0gU3ViLXRhYiBiYXIg4oCUIG9ubHkgaWYgYWN0aXZlIHRhYiBoYXMgc3ViLXRhYnMgLS0+XG4gICAgQGlmICh2aXNpYmxlU3ViVGFicy5sZW5ndGggPiAwKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwibmd4LWZvcm1fX3RhYnMgbmd4LWZvcm1fX3RhYnMtLXN1YlwiIHJvbGU9XCJ0YWJsaXN0XCIgZGF0YS10ZXN0aWQ9XCJzdWJ0YWItc3RyaXBcIiBzdHlsZT1cIm1hcmdpbi10b3A6IC0xMnB4OyBtYXJnaW4tYm90dG9tOiAxMnB4OyBmb250LXNpemU6IDEzcHg7XCI+XG4gICAgICAgIEBmb3IgKHN1YlRhYiBvZiB2aXNpYmxlU3ViVGFiczsgdHJhY2sgc3ViVGFiLmlkKSB7XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBjbGFzcz1cIm5neC1mb3JtX190YWIgbmd4LWZvcm1fX3RhYi0tc3ViXCJcbiAgICAgICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidzdWJ0YWItJyArIHN1YlRhYi5pZFwiXG4gICAgICAgICAgICBbY2xhc3Mubmd4LWZvcm1fX3RhYi0tYWN0aXZlXT1cIihhY3RpdmVTdWJUYWJDb25maWc/LmlkKSA9PT0gc3ViVGFiLmlkXCJcbiAgICAgICAgICAgIChjbGljayk9XCJzZXRBY3RpdmVTdWJUYWIoc3ViVGFiLmlkKVwiXG4gICAgICAgICAgICByb2xlPVwidGFiXCJcbiAgICAgICAgICAgIFthdHRyLmFyaWEtc2VsZWN0ZWRdPVwiKGFjdGl2ZVN1YlRhYkNvbmZpZz8uaWQpID09PSBzdWJUYWIuaWRcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt7IHJlc29sdmVUYWJMYWJlbChzdWJUYWIpIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIH1cblxuICAgIDwhLS1cbiAgICAgIE9uZSB0YWJwYW5lbCBwZXIgdGFiLCB3cmFwcGluZyBib3RoIGJyYW5jaGVzLiBGb2N1cyBtb3ZlcyBoZXJlIG9uIGEgdGFiIHN3aXRjaCwgYW5kIGFcbiAgICAgIG1vZHVsZSB0YWIgaXMgc3RpbGwgYSB0YWIg4oCUIHB1dHRpbmcgdGhlIHBhbmVsIHNlbWFudGljcyBvbiBvbmx5IHRoZSBmaWVsZHMgYnJhbmNoIGxlZnRcbiAgICAgIGEgbW9kdWxlIHRhYiB3aXRoIG5vd2hlcmUgZm9yIGZvY3VzIHRvIGxhbmQuXG4gICAgLS0+XG4gICAgPGRpdlxuICAgICAgcm9sZT1cInRhYnBhbmVsXCJcbiAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgI2Zvcm1QYW5lbFxuICAgICAgY2xhc3M9XCJuZ3gtZm9ybV9fdGFicGFuZWxcIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhY3RpdmVUYWJMYWJlbFwiXG4gICAgPlxuICAgIEBpZiAoYWN0aXZlVGFiTW9kdWxlQ29tcG9uZW50KSB7XG4gICAgICA8ZGl2IGNsYXNzPVwibmd4LWZvcm1fX21vZHVsZS1wYW5lbFwiIGRhdGEtdGVzdGlkPVwibW9kdWxlLXBhbmVsXCI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nQ29tcG9uZW50T3V0bGV0PVwiYWN0aXZlVGFiTW9kdWxlQ29tcG9uZW50OyBpbnB1dHM6IChhY3RpdmVTdWJUYWJDb25maWcgfHwgYWN0aXZlVGFiQ29uZmlnKT8ubW9kdWxlSW5wdXRzXCI+PC9uZy1jb250YWluZXI+XG4gICAgICA8L2Rpdj5cbiAgICB9IEBlbHNlIHtcbiAgICAgIDwhLS0gRmllbGRzIGZvciBhY3RpdmUgdGFiIChSZXNwb25zaXZlIDEyLWNvbHVtbiBncmlkKSAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJuZ3gtZm9ybV9fcGFuZWxcIiBkYXRhLXRlc3RpZD1cImZvcm0tcGFuZWxcIj5cbiAgICAgICAgQGZvciAoZmllbGQgb2YgZmllbGRzRm9yQWN0aXZlVGFiOyB0cmFjayBmaWVsZC5pZCkge1xuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwibmd4LWZvcm1fX2ZpZWxkLXNsb3RcIlxuICAgICAgICAgICAgW3N0eWxlLmdyaWRDb2x1bW5dPVwiZ2V0RmllbGRTcGFuKGZpZWxkKVwiXG4gICAgICAgICAgICBbYXR0ci5pZF09XCInZmllbGQtY29udGFpbmVyLScgKyBmaWVsZC5pZFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPG5neC1keW5hbWljLWZpZWxkXG4gICAgICAgICAgICAgIFtmaWVsZF09XCJmaWVsZFwiXG4gICAgICAgICAgICAgIFtjb250cm9sXT1cImdldENvbnRyb2woZmllbGQuaWQsIChhY3RpdmVTdWJUYWJDb25maWcgfHwgYWN0aXZlVGFiQ29uZmlnKT8uaWQpIVwiXG4gICAgICAgICAgICAgIFtjb25maWddPVwiY29uZmlnXCJcbiAgICAgICAgICAgICAgW2N1cnJlbnRUYWJJZF09XCIoYWN0aXZlU3ViVGFiQ29uZmlnIHx8IGFjdGl2ZVRhYkNvbmZpZyk/LmlkXCJcbiAgICAgICAgICAgICAgW2xhbmd1YWdlXT1cImxhbmd1YWdlXCJcbiAgICAgICAgICAgICAgW3JlYWRvbmx5XT1cImlzRmllbGRSZWFkb25seShmaWVsZClcIlxuICAgICAgICAgICAgICBbdXNlclJvbGVzXT1cInVzZXJSb2xlc1wiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgQGlmIChmaWVsZC5oYXNEcmlmdCkge1xuICAgICAgICAgICAgICA8IS0tXG4gICAgICAgICAgICAgICAgRHJpZnQgd2FzIHByZXZpb3VzbHkgdmlzaWJsZSBvbmx5IGluIHRoZSBidWlsZGVyLCBzbyBhIHJlZmVyZW5jZWQgZmllbGQgd2hvc2VcbiAgICAgICAgICAgICAgICBzb3VyY2UgaGFkIGNoYW5nZWQgbG9va2VkIGNvbXBsZXRlbHkgbm9ybWFsIHRvIHRoZSBwZXJzb24gZmlsbGluZyB0aGUgZm9ybSBpbi5cbiAgICAgICAgICAgICAgICByb2xlPVwic3RhdHVzXCIgcmF0aGVyIHRoYW4gXCJhbGVydFwiOiBpdCBpcyBpbmZvcm1hdGlvbiwgbm90IGFuIGVycm9yLlxuICAgICAgICAgICAgICAtLT5cbiAgICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgICBjbGFzcz1cIm5neC1maWVsZF9fZHJpZnRcIlxuICAgICAgICAgICAgICAgIHJvbGU9XCJzdGF0dXNcIlxuICAgICAgICAgICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLWRyaWZ0J1wiXG4gICAgICAgICAgICAgICAgW3RpdGxlXT1cImRyaWZ0SGludChmaWVsZClcIlxuICAgICAgICAgICAgICA+4pqgIHt7IGRyaWZ0SGludChmaWVsZCkgfX08L3NwYW4+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBAaWYgKGZpZWxkLmNyaXRpY2FsRmllbGQgJiYgIXJlYWRvbmx5KSB7XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cIm5neC1mb3JtX19sb2NrXCJcbiAgICAgICAgICAgICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCInbG9jay0nICsgZmllbGQuaWRcIlxuICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtcHJlc3NlZF09XCIhaXNGaWVsZExvY2tlZChmaWVsZClcIlxuICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiXG4gICAgICAgICAgICAgICAgICAoaXNGaWVsZExvY2tlZChmaWVsZCkgPyAnVW5sb2NrICcgOiAnTG9jayAnKSArIHJlc29sdmVGaWVsZExhYmVsKGZpZWxkKVxuICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgW3RpdGxlXT1cIlxuICAgICAgICAgICAgICAgICAgaXNGaWVsZExvY2tlZChmaWVsZClcbiAgICAgICAgICAgICAgICAgICAgPyAnQ3JpdGljYWwgZmllbGQg4oCUIGNsaWNrIHRvIHVubG9jayBmb3IgZWRpdGluZydcbiAgICAgICAgICAgICAgICAgICAgOiAnQ3JpdGljYWwgZmllbGQg4oCUIGNsaWNrIHRvIGxvY2snXG4gICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlRmllbGRMb2NrKGZpZWxkKVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7eyBpc0ZpZWxkTG9ja2VkKGZpZWxkKSA/ICfwn5SSJyA6ICfwn5STJyB9fVxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgfVxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBTdWJtaXQgYnV0dG9uIOKAlCBnYXRlZCBieSBSQkFDIGFuZCBpc1NhdmluZyBsb2NrIC0tPlxuICAgIEBpZiAoIXJlYWRvbmx5ICYmIHBlcm1pc3Npb25zLmNhbkVkaXQpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJuZ3gtZm9ybV9fYWN0aW9uc1wiIGRhdGEtdGVzdGlkPVwiZm9ybS1hY3Rpb25zXCI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICBjbGFzcz1cIm5neC1mb3JtX19yZXNldFwiXG4gICAgICAgICAgZGF0YS10ZXN0aWQ9XCJmb3JtLXJlc2V0XCJcbiAgICAgICAgICAoY2xpY2spPVwicmVzZXQoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cImlzU2F2aW5nKClcIlxuICAgICAgICA+XG4gICAgICAgICAgUmVzZXRcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICB0eXBlPVwic3VibWl0XCJcbiAgICAgICAgICBjbGFzcz1cIm5neC1mb3JtX19zdWJtaXRcIlxuICAgICAgICAgIGRhdGEtdGVzdGlkPVwiZm9ybS1zdWJtaXRcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJzdWJtaXRCbG9ja2VkXCJcbiAgICAgICAgICB0aXRsZT1cIlNob3J0Y3V0OiBDdHJsK1NcIlxuICAgICAgICA+XG4gICAgICAgICAgQGlmIChpc1NhdmluZygpIHx8IGxvYWRpbmcpIHtcbiAgICAgICAgICAgIFNhdmluZ+KAplxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgU2F2ZVxuICAgICAgICAgIH1cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICB9XG5cbiAgPC9mb3JtPlxufSBAZWxzZSB7XG4gIDwhLS0gcGVybWlzc2lvbnMudmlldyBkZW5pZWQ6IHJlbmRlciBub3RoaW5nIG9mIHRoZSByZWNvcmQuXG4gICAgICAgUHJlc2VudGF0aW9uYWwgb25seSDigJQgdGhlIHNlcnZlciBtdXN0IG5vdCBzZW5kIGRhdGEgdGhpcyB1c2VyIG1heSBub3Qgc2VlLiAtLT5cbiAgPGRpdiBjbGFzcz1cIm5neC1mb3JtX19kZW5pZWRcIiByb2xlPVwic3RhdHVzXCIgZGF0YS10ZXN0aWQ9XCJmb3JtLWFjY2Vzcy1kZW5pZWRcIj5cbiAgICBZb3UgZG8gbm90IGhhdmUgcGVybWlzc2lvbiB0byB2aWV3IHRoaXMgcmVjb3JkLlxuICA8L2Rpdj5cbn1cbiJdfQ==