@mediusinc/mng-commons 5.5.0-rc.0 → 5.5.0-rc.2

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 (170) hide show
  1. package/core/descriptors/table.descriptor.d.ts +4 -2
  2. package/core/directives/rerender.directive.d.ts +9 -0
  3. package/core/helpers/route.d.ts +25 -25
  4. package/core/index.d.ts +2 -0
  5. package/core/reactivity/effect.d.ts +16 -0
  6. package/esm2022/core/components/notification/notification-wrapper.component.mjs +4 -4
  7. package/esm2022/core/components/pages/error/error.page.component.mjs +4 -4
  8. package/esm2022/core/components/pages/not-found/not-found.page.component.mjs +4 -4
  9. package/esm2022/core/data-list/data-list-params-helpers.mjs +18 -3
  10. package/esm2022/core/descriptors/table.descriptor.mjs +1 -1
  11. package/esm2022/core/directives/component.directive.mjs +4 -4
  12. package/esm2022/core/directives/rerender.directive.mjs +25 -0
  13. package/esm2022/core/directives/template.directive.mjs +4 -4
  14. package/esm2022/core/index.mjs +4 -1
  15. package/esm2022/core/pipes/boolean.pipe.mjs +6 -6
  16. package/esm2022/core/pipes/class-map.pipe.mjs +4 -4
  17. package/esm2022/core/pipes/enum.pipe.mjs +4 -4
  18. package/esm2022/core/pipes/enumerate-async.pipe.mjs +4 -4
  19. package/esm2022/core/pipes/enumerate.pipe.mjs +4 -4
  20. package/esm2022/core/pipes/getter.pipe.mjs +5 -5
  21. package/esm2022/core/pipes/i18n-property.pipe.mjs +4 -4
  22. package/esm2022/core/pipes/json-path.pipe.mjs +4 -4
  23. package/esm2022/core/pipes/parametrize.pipe.mjs +4 -4
  24. package/esm2022/core/pipes/template.pipe.mjs +4 -4
  25. package/esm2022/core/reactivity/effect.mjs +22 -0
  26. package/esm2022/core/security/permission.service.mjs +4 -4
  27. package/esm2022/core/services/commons-init.service.mjs +4 -4
  28. package/esm2022/core/services/commons-router.service.mjs +4 -4
  29. package/esm2022/core/services/commons-storage.service.mjs +4 -4
  30. package/esm2022/core/services/commons.service.mjs +8 -8
  31. package/esm2022/filter/descriptors/filter-lookup.descriptor.mjs +32 -25
  32. package/esm2022/filter/descriptors/filter.descriptor.mjs +53 -1
  33. package/esm2022/form/components/autocomplete/autocomplete.component.mjs +4 -4
  34. package/esm2022/form/components/date-range/date-range.component.mjs +4 -4
  35. package/esm2022/form/components/dropdown/dropdown.component.mjs +4 -4
  36. package/esm2022/form/components/number-range/number-range.component.mjs +4 -4
  37. package/esm2022/form/directives/input-trim.directive.mjs +4 -4
  38. package/esm2022/table/api/descriptors/sort.descriptor.mjs +2 -2
  39. package/esm2022/table/api/descriptors/table.descriptor.mjs +32 -8
  40. package/esm2022/table/components/column-filter/column-filter.component.mjs +33 -40
  41. package/esm2022/table/components/column-value/column-value.component.mjs +6 -6
  42. package/esm2022/table/components/filter/filter-active-tag/filter-active-tag.component.mjs +7 -7
  43. package/esm2022/table/components/filter/filter-form/filter-form.component.mjs +24 -34
  44. package/esm2022/table/components/filter/filter-overlay-with-tag/filter-overlay-with-tag.component.mjs +44 -45
  45. package/esm2022/table/components/table/table.component.mjs +114 -430
  46. package/esm2022/table/helpers/filters.mjs +9 -25
  47. package/esm2022/table/helpers/table.mjs +24 -0
  48. package/esm2022/table/index.mjs +2 -2
  49. package/esm2022/table/models/column-preferences.model.mjs +1 -1
  50. package/esm2022/table/models/filter.model.mjs +1 -1
  51. package/esm2022/table/pipes/filter-value.pipe.mjs +4 -4
  52. package/esm2022/table/pipes/locale-default-row-class.pipe.mjs +4 -4
  53. package/esm2022/table/pipes/table-column-filter-class.pipe.mjs +4 -4
  54. package/esm2022/table/services/table-data.service.mjs +194 -0
  55. package/esm2022/table/services/table-metadata.service.mjs +136 -0
  56. package/esm2022/table/services/table-preferences.service.mjs +142 -0
  57. package/esm2022/tableview/action/components/action/action.component.mjs +6 -7
  58. package/esm2022/tableview/action/components/editor/action-editor.component.mjs +4 -4
  59. package/esm2022/tableview/action/components/editor/injector-context/action-editor-injector-context.component.mjs +69 -46
  60. package/esm2022/tableview/action/components/localization/data-language-dropdown.component.mjs +4 -4
  61. package/esm2022/tableview/action/components/route/action-route.component.mjs +5 -6
  62. package/esm2022/tableview/action/components/table/action-table.component.mjs +4 -4
  63. package/esm2022/tableview/action/helpers/action-execution.mjs +25 -0
  64. package/esm2022/tableview/action/models/execution/action-instance.model.mjs +2 -3
  65. package/esm2022/tableview/action/services/action-executor.service.mjs +12 -79
  66. package/esm2022/tableview/action/services/component-action-executor.service.mjs +4 -4
  67. package/esm2022/tableview/action/services/data-provider-executor.service.mjs +4 -4
  68. package/esm2022/tableview/action/services/navigation.service.mjs +4 -4
  69. package/esm2022/tableview/action/services/root-action-executor.service.mjs +4 -4
  70. package/esm2022/tableview/action/services/view-container.service.mjs +4 -4
  71. package/esm2022/tableview/api/action/descriptors/action-confirmation.descriptor.mjs +13 -1
  72. package/esm2022/tableview/api/action/descriptors/action-editor.descriptor.mjs +67 -10
  73. package/esm2022/tableview/api/action/descriptors/action-link-descriptor.factory.mjs +2 -2
  74. package/esm2022/tableview/api/action/descriptors/action-link.descriptor.mjs +17 -1
  75. package/esm2022/tableview/api/action/descriptors/action.descriptor.mjs +32 -7
  76. package/esm2022/tableview/api/action/models/execution/action-instance-state.model.mjs +2 -2
  77. package/esm2022/tableview/api/editor/descriptors/field-base.descriptor.mjs +20 -1
  78. package/esm2022/tableview/api/editor/descriptors/field-many.descriptor.mjs +2 -1
  79. package/esm2022/tableview/api/editor/models/formly-custom-field.model.mjs +4 -4
  80. package/esm2022/tableview/api/tableview/descriptors/tableview.descriptor.mjs +13 -5
  81. package/esm2022/tableview/api/tableview/helpers/tableview-default-actions.mjs +3 -2
  82. package/esm2022/tableview/api/tableview/helpers/tableview-descriptor-helpers.mjs +2 -2
  83. package/esm2022/tableview/editor/components/editor/auto-save-status/auto-save-status.component.mjs +4 -4
  84. package/esm2022/tableview/editor/components/editor/form-editor.component.mjs +31 -38
  85. package/esm2022/tableview/editor/components/formly/constants.mjs +2 -0
  86. package/esm2022/tableview/editor/components/formly/fields/formly-field-action/formly-field-action.component.mjs +4 -4
  87. package/esm2022/tableview/editor/components/formly/fields/formly-field-autocomplete/formly-field-autocomplete.component.mjs +7 -5
  88. package/esm2022/tableview/editor/components/formly/fields/formly-field-custom/formly-field-custom.component.mjs +4 -4
  89. package/esm2022/tableview/editor/components/formly/fields/formly-field-datepicker/formly-field-datepicker.component.mjs +7 -5
  90. package/esm2022/tableview/editor/components/formly/fields/formly-field-dropdown/formly-field-dropdown.component.mjs +7 -5
  91. package/esm2022/tableview/editor/components/formly/fields/formly-field-fieldset/formly-field-fieldset.component.mjs +4 -4
  92. package/esm2022/tableview/editor/components/formly/fields/formly-field-input/formly-field-input.component.mjs +5 -5
  93. package/esm2022/tableview/editor/components/formly/fields/formly-field-label/formly-field-label.component.mjs +4 -4
  94. package/esm2022/tableview/editor/components/formly/fields/formly-field-lookup-dialog/formly-field-lookup-dialog.component.mjs +5 -6
  95. package/esm2022/tableview/editor/components/formly/fields/formly-field-table-dialog-form/formly-field-table-dialog-form.component.mjs +10 -6
  96. package/esm2022/tableview/editor/components/formly/fields/formly-field-table-dialog-multiselect/formly-field-table-dialog-multiselect.component.mjs +11 -7
  97. package/esm2022/tableview/editor/components/formly/fields/formly-field-tabs/formly-field-tabs.component.mjs +4 -4
  98. package/esm2022/tableview/editor/components/formly/fields/formly-field-type.abstract.component.mjs +6 -5
  99. package/esm2022/tableview/editor/components/formly/pipes/formly-field-label.pipe.mjs +4 -4
  100. package/esm2022/tableview/editor/components/formly/wrappers/formly-field-no-label-wrapper/formly-field-no-label-wrapper.component.mjs +4 -4
  101. package/esm2022/tableview/editor/components/formly/wrappers/formly-field-wrapper/formly-field-wrapper.component.mjs +10 -5
  102. package/esm2022/tableview/editor/helpers/editor-autosave.mjs +2 -2
  103. package/esm2022/tableview/editor/services/form-editor.service.mjs +4 -4
  104. package/esm2022/tableview/index.mjs +1 -2
  105. package/esm2022/tableview/tableview/components/route/tableview-route.component.mjs +4 -4
  106. package/esm2022/tableview/tableview/components/tableview/tableview.component.mjs +4 -4
  107. package/fesm2022/mediusinc-mng-commons-core.mjs +130 -71
  108. package/fesm2022/mediusinc-mng-commons-core.mjs.map +1 -1
  109. package/fesm2022/mediusinc-mng-commons-filter.mjs +83 -24
  110. package/fesm2022/mediusinc-mng-commons-filter.mjs.map +1 -1
  111. package/fesm2022/mediusinc-mng-commons-form-api.mjs.map +1 -1
  112. package/fesm2022/mediusinc-mng-commons-form.mjs +15 -15
  113. package/fesm2022/mediusinc-mng-commons-form.mjs.map +1 -1
  114. package/fesm2022/mediusinc-mng-commons-model.mjs.map +1 -1
  115. package/fesm2022/mediusinc-mng-commons-table-api.mjs +32 -8
  116. package/fesm2022/mediusinc-mng-commons-table-api.mjs.map +1 -1
  117. package/fesm2022/mediusinc-mng-commons-table.mjs +700 -603
  118. package/fesm2022/mediusinc-mng-commons-table.mjs.map +1 -1
  119. package/fesm2022/mediusinc-mng-commons-tableview-api.mjs +165 -26
  120. package/fesm2022/mediusinc-mng-commons-tableview-api.mjs.map +1 -1
  121. package/fesm2022/mediusinc-mng-commons-tableview.mjs +265 -317
  122. package/fesm2022/mediusinc-mng-commons-tableview.mjs.map +1 -1
  123. package/fesm2022/mediusinc-mng-commons.mjs.map +1 -1
  124. package/filter/descriptors/filter-lookup.descriptor.d.ts +17 -20
  125. package/filter/descriptors/filter.descriptor.d.ts +32 -2
  126. package/form/components/date-range/date-range.component.d.ts +3 -3
  127. package/form/components/number-range/number-range.component.d.ts +2 -2
  128. package/package.json +4 -4
  129. package/table/api/descriptors/column.descriptor.d.ts +1 -1
  130. package/table/api/descriptors/sort.descriptor.d.ts +2 -2
  131. package/table/api/descriptors/table.descriptor.d.ts +21 -7
  132. package/table/components/column-filter/column-filter.component.d.ts +8 -14
  133. package/table/components/filter/filter-active-tag/filter-active-tag.component.d.ts +5 -5
  134. package/table/components/filter/filter-form/filter-form.component.d.ts +10 -19
  135. package/table/components/filter/filter-overlay-with-tag/filter-overlay-with-tag.component.d.ts +11 -13
  136. package/table/components/table/table.component.d.ts +20 -64
  137. package/table/helpers/filters.d.ts +4 -7
  138. package/table/helpers/table.d.ts +6 -0
  139. package/table/index.d.ts +1 -1
  140. package/table/models/column-preferences.model.d.ts +2 -2
  141. package/table/models/filter.model.d.ts +14 -2
  142. package/table/services/table-data.service.d.ts +36 -0
  143. package/table/services/table-metadata.service.d.ts +31 -0
  144. package/table/services/table-preferences.service.d.ts +25 -0
  145. package/tableview/action/components/editor/injector-context/action-editor-injector-context.component.d.ts +4 -7
  146. package/tableview/action/components/localization/data-language-dropdown.component.d.ts +1 -1
  147. package/tableview/action/helpers/action-execution.d.ts +7 -0
  148. package/tableview/action/models/execution/action-instance.model.d.ts +1 -2
  149. package/tableview/action/services/action-executor.service.d.ts +1 -2
  150. package/tableview/api/action/descriptors/action-confirmation.descriptor.d.ts +1 -0
  151. package/tableview/api/action/descriptors/action-editor.descriptor.d.ts +12 -4
  152. package/tableview/api/action/descriptors/action-link.descriptor.d.ts +1 -0
  153. package/tableview/api/action/descriptors/action.descriptor.d.ts +5 -3
  154. package/tableview/api/action/models/execution/action-instance-state.model.d.ts +1 -1
  155. package/tableview/api/editor/descriptors/field-base.descriptor.d.ts +15 -10
  156. package/tableview/api/editor/descriptors/field-group.descriptor.d.ts +1 -1
  157. package/tableview/api/tableview/descriptors/tableview.descriptor.d.ts +6 -4
  158. package/tableview/editor/components/editor/form-editor.component.d.ts +3 -2
  159. package/tableview/editor/components/formly/constants.d.ts +1 -0
  160. package/tableview/editor/components/formly/fields/formly-field-fieldset/formly-field-fieldset.component.d.ts +1 -1
  161. package/tableview/editor/components/formly/fields/formly-field-table-dialog-form/formly-field-table-dialog-form.component.d.ts +1 -0
  162. package/tableview/editor/components/formly/fields/formly-field-table-dialog-multiselect/formly-field-table-dialog-multiselect.component.d.ts +1 -0
  163. package/tableview/editor/components/formly/fields/formly-field-type.abstract.component.d.ts +2 -1
  164. package/tableview/editor/components/formly/wrappers/formly-field-wrapper/formly-field-wrapper.component.d.ts +1 -0
  165. package/tableview/index.d.ts +0 -1
  166. package/version-info.json +5 -5
  167. package/esm2022/table/services/data-list.service.mjs +0 -29
  168. package/esm2022/tableview/action/models/execution/action-instance-state.model.mjs +0 -32
  169. package/table/services/data-list.service.d.ts +0 -19
  170. package/tableview/action/models/execution/action-instance-state.model.d.ts +0 -30
@@ -1,5 +1,5 @@
1
- import { AsyncPipe, NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
2
- import { ChangeDetectionStrategy, Component, Injector, afterNextRender, booleanAttribute, computed, contentChildren, effect, inject, input, output, signal, viewChild, viewChildren } from '@angular/core';
1
+ import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
2
+ import { ChangeDetectionStrategy, Component, afterNextRender, booleanAttribute, computed, contentChildren, inject, input, output, signal, viewChild, viewChildren } from '@angular/core';
3
3
  import { outputFromObservable, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
4
4
  import { FormsModule } from '@angular/forms';
5
5
  import { ActivatedRoute, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';
@@ -9,21 +9,19 @@ import { ButtonModule } from 'primeng/button';
9
9
  import { MultiSelectModule } from 'primeng/multiselect';
10
10
  import { Table, TableModule } from 'primeng/table';
11
11
  import { TooltipModule } from 'primeng/tooltip';
12
- import { NEVER, Subject, combineLatest, of, switchMap } from 'rxjs';
13
- import { filter } from 'rxjs/operators';
14
- import { ClassMapPipe, CommonsService, CommonsStorageService, ComponentDirective, FilterMatchMode, I18nPropertyPipe, LoggerService, TemplateDirective, booleanOrUndefinedAttribute, toObservable as commonsToObservable, dataListParamsToUrlQuery, findTemplateByName, fromSubscribeError, fromTableLoadToDataListParams, fromUrlQueryToDataListParams, getErrorLogLevel, mergeDataListParamsWithDefaults } from '@mediusinc/mng-commons/core';
15
- import { FilterDisplayTypeEnum, FilterTypeEnum } from '@mediusinc/mng-commons/filter';
16
- import { TableDynamicDescriptorInst, TablePaginationModeEnum, TableSizeEnum, tableDescriptor } from '@mediusinc/mng-commons/table/api';
17
- import { createFilterDescriptorsFromGeneric } from '../../helpers/filters';
12
+ import { NEVER, Subject, filter, of, switchMap } from 'rxjs';
13
+ import { ClassMapPipe, ComponentDirective, I18nPropertyPipe, LoggerService, TemplateDirective, booleanOrUndefinedAttribute, dataListParamsToUrlQuery, effectWithDeps, findTemplateByName, fromSubscribeError, fromTableLoadToDataListParams, fromUrlQueryToDataListParams, getErrorLogLevel, mergeDataListParamsWithDefaults } from '@mediusinc/mng-commons/core';
14
+ import { FilterDisplayTypeEnum } from '@mediusinc/mng-commons/filter';
15
+ import { TablePaginationModeEnum, TableSizeEnum } from '@mediusinc/mng-commons/table/api';
18
16
  import { tableNotificationError } from '../../helpers/notification';
19
- import { generateTableLayoutPrefsKey } from '../../helpers/table-layout-prefs';
20
17
  import { LocaleDefaultRowClassPipe } from '../../pipes/locale-default-row-class.pipe';
21
18
  import { TableColumnFilterClassPipe } from '../../pipes/table-column-filter-class.pipe';
22
- import { DataListService } from '../../services/data-list.service';
23
- import { COMMONS_TABLE_FEATURE_CONFIG_IT } from '../../services/table-feature-config.token';
19
+ import { TableDataService } from '../../services/table-data.service';
20
+ import { TableMetadataService } from '../../services/table-metadata.service';
21
+ import { TablePreferencesService } from '../../services/table-preferences.service';
24
22
  import { TableColumnFilterComponent } from '../column-filter/column-filter.component';
25
23
  import { TableColumnValueComponent } from '../column-value/column-value.component';
26
- import { FilterOverlayWithTagComponent } from '../filter/filter-overlay-with-tag/filter-overlay-with-tag.component';
24
+ import { TableFilterOverlayWithTagComponent } from '../filter/filter-overlay-with-tag/filter-overlay-with-tag.component';
27
25
  import * as i0 from "@angular/core";
28
26
  import * as i1 from "primeng/table";
29
27
  import * as i2 from "primeng/api";
@@ -33,21 +31,27 @@ import * as i5 from "primeng/tooltip";
33
31
  import * as i6 from "@ngx-translate/core";
34
32
  import * as i7 from "@angular/forms";
35
33
  export class TableComponent {
34
+ // subscriptions and refs
35
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
36
+ #dataProviderEagerFirstLoad;
37
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
38
+ #dataProviderReloadSubscription;
39
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
40
+ #routeQueryParamsSubscription;
41
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
42
+ #routerEventsSubscription;
43
+ #afterNextRenderRef;
36
44
  constructor() {
37
45
  this.filterKeyPrepend = 'f_';
38
- this.cmpTypeName = 'TableComponent';
39
- this.logger = inject(LoggerService).create(this.cmpTypeName);
40
- this.injector = inject(Injector);
46
+ this.logger = inject(LoggerService).create(TableMetadataService.cmpTypeName);
41
47
  this.router = inject(Router);
42
48
  this.route = inject(ActivatedRoute);
43
49
  this.translate = inject(TranslateService);
44
50
  this.messageService = inject(MessageService);
45
- this.commons = inject(CommonsService);
46
- this.storageService = inject(CommonsStorageService);
47
- this.config = inject(COMMONS_TABLE_FEATURE_CONFIG_IT, { optional: true });
48
- this.dataListService = inject((DataListService));
49
- this.defaultFilterDisplayType = this.config?.filterDisplayType ?? FilterDisplayTypeEnum.Column;
50
- // metadata input
51
+ this.metadata = inject(TableMetadataService);
52
+ this.prefs = inject(TablePreferencesService);
53
+ this.data = inject((TableDataService));
54
+ // descriptor
51
55
  this.descriptorInput = input.required({ alias: 'descriptor' });
52
56
  // data source inputs
53
57
  this.items = input();
@@ -60,12 +64,28 @@ export class TableComponent {
60
64
  this.selectionMode = input('multiple');
61
65
  this.selectionEnabled = input(false, { transform: booleanAttribute });
62
66
  this.rowReorderEnabledInput = input(true, { alias: 'rowReorderEnabled', transform: booleanAttribute });
63
- this.rowReorderEnabled = computed(() => this.rowReorderEnabledInput() && this.descriptor().rowReorderable);
67
+ this.rowReorderEnabled = computed(() => this.rowReorderEnabledInput() && this.metadata.descriptor().rowReorderable);
68
+ this.expandedRowKeys = computed(() => {
69
+ const descriptor = this.metadata.descriptor();
70
+ if (typeof descriptor.isRowExpanded === 'string') {
71
+ return this.data.data()?.reduce((acc, item) => {
72
+ acc[item[descriptor.trackProperty]] = !!item[descriptor.isRowExpanded];
73
+ return acc;
74
+ }, {});
75
+ }
76
+ else if (typeof descriptor.isRowExpanded === 'function') {
77
+ return this.data.data()?.reduce((acc, item) => {
78
+ acc[item[descriptor.trackProperty]] = descriptor.isRowExpanded(item);
79
+ return acc;
80
+ }, {});
81
+ }
82
+ return {};
83
+ });
64
84
  // styling
65
85
  this.columnLastMinWidth = input();
66
86
  this.columnsColspan = computed(() => this.visibleColumns().length + (this.hasLastColumn() ? 1 : 0) + (this.selectionEnabled() ? 1 : 0) + (this.rowReorderEnabled() ? 1 : 0));
67
- this.hasTitleDisplay = computed(() => this.captionTemplate() || this.captionComponent() || this.descriptor().title);
68
- this.isCaptionVisible = computed(() => this.hasTitleDisplay() || this.overlayWithTagFilters().length > 0 || this.descriptor().search);
87
+ this.hasTitleDisplay = computed(() => this.captionTemplate() || this.captionComponent() || this.metadata.descriptor().title);
88
+ this.isCaptionVisible = computed(() => this.hasTitleDisplay() || this.overlayWithTagFilters().length > 0 || this.metadata.descriptor().search);
69
89
  // component inputs
70
90
  this.captionComponent = input();
71
91
  this.columnCustomLastComponent = input();
@@ -84,7 +104,7 @@ export class TableComponent {
84
104
  // content and view queries
85
105
  this.templates = contentChildren(TemplateDirective);
86
106
  this.components = viewChildren((ComponentDirective));
87
- this.primeTable = viewChild.required(Table);
107
+ this.primeTable = viewChild(Table);
88
108
  // templates
89
109
  this.captionTemplate = computed(() => findTemplateByName([...this.templates()], 'caption'));
90
110
  this.columnCustomLastTemplate = computed(() => findTemplateByName([...this.templates()], 'columnCustomLast'));
@@ -92,25 +112,12 @@ export class TableComponent {
92
112
  this.rowExpandTemplate = computed(() => findTemplateByName([...this.templates()], 'rowExpandContent'));
93
113
  // data provider and items
94
114
  this.isLazy = computed(() => this.dataProvider()?.isLazy === true);
95
- this.isPagination = computed(() => this.paginationMode() === TablePaginationModeEnum.Pagination);
115
+ this.isPagination = computed(() => this.data.paginationMode() === TablePaginationModeEnum.Pagination);
96
116
  this.useQueryParamsInitialized = signal(false);
97
117
  // visual
98
- this.paginationMode = computed(() => {
99
- if (typeof this.descriptor().paginationMode !== 'undefined') {
100
- // descriptor choice is the strongest - if defined, use this value
101
- return this.descriptor().paginationMode;
102
- }
103
- else if (typeof this.dataProvider() !== 'undefined') {
104
- // when data provider is used, use pagination
105
- return TablePaginationModeEnum.Pagination;
106
- }
107
- else {
108
- return TablePaginationModeEnum.None;
109
- }
110
- });
111
118
  this.className = computed(() => {
112
- let className = this.descriptor().className ?? '';
113
- switch (this.descriptor().size) {
119
+ let className = this.metadata.descriptor().className ?? '';
120
+ switch (this.metadata.descriptor().size) {
114
121
  case TableSizeEnum.Small:
115
122
  className += ' p-datatable-sm';
116
123
  break;
@@ -118,7 +125,7 @@ export class TableComponent {
118
125
  className += ' p-datatable-lg';
119
126
  break;
120
127
  }
121
- if (this.descriptor().hasGridlines) {
128
+ if (this.metadata.descriptor().hasGridlines) {
122
129
  className += ' p-datatable-gridlines';
123
130
  }
124
131
  if (!this.isCaptionVisible()) {
@@ -126,188 +133,86 @@ export class TableComponent {
126
133
  }
127
134
  return className;
128
135
  });
129
- // data provider
130
- this.dataProviderService = computed(() => {
131
- const dataProvider = this.dataProvider();
132
- return dataProvider?.serviceType ? this.injector.get(dataProvider.serviceType) : null;
133
- });
134
- // descriptors
135
- this.descriptor = signal(tableDescriptor());
136
- this.localstorageKey = computed(() => {
137
- const descriptor = this.descriptor();
138
- return descriptor.model.i18nBaseKey ? generateTableLayoutPrefsKey(descriptor.model.i18nBaseKey, this.router.url, descriptor.identifier) : null;
139
- });
140
- this.layoutPrefsSaveCnt = signal(0);
141
- this.layoutPreferences = computed(() => {
142
- const lsKey = this.localstorageKey();
143
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
144
- const cnt = this.layoutPrefsSaveCnt(); // needed to force updates on user changes
145
- const layoutPrefs = lsKey ? this.storageService.getItem(this.cmpTypeName, lsKey) : undefined;
146
- return layoutPrefs ?? { columnWidths: {} };
147
- });
148
- this.columns = computed(() => this.computeColumnsWithLayout());
149
- this.visibleColumns = computed(() => this.columns().filter(col => col.isVisible));
136
+ // columns
137
+ this.visibleColumns = computed(() => this.prefs.columnsWithPrefs().filter(col => col.isVisible));
138
+ this.areColumnsReorderable = computed(() => this.prefs.columnsWithPrefs().some(col => col.descriptor.isReorderable));
139
+ this.areColumnsToggleable = computed(() => this.prefs.columnsWithPrefs().some(col => col.descriptor.isToggleable));
150
140
  // filter, sort
151
- this.filterDescriptors = computed(() => this.descriptor().filters);
152
- this.genericFilterDescriptor = computed(() => this.descriptor().genericFilter);
153
- this.filterDescriptorsFromGeneric = signal([]);
154
- this.hasColumnFilters = computed(() => (this.defaultFilterDisplayType === FilterDisplayTypeEnum.OverlayWithTag && this.filterDescriptors().some(d => d.displayType === FilterDisplayTypeEnum.Column)) ||
155
- (this.defaultFilterDisplayType === FilterDisplayTypeEnum.Column && this.filterDescriptors().some(d => d.displayType == null)));
141
+ this.hasColumnFilters = computed(() => (this.metadata.defaultFilterDisplayType === FilterDisplayTypeEnum.OverlayWithTag &&
142
+ this.metadata.filterDescriptors().some(d => d.displayType === FilterDisplayTypeEnum.Column)) ||
143
+ (this.metadata.defaultFilterDisplayType === FilterDisplayTypeEnum.Column && this.metadata.filterDescriptors().some(d => d.displayType == null)));
156
144
  this.overlayWithTagFilters = computed(() => {
157
- const filters = this.filterDescriptors().filter(d => (d.displayType == null && this.defaultFilterDisplayType === FilterDisplayTypeEnum.OverlayWithTag) || d.displayType === FilterDisplayTypeEnum.OverlayWithTag);
158
- return filters.concat(this.filterDescriptorsFromGeneric());
145
+ // statically defined filters AND generic filters
146
+ const filters = this.metadata
147
+ .filters()
148
+ .filter(d => (d.descriptor.displayType == null && this.metadata.defaultFilterDisplayType === FilterDisplayTypeEnum.OverlayWithTag) ||
149
+ d.descriptor.displayType === FilterDisplayTypeEnum.OverlayWithTag);
150
+ return filters.concat(this.metadata.genericFilters());
159
151
  });
160
- this.defaultParams = computed(() => this.computeDefaultDataListParams());
161
152
  this.anyColumnVisible = computed(() => this.visibleColumns().length > 0);
162
153
  this.hasCustomLastColumn = computed(() => this.columnCustomLastComponent() || this.columnCustomLastTemplate());
163
154
  this.hasLastColumn = computed(() => this.hasCustomLastColumn() || this.areColumnsToggleable() || this.areColumnsReorderable());
164
- // layout prefs
165
- this.areColumnsReorderable = computed(() => this.columns().some(col => col.descriptor.isReorderable));
166
- this.areColumnsToggleable = computed(() => this.columns().some(col => col.descriptor.isToggleable));
167
- this.globalSearchParamFromUrl = signal(undefined);
168
155
  // other
169
156
  this.lastQueryParams = this.route.snapshot.queryParams;
170
157
  this.navigationOutOfTableInProgress = false;
171
158
  this.navigationInTableInProgress = false;
172
- effect(() => {
173
- const descriptor = this.descriptor();
174
- if (Array.isArray(descriptor.rowsPerPageOptions) && descriptor.rowsPerPageOptions.length > 0) {
175
- this.dataListService.rowsPerPageOptions.set(descriptor.rowsPerPageOptions);
176
- }
177
- if (descriptor.defaultNumRows) {
178
- this.dataListService.rows.set(this.dataListService.rowsPerPageOptions().includes(descriptor.defaultNumRows) ? descriptor.defaultNumRows : this.dataListService.rowsPerPageOptions()[0]);
179
- }
180
- }, { allowSignalWrites: true });
181
- effect(() => {
182
- const loading = this.loadingInput();
183
- if (loading !== undefined) {
184
- this.dataListService.loading.set(loading);
185
- }
186
- }, { allowSignalWrites: true });
187
- effect(() => {
188
- const result = this.result();
189
- if (result !== undefined) {
190
- this.dataListService.setData(result.data, result.totalCount);
191
- const loading = this.loadingInput();
192
- if (loading == undefined) {
193
- // only set if input is not defined
194
- this.dataListService.loading.set(false);
195
- }
196
- }
197
- }, { allowSignalWrites: true });
198
- effect(() => {
199
- const result = this.result();
200
- const items = this.items();
201
- if (result == undefined && items !== undefined) {
202
- this.dataListService.setData(items);
203
- const loading = this.loadingInput();
204
- if (loading == undefined) {
205
- // only set if input is not defined
206
- this.dataListService.loading.set(false);
207
- }
159
+ // subscriptions and refs
160
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
161
+ this.#dataProviderEagerFirstLoad = effectWithDeps([this.dataProvider], ([dataProvider]) => {
162
+ if (dataProvider?.isLazy === false) {
163
+ this.loadTableWithDataProvider(this.metadata.defaultParams());
208
164
  }
209
- }, { allowSignalWrites: true });
210
- effect(() => {
211
- const descriptor = this.descriptor();
212
- this.dataListService.globalFilterFields.set(this.globalFilterFieldsInput() ??
213
- (this.descriptor().search && descriptor.searchFields ? descriptor.searchFields : this.columns().map(c => c.descriptor.property)));
214
- }, { allowSignalWrites: true });
215
- afterNextRender(() => {
216
- this.isCellClickObserved.set(this.cellClickSubject.observed);
217
- });
218
- toObservable(this.dataProvider)
219
- .pipe(switchMap(dp => dp?.tableReload$ ?? of({})))
165
+ }, { firstOnly: true });
166
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
167
+ this.#dataProviderReloadSubscription = toObservable(this.dataProvider)
168
+ .pipe(switchMap(dp => dp?.tableReload$ ?? of({})), takeUntilDestroyed())
220
169
  .subscribe({
221
170
  next: e => {
222
171
  this.reload(e);
223
172
  }
224
173
  });
225
- combineLatest([toObservable(this.descriptorInput), toObservable(this.dataProvider), toObservable(this.useQueryParams)])
226
- .pipe(
227
- // dataProvider is needed to ensure correct order of execution and reload
228
174
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
229
- switchMap(([descriptorInput, dataProvider, useQueryParams]) => {
230
- if (descriptorInput !== this.descriptor()) {
231
- this.descriptor.set(descriptorInput);
232
- }
233
- if (useQueryParams) {
234
- // trigger table loads from route updates
235
- return this.route.queryParams;
236
- }
237
- else {
238
- return of(null);
239
- }
240
- }))
175
+ this.#routeQueryParamsSubscription = toObservable(this.useQueryParams)
176
+ .pipe(switchMap(useQp => (useQp ? this.route.queryParams : NEVER)), takeUntilDestroyed())
241
177
  .subscribe(qp => {
242
- if (qp === null) {
243
- // load data immediately by creating default sorts and filters (primeng will trigger onLazyLoad event on sort&filter metadata change)
244
- const defaultSort = this.createSortMeta(this.defaultParams());
245
- if (!defaultSort || defaultSort.length > 0) {
246
- this.dataListService.sortMeta.set(defaultSort);
247
- }
248
- const defaultFilter = this.createFilterMeta();
249
- if (defaultFilter) {
250
- this.dataListService.filterMeta.set(defaultFilter);
251
- }
252
- this.loadTableWithDataProvider({});
253
- }
254
- else {
255
- this.loadTableFromRouteUpdate(qp);
256
- }
178
+ this.loadTableFromRouteUpdate(qp);
257
179
  });
258
- toObservable(this.useQueryParams)
180
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
181
+ this.#routerEventsSubscription = toObservable(this.useQueryParams)
259
182
  .pipe(switchMap(useQp => (useQp ? this.router.events : NEVER)), filter(e => (e instanceof NavigationStart && e.url.split('?')[0].split('#')[0] !== this.router.url.split('?')[0].split('#')[0]) ||
260
183
  e instanceof NavigationEnd ||
261
184
  e instanceof NavigationCancel ||
262
- e instanceof NavigationError))
185
+ e instanceof NavigationError), takeUntilDestroyed())
263
186
  .subscribe(e => {
264
187
  this.navigationOutOfTableInProgress = e instanceof NavigationStart;
265
188
  });
266
- toObservable(this.genericFilterDescriptor)
267
- .pipe(switchMap(genericFilterDescriptor => {
268
- if (genericFilterDescriptor) {
269
- const dataProvider = this.genericFilterDescriptor()?.propertyLookup;
270
- const genericFilterService = dataProvider?.serviceType ? this.injector.get(dataProvider.serviceType) : null;
271
- // fetch filterable properties
272
- return commonsToObservable(genericFilterDescriptor.propertyLookup.lookup({}, genericFilterService));
273
- }
274
- return of([]);
275
- }), takeUntilDestroyed())
276
- .subscribe({
277
- next: genericFilters => {
278
- // set descriptors from generic filter data
279
- this.filterDescriptorsFromGeneric.set(createFilterDescriptorsFromGeneric(genericFilters, this.genericFilterDescriptor()?.valueLookup));
280
- }
189
+ this.#afterNextRenderRef = afterNextRender(() => {
190
+ this.isCellClickObserved.set(this.cellClickSubject.observed);
281
191
  });
282
- }
283
- ngOnDestroy() {
284
- this.dataProviderSubscription?.unsubscribe();
192
+ this.metadata.setSignalSources(this.descriptorInput, this.globalFilterFieldsInput);
193
+ this.data.setDataSources(this.items, this.result, this.dataProvider, this.loadingInput);
285
194
  }
286
195
  reload(emitEventOrEvent = false, resetParamsParam = false) {
287
- const emitEvent = typeof emitEventOrEvent === 'boolean' ? emitEventOrEvent : emitEventOrEvent?.emitEvent ?? false;
196
+ const emitEvent = typeof emitEventOrEvent === 'boolean' ? emitEventOrEvent : (emitEventOrEvent?.emitEvent ?? false);
288
197
  const resetParams = typeof emitEventOrEvent === 'object' ? emitEventOrEvent?.resetParams : resetParamsParam;
289
- const params = typeof emitEventOrEvent === 'object' && emitEventOrEvent?.params
290
- ? emitEventOrEvent?.params
291
- : resetParams
292
- ? undefined
293
- : this.latestParamsWithDefaults;
294
- const reloadParams = mergeDataListParamsWithDefaults(params ?? {}, this.defaultParams());
198
+ const params = typeof emitEventOrEvent === 'object' && emitEventOrEvent?.params ? emitEventOrEvent?.params : resetParams ? undefined : this.lastParamsWithDefaults;
199
+ const reloadParams = mergeDataListParamsWithDefaults(params ?? {}, this.metadata.defaultParams());
295
200
  this.loadTableWithDataProvider(reloadParams, emitEvent);
296
201
  }
297
202
  onTableLazyLoad(event) {
298
- this.dataProviderLatestLazyLoadEvent = event;
203
+ this.lastLazyLoadEvent = event;
299
204
  const params = fromTableLoadToDataListParams(event);
300
205
  if (this.useQueryParams()) {
301
206
  if (!this.navigationOutOfTableInProgress && !this.navigationInTableInProgress) {
207
+ // this check is necessary: from some reason, primeNG commits one last lazy load event whenever any angular router navigation occurs
302
208
  this.navigationInTableInProgress = true;
303
- const newParams = dataListParamsToUrlQuery(params, this.defaultParams(), { prependFilterName: this.filterKeyPrepend });
209
+ const newParams = dataListParamsToUrlQuery(params, this.metadata.defaultParams(), { prependFilterName: this.filterKeyPrepend });
304
210
  const newParamsWithParamsToRemove = { ...newParams };
305
211
  if (this.lastQueryParams) {
306
212
  Object.keys(this.lastQueryParams)
307
213
  .filter(k => (k.startsWith(this.filterKeyPrepend) || ['offset', 'limit', 'sort', 'q'].indexOf(k) >= 0) && newParams[k] === undefined)
308
214
  .forEach(k => (newParamsWithParamsToRemove[k] = null));
309
215
  }
310
- // this check is necessary: from some reason, primeNG commits one last lazy load event whenever any angular router navigation occurs
311
216
  this.router
312
217
  .navigate([], {
313
218
  relativeTo: this.route,
@@ -324,10 +229,8 @@ export class TableComponent {
324
229
  }
325
230
  }
326
231
  else {
327
- const paramsWithDefaults = mergeDataListParamsWithDefaults(params, this.defaultParams());
328
- if (!this.compareWithCurrentParams(paramsWithDefaults)) {
329
- this.updatePrimeSortAndFilter(paramsWithDefaults);
330
- }
232
+ const paramsWithDefaults = mergeDataListParamsWithDefaults(params, this.metadata.defaultParams());
233
+ this.data.setParams(paramsWithDefaults);
331
234
  this.loadTableWithDataProvider(paramsWithDefaults);
332
235
  }
333
236
  }
@@ -336,13 +239,11 @@ export class TableComponent {
336
239
  return;
337
240
  }
338
241
  const params = fromTableLoadToDataListParams({ filters: event.filters });
339
- const paramsWithDefaults = mergeDataListParamsWithDefaults(params, this.defaultParams());
242
+ const paramsWithDefaults = mergeDataListParamsWithDefaults(params, this.metadata.defaultParams());
340
243
  // if table doesn't use lazy loading, filter params need to be set here
341
244
  // because the onTableLazyLoad event is not emitted
342
245
  if (!this.isLazy()) {
343
- if (!this.compareWithCurrentParams(paramsWithDefaults)) {
344
- this.updatePrimeSortAndFilter(paramsWithDefaults);
345
- }
246
+ this.data.setParams(paramsWithDefaults);
346
247
  }
347
248
  }
348
249
  onCellClick(event, col, item, idx) {
@@ -363,256 +264,39 @@ export class TableComponent {
363
264
  onRowReorder(event) {
364
265
  this.rowReorder.emit(event);
365
266
  }
366
- /**
367
- * Method is called on column resize
368
- * @param element event's element
369
- */
370
- onTableColumnResize({ element }) {
371
- const fieldId = element.id;
372
- const width = element.offsetWidth;
373
- const layoutPrefs = this.layoutPreferences();
374
- const col = this.columns().find(el => el.descriptor.property === fieldId);
375
- if (col)
376
- col.width = width;
377
- if (!layoutPrefs.columnWidths)
378
- layoutPrefs.columnWidths = {};
379
- layoutPrefs.columnWidths[fieldId] = width;
380
- this.saveLayoutPreferences(layoutPrefs);
381
- }
382
267
  loadTableWithDataProvider(paramsWithDefaults, emitEvent = true) {
383
- const dataProvider = this.dataProvider();
384
- if (!dataProvider || paramsWithDefaults.limit === 0) {
385
- return;
386
- }
387
- this.dataProviderSubscription?.unsubscribe();
388
- this.dataListService.loading.set(true);
389
- this.latestParamsWithDefaults = paramsWithDefaults;
390
- this.dataProviderSubscription = commonsToObservable(dataProvider.getAll(paramsWithDefaults, this.dataProviderService(), this.descriptor().isLocalized ? this.commons.appDataLocale() ?? undefined : undefined)).subscribe({
391
- next: res => {
392
- const descriptorInput = this.descriptorInput();
393
- if (descriptorInput instanceof TableDynamicDescriptorInst) {
394
- this.descriptor.set(descriptorInput.toTableDescriptorFromData(res));
395
- }
396
- this.dataListService.setData(res?.data ?? [], res?.totalCount);
397
- this.dataListService.loading.set(false);
398
- },
399
- error: err => {
400
- tableNotificationError(this.translate, this.descriptor(), err, this.messageService);
401
- this.dataListService.setData([]);
402
- this.dataListService.loading.set(false);
403
- const error = fromSubscribeError(err, 'TableComponentError', {
404
- queryParam: paramsWithDefaults
405
- });
406
- this.logger.log(error, getErrorLogLevel(error));
407
- }
408
- });
409
- if (emitEvent) {
410
- const tableEvent = {
411
- originalEvent: this.dataProviderLatestLazyLoadEvent,
268
+ const isFetched = this.data.fetchWithDataProvider(paramsWithDefaults, error => {
269
+ tableNotificationError(this.translate, this.metadata.descriptor(), error, this.messageService);
270
+ const commonsError = fromSubscribeError(error, 'TableComponentError', {
412
271
  params: paramsWithDefaults
413
- };
414
- this.tableLoad.emit(tableEvent);
272
+ });
273
+ this.logger.log(commonsError, getErrorLogLevel(commonsError));
274
+ });
275
+ if (isFetched) {
276
+ this.lastParamsWithDefaults = paramsWithDefaults;
277
+ if (emitEvent) {
278
+ const tableEvent = {
279
+ originalEvent: this.lastLazyLoadEvent,
280
+ params: paramsWithDefaults
281
+ };
282
+ this.tableLoad.emit(tableEvent);
283
+ }
415
284
  }
416
285
  }
417
286
  loadTableFromRouteUpdate(urlParams) {
418
287
  const paramsWithDefaults = mergeDataListParamsWithDefaults(fromUrlQueryToDataListParams(urlParams, {
419
288
  prependFilterName: this.filterKeyPrepend,
420
289
  searchAsGlobal: true
421
- }), this.defaultParams());
422
- this.updatePrimeSortAndFilter(paramsWithDefaults);
423
- if (!this.useQueryParamsInitialized() && paramsWithDefaults?.search) {
424
- this.globalSearchParamFromUrl.set({ value: paramsWithDefaults?.search, caseSensitive: paramsWithDefaults.filters?.['global']?.caseSensitive ?? false });
425
- }
426
- this.useQueryParamsInitialized.set(true);
290
+ }), this.metadata.defaultParams());
291
+ this.data.setParams(paramsWithDefaults, true);
427
292
  this.loadTableWithDataProvider(paramsWithDefaults);
428
293
  }
429
- updatePrimeSortAndFilter(paramsWithDefaults) {
430
- this.dataListService.sortMeta.set(this.createSortMeta(paramsWithDefaults));
431
- this.dataListService.filterMeta.set(this.createFilterMeta(paramsWithDefaults));
432
- this.dataListService.rows.set(paramsWithDefaults?.limit ?? this.dataListService.rows());
433
- this.dataListService.offset.set(paramsWithDefaults?.offset ?? 0);
434
- }
435
- createFilterMeta(paramsWithDefaults) {
436
- const primeFilterMeta = {};
437
- // if any filter is present, no default filters should be applied!
438
- if (paramsWithDefaults?.filters) {
439
- Object.entries(paramsWithDefaults.filters).forEach(([key, value]) => {
440
- primeFilterMeta[key] = {
441
- value: value?.value,
442
- matchMode: value?.matchMode,
443
- caseSensitive: value?.caseSensitive
444
- };
445
- });
446
- }
447
- return primeFilterMeta;
448
- }
449
- createSortMeta(paramsWithDefaults) {
450
- if (paramsWithDefaults?.sort !== undefined && Array.isArray(paramsWithDefaults?.sort) && paramsWithDefaults?.sort.length > 0) {
451
- return paramsWithDefaults?.sort.map(s => ({
452
- field: s.property,
453
- order: s.ascending ? 1 : -1
454
- }));
455
- }
456
- return null;
457
- }
458
- onColumnToggle(event) {
459
- const layoutPrefs = this.layoutPreferences();
460
- const selectedColumns = event.value.map(v => v.descriptor.property);
461
- layoutPrefs.columnHidden = this.columns()
462
- .filter(c => selectedColumns.indexOf(c.descriptor.property) < 0)
463
- .map(c => c.descriptor.property);
464
- this.saveLayoutPreferences(layoutPrefs);
465
- }
466
- onColumnToggleAll() {
467
- const layoutPrefs = this.layoutPreferences();
468
- const columns = [...this.columns()];
469
- const isVisible = !this.columns().some(c => c.isVisible);
470
- for (const col of columns) {
471
- if (isVisible !== col.isVisible) {
472
- col.isVisible = isVisible;
473
- }
474
- }
475
- layoutPrefs.columnHidden = columns.filter(c => !c.isVisible).map(c => c.descriptor.property);
476
- this.saveLayoutPreferences(layoutPrefs);
477
- }
478
- onColumnReorder(event) {
479
- if (event.dropIndex !== undefined && event.dropIndex >= 0 && event.dragIndex !== undefined && event.dragIndex >= 0 && event.dropIndex !== event.dragIndex) {
480
- const eventDropIndex = event.dropIndex;
481
- const eventDragIndex = event.dragIndex;
482
- const prevVisibleColumns = this.columns().filter(c => c.isVisible);
483
- const colAtDrop = prevVisibleColumns[eventDropIndex];
484
- const colAtDrag = prevVisibleColumns[eventDragIndex];
485
- const colAtDropIndex = this.columns().findIndex(el => el.id === colAtDrop.id);
486
- const colAtDragIndex = this.columns().findIndex(el => el.id === colAtDrag.id);
487
- if (colAtDropIndex > -1 && colAtDragIndex > -1) {
488
- let columns = [...this.columns()];
489
- columns.splice(colAtDragIndex, 1);
490
- const dropIndex = columns.findIndex(el => el.id === colAtDrop.id) + (eventDropIndex > eventDragIndex ? 1 : 0);
491
- columns = [...columns.slice(0, dropIndex), colAtDrag, ...columns.slice(dropIndex)];
492
- const layoutPrefs = this.layoutPreferences();
493
- layoutPrefs.columnOrder = columns.map(el => el.descriptor.property);
494
- this.saveLayoutPreferences(layoutPrefs);
495
- }
496
- }
497
- }
498
- saveLayoutPreferences(layoutPrefs) {
499
- const key = this.localstorageKey();
500
- if (key) {
501
- this.storageService.setItem(this.cmpTypeName, key, layoutPrefs);
502
- this.layoutPrefsSaveCnt.update(v => v + 1);
503
- }
504
- }
505
- computeDefaultDataListParams() {
506
- const params = {
507
- offset: 0,
508
- limit: this.dataListService.rowsPerPageOptions()[0],
509
- sort: this.descriptor()
510
- .sorts.filter(s => s.defaultIsEnabled)
511
- .sort((s1, s2) => (s1.defaultOrder ?? 1000) - (s2.defaultOrder ?? 1000))
512
- .map(s => ({
513
- property: s.property,
514
- ascending: s.defaultIsAscending
515
- })),
516
- filters: {}
517
- };
518
- this.filterDescriptors()
519
- .filter(d => d.hasDefaultValue)
520
- .forEach(f => {
521
- let matchMode = f.defaultMatchMode;
522
- if (!matchMode) {
523
- switch (f.filterType) {
524
- case FilterTypeEnum.String:
525
- matchMode = FilterMatchMode.Contains;
526
- break;
527
- case FilterTypeEnum.Lookup:
528
- case FilterTypeEnum.LookupEnum: {
529
- const lookupFilter = f;
530
- if (lookupFilter.multiselect) {
531
- matchMode = FilterMatchMode.In;
532
- }
533
- break;
534
- }
535
- default:
536
- break;
537
- }
538
- }
539
- if (!matchMode) {
540
- matchMode = FilterMatchMode.Equals;
541
- }
542
- if (f.matchModes && !f.matchModes?.includes(matchMode)) {
543
- matchMode = f.matchModes[0];
544
- }
545
- let value = undefined;
546
- if (Array.isArray(value)) {
547
- value = [...value];
548
- }
549
- else {
550
- value = f.defaultValue;
551
- }
552
- const property = f.property;
553
- params.filters[property] = {
554
- value: value,
555
- matchMode: matchMode
556
- };
557
- });
558
- return params;
559
- }
560
- computeColumnsWithLayout() {
561
- const descriptor = this.descriptor();
562
- const layoutPrefs = this.layoutPreferences();
563
- // initialize columns with additional properties
564
- const timestamp = new Date().getTime();
565
- const columns = descriptor.columns.map(col => ({
566
- id: `${col.property}-${timestamp}`,
567
- descriptor: col,
568
- filter: descriptor.filters.find(f => f.showOnColumn === col.property &&
569
- ((f.displayType == null && this.defaultFilterDisplayType === FilterDisplayTypeEnum.Column) || f.displayType === FilterDisplayTypeEnum.Column)),
570
- sort: descriptor.sorts.find(f => f.showOnColumn === col.property),
571
- disabled: !col.isToggleable,
572
- isVisible: layoutPrefs.columnHidden ? !layoutPrefs.columnHidden.includes(col.property) : col.isVisible,
573
- width: layoutPrefs.columnWidths?.[col.property]
574
- }));
575
- if (layoutPrefs.columnOrder) {
576
- for (let i = 0; i < layoutPrefs.columnOrder.length; i++) {
577
- const colName = layoutPrefs.columnOrder[i];
578
- const colWithPrefs = columns.find(el => el.descriptor.property === colName);
579
- if (colWithPrefs) {
580
- colWithPrefs.orderIdx = i;
581
- }
582
- }
583
- }
584
- return columns.sort((a, b) => (a.orderIdx !== undefined && b.orderIdx !== undefined ? a.orderIdx - b.orderIdx : 0));
585
- }
586
- /**
587
- * Reset column order and column visibility to default settings
588
- */
589
- resetDefaultLayout() {
590
- const key = this.localstorageKey();
591
- if (key) {
592
- this.storageService.removeItem(this.cmpTypeName, key);
593
- this.layoutPrefsSaveCnt.update(v => v + 1);
594
- }
595
- }
596
- /**
597
- * Compare the given params with the stored params in the DataListService.
598
- *
599
- * @param {DataListParams} params - The params to compare with the stored params.
600
- *
601
- * @return {boolean} - True if the given params match the stored params, otherwise false.
602
- */
603
- compareWithCurrentParams(params) {
604
- return (params.offset === this.dataListService.offset() &&
605
- params.limit === this.dataListService.rows() &&
606
- JSON.stringify(this.createSortMeta(params)) === JSON.stringify(this.dataListService.sortMeta()) &&
607
- JSON.stringify(this.createFilterMeta(params)) === JSON.stringify(this.dataListService.filterMeta()));
608
- }
609
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
610
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: TableComponent, isStandalone: true, selector: "mng-table", inputs: { descriptorInput: { classPropertyName: "descriptorInput", publicName: "descriptor", isSignal: true, isRequired: true, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, result: { classPropertyName: "result", publicName: "result", isSignal: true, isRequired: false, transformFunction: null }, loadingInput: { classPropertyName: "loadingInput", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, dataProvider: { classPropertyName: "dataProvider", publicName: "dataProvider", isSignal: true, isRequired: false, transformFunction: null }, useQueryParams: { classPropertyName: "useQueryParams", publicName: "useQueryParams", isSignal: true, isRequired: false, transformFunction: null }, cellClickEnabled: { classPropertyName: "cellClickEnabled", publicName: "cellClickEnabled", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selectionEnabled: { classPropertyName: "selectionEnabled", publicName: "selectionEnabled", isSignal: true, isRequired: false, transformFunction: null }, rowReorderEnabledInput: { classPropertyName: "rowReorderEnabledInput", publicName: "rowReorderEnabled", isSignal: true, isRequired: false, transformFunction: null }, columnLastMinWidth: { classPropertyName: "columnLastMinWidth", publicName: "columnLastMinWidth", isSignal: true, isRequired: false, transformFunction: null }, captionComponent: { classPropertyName: "captionComponent", publicName: "captionComponent", isSignal: true, isRequired: false, transformFunction: null }, columnCustomLastComponent: { classPropertyName: "columnCustomLastComponent", publicName: "columnCustomLastComponent", isSignal: true, isRequired: false, transformFunction: null }, globalFilterFieldsInput: { classPropertyName: "globalFilterFieldsInput", publicName: "globalFilterFields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tableLoad: "tableLoad", cellClick: "cellClick", selectionChange: "selectionChange", captionComponentInstance: "captionComponentInstance", columnCustomLastComponentInstance: "columnCustomLastComponentInstance", rowReorder: "rowReorder" }, providers: [DataListService], queries: [{ propertyName: "templates", predicate: TemplateDirective, isSignal: true }], viewQueries: [{ propertyName: "components", predicate: (ComponentDirective), descendants: true, isSignal: true }, { propertyName: "primeTable", first: true, predicate: Table, descendants: true, isSignal: true }], ngImport: i0, template: "<div>\n <!-- MUST NOT use observable for value when using virtual scroll - does not work for some reason -->\n @if (!useQueryParams() || useQueryParamsInitialized()) {\n <p-table\n [value]=\"dataListService.data()\"\n [dataKey]=\"descriptor().trackProperty\"\n [lazy]=\"isLazy()\"\n [loading]=\"dataListService.loading()\"\n [paginator]=\"isPagination()\"\n [rows]=\"dataListService.rows()\"\n [first]=\"dataListService.offset()\"\n [totalRecords]=\"dataListService.count()\"\n [rowsPerPageOptions]=\"dataListService.rowsPerPageOptions()\"\n [showCurrentPageReport]=\"true\"\n [currentPageReportTemplate]=\"'mngTable.paginationMsg' | translate\"\n [multiSortMeta]=\"dataListService.sortMeta()\"\n [filters]=\"dataListService.filterMeta()\"\n [globalFilterFields]=\"dataListService.globalFilterFields()\"\n sortMode=\"multiple\"\n [selection]=\"[]\"\n (selectionChange)=\"onSelectionChange($event)\"\n [selectionMode]=\"selectionEnabled() ? selectionMode() : null\"\n [scrollable]=\"true\"\n scrollHeight=\"flex\"\n [rowHover]=\"descriptor().hasHover\"\n [styleClass]=\"className()\"\n [resizableColumns]=\"descriptor().hasResizableColumns\"\n [columnResizeMode]=\"descriptor().columnResizeMode ?? 'expand'\"\n [reorderableColumns]=\"areColumnsReorderable()\"\n paginatorDropdownAppendTo=\"body\"\n [columns]=\"visibleColumns()\"\n (onColResize)=\"onTableColumnResize($event)\"\n (onColReorder)=\"onColumnReorder($event)\"\n (onLazyLoad)=\"onTableLazyLoad($event)\"\n (onFilter)=\"onTableFilter($event)\"\n (onRowReorder)=\"onRowReorder($event)\">\n <ng-template pTemplate=\"caption\">\n @if (isCaptionVisible()) {\n <div class=\"table-header\">\n @if (overlayWithTagFilters().length > 0 || descriptor().search) {\n <mng-filter-overlay-with-tag\n [title]=\"descriptor().title\"\n [descriptors]=\"overlayWithTagFilters()\"\n [genericFilterDescriptor]=\"genericFilterDescriptor()\"\n [model]=\"descriptor().model\"\n [enableSearch]=\"descriptor().search\"\n [search]=\"globalSearchParamFromUrl()\"\n [searchLimitWordMax]=\"descriptor().searchLimitMaxWords\"\n [enableCaseSensitive]=\"isLazy()\">\n @if (hasTitleDisplay()) {\n <ng-template mngTemplate=\"title\">\n <ng-container *ngTemplateOutlet=\"captionTemplateOrComponentOrTitle\"></ng-container>\n </ng-template>\n }\n </mng-filter-overlay-with-tag>\n } @else {\n <ng-container *ngTemplateOutlet=\"captionTemplateOrComponentOrTitle\"></ng-container>\n }\n <ng-template #captionTemplateOrComponentOrTitle>\n @if (captionTemplate()) {\n <ng-container *ngTemplateOutlet=\"captionTemplate()\"></ng-container>\n } @else if (captionComponent()) {\n <ng-container [mngComponent]=\"captionComponent()\" (instanceCreated)=\"captionComponentInstance.emit($event)\"></ng-container>\n } @else if (descriptor().title) {\n <h5 class=\"p-0 m-0\">{{ descriptor().title! | translate }}</h5>\n }\n </ng-template>\n </div>\n }\n </ng-template>\n <ng-template pTemplate=\"header\">\n @if (!descriptor().hideHeader) {\n <tr class=\"mng-table-header\" [class]=\"descriptor().headerClassName\">\n @if (selectionEnabled()) {\n @if (selectionMode() === 'multiple') {\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\">\n <p-tableHeaderCheckbox></p-tableHeaderCheckbox>\n </th>\n } @else {\n <!-- We need the line below, because otherwise p-tableRadioButton shifts the rest of the columns in table -->\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\"></th>\n }\n }\n @if (descriptor().rowExpandable) {\n <th scope=\"col\" pFrozenColumn [frozen]=\"true\"></th>\n }\n @if (rowReorderEnabled()) {\n <th scope=\"col\"></th>\n }\n @for (col of visibleColumns(); track col.id) {\n <ng-template #sortableColumnTHTemplate>\n <div class=\"flex justify-content-between align-items-center\">\n {{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: descriptor().model) | translate }}\n <p-sortIcon [field]=\"col.descriptor.property\"></p-sortIcon>\n </div>\n </ng-template>\n <ng-template #nonSortableColumnTHTemplate>\n {{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: descriptor().model) | translate }}\n </ng-template>\n @if (col.descriptor.isReorderable) {\n <th\n pResizableColumn\n pReorderableColumn\n [id]=\"col.descriptor.property\"\n [pSortableColumn]=\"col.sort?.property\"\n [pSortableColumnDisabled]=\"!col.sort\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\"\n [class]=\"col.descriptor.headerClassName | mngTableColumnFilterClass: col.filter : hasColumnFilters() && !col.width\">\n <ng-container *ngTemplateOutlet=\"col.sort ? sortableColumnTHTemplate : nonSortableColumnTHTemplate\"></ng-container>\n </th>\n } @else {\n <th\n pResizableColumn\n [id]=\"col.descriptor.property\"\n [pSortableColumn]=\"col.sort?.property\"\n [pSortableColumnDisabled]=\"!col.sort\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\"\n [class]=\"col.descriptor.headerClassName | mngTableColumnFilterClass: col.filter : hasColumnFilters() && !col.width\">\n <ng-container *ngTemplateOutlet=\"col.sort ? sortableColumnTHTemplate : nonSortableColumnTHTemplate\"></ng-container>\n </th>\n }\n }\n @if (hasLastColumn()) {\n <th\n [style.min-width.px]=\"columnLastMinWidth()\"\n pFrozenColumn\n [frozen]=\"descriptor().actionColumnFrozen ?? areColumnsToggleable()\"\n alignFrozen=\"right\"\n class=\"column-custom-last text-right\">\n @if (areColumnsToggleable()) {\n <p-multiSelect\n #columnToggleMultiselect\n styleClass=\"p-button-primary mng-table-columns-multiselect\"\n appendTo=\"body\"\n dataKey=\"id\"\n tooltipPosition=\"left\"\n placeholder=\"\"\n dropdownIcon=\"pi pi-sliders-h\"\n [filter]=\"false\"\n [options]=\"columns()\"\n [ngModel]=\"visibleColumns()\"\n [pTooltip]=\"'mngTable.adjustTable' | translate\"\n [displaySelectedLabel]=\"false\"\n (onChange)=\"onColumnToggle($event)\">\n <ng-template pTemplate=\"filter\">\n <div class=\"p-checkbox p-component ml-1\">\n <div class=\"p-hidden-accessible\">\n <input\n type=\"checkbox\"\n readonly=\"readonly\"\n [checked]=\"columnToggleMultiselect.allSelected\"\n (focus)=\"columnToggleMultiselect.onHeaderCheckboxFocus()\"\n (blur)=\"columnToggleMultiselect.onHeaderCheckboxBlur()\"\n (keydown.space)=\"columnToggleMultiselect.onToggleAll($event)\" />\n </div>\n <div\n class=\"p-checkbox-box\"\n role=\"checkbox\"\n [attr.aria-checked]=\"columnToggleMultiselect.allSelected\"\n [ngClass]=\"{\n 'p-highlight': anyColumnVisible()\n }\"\n (click)=\"onColumnToggleAll()\">\n <span class=\"p-checkbox-icon\" [ngClass]=\"{'pi pi-check': anyColumnVisible()}\"></span>\n </div>\n </div>\n <p-button\n icon=\"pi pi-replay\"\n styleClass=\"p-button-secondary\"\n [pTooltip]=\"'mngTable.resetLayout' | translate\"\n tooltipPosition=\"left\"\n (click)=\"resetDefaultLayout()\"></p-button>\n </ng-template>\n <ng-template let-item pTemplate=\"item\">\n {{ item.descriptor.title ?? (item.descriptor.property | mngI18nProperty: descriptor().model) | translate }}\n </ng-template>\n </p-multiSelect>\n }\n </th>\n }\n </tr>\n }\n @if (hasColumnFilters()) {\n <tr class=\"mng-column-filter-row\">\n <!-- We need the line below, because otherwise p-tableRadioButton shifts the rest of the columns in table -->\n @if (selectionEnabled()) {\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\"></th>\n }\n @if (rowReorderEnabled()) {\n <th scope=\"col\"></th>\n }\n @if (descriptor().rowExpandable) {\n <th scope=\"col\"></th>\n }\n @for (col of visibleColumns(); track col.id) {\n <th\n [class]=\"col.filter?.columnClassName | mngTableColumnFilterClass: col.filter : hasColumnFilters() && !col.width\"\n [style.width.px]=\"col.width\"\n [style.width.%]=\"col.width ? null : col.filter?.columnWidth ?? col.descriptor.width ?? null\"\n [style.min-width.px]=\"col.width ? null : col.filter?.columnMinWidth ?? col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\">\n @if (col.filter) {\n <mng-table-column-filter [descriptor]=\"col.filter\"></mng-table-column-filter>\n }\n </th>\n }\n @if (hasLastColumn()) {\n <th class=\"column-custom-last\" [style.min-width.px]=\"columnLastMinWidth()\"></th>\n }\n </tr>\n }\n </ng-template>\n <ng-template pTemplate=\"body\" let-item let-idx=\"rowIndex\" let-expanded=\"expanded\">\n <tr\n [pReorderableRow]=\"idx\"\n [ngClass]=\"descriptor().rowClassName | mngClassMap: descriptor().rowClassNameMapFn : item | mngLocaleDefaultRowClass: descriptor() : item\">\n @if (selectionEnabled()) {\n @if (selectionMode() === 'multiple') {\n <td style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\">\n <p-tableCheckbox [value]=\"item\"></p-tableCheckbox>\n </td>\n } @else {\n <td style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\">\n <p-tableRadioButton [value]=\"item\"></p-tableRadioButton>\n </td>\n }\n }\n @if (descriptor().rowExpandable) {\n <td>\n @if (!descriptor().rowExpandableProperty || item[descriptor().rowExpandableProperty!]) {\n <button\n pButton\n type=\"button\"\n [pRowToggler]=\"item\"\n class=\"p-button-text p-button-rounded p-button-plain mng-table-row-expand-button\"\n [icon]=\"expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'\"></button>\n }\n </td>\n }\n @if (rowReorderEnabled()) {\n <td>\n <span class=\"pi pi-bars\" pReorderableRowHandle></span>\n </td>\n }\n @for (col of visibleColumns(); track col.id) {\n <td\n (click)=\"onCellClick($event, col.descriptor, item, idx)\"\n [class]=\"\n col.descriptor.className\n | mngClassMap: col.descriptor.classNameMapFn : item\n | mngTableColumnFilterClass: col.filter : hasColumnFilters() && !col.width\n \"\n [class.clickable]=\"isCellClickEnabled()\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\">\n <span class=\"p-column-title\">{{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: descriptor().model) | translate }}</span>\n <mng-table-column-value [descriptor]=\"col.descriptor\" [item]=\"item\"></mng-table-column-value>\n </td>\n }\n @if (hasLastColumn()) {\n <td\n class=\"column-custom-last justify-content-end text-right\"\n [style.min-width.px]=\"columnLastMinWidth()\"\n pFrozenColumn\n [frozen]=\"descriptor().actionColumnFrozen ?? true\"\n alignFrozen=\"right\">\n @if (columnCustomLastTemplate()) {\n <ng-container *ngTemplateOutlet=\"columnCustomLastTemplate(); context: {rowItem: item, rowIndex: idx}\"></ng-container>\n } @else if (columnCustomLastComponent()) {\n <div [mngComponent]=\"columnCustomLastComponent()\" (instanceCreated)=\"columnCustomLastComponentInstance.emit($event)\"></div>\n }\n </td>\n }\n </tr>\n </ng-template>\n <ng-template pTemplate=\"rowexpansion\" let-item>\n @if (descriptor().rowExpandable) {\n <tr>\n <td></td>\n <td [colSpan]=\"descriptor().rowExpandableColSpan\">\n @if (descriptor().rowExpandableComponentType !== undefined) {\n <ng-container [mngComponent]=\"descriptor().rowExpandableComponentType\" [inputs]=\"{item}\"> </ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowExpandTemplate(); context: {rowItem: item}\"></ng-container>\n }\n </td>\n </tr>\n }\n </ng-template>\n <ng-template pTemplate=\"loadingicon\">\n <div class=\"flex flex-column align-items-center\">\n @if (descriptor().loadingIcon) {\n <i [class]=\"'text-white text-4xl pi-spin ' + descriptor().loadingIcon\"></i>\n }\n @if (descriptor().loadingText) {\n <div class=\"text text-white text-lg font-semibold\" [ngClass]=\"{'mt-3': descriptor().loadingIcon}\">\n {{ descriptor().loadingText ?? '' | translate }}\n </div>\n }\n </div>\n </ng-template>\n <ng-template pTemplate=\"loadingbody\">\n <tr>\n <td [attr.colspan]=\"columnsColspan()\">\n <div class=\"loading-text\"></div>\n <p-skeleton [ngStyle]=\"{width: '100%'}\"></p-skeleton>\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td [attr.colspan]=\"columnsColspan()\">\n {{ 'mngTable.noItems' | translate }}\n </td>\n </tr>\n </ng-template>\n @if (footerTemplate()) {\n <ng-template pTemplate=\"summary\">\n <ng-container *ngTemplateOutlet=\"footerTemplate(); context: {data: dataListService.data(), totalCount: dataListService.count()}\"></ng-container>\n </ng-template>\n }\n </p-table>\n }\n</div>\n", dependencies: [{ kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }, { kind: "pipe", type: I18nPropertyPipe, name: "mngI18nProperty" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TableColumnValueComponent, selector: "mng-table-column-value", inputs: ["descriptor", "item"] }, { kind: "pipe", type: ClassMapPipe, name: "mngClassMap" }, { kind: "pipe", type: LocaleDefaultRowClassPipe, name: "mngLocaleDefaultRowClass" }, { kind: "component", type: TableColumnFilterComponent, selector: "mng-table-column-filter", inputs: ["descriptor"] }, { kind: "pipe", type: TableColumnFilterClassPipe, name: "mngTableColumnFilterClass" }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll", "virtualRowHeight"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i1.FrozenColumn, selector: "[pFrozenColumn]", inputs: ["frozen", "alignFrozen"] }, { kind: "directive", type: i1.RowToggler, selector: "[pRowToggler]", inputs: ["pRowToggler", "pRowTogglerDisabled"] }, { kind: "directive", type: i1.ResizableColumn, selector: "[pResizableColumn]", inputs: ["pResizableColumnDisabled"] }, { kind: "directive", type: i1.ReorderableColumn, selector: "[pReorderableColumn]", inputs: ["pReorderableColumnDisabled"] }, { kind: "component", type: i1.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i1.TableRadioButton, selector: "p-tableRadioButton", inputs: ["disabled", "value", "index", "inputId", "name", "ariaLabel"] }, { kind: "component", type: i1.TableCheckbox, selector: "p-tableCheckbox", inputs: ["disabled", "value", "index", "inputId", "name", "required", "ariaLabel"] }, { kind: "component", type: i1.TableHeaderCheckbox, selector: "p-tableHeaderCheckbox", inputs: ["disabled", "inputId", "name", "ariaLabel"] }, { kind: "directive", type: i1.ReorderableRowHandle, selector: "[pReorderableRowHandle]" }, { kind: "directive", type: i1.ReorderableRow, selector: "[pReorderableRow]", inputs: ["pReorderableRow", "pReorderableRowDisabled"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i3.MultiSelect, selector: "p-multiSelect", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }, { kind: "component", type: FilterOverlayWithTagComponent, selector: "mng-filter-overlay-with-tag", inputs: ["descriptors", "genericFilterDescriptor", "model", "enableSearch", "search", "searchLimitWordMax", "enableCaseSensitive"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TemplateDirective, selector: "[mngTemplate]", inputs: ["type", "mngTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
294
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
295
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: TableComponent, isStandalone: true, selector: "mng-table", inputs: { descriptorInput: { classPropertyName: "descriptorInput", publicName: "descriptor", isSignal: true, isRequired: true, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, result: { classPropertyName: "result", publicName: "result", isSignal: true, isRequired: false, transformFunction: null }, loadingInput: { classPropertyName: "loadingInput", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, dataProvider: { classPropertyName: "dataProvider", publicName: "dataProvider", isSignal: true, isRequired: false, transformFunction: null }, useQueryParams: { classPropertyName: "useQueryParams", publicName: "useQueryParams", isSignal: true, isRequired: false, transformFunction: null }, cellClickEnabled: { classPropertyName: "cellClickEnabled", publicName: "cellClickEnabled", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selectionEnabled: { classPropertyName: "selectionEnabled", publicName: "selectionEnabled", isSignal: true, isRequired: false, transformFunction: null }, rowReorderEnabledInput: { classPropertyName: "rowReorderEnabledInput", publicName: "rowReorderEnabled", isSignal: true, isRequired: false, transformFunction: null }, columnLastMinWidth: { classPropertyName: "columnLastMinWidth", publicName: "columnLastMinWidth", isSignal: true, isRequired: false, transformFunction: null }, captionComponent: { classPropertyName: "captionComponent", publicName: "captionComponent", isSignal: true, isRequired: false, transformFunction: null }, columnCustomLastComponent: { classPropertyName: "columnCustomLastComponent", publicName: "columnCustomLastComponent", isSignal: true, isRequired: false, transformFunction: null }, globalFilterFieldsInput: { classPropertyName: "globalFilterFieldsInput", publicName: "globalFilterFields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tableLoad: "tableLoad", cellClick: "cellClick", selectionChange: "selectionChange", captionComponentInstance: "captionComponentInstance", columnCustomLastComponentInstance: "columnCustomLastComponentInstance", rowReorder: "rowReorder" }, providers: [TableMetadataService, TableDataService, TablePreferencesService], queries: [{ propertyName: "templates", predicate: TemplateDirective, isSignal: true }], viewQueries: [{ propertyName: "components", predicate: (ComponentDirective), descendants: true, isSignal: true }, { propertyName: "primeTable", first: true, predicate: Table, descendants: true, isSignal: true }], ngImport: i0, template: "<div>\n <!-- MUST NOT use observable for value when using virtual scroll - does not work for some reason -->\n @if (data.isAllPaginationMetaInitialized()) {\n <p-table\n [value]=\"data.data()\"\n [dataKey]=\"metadata.descriptor().trackProperty\"\n [lazy]=\"isLazy()\"\n [loading]=\"data.loading()\"\n [paginator]=\"isPagination()\"\n [rows]=\"data.rows()\"\n [first]=\"data.offset()\"\n [totalRecords]=\"data.count()\"\n [rowsPerPageOptions]=\"metadata.rowsPerPageOptions()\"\n [showCurrentPageReport]=\"true\"\n [currentPageReportTemplate]=\"'mngTable.paginationMsg' | translate\"\n [multiSortMeta]=\"data.sortMeta()\"\n [filters]=\"data.filterMeta()\"\n [globalFilterFields]=\"metadata.searchFields()\"\n sortMode=\"multiple\"\n [selection]=\"[]\"\n (selectionChange)=\"onSelectionChange($event)\"\n [selectionMode]=\"selectionEnabled() ? selectionMode() : null\"\n [scrollable]=\"true\"\n scrollHeight=\"flex\"\n [rowHover]=\"metadata.descriptor().hasHover\"\n [styleClass]=\"className()\"\n [resizableColumns]=\"metadata.descriptor().hasResizableColumns\"\n [columnResizeMode]=\"metadata.descriptor().columnResizeMode ?? 'expand'\"\n [reorderableColumns]=\"areColumnsReorderable()\"\n paginatorDropdownAppendTo=\"body\"\n [columns]=\"visibleColumns()\"\n [expandedRowKeys]=\"expandedRowKeys()\"\n (onColResize)=\"prefs.onColumnResize($event)\"\n (onColReorder)=\"prefs.onColumnReorder($event)\"\n (onLazyLoad)=\"onTableLazyLoad($event)\"\n (onFilter)=\"onTableFilter($event)\"\n (onRowReorder)=\"onRowReorder($event)\">\n <ng-template pTemplate=\"caption\">\n @if (isCaptionVisible()) {\n <div class=\"table-header\">\n @if (overlayWithTagFilters().length > 0 || metadata.descriptor().search) {\n <mng-table-filter-overlay-with-tag\n [title]=\"metadata.descriptor().title\"\n [metadata]=\"overlayWithTagFilters()\"\n [genericFilterDescriptor]=\"metadata.genericFilterDescriptor()\"\n [model]=\"metadata.descriptor().model\"\n [enableSearch]=\"metadata.descriptor().search\"\n [search]=\"data.searchMeta()\"\n [searchLimitWordMax]=\"metadata.descriptor().searchLimitMaxWords\"\n [enableCaseSensitive]=\"isLazy()\">\n @if (hasTitleDisplay()) {\n <ng-template mngTemplate=\"title\">\n <ng-container *ngTemplateOutlet=\"captionTemplateOrComponentOrTitle\"></ng-container>\n </ng-template>\n }\n </mng-table-filter-overlay-with-tag>\n } @else {\n <ng-container *ngTemplateOutlet=\"captionTemplateOrComponentOrTitle\"></ng-container>\n }\n <ng-template #captionTemplateOrComponentOrTitle>\n @if (captionTemplate()) {\n <ng-container *ngTemplateOutlet=\"captionTemplate()\"></ng-container>\n } @else if (captionComponent()) {\n <ng-container [mngComponent]=\"captionComponent()\" (instanceCreated)=\"captionComponentInstance.emit($event)\"></ng-container>\n } @else if (metadata.descriptor().title) {\n <h5 class=\"p-0 m-0\">{{ metadata.descriptor().title! | translate }}</h5>\n }\n </ng-template>\n </div>\n }\n </ng-template>\n <ng-template pTemplate=\"header\">\n @if (!metadata.descriptor().hideHeader) {\n <tr class=\"mng-table-header\" [class]=\"metadata.descriptor().headerClassName\">\n @if (selectionEnabled()) {\n @if (selectionMode() === 'multiple') {\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\">\n <p-tableHeaderCheckbox></p-tableHeaderCheckbox>\n </th>\n } @else {\n <!-- We need the line below, because otherwise p-tableRadioButton shifts the rest of the columns in table -->\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\"></th>\n }\n }\n @if (metadata.descriptor().rowExpandable) {\n <th scope=\"col\" pFrozenColumn [frozen]=\"true\"></th>\n }\n @if (rowReorderEnabled()) {\n <th scope=\"col\"></th>\n }\n @for (col of visibleColumns(); track col.id) {\n <ng-template #sortableColumnTHTemplate>\n <div class=\"flex justify-content-between align-items-center\">\n {{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: metadata.descriptor().model) | translate }}\n <p-sortIcon [field]=\"col.descriptor.property\"></p-sortIcon>\n </div>\n </ng-template>\n <ng-template #nonSortableColumnTHTemplate>\n {{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: metadata.descriptor().model) | translate }}\n </ng-template>\n @if (col.descriptor.isReorderable) {\n <th\n pResizableColumn\n pReorderableColumn\n [id]=\"col.descriptor.property\"\n [pSortableColumn]=\"col.sort?.property\"\n [pSortableColumnDisabled]=\"!col.sort\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\"\n [class]=\"col.descriptor.headerClassName | mngTableColumnFilterClass: col.filter?.descriptor : hasColumnFilters() && !col.width\">\n <ng-container *ngTemplateOutlet=\"col.sort ? sortableColumnTHTemplate : nonSortableColumnTHTemplate\"></ng-container>\n </th>\n } @else {\n <th\n pResizableColumn\n [id]=\"col.descriptor.property\"\n [pSortableColumn]=\"col.sort?.property\"\n [pSortableColumnDisabled]=\"!col.sort\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\"\n [class]=\"col.descriptor.headerClassName | mngTableColumnFilterClass: col.filter?.descriptor : hasColumnFilters() && !col.width\">\n <ng-container *ngTemplateOutlet=\"col.sort ? sortableColumnTHTemplate : nonSortableColumnTHTemplate\"></ng-container>\n </th>\n }\n }\n @if (hasLastColumn()) {\n <th\n [style.min-width.px]=\"columnLastMinWidth()\"\n pFrozenColumn\n [frozen]=\"metadata.descriptor().actionColumnFrozen ?? areColumnsToggleable()\"\n alignFrozen=\"right\"\n class=\"column-custom-last text-right\">\n @if (areColumnsToggleable()) {\n <p-multiSelect\n #columnToggleMultiselect\n styleClass=\"p-button-primary mng-table-columns-multiselect\"\n appendTo=\"body\"\n dataKey=\"id\"\n tooltipPosition=\"left\"\n placeholder=\"\"\n dropdownIcon=\"pi pi-sliders-h\"\n [filter]=\"false\"\n [options]=\"prefs.columnsWithPrefs()\"\n [ngModel]=\"visibleColumns()\"\n [pTooltip]=\"'mngTable.adjustTable' | translate\"\n [displaySelectedLabel]=\"false\"\n (onChange)=\"prefs.onColumnToggle($event)\">\n <ng-template pTemplate=\"filter\">\n <div class=\"p-checkbox p-component ml-1\">\n <div class=\"p-hidden-accessible\">\n <input\n type=\"checkbox\"\n readonly=\"readonly\"\n [checked]=\"columnToggleMultiselect.allSelected\"\n (focus)=\"columnToggleMultiselect.onHeaderCheckboxFocus()\"\n (blur)=\"columnToggleMultiselect.onHeaderCheckboxBlur()\"\n (keydown.space)=\"columnToggleMultiselect.onToggleAll($event)\" />\n </div>\n <div\n class=\"p-checkbox-box\"\n role=\"checkbox\"\n [attr.aria-checked]=\"columnToggleMultiselect.allSelected\"\n [ngClass]=\"{\n 'p-highlight': anyColumnVisible()\n }\"\n (click)=\"prefs.onColumnToggleAll()\">\n <span class=\"p-checkbox-icon\" [ngClass]=\"{'pi pi-check': anyColumnVisible()}\"></span>\n </div>\n </div>\n <p-button\n icon=\"pi pi-replay\"\n styleClass=\"p-button-secondary\"\n [pTooltip]=\"'mngTable.resetLayout' | translate\"\n tooltipPosition=\"left\"\n (click)=\"prefs.clearLayoutPreferences()\"></p-button>\n </ng-template>\n <ng-template let-item pTemplate=\"item\">\n {{ item.descriptor.title ?? (item.descriptor.property | mngI18nProperty: metadata.descriptor().model) | translate }}\n </ng-template>\n </p-multiSelect>\n }\n </th>\n }\n </tr>\n }\n @if (hasColumnFilters()) {\n <tr class=\"mng-column-filter-row\">\n <!-- We need the line below, because otherwise p-tableRadioButton shifts the rest of the columns in table -->\n @if (selectionEnabled()) {\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\"></th>\n }\n @if (rowReorderEnabled()) {\n <th scope=\"col\"></th>\n }\n @if (metadata.descriptor().rowExpandable) {\n <th scope=\"col\"></th>\n }\n @for (col of visibleColumns(); track col.id) {\n <th\n [class]=\"col.filter?.descriptor?.columnClassName | mngTableColumnFilterClass: col.filter?.descriptor : hasColumnFilters() && !col.width\"\n [style.width.px]=\"col.width\"\n [style.width.%]=\"col.width ? null : (col.filter?.descriptor?.columnWidth ?? col.descriptor.width ?? null)\"\n [style.min-width.px]=\"col.width ? null : (col.filter?.descriptor?.columnMinWidth ?? col.descriptor.minWidth)\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\">\n @if (col.filter) {\n <mng-table-column-filter [metadata]=\"col.filter\"></mng-table-column-filter>\n }\n </th>\n }\n @if (hasLastColumn()) {\n <th class=\"column-custom-last\" [style.min-width.px]=\"columnLastMinWidth()\"></th>\n }\n </tr>\n }\n </ng-template>\n <ng-template pTemplate=\"body\" let-item let-idx=\"rowIndex\" let-expanded=\"expanded\">\n <tr\n [pReorderableRow]=\"idx\"\n [ngClass]=\"\n metadata.descriptor().rowClassName | mngClassMap: metadata.descriptor().rowClassNameMapFn : item | mngLocaleDefaultRowClass: metadata.descriptor() : item\n \">\n @if (selectionEnabled()) {\n @if (selectionMode() === 'multiple') {\n <td style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\">\n <p-tableCheckbox [value]=\"item\"></p-tableCheckbox>\n </td>\n } @else {\n <td style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\">\n <p-tableRadioButton [value]=\"item\"></p-tableRadioButton>\n </td>\n }\n }\n @if (metadata.descriptor().rowExpandable) {\n <td>\n @if (!metadata.descriptor().rowExpandableProperty || item[metadata.descriptor().rowExpandableProperty!]) {\n <button\n pButton\n type=\"button\"\n [pRowToggler]=\"item\"\n class=\"p-button-text p-button-rounded p-button-plain mng-table-row-expand-button\"\n [icon]=\"expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'\"></button>\n }\n </td>\n }\n @if (rowReorderEnabled()) {\n <td>\n <span class=\"pi pi-bars\" pReorderableRowHandle></span>\n </td>\n }\n @for (col of visibleColumns(); track col.id) {\n <td\n (click)=\"onCellClick($event, col.descriptor, item, idx)\"\n [class]=\"\n col.descriptor.className\n | mngClassMap: col.descriptor.classNameMapFn : item\n | mngTableColumnFilterClass: col.filter?.descriptor : hasColumnFilters() && !col.width\n \"\n [class.clickable]=\"isCellClickEnabled()\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\">\n <span class=\"p-column-title\">{{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: metadata.descriptor().model) | translate }}</span>\n <mng-table-column-value [descriptor]=\"col.descriptor\" [item]=\"item\"></mng-table-column-value>\n </td>\n }\n @if (hasLastColumn()) {\n <td\n class=\"column-custom-last justify-content-end text-right\"\n [style.min-width.px]=\"columnLastMinWidth()\"\n pFrozenColumn\n [frozen]=\"metadata.descriptor().actionColumnFrozen ?? true\"\n alignFrozen=\"right\">\n @if (columnCustomLastTemplate()) {\n <ng-container *ngTemplateOutlet=\"columnCustomLastTemplate(); context: {rowItem: item, rowIndex: idx}\"></ng-container>\n } @else if (columnCustomLastComponent()) {\n <div [mngComponent]=\"columnCustomLastComponent()\" (instanceCreated)=\"columnCustomLastComponentInstance.emit($event)\"></div>\n }\n </td>\n }\n </tr>\n </ng-template>\n <ng-template pTemplate=\"rowexpansion\" let-item>\n @if (metadata.descriptor().rowExpandable) {\n <tr>\n <td></td>\n <td [colSpan]=\"metadata.descriptor().rowExpandableColSpan\">\n @if (metadata.descriptor().rowExpandableComponentType !== undefined) {\n <ng-container [mngComponent]=\"metadata.descriptor().rowExpandableComponentType\" [inputs]=\"{item}\"> </ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowExpandTemplate(); context: {rowItem: item}\"></ng-container>\n }\n </td>\n </tr>\n }\n </ng-template>\n <ng-template pTemplate=\"loadingicon\">\n <div class=\"flex flex-column align-items-center\">\n @if (metadata.descriptor().loadingIcon) {\n <i [class]=\"'text-white text-4xl pi-spin ' + metadata.descriptor().loadingIcon\"></i>\n }\n @if (metadata.descriptor().loadingText) {\n <div class=\"text text-white text-lg font-semibold\" [ngClass]=\"{'mt-3': metadata.descriptor().loadingIcon}\">\n {{ metadata.descriptor().loadingText ?? '' | translate }}\n </div>\n }\n </div>\n </ng-template>\n <ng-template pTemplate=\"loadingbody\">\n <tr>\n <td [attr.colspan]=\"columnsColspan()\">\n <div class=\"loading-text\"></div>\n <p-skeleton [ngStyle]=\"{width: '100%'}\"></p-skeleton>\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td [attr.colspan]=\"columnsColspan()\">\n {{ 'mngTable.noItems' | translate }}\n </td>\n </tr>\n </ng-template>\n @if (footerTemplate()) {\n <ng-template pTemplate=\"summary\">\n <ng-container *ngTemplateOutlet=\"footerTemplate(); context: {data: data.data(), totalCount: data.count()}\"></ng-container>\n </ng-template>\n }\n </p-table>\n }\n</div>\n", dependencies: [{ kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }, { kind: "pipe", type: I18nPropertyPipe, name: "mngI18nProperty" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TableColumnValueComponent, selector: "mng-table-column-value", inputs: ["descriptor", "item"] }, { kind: "pipe", type: ClassMapPipe, name: "mngClassMap" }, { kind: "pipe", type: LocaleDefaultRowClassPipe, name: "mngLocaleDefaultRowClass" }, { kind: "component", type: TableColumnFilterComponent, selector: "mng-table-column-filter", inputs: ["metadata"] }, { kind: "pipe", type: TableColumnFilterClassPipe, name: "mngTableColumnFilterClass" }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll", "virtualRowHeight"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i1.FrozenColumn, selector: "[pFrozenColumn]", inputs: ["frozen", "alignFrozen"] }, { kind: "directive", type: i1.RowToggler, selector: "[pRowToggler]", inputs: ["pRowToggler", "pRowTogglerDisabled"] }, { kind: "directive", type: i1.ResizableColumn, selector: "[pResizableColumn]", inputs: ["pResizableColumnDisabled"] }, { kind: "directive", type: i1.ReorderableColumn, selector: "[pReorderableColumn]", inputs: ["pReorderableColumnDisabled"] }, { kind: "component", type: i1.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i1.TableRadioButton, selector: "p-tableRadioButton", inputs: ["disabled", "value", "index", "inputId", "name", "ariaLabel"] }, { kind: "component", type: i1.TableCheckbox, selector: "p-tableCheckbox", inputs: ["disabled", "value", "index", "inputId", "name", "required", "ariaLabel"] }, { kind: "component", type: i1.TableHeaderCheckbox, selector: "p-tableHeaderCheckbox", inputs: ["disabled", "inputId", "name", "ariaLabel"] }, { kind: "directive", type: i1.ReorderableRowHandle, selector: "[pReorderableRowHandle]" }, { kind: "directive", type: i1.ReorderableRow, selector: "[pReorderableRow]", inputs: ["pReorderableRow", "pReorderableRowDisabled"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i3.MultiSelect, selector: "p-multiSelect", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }, { kind: "component", type: TableFilterOverlayWithTagComponent, selector: "mng-table-filter-overlay-with-tag", inputs: ["metadata", "genericFilterDescriptor", "model", "enableSearch", "search", "searchLimitWordMax", "enableCaseSensitive"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TemplateDirective, selector: "[mngTemplate]", inputs: ["type", "mngTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
611
296
  }
612
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: TableComponent, decorators: [{
297
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TableComponent, decorators: [{
613
298
  type: Component,
614
299
  args: [{ standalone: true, selector: 'mng-table', imports: [
615
- AsyncPipe,
616
300
  ComponentDirective,
617
301
  I18nPropertyPipe,
618
302
  NgClass,
@@ -628,9 +312,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImpor
628
312
  ButtonModule,
629
313
  TooltipModule,
630
314
  TranslateModule,
631
- FilterOverlayWithTagComponent,
315
+ TableFilterOverlayWithTagComponent,
632
316
  FormsModule,
633
317
  TemplateDirective
634
- ], providers: [DataListService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div>\n <!-- MUST NOT use observable for value when using virtual scroll - does not work for some reason -->\n @if (!useQueryParams() || useQueryParamsInitialized()) {\n <p-table\n [value]=\"dataListService.data()\"\n [dataKey]=\"descriptor().trackProperty\"\n [lazy]=\"isLazy()\"\n [loading]=\"dataListService.loading()\"\n [paginator]=\"isPagination()\"\n [rows]=\"dataListService.rows()\"\n [first]=\"dataListService.offset()\"\n [totalRecords]=\"dataListService.count()\"\n [rowsPerPageOptions]=\"dataListService.rowsPerPageOptions()\"\n [showCurrentPageReport]=\"true\"\n [currentPageReportTemplate]=\"'mngTable.paginationMsg' | translate\"\n [multiSortMeta]=\"dataListService.sortMeta()\"\n [filters]=\"dataListService.filterMeta()\"\n [globalFilterFields]=\"dataListService.globalFilterFields()\"\n sortMode=\"multiple\"\n [selection]=\"[]\"\n (selectionChange)=\"onSelectionChange($event)\"\n [selectionMode]=\"selectionEnabled() ? selectionMode() : null\"\n [scrollable]=\"true\"\n scrollHeight=\"flex\"\n [rowHover]=\"descriptor().hasHover\"\n [styleClass]=\"className()\"\n [resizableColumns]=\"descriptor().hasResizableColumns\"\n [columnResizeMode]=\"descriptor().columnResizeMode ?? 'expand'\"\n [reorderableColumns]=\"areColumnsReorderable()\"\n paginatorDropdownAppendTo=\"body\"\n [columns]=\"visibleColumns()\"\n (onColResize)=\"onTableColumnResize($event)\"\n (onColReorder)=\"onColumnReorder($event)\"\n (onLazyLoad)=\"onTableLazyLoad($event)\"\n (onFilter)=\"onTableFilter($event)\"\n (onRowReorder)=\"onRowReorder($event)\">\n <ng-template pTemplate=\"caption\">\n @if (isCaptionVisible()) {\n <div class=\"table-header\">\n @if (overlayWithTagFilters().length > 0 || descriptor().search) {\n <mng-filter-overlay-with-tag\n [title]=\"descriptor().title\"\n [descriptors]=\"overlayWithTagFilters()\"\n [genericFilterDescriptor]=\"genericFilterDescriptor()\"\n [model]=\"descriptor().model\"\n [enableSearch]=\"descriptor().search\"\n [search]=\"globalSearchParamFromUrl()\"\n [searchLimitWordMax]=\"descriptor().searchLimitMaxWords\"\n [enableCaseSensitive]=\"isLazy()\">\n @if (hasTitleDisplay()) {\n <ng-template mngTemplate=\"title\">\n <ng-container *ngTemplateOutlet=\"captionTemplateOrComponentOrTitle\"></ng-container>\n </ng-template>\n }\n </mng-filter-overlay-with-tag>\n } @else {\n <ng-container *ngTemplateOutlet=\"captionTemplateOrComponentOrTitle\"></ng-container>\n }\n <ng-template #captionTemplateOrComponentOrTitle>\n @if (captionTemplate()) {\n <ng-container *ngTemplateOutlet=\"captionTemplate()\"></ng-container>\n } @else if (captionComponent()) {\n <ng-container [mngComponent]=\"captionComponent()\" (instanceCreated)=\"captionComponentInstance.emit($event)\"></ng-container>\n } @else if (descriptor().title) {\n <h5 class=\"p-0 m-0\">{{ descriptor().title! | translate }}</h5>\n }\n </ng-template>\n </div>\n }\n </ng-template>\n <ng-template pTemplate=\"header\">\n @if (!descriptor().hideHeader) {\n <tr class=\"mng-table-header\" [class]=\"descriptor().headerClassName\">\n @if (selectionEnabled()) {\n @if (selectionMode() === 'multiple') {\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\">\n <p-tableHeaderCheckbox></p-tableHeaderCheckbox>\n </th>\n } @else {\n <!-- We need the line below, because otherwise p-tableRadioButton shifts the rest of the columns in table -->\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\"></th>\n }\n }\n @if (descriptor().rowExpandable) {\n <th scope=\"col\" pFrozenColumn [frozen]=\"true\"></th>\n }\n @if (rowReorderEnabled()) {\n <th scope=\"col\"></th>\n }\n @for (col of visibleColumns(); track col.id) {\n <ng-template #sortableColumnTHTemplate>\n <div class=\"flex justify-content-between align-items-center\">\n {{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: descriptor().model) | translate }}\n <p-sortIcon [field]=\"col.descriptor.property\"></p-sortIcon>\n </div>\n </ng-template>\n <ng-template #nonSortableColumnTHTemplate>\n {{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: descriptor().model) | translate }}\n </ng-template>\n @if (col.descriptor.isReorderable) {\n <th\n pResizableColumn\n pReorderableColumn\n [id]=\"col.descriptor.property\"\n [pSortableColumn]=\"col.sort?.property\"\n [pSortableColumnDisabled]=\"!col.sort\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\"\n [class]=\"col.descriptor.headerClassName | mngTableColumnFilterClass: col.filter : hasColumnFilters() && !col.width\">\n <ng-container *ngTemplateOutlet=\"col.sort ? sortableColumnTHTemplate : nonSortableColumnTHTemplate\"></ng-container>\n </th>\n } @else {\n <th\n pResizableColumn\n [id]=\"col.descriptor.property\"\n [pSortableColumn]=\"col.sort?.property\"\n [pSortableColumnDisabled]=\"!col.sort\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\"\n [class]=\"col.descriptor.headerClassName | mngTableColumnFilterClass: col.filter : hasColumnFilters() && !col.width\">\n <ng-container *ngTemplateOutlet=\"col.sort ? sortableColumnTHTemplate : nonSortableColumnTHTemplate\"></ng-container>\n </th>\n }\n }\n @if (hasLastColumn()) {\n <th\n [style.min-width.px]=\"columnLastMinWidth()\"\n pFrozenColumn\n [frozen]=\"descriptor().actionColumnFrozen ?? areColumnsToggleable()\"\n alignFrozen=\"right\"\n class=\"column-custom-last text-right\">\n @if (areColumnsToggleable()) {\n <p-multiSelect\n #columnToggleMultiselect\n styleClass=\"p-button-primary mng-table-columns-multiselect\"\n appendTo=\"body\"\n dataKey=\"id\"\n tooltipPosition=\"left\"\n placeholder=\"\"\n dropdownIcon=\"pi pi-sliders-h\"\n [filter]=\"false\"\n [options]=\"columns()\"\n [ngModel]=\"visibleColumns()\"\n [pTooltip]=\"'mngTable.adjustTable' | translate\"\n [displaySelectedLabel]=\"false\"\n (onChange)=\"onColumnToggle($event)\">\n <ng-template pTemplate=\"filter\">\n <div class=\"p-checkbox p-component ml-1\">\n <div class=\"p-hidden-accessible\">\n <input\n type=\"checkbox\"\n readonly=\"readonly\"\n [checked]=\"columnToggleMultiselect.allSelected\"\n (focus)=\"columnToggleMultiselect.onHeaderCheckboxFocus()\"\n (blur)=\"columnToggleMultiselect.onHeaderCheckboxBlur()\"\n (keydown.space)=\"columnToggleMultiselect.onToggleAll($event)\" />\n </div>\n <div\n class=\"p-checkbox-box\"\n role=\"checkbox\"\n [attr.aria-checked]=\"columnToggleMultiselect.allSelected\"\n [ngClass]=\"{\n 'p-highlight': anyColumnVisible()\n }\"\n (click)=\"onColumnToggleAll()\">\n <span class=\"p-checkbox-icon\" [ngClass]=\"{'pi pi-check': anyColumnVisible()}\"></span>\n </div>\n </div>\n <p-button\n icon=\"pi pi-replay\"\n styleClass=\"p-button-secondary\"\n [pTooltip]=\"'mngTable.resetLayout' | translate\"\n tooltipPosition=\"left\"\n (click)=\"resetDefaultLayout()\"></p-button>\n </ng-template>\n <ng-template let-item pTemplate=\"item\">\n {{ item.descriptor.title ?? (item.descriptor.property | mngI18nProperty: descriptor().model) | translate }}\n </ng-template>\n </p-multiSelect>\n }\n </th>\n }\n </tr>\n }\n @if (hasColumnFilters()) {\n <tr class=\"mng-column-filter-row\">\n <!-- We need the line below, because otherwise p-tableRadioButton shifts the rest of the columns in table -->\n @if (selectionEnabled()) {\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\"></th>\n }\n @if (rowReorderEnabled()) {\n <th scope=\"col\"></th>\n }\n @if (descriptor().rowExpandable) {\n <th scope=\"col\"></th>\n }\n @for (col of visibleColumns(); track col.id) {\n <th\n [class]=\"col.filter?.columnClassName | mngTableColumnFilterClass: col.filter : hasColumnFilters() && !col.width\"\n [style.width.px]=\"col.width\"\n [style.width.%]=\"col.width ? null : col.filter?.columnWidth ?? col.descriptor.width ?? null\"\n [style.min-width.px]=\"col.width ? null : col.filter?.columnMinWidth ?? col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\">\n @if (col.filter) {\n <mng-table-column-filter [descriptor]=\"col.filter\"></mng-table-column-filter>\n }\n </th>\n }\n @if (hasLastColumn()) {\n <th class=\"column-custom-last\" [style.min-width.px]=\"columnLastMinWidth()\"></th>\n }\n </tr>\n }\n </ng-template>\n <ng-template pTemplate=\"body\" let-item let-idx=\"rowIndex\" let-expanded=\"expanded\">\n <tr\n [pReorderableRow]=\"idx\"\n [ngClass]=\"descriptor().rowClassName | mngClassMap: descriptor().rowClassNameMapFn : item | mngLocaleDefaultRowClass: descriptor() : item\">\n @if (selectionEnabled()) {\n @if (selectionMode() === 'multiple') {\n <td style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\">\n <p-tableCheckbox [value]=\"item\"></p-tableCheckbox>\n </td>\n } @else {\n <td style=\"min-width: 36px\" pFrozenColumn [frozen]=\"descriptor().selectionColumnFrozen ?? true\">\n <p-tableRadioButton [value]=\"item\"></p-tableRadioButton>\n </td>\n }\n }\n @if (descriptor().rowExpandable) {\n <td>\n @if (!descriptor().rowExpandableProperty || item[descriptor().rowExpandableProperty!]) {\n <button\n pButton\n type=\"button\"\n [pRowToggler]=\"item\"\n class=\"p-button-text p-button-rounded p-button-plain mng-table-row-expand-button\"\n [icon]=\"expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'\"></button>\n }\n </td>\n }\n @if (rowReorderEnabled()) {\n <td>\n <span class=\"pi pi-bars\" pReorderableRowHandle></span>\n </td>\n }\n @for (col of visibleColumns(); track col.id) {\n <td\n (click)=\"onCellClick($event, col.descriptor, item, idx)\"\n [class]=\"\n col.descriptor.className\n | mngClassMap: col.descriptor.classNameMapFn : item\n | mngTableColumnFilterClass: col.filter : hasColumnFilters() && !col.width\n \"\n [class.clickable]=\"isCellClickEnabled()\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\">\n <span class=\"p-column-title\">{{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: descriptor().model) | translate }}</span>\n <mng-table-column-value [descriptor]=\"col.descriptor\" [item]=\"item\"></mng-table-column-value>\n </td>\n }\n @if (hasLastColumn()) {\n <td\n class=\"column-custom-last justify-content-end text-right\"\n [style.min-width.px]=\"columnLastMinWidth()\"\n pFrozenColumn\n [frozen]=\"descriptor().actionColumnFrozen ?? true\"\n alignFrozen=\"right\">\n @if (columnCustomLastTemplate()) {\n <ng-container *ngTemplateOutlet=\"columnCustomLastTemplate(); context: {rowItem: item, rowIndex: idx}\"></ng-container>\n } @else if (columnCustomLastComponent()) {\n <div [mngComponent]=\"columnCustomLastComponent()\" (instanceCreated)=\"columnCustomLastComponentInstance.emit($event)\"></div>\n }\n </td>\n }\n </tr>\n </ng-template>\n <ng-template pTemplate=\"rowexpansion\" let-item>\n @if (descriptor().rowExpandable) {\n <tr>\n <td></td>\n <td [colSpan]=\"descriptor().rowExpandableColSpan\">\n @if (descriptor().rowExpandableComponentType !== undefined) {\n <ng-container [mngComponent]=\"descriptor().rowExpandableComponentType\" [inputs]=\"{item}\"> </ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowExpandTemplate(); context: {rowItem: item}\"></ng-container>\n }\n </td>\n </tr>\n }\n </ng-template>\n <ng-template pTemplate=\"loadingicon\">\n <div class=\"flex flex-column align-items-center\">\n @if (descriptor().loadingIcon) {\n <i [class]=\"'text-white text-4xl pi-spin ' + descriptor().loadingIcon\"></i>\n }\n @if (descriptor().loadingText) {\n <div class=\"text text-white text-lg font-semibold\" [ngClass]=\"{'mt-3': descriptor().loadingIcon}\">\n {{ descriptor().loadingText ?? '' | translate }}\n </div>\n }\n </div>\n </ng-template>\n <ng-template pTemplate=\"loadingbody\">\n <tr>\n <td [attr.colspan]=\"columnsColspan()\">\n <div class=\"loading-text\"></div>\n <p-skeleton [ngStyle]=\"{width: '100%'}\"></p-skeleton>\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td [attr.colspan]=\"columnsColspan()\">\n {{ 'mngTable.noItems' | translate }}\n </td>\n </tr>\n </ng-template>\n @if (footerTemplate()) {\n <ng-template pTemplate=\"summary\">\n <ng-container *ngTemplateOutlet=\"footerTemplate(); context: {data: dataListService.data(), totalCount: dataListService.count()}\"></ng-container>\n </ng-template>\n }\n </p-table>\n }\n</div>\n" }]
318
+ ], providers: [TableMetadataService, TableDataService, TablePreferencesService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div>\n <!-- MUST NOT use observable for value when using virtual scroll - does not work for some reason -->\n @if (data.isAllPaginationMetaInitialized()) {\n <p-table\n [value]=\"data.data()\"\n [dataKey]=\"metadata.descriptor().trackProperty\"\n [lazy]=\"isLazy()\"\n [loading]=\"data.loading()\"\n [paginator]=\"isPagination()\"\n [rows]=\"data.rows()\"\n [first]=\"data.offset()\"\n [totalRecords]=\"data.count()\"\n [rowsPerPageOptions]=\"metadata.rowsPerPageOptions()\"\n [showCurrentPageReport]=\"true\"\n [currentPageReportTemplate]=\"'mngTable.paginationMsg' | translate\"\n [multiSortMeta]=\"data.sortMeta()\"\n [filters]=\"data.filterMeta()\"\n [globalFilterFields]=\"metadata.searchFields()\"\n sortMode=\"multiple\"\n [selection]=\"[]\"\n (selectionChange)=\"onSelectionChange($event)\"\n [selectionMode]=\"selectionEnabled() ? selectionMode() : null\"\n [scrollable]=\"true\"\n scrollHeight=\"flex\"\n [rowHover]=\"metadata.descriptor().hasHover\"\n [styleClass]=\"className()\"\n [resizableColumns]=\"metadata.descriptor().hasResizableColumns\"\n [columnResizeMode]=\"metadata.descriptor().columnResizeMode ?? 'expand'\"\n [reorderableColumns]=\"areColumnsReorderable()\"\n paginatorDropdownAppendTo=\"body\"\n [columns]=\"visibleColumns()\"\n [expandedRowKeys]=\"expandedRowKeys()\"\n (onColResize)=\"prefs.onColumnResize($event)\"\n (onColReorder)=\"prefs.onColumnReorder($event)\"\n (onLazyLoad)=\"onTableLazyLoad($event)\"\n (onFilter)=\"onTableFilter($event)\"\n (onRowReorder)=\"onRowReorder($event)\">\n <ng-template pTemplate=\"caption\">\n @if (isCaptionVisible()) {\n <div class=\"table-header\">\n @if (overlayWithTagFilters().length > 0 || metadata.descriptor().search) {\n <mng-table-filter-overlay-with-tag\n [title]=\"metadata.descriptor().title\"\n [metadata]=\"overlayWithTagFilters()\"\n [genericFilterDescriptor]=\"metadata.genericFilterDescriptor()\"\n [model]=\"metadata.descriptor().model\"\n [enableSearch]=\"metadata.descriptor().search\"\n [search]=\"data.searchMeta()\"\n [searchLimitWordMax]=\"metadata.descriptor().searchLimitMaxWords\"\n [enableCaseSensitive]=\"isLazy()\">\n @if (hasTitleDisplay()) {\n <ng-template mngTemplate=\"title\">\n <ng-container *ngTemplateOutlet=\"captionTemplateOrComponentOrTitle\"></ng-container>\n </ng-template>\n }\n </mng-table-filter-overlay-with-tag>\n } @else {\n <ng-container *ngTemplateOutlet=\"captionTemplateOrComponentOrTitle\"></ng-container>\n }\n <ng-template #captionTemplateOrComponentOrTitle>\n @if (captionTemplate()) {\n <ng-container *ngTemplateOutlet=\"captionTemplate()\"></ng-container>\n } @else if (captionComponent()) {\n <ng-container [mngComponent]=\"captionComponent()\" (instanceCreated)=\"captionComponentInstance.emit($event)\"></ng-container>\n } @else if (metadata.descriptor().title) {\n <h5 class=\"p-0 m-0\">{{ metadata.descriptor().title! | translate }}</h5>\n }\n </ng-template>\n </div>\n }\n </ng-template>\n <ng-template pTemplate=\"header\">\n @if (!metadata.descriptor().hideHeader) {\n <tr class=\"mng-table-header\" [class]=\"metadata.descriptor().headerClassName\">\n @if (selectionEnabled()) {\n @if (selectionMode() === 'multiple') {\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\">\n <p-tableHeaderCheckbox></p-tableHeaderCheckbox>\n </th>\n } @else {\n <!-- We need the line below, because otherwise p-tableRadioButton shifts the rest of the columns in table -->\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\"></th>\n }\n }\n @if (metadata.descriptor().rowExpandable) {\n <th scope=\"col\" pFrozenColumn [frozen]=\"true\"></th>\n }\n @if (rowReorderEnabled()) {\n <th scope=\"col\"></th>\n }\n @for (col of visibleColumns(); track col.id) {\n <ng-template #sortableColumnTHTemplate>\n <div class=\"flex justify-content-between align-items-center\">\n {{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: metadata.descriptor().model) | translate }}\n <p-sortIcon [field]=\"col.descriptor.property\"></p-sortIcon>\n </div>\n </ng-template>\n <ng-template #nonSortableColumnTHTemplate>\n {{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: metadata.descriptor().model) | translate }}\n </ng-template>\n @if (col.descriptor.isReorderable) {\n <th\n pResizableColumn\n pReorderableColumn\n [id]=\"col.descriptor.property\"\n [pSortableColumn]=\"col.sort?.property\"\n [pSortableColumnDisabled]=\"!col.sort\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\"\n [class]=\"col.descriptor.headerClassName | mngTableColumnFilterClass: col.filter?.descriptor : hasColumnFilters() && !col.width\">\n <ng-container *ngTemplateOutlet=\"col.sort ? sortableColumnTHTemplate : nonSortableColumnTHTemplate\"></ng-container>\n </th>\n } @else {\n <th\n pResizableColumn\n [id]=\"col.descriptor.property\"\n [pSortableColumn]=\"col.sort?.property\"\n [pSortableColumnDisabled]=\"!col.sort\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\"\n [class]=\"col.descriptor.headerClassName | mngTableColumnFilterClass: col.filter?.descriptor : hasColumnFilters() && !col.width\">\n <ng-container *ngTemplateOutlet=\"col.sort ? sortableColumnTHTemplate : nonSortableColumnTHTemplate\"></ng-container>\n </th>\n }\n }\n @if (hasLastColumn()) {\n <th\n [style.min-width.px]=\"columnLastMinWidth()\"\n pFrozenColumn\n [frozen]=\"metadata.descriptor().actionColumnFrozen ?? areColumnsToggleable()\"\n alignFrozen=\"right\"\n class=\"column-custom-last text-right\">\n @if (areColumnsToggleable()) {\n <p-multiSelect\n #columnToggleMultiselect\n styleClass=\"p-button-primary mng-table-columns-multiselect\"\n appendTo=\"body\"\n dataKey=\"id\"\n tooltipPosition=\"left\"\n placeholder=\"\"\n dropdownIcon=\"pi pi-sliders-h\"\n [filter]=\"false\"\n [options]=\"prefs.columnsWithPrefs()\"\n [ngModel]=\"visibleColumns()\"\n [pTooltip]=\"'mngTable.adjustTable' | translate\"\n [displaySelectedLabel]=\"false\"\n (onChange)=\"prefs.onColumnToggle($event)\">\n <ng-template pTemplate=\"filter\">\n <div class=\"p-checkbox p-component ml-1\">\n <div class=\"p-hidden-accessible\">\n <input\n type=\"checkbox\"\n readonly=\"readonly\"\n [checked]=\"columnToggleMultiselect.allSelected\"\n (focus)=\"columnToggleMultiselect.onHeaderCheckboxFocus()\"\n (blur)=\"columnToggleMultiselect.onHeaderCheckboxBlur()\"\n (keydown.space)=\"columnToggleMultiselect.onToggleAll($event)\" />\n </div>\n <div\n class=\"p-checkbox-box\"\n role=\"checkbox\"\n [attr.aria-checked]=\"columnToggleMultiselect.allSelected\"\n [ngClass]=\"{\n 'p-highlight': anyColumnVisible()\n }\"\n (click)=\"prefs.onColumnToggleAll()\">\n <span class=\"p-checkbox-icon\" [ngClass]=\"{'pi pi-check': anyColumnVisible()}\"></span>\n </div>\n </div>\n <p-button\n icon=\"pi pi-replay\"\n styleClass=\"p-button-secondary\"\n [pTooltip]=\"'mngTable.resetLayout' | translate\"\n tooltipPosition=\"left\"\n (click)=\"prefs.clearLayoutPreferences()\"></p-button>\n </ng-template>\n <ng-template let-item pTemplate=\"item\">\n {{ item.descriptor.title ?? (item.descriptor.property | mngI18nProperty: metadata.descriptor().model) | translate }}\n </ng-template>\n </p-multiSelect>\n }\n </th>\n }\n </tr>\n }\n @if (hasColumnFilters()) {\n <tr class=\"mng-column-filter-row\">\n <!-- We need the line below, because otherwise p-tableRadioButton shifts the rest of the columns in table -->\n @if (selectionEnabled()) {\n <th style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\"></th>\n }\n @if (rowReorderEnabled()) {\n <th scope=\"col\"></th>\n }\n @if (metadata.descriptor().rowExpandable) {\n <th scope=\"col\"></th>\n }\n @for (col of visibleColumns(); track col.id) {\n <th\n [class]=\"col.filter?.descriptor?.columnClassName | mngTableColumnFilterClass: col.filter?.descriptor : hasColumnFilters() && !col.width\"\n [style.width.px]=\"col.width\"\n [style.width.%]=\"col.width ? null : (col.filter?.descriptor?.columnWidth ?? col.descriptor.width ?? null)\"\n [style.min-width.px]=\"col.width ? null : (col.filter?.descriptor?.columnMinWidth ?? col.descriptor.minWidth)\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\">\n @if (col.filter) {\n <mng-table-column-filter [metadata]=\"col.filter\"></mng-table-column-filter>\n }\n </th>\n }\n @if (hasLastColumn()) {\n <th class=\"column-custom-last\" [style.min-width.px]=\"columnLastMinWidth()\"></th>\n }\n </tr>\n }\n </ng-template>\n <ng-template pTemplate=\"body\" let-item let-idx=\"rowIndex\" let-expanded=\"expanded\">\n <tr\n [pReorderableRow]=\"idx\"\n [ngClass]=\"\n metadata.descriptor().rowClassName | mngClassMap: metadata.descriptor().rowClassNameMapFn : item | mngLocaleDefaultRowClass: metadata.descriptor() : item\n \">\n @if (selectionEnabled()) {\n @if (selectionMode() === 'multiple') {\n <td style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\">\n <p-tableCheckbox [value]=\"item\"></p-tableCheckbox>\n </td>\n } @else {\n <td style=\"min-width: 36px\" pFrozenColumn [frozen]=\"metadata.descriptor().selectionColumnFrozen ?? true\">\n <p-tableRadioButton [value]=\"item\"></p-tableRadioButton>\n </td>\n }\n }\n @if (metadata.descriptor().rowExpandable) {\n <td>\n @if (!metadata.descriptor().rowExpandableProperty || item[metadata.descriptor().rowExpandableProperty!]) {\n <button\n pButton\n type=\"button\"\n [pRowToggler]=\"item\"\n class=\"p-button-text p-button-rounded p-button-plain mng-table-row-expand-button\"\n [icon]=\"expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'\"></button>\n }\n </td>\n }\n @if (rowReorderEnabled()) {\n <td>\n <span class=\"pi pi-bars\" pReorderableRowHandle></span>\n </td>\n }\n @for (col of visibleColumns(); track col.id) {\n <td\n (click)=\"onCellClick($event, col.descriptor, item, idx)\"\n [class]=\"\n col.descriptor.className\n | mngClassMap: col.descriptor.classNameMapFn : item\n | mngTableColumnFilterClass: col.filter?.descriptor : hasColumnFilters() && !col.width\n \"\n [class.clickable]=\"isCellClickEnabled()\"\n [style.width]=\"col.width ? col.width + 'px' : col.descriptor.width + '%'\"\n [style.min-width.px]=\"col.width ? null : col.descriptor.minWidth\"\n [style.max-width.px]=\"col.width ?? col.descriptor.maxWidth\">\n <span class=\"p-column-title\">{{ col.descriptor.title ?? (col.descriptor.property | mngI18nProperty: metadata.descriptor().model) | translate }}</span>\n <mng-table-column-value [descriptor]=\"col.descriptor\" [item]=\"item\"></mng-table-column-value>\n </td>\n }\n @if (hasLastColumn()) {\n <td\n class=\"column-custom-last justify-content-end text-right\"\n [style.min-width.px]=\"columnLastMinWidth()\"\n pFrozenColumn\n [frozen]=\"metadata.descriptor().actionColumnFrozen ?? true\"\n alignFrozen=\"right\">\n @if (columnCustomLastTemplate()) {\n <ng-container *ngTemplateOutlet=\"columnCustomLastTemplate(); context: {rowItem: item, rowIndex: idx}\"></ng-container>\n } @else if (columnCustomLastComponent()) {\n <div [mngComponent]=\"columnCustomLastComponent()\" (instanceCreated)=\"columnCustomLastComponentInstance.emit($event)\"></div>\n }\n </td>\n }\n </tr>\n </ng-template>\n <ng-template pTemplate=\"rowexpansion\" let-item>\n @if (metadata.descriptor().rowExpandable) {\n <tr>\n <td></td>\n <td [colSpan]=\"metadata.descriptor().rowExpandableColSpan\">\n @if (metadata.descriptor().rowExpandableComponentType !== undefined) {\n <ng-container [mngComponent]=\"metadata.descriptor().rowExpandableComponentType\" [inputs]=\"{item}\"> </ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowExpandTemplate(); context: {rowItem: item}\"></ng-container>\n }\n </td>\n </tr>\n }\n </ng-template>\n <ng-template pTemplate=\"loadingicon\">\n <div class=\"flex flex-column align-items-center\">\n @if (metadata.descriptor().loadingIcon) {\n <i [class]=\"'text-white text-4xl pi-spin ' + metadata.descriptor().loadingIcon\"></i>\n }\n @if (metadata.descriptor().loadingText) {\n <div class=\"text text-white text-lg font-semibold\" [ngClass]=\"{'mt-3': metadata.descriptor().loadingIcon}\">\n {{ metadata.descriptor().loadingText ?? '' | translate }}\n </div>\n }\n </div>\n </ng-template>\n <ng-template pTemplate=\"loadingbody\">\n <tr>\n <td [attr.colspan]=\"columnsColspan()\">\n <div class=\"loading-text\"></div>\n <p-skeleton [ngStyle]=\"{width: '100%'}\"></p-skeleton>\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td [attr.colspan]=\"columnsColspan()\">\n {{ 'mngTable.noItems' | translate }}\n </td>\n </tr>\n </ng-template>\n @if (footerTemplate()) {\n <ng-template pTemplate=\"summary\">\n <ng-container *ngTemplateOutlet=\"footerTemplate(); context: {data: data.data(), totalCount: data.count()}\"></ng-container>\n </ng-template>\n }\n </p-table>\n }\n</div>\n" }]
635
319
  }], ctorParameters: () => [] });
636
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGFibGUvc3JjL2NvbXBvbmVudHMvdGFibGUvdGFibGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vdGFibGUvc3JjL2NvbXBvbmVudHMvdGFibGUvdGFibGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLGdCQUFnQixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDOUUsT0FBTyxFQUNILHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsUUFBUSxFQUtSLGVBQWUsRUFDZixnQkFBZ0IsRUFDaEIsUUFBUSxFQUNSLGVBQWUsRUFDZixNQUFNLEVBQ04sTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBQ04sTUFBTSxFQUNOLFNBQVMsRUFDVCxZQUFZLEVBQ2YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLG9CQUFvQixFQUFFLGtCQUFrQixFQUFFLFlBQVksRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBQ2xHLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUMsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFVLE1BQU0sRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRWxJLE9BQU8sRUFBQyxlQUFlLEVBQUUsZ0JBQWdCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RSxPQUFPLEVBQUMsY0FBYyxFQUFXLE1BQU0sYUFBYSxDQUFDO0FBQ3JELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1QyxPQUFPLEVBQXlCLGlCQUFpQixFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDOUUsT0FBTyxFQUFDLEtBQUssRUFBaUUsV0FBVyxFQUF1QixN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QkFDWixhQUFhLHFYQUNiLGVBQWUsNEZBQ2YsNkJBQTZCLDJNQUM3QixXQUFXLCtWQUNYLGlCQUFpQjs7MkZBS1osY0FBYztrQkE1QjFCLFNBQVM7aUNBQ00sSUFBSSxZQUNOLFdBQVcsV0FFWjt3QkFDTCxTQUFTO3dCQUNULGtCQUFrQjt3QkFDbEIsZ0JBQWdCO3dCQUNoQixPQUFPO3dCQUNQLE9BQU87d0JBQ1AsZ0JBQWdCO3dCQUNoQix5QkFBeUI7d0JBQ3pCLFlBQVk7d0JBQ1oseUJBQXlCO3dCQUN6QiwwQkFBMEI7d0JBQzFCLDBCQUEwQjt3QkFDMUIsV0FBVzt3QkFDWCxpQkFBaUI7d0JBQ2pCLFlBQVk7d0JBQ1osYUFBYTt3QkFDYixlQUFlO3dCQUNmLDZCQUE2Qjt3QkFDN0IsV0FBVzt3QkFDWCxpQkFBaUI7cUJBQ3BCLGFBQ1UsQ0FBQyxlQUFlLENBQUMsbUJBQ1gsdUJBQXVCLENBQUMsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7QXN5bmNQaXBlLCBOZ0NsYXNzLCBOZ1N0eWxlLCBOZ1RlbXBsYXRlT3V0bGV0fSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgICBDb21wb25lbnQsXG4gICAgSW5qZWN0b3IsXG4gICAgT25EZXN0cm95LFxuICAgIFNpZ25hbCxcbiAgICBUZW1wbGF0ZVJlZixcbiAgICBUeXBlLFxuICAgIGFmdGVyTmV4dFJlbmRlcixcbiAgICBib29sZWFuQXR0cmlidXRlLFxuICAgIGNvbXB1dGVkLFxuICAgIGNvbnRlbnRDaGlsZHJlbixcbiAgICBlZmZlY3QsXG4gICAgaW5qZWN0LFxuICAgIGlucHV0LFxuICAgIG91dHB1dCxcbiAgICBzaWduYWwsXG4gICAgdmlld0NoaWxkLFxuICAgIHZpZXdDaGlsZHJlblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7b3V0cHV0RnJvbU9ic2VydmFibGUsIHRha2VVbnRpbERlc3Ryb3llZCwgdG9PYnNlcnZhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQge0Zvcm1zTW9kdWxlfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge0FjdGl2YXRlZFJvdXRlLCBOYXZpZ2F0aW9uQ2FuY2VsLCBOYXZpZ2F0aW9uRW5kLCBOYXZpZ2F0aW9uRXJyb3IsIE5hdmlnYXRpb25TdGFydCwgUGFyYW1zLCBSb3V0ZXJ9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbmltcG9ydCB7VHJhbnNsYXRlTW9kdWxlLCBUcmFuc2xhdGVTZXJ2aWNlfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7TWVzc2FnZVNlcnZpY2UsIFNvcnRNZXRhfSBmcm9tICdwcmltZW5nL2FwaSc7XG5pbXBvcnQge0J1dHRvbk1vZHVsZX0gZnJvbSAncHJpbWVuZy9idXR0b24nO1xuaW1wb3J0IHtNdWx0aVNlbGVjdENoYW5nZUV2ZW50LCBNdWx0aVNlbGVjdE1vZHVsZX0gZnJvbSAncHJpbWVuZy9tdWx0aXNlbGVjdCc7XG5pbXBvcnQge1RhYmxlLCBUYWJsZUNvbHVtblJlb3JkZXJFdmVudCwgVGFibGVGaWx0ZXJFdmVudCwgVGFibGVMYXp5TG9hZEV2ZW50LCBUYWJsZU1vZHVsZSwgVGFibGVSb3dSZW9yZGVyRXZlbnR9IGZyb20gJ3ByaW1lbmcvdGFibGUnO1xuaW1wb3J0IHtUb29sdGlwTW9kdWxlfSBmcm9tICdwcmltZW5nL3Rvb2x0aXAnO1xuaW1wb3J0IHtORVZFUiwgU3ViamVjdCwgU3Vic2NyaXB0aW9uLCBjb21iaW5lTGF0ZXN0LCBvZiwgc3dpdGNoTWFwfSBmcm9tICdyeGpzJztcbmltcG9ydCB7ZmlsdGVyfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7XG4gICAgQ2xhc3NNYXBQaXBlLFxuICAgIENvbW1vbnNGaWx0ZXJNZXRhZGF0YSxcbiAgICBDb21tb25zU2VydmljZSxcbiAgICBDb21tb25zU3RvcmFnZVNlcnZpY2UsXG4gICAgQ29tcG9uZW50RGlyZWN0aXZlLFxuICAgIERhdGFMaXN0UGFyYW1zLFxuICAgIERhdGFMaXN0UmVzdWx0LFxuICAgIEZpbHRlck1hdGNoTW9kZSxcbiAgICBJMThuUHJvcGVydHlQaXBlLFxuICAgIExvZ2dlclNlcnZpY2UsXG4gICAgVGVtcGxhdGVEaXJlY3RpdmUsXG4gICAgYm9vbGVhbk9yVW5kZWZpbmVkQXR0cmlidXRlLFxuICAgIHRvT2JzZXJ2YWJsZSBhcyBjb21tb25zVG9PYnNlcnZhYmxlLFxuICAgIGRhdGFMaXN0UGFyYW1zVG9VcmxRdWVyeSxcbiAgICBmaW5kVGVtcGxhdGVCeU5hbWUsXG4gICAgZnJvbVN1YnNjcmliZUVycm9yLFxuICAgIGZyb21UYWJsZUxvYWRUb0RhdGFMaXN0UGFyYW1zLFxuICAgIGZyb21VcmxRdWVyeVRvRGF0YUxpc3RQYXJhbXMsXG4gICAgZ2V0RXJyb3JMb2dMZXZlbCxcbiAgICBtZXJnZURhdGFMaXN0UGFyYW1zV2l0aERlZmF1bHRzXG59IGZyb20gJ0BtZWRpdXNpbmMvbW5nLWNvbW1vbnMvY29yZSc7XG5pbXBvcnQge0ZpbHRlckRlc2NyaXB0b3IsIEZpbHRlckRpc3BsYXlUeXBlRW51bSwgRmlsdGVyTG9va3VwRGVzY3JpcHRvciwgRmlsdGVyVHlwZUVudW19IGZyb20gJ0BtZWRpdXNpbmMvbW5nLWNvbW1vbnMvZmlsdGVyJztcbmltcG9ydCB7XG4gICAgQ29sdW1uRGVzY3JpcHRvcixcbiAgICBJVGFibGVEYXRhUHJvdmlkZXIsXG4gICAgVGFibGVDZWxsQ2xpY2tFdmVudCxcbiAgICBUYWJsZURlc2NyaXB0b3JJbnN0LFxuICAgIFRhYmxlRHluYW1pY0Rlc2NyaXB0b3JJbnN0LFxuICAgIFRhYmxlTGF5b3V0UHJlZmVyZW5jZXMsXG4gICAgVGFibGVMb2FkRXZlbnQsXG4gICAgVGFibGVQYWdpbmF0aW9uTW9kZUVudW0sXG4gICAgVGFibGVSZWxvYWRFdmVudCxcbiAgICBUYWJsZVNpemVFbnVtLFxuICAgIHRhYmxlRGVzY3JpcHRvclxufSBmcm9tICdAbWVkaXVzaW5jL21uZy1jb21tb25zL3RhYmxlL2FwaSc7XG5cbmltcG9ydCB7Y3JlYXRlRmlsdGVyRGVzY3JpcHRvcnNGcm9tR2VuZXJpY30gZnJvbSAnLi4vLi4vaGVscGVycy9maWx0ZXJzJztcbmltcG9ydCB7dGFibGVOb3RpZmljYXRpb25FcnJvcn0gZnJvbSAnLi4vLi4vaGVscGVycy9ub3RpZmljYXRpb24nO1xuaW1wb3J0IHtnZW5lcmF0ZVRhYmxlTGF5b3V0UHJlZnNLZXl9IGZyb20gJy4uLy4uL2hlbHBlcnMvdGFibGUtbGF5b3V0LXByZWZzJztcbmltcG9ydCB7Q29sdW1uV2l0aFByZWZlcmVuY2VzfSBmcm9tICcuLi8uLi9tb2RlbHMvY29sdW1uLXByZWZlcmVuY2VzLm1vZGVsJztcbmltcG9ydCB7TG9jYWxlRGVmYXVsdFJvd0NsYXNzUGlwZX0gZnJvbSAnLi4vLi4vcGlwZXMvbG9jYWxlLWRlZmF1bHQtcm93LWNsYXNzLnBpcGUnO1xuaW1wb3J0IHtUYWJsZUNvbHVtbkZpbHRlckNsYXNzUGlwZX0gZnJvbSAnLi4vLi4vcGlwZXMvdGFibGUtY29sdW1uLWZpbHRlci1jbGFzcy5waXBlJztcbmltcG9ydCB7RGF0YUxpc3RTZXJ2aWNlfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9kYXRhLWxpc3Quc2VydmljZSc7XG5pbXBvcnQge0NPTU1PTlNfVEFCTEVfRkVBVFVSRV9DT05GSUdfSVR9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3RhYmxlLWZlYXR1cmUtY29uZmlnLnRva2VuJztcbmltcG9ydCB7VGFibGVDb2x1bW5GaWx0ZXJDb21wb25lbnR9IGZyb20gJy4uL2NvbHVtbi1maWx0ZXIvY29sdW1uLWZpbHRlci5jb21wb25lbnQnO1xuaW1wb3J0IHtUYWJsZUNvbHVtblZhbHVlQ29tcG9uZW50fSBmcm9tICcuLi9jb2x1bW4tdmFsdWUvY29sdW1uLXZhbHVlLmNvbXBvbmVudCc7XG5pbXBvcnQge0ZpbHRlck92ZXJsYXlXaXRoVGFnQ29tcG9uZW50fSBmcm9tICcuLi9maWx0ZXIvZmlsdGVyLW92ZXJsYXktd2l0aC10YWcvZmlsdGVyLW92ZXJsYXktd2l0aC10YWcuY29tcG9uZW50JztcblxuQENvbXBvbmVudCh7XG4gICAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgICBzZWxlY3RvcjogJ21uZy10YWJsZScsXG4gICAgdGVtcGxhdGVVcmw6ICcuL3RhYmxlLmNvbXBvbmVudC5odG1sJyxcbiAgICBpbXBvcnRzOiBbXG4gICAgICAgIEFzeW5jUGlwZSxcbiAgICAgICAgQ29tcG9uZW50RGlyZWN0aXZlLFxuICAgICAgICBJMThuUHJvcGVydHlQaXBlLFxuICAgICAgICBOZ0NsYXNzLFxuICAgICAgICBOZ1N0eWxlLFxuICAgICAgICBOZ1RlbXBsYXRlT3V0bGV0LFxuICAgICAgICBUYWJsZUNvbHVtblZhbHVlQ29tcG9uZW50LFxuICAgICAgICBDbGFzc01hcFBpcGUsXG4gICAgICAgIExvY2FsZURlZmF1bHRSb3dDbGFzc1BpcGUsXG4gICAgICAgIFRhYmxlQ29sdW1uRmlsdGVyQ29tcG9uZW50LFxuICAgICAgICBUYWJsZUNvbHVtbkZpbHRlckNsYXNzUGlwZSxcbiAgICAgICAgVGFibGVNb2R1bGUsXG4gICAgICAgIE11bHRpU2VsZWN0TW9kdWxlLFxuICAgICAgICBCdXR0b25Nb2R1bGUsXG4gICAgICAgIFRvb2x0aXBNb2R1bGUsXG4gICAgICAgIFRyYW5zbGF0ZU1vZHVsZSxcbiAgICAgICAgRmlsdGVyT3ZlcmxheVdpdGhUYWdDb21wb25lbnQsXG4gICAgICAgIEZvcm1zTW9kdWxlLFxuICAgICAgICBUZW1wbGF0ZURpcmVjdGl2ZVxuICAgIF0sXG4gICAgcHJvdmlkZXJzOiBbRGF0YUxpc3RTZXJ2aWNlXSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBUYWJsZUNvbXBvbmVudDxJdGVtID0gYW55LCBTZXJ2aWNlID0gdW5kZWZpbmVkLCBTb3J0cyA9IGFueSwgRmlsdGVycyBleHRlbmRzIGtleW9mIGFueSA9IGFueT4gaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZmlsdGVyS2V5UHJlcGVuZCA9ICdmXyc7XG4gICAgcHVibGljIHJlYWRvbmx5IGNtcFR5cGVOYW1lID0gJ1RhYmxlQ29tcG9uZW50JztcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gaW5qZWN0KExvZ2dlclNlcnZpY2UpLmNyZWF0ZSh0aGlzLmNtcFR5cGVOYW1lKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGluamVjdG9yID0gaW5qZWN0KEluamVjdG9yKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgcm91dGUgPSBpbmplY3QoQWN0aXZhdGVkUm91dGUpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgdHJhbnNsYXRlID0gaW5qZWN0KFRyYW5zbGF0ZVNlcnZpY2UpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbWVzc2FnZVNlcnZpY2UgPSBpbmplY3QoTWVzc2FnZVNlcnZpY2UpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY29tbW9ucyA9IGluamVjdChDb21tb25zU2VydmljZSk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBzdG9yYWdlU2VydmljZSA9IGluamVjdChDb21tb25zU3RvcmFnZVNlcnZpY2UpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnID0gaW5qZWN0KENPTU1PTlNfVEFCTEVfRkVBVFVSRV9DT05GSUdfSVQsIHtvcHRpb25hbDogdHJ1ZX0pO1xuICAgIHB1YmxpYyByZWFkb25seSBkYXRhTGlzdFNlcnZpY2UgPSBpbmplY3QoRGF0YUxpc3RTZXJ2aWNlPEl0ZW0+KTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdEZpbHRlckRpc3BsYXlUeXBlOiBGaWx0ZXJEaXNwbGF5VHlwZUVudW0gPSB0aGlzLmNvbmZpZz8uZmlsdGVyRGlzcGxheVR5cGUgPz8gRmlsdGVyRGlzcGxheVR5cGVFbnVtLkNvbHVtbjtcblxuICAgIC8vIG1ldGFkYXRhIGlucHV0XG4gICAgcHVibGljIGRlc2NyaXB0b3JJbnB1dCA9IGlucHV0LnJlcXVpcmVkPFRhYmxlRGVzY3JpcHRvckluc3Q8SXRlbSwgU29ydHMsIEZpbHRlcnM+Pih7YWxpYXM6ICdkZXNjcmlwdG9yJ30pO1xuXG4gICAgLy8gZGF0YSBzb3VyY2UgaW5wdXRzXG4gICAgcHVibGljIGl0ZW1zID0gaW5wdXQ8SXRlbVtdPigpO1xuICAgIHB1YmxpYyByZXN1bHQgPSBpbnB1dDxEYXRhTGlzdFJlc3VsdDxJdGVtPj4oKTtcbiAgICBwdWJsaWMgbG9hZGluZ0lucHV0ID0gaW5wdXQodW5kZWZpbmVkLCB7YWxpYXM6ICdsb2FkaW5nJywgdHJhbnNmb3JtOiBib29sZWFuT3JVbmRlZmluZWRBdHRyaWJ1dGV9KTtcbiAgICBwdWJsaWMgZGF0YVByb3ZpZGVyID0gaW5wdXQ8SVRhYmxlRGF0YVByb3ZpZGVyPEl0ZW0sIFNlcnZpY2UsIFNvcnRzLCBGaWx0ZXJzPj4oKTtcblxuICAgIC8vIGV4dHJhIGZlYXR1cmVzIGlucHV0XG4gICAgcHVibGljIHVzZVF1ZXJ5UGFyYW1zID0gaW5wdXQoZmFsc2UsIHt0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGV9KTtcbiAgICBwdWJsaWMgY2VsbENsaWNrRW5hYmxlZCA9IGlucHV0KHRydWUsIHt0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGV9KTtcbiAgICBwdWJsaWMgc2VsZWN0aW9uTW9kZSA9IGlucHV0PCdzaW5nbGUnIHwgJ211bHRpcGxlJz4oJ211bHRpcGxlJyk7XG4gICAgcHVibGljIHNlbGVjdGlvbkVuYWJsZWQgPSBpbnB1dChmYWxzZSwge3RyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZX0pO1xuICAgIHB1YmxpYyByb3dSZW9yZGVyRW5hYmxlZElucHV0ID0gaW5wdXQodHJ1ZSwge2FsaWFzOiAncm93UmVvcmRlckVuYWJsZWQnLCB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGV9KTtcbiAgICBwdWJsaWMgcm93UmVvcmRlckVuYWJsZWQgPSBjb21wdXRlZDxib29sZWFuPigoKSA9PiB0aGlzLnJvd1Jlb3JkZXJFbmFibGVkSW5wdXQoKSAmJiB0aGlzLmRlc2NyaXB0b3IoKS5yb3dSZW9yZGVyYWJsZSk7XG5cbiAgICAvLyBzdHlsaW5nXG4gICAgcHVibGljIGNvbHVtbkxhc3RNaW5XaWR0aCA9IGlucHV0PG51bWJlcj4oKTtcbiAgICBwdWJsaWMgY29sdW1uc0NvbHNwYW4gPSBjb21wdXRlZCgoKSA9PiB0aGlzLnZpc2libGVDb2x1bW5zKCkubGVuZ3RoICsgKHRoaXMuaGFzTGFzdENvbHVtbigpID8gMSA6IDApICsgKHRoaXMuc2VsZWN0aW9uRW5hYmxlZCgpID8gMSA6IDApICsgKHRoaXMucm93UmVvcmRlckVuYWJsZWQoKSA/IDEgOiAwKSk7XG4gICAgcHVibGljIGhhc1RpdGxlRGlzcGxheSA9IGNvbXB1dGVkKCgpID0+IHRoaXMuY2FwdGlvblRlbXBsYXRlKCkgfHwgdGhpcy5jYXB0aW9uQ29tcG9uZW50KCkgfHwgdGhpcy5kZXNjcmlwdG9yKCkudGl0bGUpO1xuICAgIHB1YmxpYyBpc0NhcHRpb25WaXNpYmxlID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5oYXNUaXRsZURpc3BsYXkoKSB8fCB0aGlzLm92ZXJsYXlXaXRoVGFnRmlsdGVycygpLmxlbmd0aCA+IDAgfHwgdGhpcy5kZXNjcmlwdG9yKCkuc2VhcmNoKTtcblxuICAgIC8vIGNvbXBvbmVudCBpbnB1dHNcbiAgICBwdWJsaWMgY2FwdGlvbkNvbXBvbmVudCA9IGlucHV0PFR5cGU8YW55Pj4oKTtcbiAgICBwdWJsaWMgY29sdW1uQ3VzdG9tTGFzdENvbXBvbmVudCA9IGlucHV0PFR5cGU8YW55Pj4oKTtcbiAgICBwdWJsaWMgZ2xvYmFsRmlsdGVyRmllbGRzSW5wdXQgPSBpbnB1dDxzdHJpbmdbXSB8IHVuZGVmaW5lZD4odW5kZWZpbmVkLCB7YWxpYXM6ICdnbG9iYWxGaWx0ZXJGaWVsZHMnfSk7XG5cbiAgICAvLyBjZWxsIGNsaWNrXG4gICAgcHJpdmF0ZSBjZWxsQ2xpY2tTdWJqZWN0ID0gbmV3IFN1YmplY3Q8VGFibGVDZWxsQ2xpY2tFdmVudDxJdGVtPj4oKTtcbiAgICBwdWJsaWMgaXNDZWxsQ2xpY2tPYnNlcnZlZCA9IHNpZ25hbCh0aGlzLmNlbGxDbGlja1N1YmplY3Qub2JzZXJ2ZWQpO1xuICAgIHB1YmxpYyBpc0NlbGxDbGlja0VuYWJsZWQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmNlbGxDbGlja0VuYWJsZWQoKSAmJiB0aGlzLmlzQ2VsbENsaWNrT2JzZXJ2ZWQoKSk7XG5cbiAgICAvLyBldmVudCBvdXRwdXRzXG4gICAgcHVibGljIHRhYmxlTG9hZCA9IG91dHB1dDxUYWJsZUxvYWRFdmVudD4oKTtcbiAgICBwdWJsaWMgY2VsbENsaWNrID0gb3V0cHV0RnJvbU9ic2VydmFibGUodGhpcy5jZWxsQ2xpY2tTdWJqZWN0KTtcbiAgICBwdWJsaWMgc2VsZWN0aW9uQ2hhbmdlID0gb3V0cHV0PEFycmF5PEl0ZW0+PigpO1xuICAgIHB1YmxpYyBjYXB0aW9uQ29tcG9uZW50SW5zdGFuY2UgPSBvdXRwdXQ8YW55PigpO1xuICAgIHB1YmxpYyBjb2x1bW5DdXN0b21MYXN0Q29tcG9uZW50SW5zdGFuY2UgPSBvdXRwdXQ8YW55PigpO1xuICAgIHB1YmxpYyByb3dSZW9yZGVyID0gb3V0cHV0PFRhYmxlUm93UmVvcmRlckV2ZW50PigpO1xuXG4gICAgLy8gY29udGVudCBhbmQgdmlldyBxdWVyaWVzXG4gICAgcHVibGljIHRlbXBsYXRlcyA9IGNvbnRlbnRDaGlsZHJlbihUZW1wbGF0ZURpcmVjdGl2ZSk7XG4gICAgcHVibGljIGNvbXBvbmVudHMgPSB2aWV3Q2hpbGRyZW4oQ29tcG9uZW50RGlyZWN0aXZlPGFueT4pO1xuICAgIHB1YmxpYyBwcmltZVRhYmxlID0gdmlld0NoaWxkLnJlcXVpcmVkKFRhYmxlKTtcblxuICAgIC8vIHRlbXBsYXRlc1xuICAgIHB1YmxpYyBjYXB0aW9uVGVtcGxhdGU6IFNpZ25hbDxUZW1wbGF0ZVJlZjxhbnk+IHwgbnVsbD4gPSBjb21wdXRlZCgoKSA9PiBmaW5kVGVtcGxhdGVCeU5hbWUoWy4uLnRoaXMudGVtcGxhdGVzKCldLCAnY2FwdGlvbicpKTtcbiAgICBwdWJsaWMgY29sdW1uQ3VzdG9tTGFzdFRlbXBsYXRlOiBTaWduYWw8VGVtcGxhdGVSZWY8YW55PiB8IG51bGw+ID0gY29tcHV0ZWQoKCkgPT4gZmluZFRlbXBsYXRlQnlOYW1lKFsuLi50aGlzLnRlbXBsYXRlcygpXSwgJ2NvbHVtbkN1c3RvbUxhc3QnKSk7XG4gICAgcHVibGljIGZvb3RlclRlbXBsYXRlOiBTaWduYWw8VGVtcGxhdGVSZWY8YW55PiB8IG51bGw+ID0gY29tcHV0ZWQoKCkgPT4gZmluZFRlbXBsYXRlQnlOYW1lKFsuLi50aGlzLnRlbXBsYXRlcygpXSwgJ2Zvb3RlcicpKTtcbiAgICBwdWJsaWMgcm93RXhwYW5kVGVtcGxhdGU6IFNpZ25hbDxUZW1wbGF0ZVJlZjxhbnk+IHwgbnVsbD4gPSBjb21wdXRlZCgoKSA9PiBmaW5kVGVtcGxhdGVCeU5hbWUoWy4uLnRoaXMudGVtcGxhdGVzKCldLCAncm93RXhwYW5kQ29udGVudCcpKTtcblxuICAgIC8vIGRhdGEgcHJvdmlkZXIgYW5kIGl0ZW1zXG4gICAgcHVibGljIGlzTGF6eSA9IGNvbXB1dGVkKCgpID0+IHRoaXMuZGF0YVByb3ZpZGVyKCk/LmlzTGF6eSA9PT0gdHJ1ZSk7XG4gICAgcHVibGljIGlzUGFnaW5hdGlvbiA9IGNvbXB1dGVkKCgpID0+IHRoaXMucGFnaW5hdGlvbk1vZGUoKSA9PT0gVGFibGVQYWdpbmF0aW9uTW9kZUVudW0uUGFnaW5hdGlvbik7XG4gICAgcHVibGljIHVzZVF1ZXJ5UGFyYW1zSW5pdGlhbGl6ZWQgPSBzaWduYWwoZmFsc2UpO1xuXG4gICAgLy8gdmlzdWFsXG4gICAgcHJpdmF0ZSBwYWdpbmF0aW9uTW9kZSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmRlc2NyaXB0b3IoKS5wYWdpbmF0aW9uTW9kZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIC8vIGRlc2NyaXB0b3IgY2hvaWNlIGlzIHRoZSBzdHJvbmdlc3QgLSBpZiBkZWZpbmVkLCB1c2UgdGhpcyB2YWx1ZVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRvcigpLnBhZ2luYXRpb25Nb2RlO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLmRhdGFQcm92aWRlcigpICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgLy8gd2hlbiBkYXRhIHByb3ZpZGVyIGlzIHVzZWQsIHVzZSBwYWdpbmF0aW9uXG4gICAgICAgICAgICByZXR1cm4gVGFibGVQYWdpbmF0aW9uTW9kZUVudW0uUGFnaW5hdGlvbjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBUYWJsZVBhZ2luYXRpb25Nb2RlRW51bS5Ob25lO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcHVibGljIGNsYXNzTmFtZSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgICAgbGV0IGNsYXNzTmFtZSA9IHRoaXMuZGVzY3JpcHRvcigpLmNsYXNzTmFtZSA/PyAnJztcbiAgICAgICAgc3dpdGNoICh0aGlzLmRlc2NyaXB0b3IoKS5zaXplKSB7XG4gICAgICAgICAgICBjYXNlIFRhYmxlU2l6ZUVudW0uU21hbGw6XG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lICs9ICcgcC1kYXRhdGFibGUtc20nO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBUYWJsZVNpemVFbnVtLkxhcmdlOlxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSAnIHAtZGF0YXRhYmxlLWxnJztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5kZXNjcmlwdG9yKCkuaGFzR3JpZGxpbmVzKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gJyBwLWRhdGF0YWJsZS1ncmlkbGluZXMnO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc0NhcHRpb25WaXNpYmxlKCkpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSAnIGRhdGF0YWJsZS1uby1oZWFkZXInO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjbGFzc05hbWU7XG4gICAgfSk7XG5cbiAgICAvLyBkYXRhIHByb3ZpZGVyXG4gICAgcHJpdmF0ZSBkYXRhUHJvdmlkZXJTZXJ2aWNlID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgICAgICBjb25zdCBkYXRhUHJvdmlkZXIgPSB0aGlzLmRhdGFQcm92aWRlcigpO1xuICAgICAgICByZXR1cm4gZGF0YVByb3ZpZGVyPy5zZXJ2aWNlVHlwZSA/IHRoaXMuaW5qZWN0b3IuZ2V0PGFueT4oZGF0YVByb3ZpZGVyLnNlcnZpY2VUeXBlKSA6IG51bGw7XG4gICAgfSk7XG4gICAgcHJpdmF0ZSBkYXRhUHJvdmlkZXJMYXRlc3RMYXp5TG9hZEV2ZW50PzogVGFibGVMYXp5TG9hZEV2ZW50O1xuICAgIHByaXZhdGUgbGF0ZXN0UGFyYW1zV2l0aERlZmF1bHRzPzogRGF0YUxpc3RQYXJhbXM7XG4gICAgcHJpdmF0ZSBkYXRhUHJvdmlkZXJTdWJzY3JpcHRpb24/OiBTdWJzY3JpcHRpb247XG5cbiAgICAvLyBkZXNjcmlwdG9yc1xuICAgIHB1YmxpYyBkZXNjcmlwdG9yID0gc2lnbmFsPFRhYmxlRGVzY3JpcHRvckluc3Q8YW55LCBhbnksIGFueT4+KHRhYmxlRGVzY3JpcHRvcjxzdHJpbmcsIHN0cmluZywgc3RyaW5nPigpKTtcbiAgICBwcml2YXRlIGxvY2Fsc3RvcmFnZUtleSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IHRoaXMuZGVzY3JpcHRvcigpO1xuICAgICAgICByZXR1cm4gZGVzY3JpcHRvci5tb2RlbC5pMThuQmFzZUtleSA/IGdlbmVyYXRlVGFibGVMYXlvdXRQcmVmc0tleShkZXNjcmlwdG9yLm1vZGVsLmkxOG5CYXNlS2V5LCB0aGlzLnJvdXRlci51cmwsIGRlc2NyaXB0b3IuaWRlbnRpZmllcikgOiBudWxsO1xuICAgIH0pO1xuICAgIHByaXZhdGUgbGF5b3V0UHJlZnNTYXZlQ250ID0gc2lnbmFsKDApO1xuICAgIHByaXZhdGUgbGF5b3V0UHJlZmVyZW5jZXMgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGxzS2V5ID0gdGhpcy5sb2NhbHN0b3JhZ2VLZXkoKTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgICBjb25zdCBjbnQgPSB0aGlzLmxheW91dFByZWZzU2F2ZUNudCgpOyAvLyBuZWVkZWQgdG8gZm9yY2UgdXBkYXRlcyBvbiB1c2VyIGNoYW5nZXNcbiAgICAgICAgY29uc3QgbGF5b3V0UHJlZnMgPSBsc0tleSA/IHRoaXMuc3RvcmFnZVNlcnZpY2UuZ2V0SXRlbTxUYWJsZUxheW91dFByZWZlcmVuY2VzPih0aGlzLmNtcFR5cGVOYW1lLCBsc0tleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBsYXlvdXRQcmVmcyA/PyB7Y29sdW1uV2lkdGhzOiB7fX07XG4gICAgfSk7XG4gICAgcHVibGljIGNvbHVtbnMgPSBjb21wdXRlZDxDb2x1bW5XaXRoUHJlZmVyZW5jZXNbXT4oKCkgPT4gdGhpcy5jb21wdXRlQ29sdW1uc1dpdGhMYXlvdXQoKSk7XG4gICAgcHVibGljIHZpc2libGVDb2x1bW5zID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5jb2x1bW5zKCkuZmlsdGVyKGNvbCA9PiBjb2wuaXNWaXNpYmxlKSk7XG5cbiAgICAvLyBmaWx0ZXIsIHNvcnRcbiAgICBwdWJsaWMgZmlsdGVyRGVzY3JpcHRvcnMgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmRlc2NyaXB0b3IoKS5maWx0ZXJzKTtcbiAgICBwdWJsaWMgZ2VuZXJpY0ZpbHRlckRlc2NyaXB0b3IgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmRlc2NyaXB0b3IoKS5nZW5lcmljRmlsdGVyKTtcbiAgICBwcml2YXRlIGZpbHRlckRlc2NyaXB0b3JzRnJvbUdlbmVyaWMgPSBzaWduYWw8RmlsdGVyRGVzY3JpcHRvcjxhbnksIGFueT5bXT4oW10pO1xuICAgIHB1YmxpYyBoYXNDb2x1bW5GaWx0ZXJzID0gY29tcHV0ZWQoXG4gICAgICAgICgpID0+XG4gICAgICAgICAgICAodGhpcy5kZWZhdWx0RmlsdGVyRGlzcGxheVR5cGUgPT09IEZpbHRlckRpc3BsYXlUeXBlRW51bS5PdmVybGF5V2l0aFRhZyAmJiB0aGlzLmZpbHRlckRlc2NyaXB0b3JzKCkuc29tZShkID0+IGQuZGlzcGxheVR5cGUgPT09IEZpbHRlckRpc3BsYXlUeXBlRW51bS5Db2x1bW4pKSB8fFxuICAgICAgICAgICAgKHRoaXMuZGVmYXVsdEZpbHRlckRpc3BsYXlUeXBlID09PSBGaWx0ZXJEaXNwbGF5VHlwZUVudW0uQ29sdW1uICYmIHRoaXMuZmlsdGVyRGVzY3JpcHRvcnMoKS5zb21lKGQgPT4gZC5kaXNwbGF5VHlwZSA9PSBudWxsKSlcbiAgICApO1xuICAgIHB1YmxpYyBvdmVybGF5V2l0aFRhZ0ZpbHRlcnMgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLmZpbHRlckRlc2NyaXB0b3JzKCkuZmlsdGVyKFxuICAgICAgICAgICAgZCA9PiAoZC5kaXNwbGF5VHlwZSA9PSBudWxsICYmIHRoaXMuZGVmYXVsdEZpbHRlckRpc3BsYXlUeXBlID09PSBGaWx0ZXJEaXNwbGF5VHlwZUVudW0uT3ZlcmxheVdpdGhUYWcpIHx8IGQuZGlzcGxheVR5cGUgPT09IEZpbHRlckRpc3BsYXlUeXBlRW51bS5PdmVybGF5V2l0aFRhZ1xuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiBmaWx0ZXJzLmNvbmNhdCh0aGlzLmZpbHRlckRlc2NyaXB0b3JzRnJvbUdlbmVyaWMoKSk7XG4gICAgfSk7XG5cbiAgICBwcml2YXRlIGRlZmF1bHRQYXJhbXMgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmNvbXB1dGVEZWZhdWx0RGF0YUxpc3RQYXJhbXMoKSk7XG5cbiAgICBwdWJsaWMgYW55Q29sdW1uVmlzaWJsZSA9IGNvbXB1dGVkKCgpID0+IHRoaXMudmlzaWJsZUNvbHVtbnMoKS5sZW5ndGggPiAwKTtcbiAgICBwdWJsaWMgaGFzQ3VzdG9tTGFzdENvbHVtbiA9IGNvbXB1dGVkKCgpID0+IHRoaXMuY29sdW1uQ3VzdG9tTGFzdENvbXBvbmVudCgpIHx8IHRoaXMuY29sdW1uQ3VzdG9tTGFzdFRlbXBsYXRlKCkpO1xuICAgIHB1YmxpYyBoYXNMYXN0Q29sdW1uID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5oYXNDdXN0b21MYXN0Q29sdW1uKCkgfHwgdGhpcy5hcmVDb2x1bW5zVG9nZ2xlYWJsZSgpIHx8IHRoaXMuYXJlQ29sdW1uc1Jlb3JkZXJhYmxlKCkpO1xuXG4gICAgLy8gbGF5b3V0IHByZWZzXG4gICAgcHVibGljIGFyZUNvbHVtbnNSZW9yZGVyYWJsZSA9IGNvbXB1dGVkKCgpID0+IHRoaXMuY29sdW1ucygpLnNvbWUoY29sID0+IGNvbC5kZXNjcmlwdG9yLmlzUmVvcmRlcmFibGUpKTtcbiAgICBwdWJsaWMgYXJlQ29sdW1uc1RvZ2dsZWFibGUgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmNvbHVtbnMoKS5zb21lKGNvbCA9PiBjb2wuZGVzY3JpcHRvci5pc1RvZ2dsZWFibGUpKTtcblxuICAgIHB1YmxpYyBnbG9iYWxTZWFyY2hQYXJhbUZyb21VcmwgPSBzaWduYWw8e3ZhbHVlOiBzdHJpbmc7IGNhc2VTZW5zaXRpdmU6IGJvb2xlYW59IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuXG4gICAgLy8gb3RoZXJcbiAgICBwcml2YXRlIGxhc3RRdWVyeVBhcmFtcz86IFBhcmFtcyA9IHRoaXMucm91dGUuc25hcHNob3QucXVlcnlQYXJhbXM7XG4gICAgcHJpdmF0ZSBuYXZpZ2F0aW9uT3V0T2ZUYWJsZUluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICBwcml2YXRlIG5hdmlnYXRpb25JblRhYmxlSW5Qcm9ncmVzcyA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIGVmZmVjdChcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gdGhpcy5kZXNjcmlwdG9yKCk7XG4gICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGVzY3JpcHRvci5yb3dzUGVyUGFnZU9wdGlvbnMpICYmIGRlc2NyaXB0b3Iucm93c1BlclBhZ2VPcHRpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhTGlzdFNlcnZpY2Uucm93c1BlclBhZ2VPcHRpb25zLnNldChkZXNjcmlwdG9yLnJvd3NQZXJQYWdlT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChkZXNjcmlwdG9yLmRlZmF1bHROdW1Sb3dzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YUxpc3RTZXJ2aWNlLnJvd3Muc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhTGlzdFNlcnZpY2Uucm93c1BlclBhZ2VPcHRpb25zKCkuaW5jbHVkZXMoZGVzY3JpcHRvci5kZWZhdWx0TnVtUm93cykgPyBkZXNjcmlwdG9yLmRlZmF1bHROdW1Sb3dzIDogdGhpcy5kYXRhTGlzdFNlcnZpY2Uucm93c1BlclBhZ2VPcHRpb25zKClbMF1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge2FsbG93U2lnbmFsV3JpdGVzOiB0cnVlfVxuICAgICAgICApO1xuXG4gICAgICAgIGVmZmVjdChcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBsb2FkaW5nID0gdGhpcy5sb2FkaW5nSW5wdXQoKTtcbiAgICAgICAgICAgICAgICBpZiAobG9hZGluZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YUxpc3RTZXJ2aWNlLmxvYWRpbmcuc2V0KGxvYWRpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7YWxsb3dTaWduYWxXcml0ZXM6IHRydWV9XG4gICAgICAgICk7XG5cbiAgICAgICAgZWZmZWN0KFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMucmVzdWx0KCk7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YUxpc3RTZXJ2aWNlLnNldERhdGEocmVzdWx0LmRhdGEsIHJlc3VsdC50b3RhbENvdW50KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9hZGluZyA9IHRoaXMubG9hZGluZ0lucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb2FkaW5nID09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb25seSBzZXQgaWYgaW5wdXQgaXMgbm90IGRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YUxpc3RTZXJ2aWNlLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7YWxsb3dTaWduYWxXcml0ZXM6IHRydWV9XG4gICAgICAgICk7XG5cbiAgICAgICAgZWZmZWN0KFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMucmVzdWx0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zKCk7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdCA9PSB1bmRlZmluZWQgJiYgaXRlbXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFMaXN0U2VydmljZS5zZXREYXRhKGl0ZW1zKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9hZGluZyA9IHRoaXMubG9hZGluZ0lucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb2FkaW5nID09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb25seSBzZXQgaWYgaW5wdXQgaXMgbm90IGRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YUxpc3RTZXJ2aWNlLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7YWxsb3dTaWduYWxXcml0ZXM6IHRydWV9XG4gICAgICAgICk7XG5cbiAgICAgICAgZWZmZWN0KFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSB0aGlzLmRlc2NyaXB0b3IoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFMaXN0U2VydmljZS5nbG9iYWxGaWx0ZXJGaWVsZHMuc2V0KFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmdsb2JhbEZpbHRlckZpZWxkc0lucHV0KCkgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmRlc2NyaXB0b3IoKS5zZWFyY2ggJiYgZGVzY3JpcHRvci5zZWFyY2hGaWVsZHMgPyBkZXNjcmlwdG9yLnNlYXJjaEZpZWxkcyA6IHRoaXMuY29sdW1ucygpLm1hcChjID0+IGMuZGVzY3JpcHRvci5wcm9wZXJ0eSkpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7YWxsb3dTaWduYWxXcml0ZXM6IHRydWV9XG4gICAgICAgICk7XG5cbiAgICAgICAgYWZ0ZXJOZXh0UmVuZGVyKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaXNDZWxsQ2xpY2tPYnNlcnZlZC5zZXQodGhpcy5jZWxsQ2xpY2tTdWJqZWN0Lm9ic2VydmVkKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdG9PYnNlcnZhYmxlKHRoaXMuZGF0YVByb3ZpZGVyKVxuICAgICAgICAgICAgLnBpcGUoc3dpdGNoTWFwKGRwID0+IGRwPy50YWJsZVJlbG9hZCQgPz8gb2Yoe30pKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgICAgICAgIG5leHQ6IGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbG9hZChlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBjb21iaW5lTGF0ZXN0KFt0b09ic2VydmFibGUodGhpcy5kZXNjcmlwdG9ySW5wdXQpLCB0b09ic2VydmFibGUodGhpcy5kYXRhUHJvdmlkZXIpLCB0b09ic2VydmFibGUodGhpcy51c2VRdWVyeVBhcmFtcyldKVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgLy8gZGF0YVByb3ZpZGVyIGlzIG5lZWRlZCB0byBlbnN1cmUgY29ycmVjdCBvcmRlciBvZiBleGVjdXRpb24gYW5kIHJlbG9hZFxuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKFtkZXNjcmlwdG9ySW5wdXQsIGRhdGFQcm92aWRlciwgdXNlUXVlcnlQYXJhbXNdKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZXNjcmlwdG9ySW5wdXQgIT09IHRoaXMuZGVzY3JpcHRvcigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc2NyaXB0b3Iuc2V0KGRlc2NyaXB0b3JJbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHVzZVF1ZXJ5UGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0cmlnZ2VyIHRhYmxlIGxvYWRzIGZyb20gcm91dGUgdXBkYXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm91dGUucXVlcnlQYXJhbXM7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZShxcCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHFwID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGxvYWQgZGF0YSBpbW1lZGlhdGVseSBieSBjcmVhdGluZyBkZWZhdWx0IHNvcnRzIGFuZCBmaWx0ZXJzIChwcmltZW5nIHdpbGwgdHJpZ2dlciBvbkxhenlMb2FkIGV2ZW50IG9uIHNvcnQmZmlsdGVyIG1ldGFkYXRhIGNoYW5nZSlcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVmYXVsdFNvcnQgPSB0aGlzLmNyZWF0ZVNvcnRNZXRhKHRoaXMuZGVmYXVsdFBhcmFtcygpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkZWZhdWx0U29ydCB8fCBkZWZhdWx0U29ydC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFMaXN0U2VydmljZS5zb3J0TWV0YS5zZXQoZGVmYXVsdFNvcnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVmYXVsdEZpbHRlciA9IHRoaXMuY3JlYXRlRmlsdGVyTWV0YSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGVmYXVsdEZpbHRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhTGlzdFNlcnZpY2UuZmlsdGVyTWV0YS5zZXQoZGVmYXVsdEZpbHRlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkVGFibGVXaXRoRGF0YVByb3ZpZGVyKHt9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRUYWJsZUZyb21Sb3V0ZVVwZGF0ZShxcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgdG9PYnNlcnZhYmxlKHRoaXMudXNlUXVlcnlQYXJhbXMpXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAodXNlUXAgPT4gKHVzZVFwID8gdGhpcy5yb3V0ZXIuZXZlbnRzIDogTkVWRVIpKSxcbiAgICAgICAgICAgICAgICBmaWx0ZXIoXG4gICAgICAgICAgICAgICAgICAgIGUgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgIChlIGluc3RhbmNlb2YgTmF2aWdhdGlvblN0YXJ0ICYmIGUudXJsLnNwbGl0KCc/JylbMF0uc3BsaXQoJyMnKVswXSAhPT0gdGhpcy5yb3V0ZXIudXJsLnNwbGl0KCc/JylbMF0uc3BsaXQoJyMnKVswXSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGUgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uRW5kIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBlIGluc3RhbmNlb2YgTmF2aWdhdGlvbkNhbmNlbCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZSBpbnN0YW5jZW9mIE5hdmlnYXRpb25FcnJvclxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5uYXZpZ2F0aW9uT3V0T2ZUYWJsZUluUHJvZ3Jlc3MgPSBlIGluc3RhbmNlb2YgTmF2aWdhdGlvblN0YXJ0O1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgdG9PYnNlcnZhYmxlKHRoaXMuZ2VuZXJpY0ZpbHRlckRlc2NyaXB0b3IpXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoZ2VuZXJpY0ZpbHRlckRlc2NyaXB0b3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZ2VuZXJpY0ZpbHRlckRlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFQcm92aWRlciA9IHRoaXMuZ2VuZXJpY0ZpbHRlckRlc2NyaXB0b3IoKT8ucHJvcGVydHlMb29rdXA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBnZW5lcmljRmlsdGVyU2VydmljZSA9IGRhdGFQcm92aWRlcj8uc2VydmljZVR5cGUgPyB0aGlzLmluamVjdG9yLmdldDxhbnk+KGRhdGFQcm92aWRlci5zZXJ2aWNlVHlwZSkgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmZXRjaCBmaWx0ZXJhYmxlIHByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjb21tb25zVG9PYnNlcnZhYmxlKGdlbmVyaWNGaWx0ZXJEZXNjcmlwdG9yLnByb3BlcnR5TG9va3VwLmxvb2t1cCh7fSwgZ2VuZXJpY0ZpbHRlclNlcnZpY2UpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2YoW10pO1xuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCgpXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgICAgICAgICBuZXh0OiBnZW5lcmljRmlsdGVycyA9PiB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHNldCBkZXNjcmlwdG9ycyBmcm9tIGdlbmVyaWMgZmlsdGVyIGRhdGFcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJEZXNjcmlwdG9yc0Zyb21HZW5lcmljLnNldChjcmVhdGVGaWx0ZXJEZXNjcmlwdG9yc0Zyb21HZW5lcmljKGdlbmVyaWNGaWx0ZXJzLCB0aGlzLmdlbmVyaWNGaWx0ZXJEZXNjcmlwdG9yKCk/LnZhbHVlTG9va3VwKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLmRhdGFQcm92aWRlclN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVsb2FkKCk6IHZvaWQ7XG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgVXNlIHdpdGggYFRhYmxlUmVsb2FkRXZlbnRgIG9iamVjdCBwYXJhbWV0ZXIuXG4gICAgICovXG4gICAgcHVibGljIHJlbG9hZChlbWl0RXZlbnQ6IGJvb2xlYW4pOiB2b2lkO1xuICAgIHB1YmxpYyByZWxvYWQoZW1pdEV2ZW50PzogVGFibGVSZWxvYWRFdmVudDxTb3J0cywgRmlsdGVycz4pOiB2b2lkO1xuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIFVzZSB3aXRoIGBUYWJsZVJlbG9hZEV2ZW50YCBvYmplY3QgcGFyYW1ldGVyLlxuICAgICAqL1xuICAgIHB1YmxpYyByZWxvYWQoZW1pdEV2ZW50OiBib29sZWFuLCByZXNldFBhcmFtczogYm9vbGVhbik6IHZvaWQ7XG4gICAgcHVibGljIHJlbG9hZChlbWl0RXZlbnRPckV2ZW50OiBib29sZWFuIHwgVGFibGVSZWxvYWRFdmVudDxTb3J0cywgRmlsdGVycz4gPSBmYWxzZSwgcmVzZXRQYXJhbXNQYXJhbSA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IGVtaXRFdmVudCA9IHR5cGVvZiBlbWl0RXZlbnRPckV2ZW50ID09PSAnYm9vbGVhbicgPyBlbWl0RXZlbnRPckV2ZW50IDogZW1pdEV2ZW50T3JFdmVudD8uZW1pdEV2ZW50ID8/IGZhbHNlO1xuICAgICAgICBjb25zdCByZXNldFBhcmFtcyA9IHR5cGVvZiBlbWl0RXZlbnRPckV2ZW50ID09PSAnb2JqZWN0JyA/IGVtaXRFdmVudE9yRXZlbnQ/LnJlc2V0UGFyYW1zIDogcmVzZXRQYXJhbXNQYXJhbTtcbiAgICAgICAgY29uc3QgcGFyYW1zID1cbiAgICAgICAgICAgIHR5cGVvZiBlbWl0RXZlbnRPckV2ZW50ID09PSAnb2JqZWN0JyAmJiBlbWl0RXZlbnRPckV2ZW50Py5wYXJhbXNcbiAgICAgICAgICAgICAgICA/IChlbWl0RXZlbnRPckV2ZW50Py5wYXJhbXMgYXMgRGF0YUxpc3RQYXJhbXMpXG4gICAgICAgICAgICAgICAgOiByZXNldFBhcmFtc1xuICAgICAgICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgIDogdGhpcy5sYXRlc3RQYXJhbXNXaXRoRGVmYXVsdHM7XG4gICAgICAgIGNvbnN0IHJlbG9hZFBhcmFtcyA9IG1lcmdlRGF0YUxpc3RQYXJhbXNXaXRoRGVmYXVsdHMocGFyYW1zID8/IHt9LCB0aGlzLmRlZmF1bHRQYXJhbXMoKSk7XG4gICAgICAgIHRoaXMubG9hZFRhYmxlV2l0aERhdGFQcm92aWRlcihyZWxvYWRQYXJhbXMsIGVtaXRFdmVudCk7XG4gICAgfVxuXG4gICAgcHVibGljIG9uVGFibGVMYXp5TG9hZChldmVudDogVGFibGVMYXp5TG9hZEV2ZW50KSB7XG4gICAgICAgIHRoaXMuZGF0YVByb3ZpZGVyTGF0ZXN0TGF6eUxvYWRFdmVudCA9IGV2ZW50O1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IGZyb21UYWJsZUxvYWRUb0RhdGFMaXN0UGFyYW1zKGV2ZW50KTtcblxuICAgICAgICBpZiAodGhpcy51c2VRdWVyeVBhcmFtcygpKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMubmF2aWdhdGlvbk91dE9mVGFibGVJblByb2dyZXNzICYmICF0aGlzLm5hdmlnYXRpb25JblRhYmxlSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgICAgIHRoaXMubmF2aWdhdGlvbkluVGFibGVJblByb2dyZXNzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdQYXJhbXMgPSBkYXRhTGlzdFBhcmFtc1RvVXJsUXVlcnkocGFyYW1zLCB0aGlzLmRlZmF1bHRQYXJhbXMoKSwge3ByZXBlbmRGaWx0ZXJOYW1lOiB0aGlzLmZpbHRlcktleVByZXBlbmR9KTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdQYXJhbXNXaXRoUGFyYW1zVG9SZW1vdmUgPSB7Li4ubmV3UGFyYW1zfTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5sYXN0UXVlcnlQYXJhbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXModGhpcy5sYXN0UXVlcnlQYXJhbXMpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGsgPT4gKGsuc3RhcnRzV2l0aCh0aGlzLmZpbHRlcktleVByZXBlbmQpIHx8IFsnb2Zmc2V0JywgJ2xpbWl0JywgJ3NvcnQnLCAncSddLmluZGV4T2YoaykgPj0gMCkgJiYgbmV3UGFyYW1zW2tdID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZm9yRWFjaChrID0+IChuZXdQYXJhbXNXaXRoUGFyYW1zVG9SZW1vdmVba10gPSBudWxsKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHRoaXMgY2hlY2sgaXMgbmVjZXNzYXJ5OiBmcm9tIHNvbWUgcmVhc29uLCBwcmltZU5HIGNvbW1pdHMgb25lIGxhc3QgbGF6eSBsb2FkIGV2ZW50IHdoZW5ldmVyIGFueSBhbmd1bGFyIHJvdXRlciBuYXZpZ2F0aW9uIG9jY3Vyc1xuXG4gICAgICAgICAgICAgICAgdGhpcy5yb3V0ZXJcbiAgICAgICAgICAgICAgICAgICAgLm5hdmlnYXRlKFtdLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLnJvdXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZVVybDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zOiBuZXdQYXJhbXNXaXRoUGFyYW1zVG9SZW1vdmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBxdWVyeVBhcmFtc0hhbmRsaW5nOiAnbWVyZ2UnXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdmlnYXRpb25JblRhYmxlSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGFzdFF1ZXJ5UGFyYW1zID0gbmV3UGFyYW1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmFtc1dpdGhEZWZhdWx0cyA9IG1lcmdlRGF0YUxpc3RQYXJhbXNXaXRoRGVmYXVsdHMocGFyYW1zLCB0aGlzLmRlZmF1bHRQYXJhbXMoKSk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb21wYXJlV2l0aEN1cnJlbnRQYXJhbXMocGFyYW1zV2l0aERlZmF1bHRzKSkge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlUHJpbWVTb3J0QW5kRmlsdGVyKHBhcmFtc1dpdGhEZWZhdWx0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmxvYWRUYWJsZVdpdGhEYXRhUHJvdmlkZXIocGFyYW1zV2l0aERlZmF1bHRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBvblRhYmxlRmlsdGVyKGV2ZW50OiBUYWJsZUZpbHRlckV2ZW50KSB7XG4gICAgICAgIGlmICh0aGlzLnVzZVF1ZXJ5UGFyYW1zKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXJhbXMgPSBmcm9tVGFibGVMb2FkVG9EYXRhTGlzdFBhcmFtcyh7ZmlsdGVyczogZXZlbnQuZmlsdGVyc30pO1xuICAgICAgICBjb25zdCBwYXJhbXNXaXRoRGVmYXVsdHMgPSBtZXJnZURhdGFMaXN0UGFyYW1zV2l0aERlZmF1bHRzKHBhcmFtcywgdGhpcy5kZWZhdWx0UGFyYW1zKCkpO1xuXG4gICAgICAgIC8vIGlmIHRhYmxlIGRvZXNuJ3QgdXNlIGxhenkgbG9hZGluZywgZmlsdGVyIHBhcmFtcyBuZWVkIHRvIGJlIHNldCBoZXJlXG4gICAgICAgIC8vIGJlY2F1c2UgdGhlIG9uVGFibGVMYXp5TG9hZCBldmVudCBpcyBub3QgZW1pdHRlZFxuICAgICAgICBpZiAoIXRoaXMuaXNMYXp5KCkpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb21wYXJlV2l0aEN1cnJlbnRQYXJhbXMocGFyYW1zV2l0aERlZmF1bHRzKSkge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlUHJpbWVTb3J0QW5kRmlsdGVyKHBhcmFtc1dpdGhEZWZhdWx0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgb25DZWxsQ2xpY2soZXZlbnQ6IEV2ZW50LCBjb2w6IENvbHVtbkRlc2NyaXB0b3I8YW55LCBJdGVtPiwgaXRlbTogSXRlbSwgaWR4OiBudW1iZXIpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzQ2VsbENsaWNrRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGFibGVFdmVudDogVGFibGVDZWxsQ2xpY2tFdmVudDxJdGVtPiA9IHtcbiAgICAgICAgICAgIGNvbHVtbjogY29sLFxuICAgICAgICAgICAgcm93SXRlbTogaXRlbSxcbiAgICAgICAgICAgIHJvd0luZGV4OiBpZHgsXG4gICAgICAgICAgICBldmVudDogZXZlbnRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jZWxsQ2xpY2tTdWJqZWN0Lm5leHQodGFibGVFdmVudCk7XG4gICAgfVxuXG4gICAgcHVibGljIG9uU2VsZWN0aW9uQ2hhbmdlKGV2ZW50OiBBcnJheTxJdGVtPikge1xuICAgICAgICB0aGlzLnNlbGVjdGlvbkNoYW5nZS5lbWl0KGV2ZW50KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25Sb3dSZW9yZGVyKGV2ZW50OiBUYWJsZVJvd1Jlb3JkZXJFdmVudCkge1xuICAgICAgICB0aGlzLnJvd1Jlb3JkZXIuZW1pdChldmVudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGlzIGNhbGxlZCBvbiBjb2x1bW4gcmVzaXplXG4gICAgICogQHBhcmFtIGVsZW1lbnQgZXZlbnQncyBlbGVtZW50XG4gICAgICovXG4gICAgcHVibGljIG9uVGFibGVDb2x1bW5SZXNpemUoe2VsZW1lbnR9OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZmllbGRJZDogc3RyaW5nID0gZWxlbWVudC5pZDtcbiAgICAgICAgY29uc3Qgd2lkdGg6IG51bWJlciA9IGVsZW1lbnQub2Zmc2V0V2lkdGg7XG5cbiAgICAgICAgY29uc3QgbGF5b3V0UHJlZnMgPSB0aGlzLmxheW91dFByZWZlcmVuY2VzKCk7XG4gICAgICAgIGNvbnN0IGNvbCA9IHRoaXMuY29sdW1ucygpLmZpbmQoZWwgPT4gZWwuZGVzY3JpcHRvci5wcm9wZXJ0eSA9PT0gZmllbGRJZCk7XG4gICAgICAgIGlmIChjb2wpIGNvbC53aWR0aCA9IHdpZHRoO1xuICAgICAgICBpZiAoIWxheW91dFByZWZzLmNvbHVtbldpZHRocykgbGF5b3V0UHJlZnMuY29sdW1uV2lkdGhzID0ge307XG5cbiAgICAgICAgbGF5b3V0UHJlZnMuY29sdW1uV2lkdGhzW2ZpZWxkSWRdID0gd2lkdGg7XG4gICAgICAgIHRoaXMuc2F2ZUxheW91dFByZWZlcmVuY2VzKGxheW91dFByZWZzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRUYWJsZVdpdGhEYXRhUHJvdmlkZXIocGFyYW1zV2l0aERlZmF1bHRzOiBEYXRhTGlzdFBhcmFtcywgZW1pdEV2ZW50ID0gdHJ1ZSkge1xuICAgICAgICBjb25zdCBkYXRhUHJvdmlkZXIgPSB0aGlzLmRhdGFQcm92aWRlcigpO1xuICAgICAgICBpZiAoIWRhdGFQcm92aWRlciB8fCBwYXJhbXNXaXRoRGVmYXVsdHMubGltaXQgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZGF0YVByb3ZpZGVyU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgICAgICB0aGlzLmRhdGFMaXN0U2VydmljZS5sb2FkaW5nLnNldCh0cnVlKTtcbiAgICAgICAgdGhpcy5sYXRlc3RQYXJhbXNXaXRoRGVmYXVsdHMgPSBwYXJhbXNXaXRoRGVmYXVsdHM7XG5cbiAgICAgICAgdGhpcy5kYXRhUHJvdmlkZXJTdWJzY3JpcHRpb24gPSBjb21tb25zVG9PYnNlcnZhYmxlKFxuICAgICAgICAgICAgZGF0YVByb3ZpZGVyLmdldEFsbChcbiAgICAgICAgICAgICAgICBwYXJhbXNXaXRoRGVmYXVsdHMgYXMgRGF0YUxpc3RQYXJhbXM8U29ydHMsIEZpbHRlcnM+LFxuICAgICAgICAgICAgICAgIHRoaXMuZGF0YVByb3ZpZGVyU2VydmljZSgpLFxuICAgICAgICAgICAgICAgIHRoaXMuZGVzY3JpcHRvcigpLmlzTG9jYWxpemVkID8gdGhpcy5jb21tb25zLmFwcERhdGFMb2NhbGUoKSA/PyB1bmRlZmluZWQgOiB1bmRlZmluZWRcbiAgICAgICAgICAgIClcbiAgICAgICAgKS5zdWJzY3JpYmUoe1xuICAgICAgICAgICAgbmV4dDogcmVzID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkZXNjcmlwdG9ySW5wdXQgPSB0aGlzLmRlc2NyaXB0b3JJbnB1dCgpO1xuICAgICAgICAgICAgICAgIGlmIChkZXNjcmlwdG9ySW5wdXQgaW5zdGFuY2VvZiBUYWJsZUR5bmFtaWNEZXNjcmlwdG9ySW5zdCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc2NyaXB0b3Iuc2V0KGRlc2NyaXB0b3JJbnB1dC50b1RhYmxlRGVzY3JpcHRvckZyb21EYXRhKHJlcykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFMaXN0U2VydmljZS5zZXREYXRhKHJlcz8uZGF0YSA/PyBbXSwgcmVzPy50b3RhbENvdW50KTtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFMaXN0U2VydmljZS5sb2FkaW5nLnNldChmYWxzZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXJyb3I6IGVyciA9PiB7XG4gICAgICAgICAgICAgICAgdGFibGVOb3RpZmljYXRpb25FcnJvcih0aGlzLnRyYW5zbGF0ZSwgdGhpcy5kZXNjcmlwdG9yKCksIGVyciwgdGhpcy5tZXNzYWdlU2VydmljZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhTGlzdFNlcnZpY2Uuc2V0RGF0YShbXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhTGlzdFNlcnZpY2UubG9hZGluZy5zZXQoZmFsc2UpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBmcm9tU3Vic2NyaWJlRXJyb3IoZXJyLCAnVGFibGVDb21wb25lbnRFcnJvcicsIHtcbiAgICAgICAgICAgICAgICAgICAgcXVlcnlQYXJhbTogcGFyYW1zV2l0aERlZmF1bHRzXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nKGVycm9yLCBnZXRFcnJvckxvZ0xldmVsKGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChlbWl0RXZlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRhYmxlRXZlbnQ6IFRhYmxlTG9hZEV2ZW50ID0ge1xuICAgICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IHRoaXMuZGF0YVByb3ZpZGVyTGF0ZXN0TGF6eUxvYWRFdmVudCxcbiAgICAgICAgICAgICAgICBwYXJhbXM6IHBhcmFtc1dpdGhEZWZhdWx0c1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMudGFibGVMb2FkLmVtaXQodGFibGVFdmVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRUYWJsZUZyb21Sb3V0ZVVwZGF0ZSh1cmxQYXJhbXM6IFBhcmFtcykge1xuICAgICAgICBjb25zdCBwYXJhbXNXaXRoRGVmYXVsdHMgPSBtZXJnZURhdGFMaXN0UGFyYW1zV2l0aERlZmF1bHRzKFxuICAgICAgICAgICAgZnJvbVVybFF1ZXJ5VG9EYXRhTGlzdFBhcmFtcyh1cmxQYXJhbXMsIHtcbiAgICAgICAgICAgICAgICBwcmVwZW5kRmlsdGVyTmFtZTogdGhpcy5maWx0ZXJLZXlQcmVwZW5kLFxuICAgICAgICAgICAgICAgIHNlYXJjaEFzR2xvYmFsOiB0cnVlXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIHRoaXMuZGVmYXVsdFBhcmFtcygpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMudXBkYXRlUHJpbWVTb3J0QW5kRmlsdGVyKHBhcmFtc1dpdGhEZWZhdWx0cyk7XG4gICAgICAgIGlmICghdGhpcy51c2VRdWVyeVBhcmFtc0luaXRpYWxpemVkKCkgJiYgcGFyYW1zV2l0aERlZmF1bHRzPy5zZWFyY2gpIHtcbiAgICAgICAgICAgIHRoaXMuZ2xvYmFsU2VhcmNoUGFyYW1Gcm9tVXJsLnNldCh7dmFsdWU6IHBhcmFtc1dpdGhEZWZhdWx0cz8uc2VhcmNoLCBjYXNlU2Vuc2l0aXZlOiBwYXJhbXNXaXRoRGVmYXVsdHMuZmlsdGVycz8uWydnbG9iYWwnXT8uY2FzZVNlbnNpdGl2ZSA/PyBmYWxzZX0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXNlUXVlcnlQYXJhbXNJbml0aWFsaXplZC5zZXQodHJ1ZSk7XG4gICAgICAgIHRoaXMubG9hZFRhYmxlV2l0aERhdGFQcm92aWRlcihwYXJhbXNXaXRoRGVmYXVsdHMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgdXBkYXRlUHJpbWVTb3J0QW5kRmlsdGVyKHBhcmFtc1dpdGhEZWZhdWx0czogRGF0YUxpc3RQYXJhbXMpIHtcbiAgICAgICAgdGhpcy5kYXRhTGlzdFNlcnZpY2Uuc29ydE1ldGEuc2V0KHRoaXMuY3JlYXRlU29ydE1ldGEocGFyYW1zV2l0aERlZmF1bHRzKSk7XG4gICAgICAgIHRoaXMuZGF0YUxpc3RTZXJ2aWNlLmZpbHRlck1ldGEuc2V0KHRoaXMuY3JlYXRlRmlsdGVyTWV0YShwYXJhbXNXaXRoRGVmYXVsdHMpKTtcbiAgICAgICAgdGhpcy5kYXRhTGlzdFNlcnZpY2Uucm93cy5zZXQocGFyYW1zV2l0aERlZmF1bHRzPy5saW1pdCA/PyB0aGlzLmRhdGFMaXN0U2VydmljZS5yb3dzKCkpO1xuICAgICAgICB0aGlzLmRhdGFMaXN0U2VydmljZS5vZmZzZXQuc2V0KHBhcmFtc1dpdGhEZWZhdWx0cz8ub2Zmc2V0ID8/IDApO1xuICAgIH1cblxuICAgIHByaXZhdGUgY3JlYXRlRmlsdGVyTWV0YShwYXJhbXNXaXRoRGVmYXVsdHM/OiBEYXRhTGlzdFBhcmFtcykge1xuICAgICAgICBjb25zdCBwcmltZUZpbHRlck1ldGE6IHtbczogc3RyaW5nXTogQ29tbW9uc0ZpbHRlck1ldGFkYXRhfSA9IHt9O1xuICAgICAgICAvLyBpZiBhbnkgZmlsdGVyIGlzIHByZXNlbnQsIG5vIGRlZmF1bHQgZmlsdGVycyBzaG91bGQgYmUgYXBwbGllZCFcbiAgICAgICAgaWYgKHBhcmFtc1dpdGhEZWZhdWx0cz8uZmlsdGVycykge1xuICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMocGFyYW1zV2l0aERlZmF1bHRzLmZpbHRlcnMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICAgICAgICAgIHByaW1lRmlsdGVyTWV0YVtrZXldID0ge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWU/LnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICBtYXRjaE1vZGU6IHZhbHVlPy5tYXRjaE1vZGUsXG4gICAgICAgICAgICAgICAgICAgIGNhc2VTZW5zaXRpdmU6IHZhbHVlPy5jYXNlU2Vuc2l0aXZlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwcmltZUZpbHRlck1ldGE7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjcmVhdGVTb3J0TWV0YShwYXJhbXNXaXRoRGVmYXVsdHM/OiBEYXRhTGlzdFBhcmFtcyk6IFNvcnRNZXRhW10gfCBudWxsIHtcbiAgICAgICAgaWYgKHBhcmFtc1dpdGhEZWZhdWx0cz8uc29ydCAhPT0gdW5kZWZpbmVkICYmIEFycmF5LmlzQXJyYXkocGFyYW1zV2l0aERlZmF1bHRzPy5zb3J0KSAmJiBwYXJhbXNXaXRoRGVmYXVsdHM/LnNvcnQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHBhcmFtc1dpdGhEZWZhdWx0cz8uc29ydC5tYXAoXG4gICAgICAgICAgICAgICAgcyA9PlxuICAgICAgICAgICAgICAgICAgICA8U29ydE1ldGE+e1xuICAgICAgICAgICAgICAgICAgICAgICAgZmllbGQ6IHMucHJvcGVydHksXG4gICAgICAgICAgICAgICAgICAgICAgICBvcmRlcjogcy5hc2NlbmRpbmcgPyAxIDogLTFcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHB1YmxpYyBvbkNvbHVtblRvZ2dsZShldmVudDogTXVsdGlTZWxlY3RDaGFuZ2VFdmVudCkge1xuICAgICAgICBjb25zdCBsYXlvdXRQcmVmcyA9IHRoaXMubGF5b3V0UHJlZmVyZW5jZXMoKTtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRDb2x1bW5zID0gKGV2ZW50LnZhbHVlIGFzIENvbHVtbldpdGhQcmVmZXJlbmNlc1tdKS5tYXAodiA9PiB2LmRlc2NyaXB0b3IucHJvcGVydHkpO1xuICAgICAgICBsYXlvdXRQcmVmcy5jb2x1bW5IaWRkZW4gPSB0aGlzLmNvbHVtbnMoKVxuICAgICAgICAgICAgLmZpbHRlcihjID0+IHNlbGVjdGVkQ29sdW1ucy5pbmRleE9mKGMuZGVzY3JpcHRvci5wcm9wZXJ0eSkgPCAwKVxuICAgICAgICAgICAgLm1hcChjID0+IGMuZGVzY3JpcHRvci5wcm9wZXJ0eSk7XG4gICAgICAgIHRoaXMuc2F2ZUxheW91dFByZWZlcmVuY2VzKGxheW91dFByZWZzKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25Db2x1bW5Ub2dnbGVBbGwoKSB7XG4gICAgICAgIGNvbnN0IGxheW91dFByZWZzID0gdGhpcy5sYXlvdXRQcmVmZXJlbmNlcygpO1xuICAgICAgICBjb25zdCBjb2x1bW5zID0gWy4uLnRoaXMuY29sdW1ucygpXTtcbiAgICAgICAgY29uc3QgaXNWaXNpYmxlID0gIXRoaXMuY29sdW1ucygpLnNvbWUoYyA9PiBjLmlzVmlzaWJsZSk7XG4gICAgICAgIGZvciAoY29uc3QgY29sIG9mIGNvbHVtbnMpIHtcbiAgICAgICAgICAgIGlmIChpc1Zpc2libGUgIT09IGNvbC5pc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICBjb2wuaXNWaXNpYmxlID0gaXNWaXNpYmxlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGxheW91dFByZWZzLmNvbHVtbkhpZGRlbiA9IGNvbHVtbnMuZmlsdGVyKGMgPT4gIWMuaXNWaXNpYmxlKS5tYXAoYyA9PiBjLmRlc2NyaXB0b3IucHJvcGVydHkpO1xuICAgICAgICB0aGlzLnNhdmVMYXlvdXRQcmVmZXJlbmNlcyhsYXlvdXRQcmVmcyk7XG4gICAgfVxuXG4gICAgcHVibGljIG9uQ29sdW1uUmVvcmRlcihldmVudDogVGFibGVDb2x1bW5SZW9yZGVyRXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50LmRyb3BJbmRleCAhPT0gdW5kZWZpbmVkICYmIGV2ZW50LmRyb3BJbmRleCA+PSAwICYmIGV2ZW50LmRyYWdJbmRleCAhPT0gdW5kZWZpbmVkICYmIGV2ZW50LmRyYWdJbmRleCA+PSAwICYmIGV2ZW50LmRyb3BJbmRleCAhPT0gZXZlbnQuZHJhZ0luZGV4KSB7XG4gICAgICAgICAgICBjb25zdCBldmVudERyb3BJbmRleCA9IGV2ZW50LmRyb3BJbmRleDtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50RHJhZ0luZGV4ID0gZXZlbnQuZHJhZ0luZGV4O1xuICAgICAgICAgICAgY29uc3QgcHJldlZpc2libGVDb2x1bW5zID0gdGhpcy5jb2x1bW5zKCkuZmlsdGVyKGMgPT4gYy5pc1Zpc2libGUpO1xuICAgICAgICAgICAgY29uc3QgY29sQXREcm9wID0gcHJldlZpc2libGVDb2x1bW5zW2V2ZW50RHJvcEluZGV4XTtcbiAgICAgICAgICAgIGNvbnN0IGNvbEF0RHJhZyA9IHByZXZWaXNpYmxlQ29sdW1uc1tldmVudERyYWdJbmRleF07XG4gICAgICAgICAgICBjb25zdCBjb2xBdERyb3BJbmRleCA9IHRoaXMuY29sdW1ucygpLmZpbmRJbmRleChlbCA9PiBlbC5pZCA9PT0gY29sQXREcm9wLmlkKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbEF0RHJhZ0luZGV4ID0gdGhpcy5jb2x1bW5zKCkuZmluZEluZGV4KGVsID0+IGVsLmlkID09PSBjb2xBdERyYWcuaWQpO1xuXG4gICAgICAgICAgICBpZiAoY29sQXREcm9wSW5kZXggPiAtMSAmJiBjb2xBdERyYWdJbmRleCA+IC0xKSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvbHVtbnMgPSBbLi4udGhpcy5jb2x1bW5zKCldO1xuICAgICAgICAgICAgICAgIGNvbHVtbnMuc3BsaWNlKGNvbEF0RHJhZ0luZGV4LCAxKTtcbiAgICAgICAgICAgICAgICBjb25zdCBkcm9wSW5kZXggPSBjb2x1bW5zLmZpbmRJbmRleChlbCA9PiBlbC5pZCA9PT0gY29sQXREcm9wLmlkKSArIChldmVudERyb3BJbmRleCA+IGV2ZW50RHJhZ0luZGV4ID8gMSA6IDApO1xuICAgICAgICAgICAgICAgIGNvbHVtbnMgPSBbLi4uY29sdW1ucy5zbGljZSgwLCBkcm9wSW5kZXgpLCBjb2xBdERyYWcsIC4uLmNvbHVtbnMuc2xpY2UoZHJvcEluZGV4KV07XG4gICAgICAgICAgICAgICAgY29uc3QgbGF5b3V0UHJlZnMgPSB0aGlzLmxheW91dFByZWZlcmVuY2VzKCk7XG4gICAgICAgICAgICAgICAgbGF5b3V0UHJlZnMuY29sdW1uT3JkZXIgPSBjb2x1bW5zLm1hcChlbCA9PiBlbC5kZXNjcmlwdG9yLnByb3BlcnR5KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNhdmVMYXlvdXRQcmVmZXJlbmNlcyhsYXlvdXRQcmVmcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNhdmVMYXlvdXRQcmVmZXJlbmNlcyhsYXlvdXRQcmVmczogVGFibGVMYXlvdXRQcmVmZXJlbmNlcykge1xuICAgICAgICBjb25zdCBrZXkgPSB0aGlzLmxvY2Fsc3RvcmFnZUtleSgpO1xuICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2VTZXJ2aWNlLnNldEl0ZW0odGhpcy5jbXBUeXBlTmFtZSwga2V5LCBsYXlvdXRQcmVmcyk7XG4gICAgICAgICAgICB0aGlzLmxheW91dFByZWZzU2F2ZUNudC51cGRhdGUodiA9PiB2ICsgMSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbXB1dGVEZWZhdWx0RGF0YUxpc3RQYXJhbXMoKSB7XG4gICAgICAgIGNvbnN0IHBhcmFtczogRGF0YUxpc3RQYXJhbXMgPSB7XG4gICAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgICBsaW1pdDogdGhpcy5kYXRhTGlzdFNlcnZpY2Uucm93c1BlclBhZ2VPcHRpb25zKClbMF0sXG4gICAgICAgICAgICBzb3J0OiB0aGlzLmRlc2NyaXB0b3IoKVxuICAgICAgICAgICAgICAgIC5zb3J0cy5maWx0ZXIocyA9PiBzLmRlZmF1bHRJc0VuYWJsZWQpXG4gICAgICAgICAgICAgICAgLnNvcnQoKHMxLCBzMikgPT4gKHMxLmRlZmF1bHRPcmRlciA/PyAxMDAwKSAtIChzMi5kZWZhdWx0T3JkZXIgPz8gMTAwMCkpXG4gICAgICAgICAgICAgICAgLm1hcChzID0+ICh7XG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiBzLnByb3BlcnR5LFxuICAgICAgICAgICAgICAgICAgICBhc2NlbmRpbmc6IHMuZGVmYXVsdElzQXNjZW5kaW5nXG4gICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgZmlsdGVyczoge31cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmZpbHRlckRlc2NyaXB0b3JzKClcbiAgICAgICAgICAgIC5maWx0ZXIoZCA9PiBkLmhhc0RlZmF1bHRWYWx1ZSlcbiAgICAgICAgICAgIC5mb3JFYWNoKGYgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBtYXRjaE1vZGU6IHN0cmluZyB8IHVuZGVmaW5lZCA9IGYuZGVmYXVsdE1hdGNoTW9kZTtcbiAgICAgICAgICAgICAgICBpZiAoIW1hdGNoTW9kZSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGYuZmlsdGVyVHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBGaWx0ZXJUeXBlRW51bS5TdHJpbmc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hNb2RlID0gRmlsdGVyTWF0Y2hNb2RlLkNvbnRhaW5zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBGaWx0ZXJUeXBlRW51bS5Mb29rdXA6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEZpbHRlclR5cGVFbnVtLkxvb2t1cEVudW06IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb29rdXBGaWx0ZXIgPSBmIGFzIEZpbHRlckxvb2t1cERlc2NyaXB0b3I8YW55LCBJdGVtPjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobG9va3VwRmlsdGVyLm11bHRpc2VsZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoTW9kZSA9IEZpbHRlck1hdGNoTW9kZS5JbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghbWF0Y2hNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoTW9kZSA9IEZpbHRlck1hdGNoTW9kZS5FcXVhbHM7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGYubWF0Y2hNb2RlcyAmJiAhZi5tYXRjaE1vZGVzPy5pbmNsdWRlcyhtYXRjaE1vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoTW9kZSA9IGYubWF0Y2hNb2Rlc1swXTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgdmFsdWU6IGFueSB8IGFueVtdIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IFsuLi52YWx1ZV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBmLmRlZmF1bHRWYWx1ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBwcm9wZXJ0eSA9IGYucHJvcGVydHk7XG4gICAgICAgICAgICAgICAgcGFyYW1zLmZpbHRlcnMhW3Byb3BlcnR5XSA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICBtYXRjaE1vZGU6IG1hdGNoTW9kZVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH1cblxuICAgIHByaXZhdGUgY29tcHV0ZUNvbHVtbnNXaXRoTGF5b3V0KCkge1xuICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gdGhpcy5kZXNjcmlwdG9yKCk7XG4gICAgICAgIGNvbnN0IGxheW91dFByZWZzID0gdGhpcy5sYXlvdXRQcmVmZXJlbmNlcygpO1xuXG4gICAgICAgIC8vIGluaXRpYWxpemUgY29sdW1ucyB3aXRoIGFkZGl0aW9uYWwgcHJvcGVydGllc1xuICAgICAgICBjb25zdCB0aW1lc3RhbXAgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgY29uc3QgY29sdW1uczogQ29sdW1uV2l0aFByZWZlcmVuY2VzW10gPSBkZXNjcmlwdG9yLmNvbHVtbnMubWFwKGNvbCA9PiAoe1xuICAgICAgICAgICAgaWQ6IGAke2NvbC5wcm9wZXJ0eX0tJHt0aW1lc3RhbXB9YCxcbiAgICAgICAgICAgIGRlc2NyaXB0b3I6IGNvbCxcbiAgICAgICAgICAgIGZpbHRlcjogZGVzY3JpcHRvci5maWx0ZXJzLmZpbmQoXG4gICAgICAgICAgICAgICAgZiA9PlxuICAgICAgICAgICAgICAgICAgICBmLnNob3dPbkNvbHVtbiA9PT0gY29sLnByb3BlcnR5ICYmXG4gICAgICAgICAgICAgICAgICAgICgoZi5kaXNwbGF5VHlwZSA9PSBudWxsICYmIHRoaXMuZGVmYXVsdEZpbHRlckRpc3BsYXlUeXBlID09PSBGaWx0ZXJEaXNwbGF5VHlwZUVudW0uQ29sdW1uKSB8fCBmLmRpc3BsYXlUeXBlID09PSBGaWx0ZXJEaXNwbGF5VHlwZUVudW0uQ29sdW1uKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHNvcnQ6IGRlc2NyaXB0b3Iuc29ydHMuZmluZChmID0+IGYuc2hvd09uQ29sdW1uID09PSBjb2wucHJvcGVydHkpLFxuICAgICAgICAgICAgZGlzYWJsZWQ6ICFjb2wuaXNUb2dnbGVhYmxlLFxuICAgICAgICAgICAgaXNWaXNpYmxlOiBsYXlvdXRQcmVmcy5jb2x1bW5IaWRkZW4gPyAhbGF5b3V0UHJlZnMuY29sdW1uSGlkZGVuLmluY2x1ZGVzKGNvbC5wcm9wZXJ0eSkgOiBjb2wuaXNWaXNpYmxlLFxuICAgICAgICAgICAgd2lkdGg6IGxheW91dFByZWZzLmNvbHVtbldpZHRocz8uW2NvbC5wcm9wZXJ0eV1cbiAgICAgICAgfSkpO1xuXG4gICAgICAgIGlmIChsYXlvdXRQcmVmcy5jb2x1bW5PcmRlcikge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsYXlvdXRQcmVmcy5jb2x1bW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbE5hbWUgPSBsYXlvdXRQcmVmcy5jb2x1bW5PcmRlcltpXTtcbiAgICAgICAgICAgICAgICBjb25zdCBjb2xXaXRoUHJlZnMgPSBjb2x1bW5zLmZpbmQoZWwgPT4gZWwuZGVzY3JpcHRvci5wcm9wZXJ0eSA9PT0gY29sTmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbFdpdGhQcmVmcykge1xuICAgICAgICAgICAgICAgICAgICBjb2xXaXRoUHJlZnMub3JkZXJJZHggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb2x1bW5zLnNvcnQoKGEsIGIpID0+IChhLm9yZGVySWR4ICE9PSB1bmRlZmluZWQgJiYgYi5vcmRlcklkeCAhPT0gdW5kZWZpbmVkID8gYS5vcmRlcklkeCAtIGIub3JkZXJJZHggOiAwKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzZXQgY29sdW1uIG9yZGVyIGFuZCBjb2x1bW4gdmlzaWJpbGl0eSB0byBkZWZhdWx0IHNldHRpbmdzXG4gICAgICovXG4gICAgcHVibGljIHJlc2V0RGVmYXVsdExheW91dCgpIHtcbiAgICAgICAgY29uc3Qga2V5ID0gdGhpcy5sb2NhbHN0b3JhZ2VLZXkoKTtcbiAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgdGhpcy5zdG9yYWdlU2VydmljZS5yZW1vdmVJdGVtKHRoaXMuY21wVHlwZU5hbWUsIGtleSk7XG4gICAgICAgICAgICB0aGlzLmxheW91dFByZWZzU2F2ZUNudC51cGRhdGUodiA9PiB2ICsgMSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb21wYXJlIHRoZSBnaXZlbiBwYXJhbXMgd2l0aCB0aGUgc3RvcmVkIHBhcmFtcyBpbiB0aGUgRGF0YUxpc3RTZXJ2aWNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtEYXRhTGlzdFBhcmFtc30gcGFyYW1zIC0gVGhlIHBhcmFtcyB0byBjb21wYXJlIHdpdGggdGhlIHN0b3JlZCBwYXJhbXMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtib29sZWFufSAtIFRydWUgaWYgdGhlIGdpdmVuIHBhcmFtcyBtYXRjaCB0aGUgc3RvcmVkIHBhcmFtcywgb3RoZXJ3aXNlIGZhbHNlLlxuICAgICAqL1xuICAgIHByaXZhdGUgY29tcGFyZVdpdGhDdXJyZW50UGFyYW1zKHBhcmFtczogRGF0YUxpc3RQYXJhbXMpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHBhcmFtcy5vZmZzZXQgPT09IHRoaXMuZGF0YUxpc3RTZXJ2aWNlLm9mZnNldCgpICYmXG4gICAgICAgICAgICBwYXJhbXMubGltaXQgPT09IHRoaXMuZGF0YUxpc3RTZXJ2aWNlLnJvd3MoKSAmJlxuICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkodGhpcy5jcmVhdGVTb3J0TWV0YShwYXJhbXMpKSA9PT0gSlNPTi5zdHJpbmdpZnkodGhpcy5kYXRhTGlzdFNlcnZpY2Uuc29ydE1ldGEoKSkgJiZcbiAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHRoaXMuY3JlYXRlRmlsdGVyTWV0YShwYXJhbXMpKSA9PT0gSlNPTi5zdHJpbmdpZnkodGhpcy5kYXRhTGlzdFNlcnZpY2UuZmlsdGVyTWV0YSgpKVxuICAgICAgICApO1xuICAgIH1cbn1cbiIsIjxkaXY+XG4gICAgPCEtLSBNVVNUIE5PVCB1c2Ugb2JzZXJ2YWJsZSBmb3IgdmFsdWUgd2hlbiB1c2luZyB2aXJ0dWFsIHNjcm9sbCAtIGRvZXMgbm90IHdvcmsgZm9yIHNvbWUgcmVhc29uIC0tPlxuICAgIEBpZiAoIXVzZVF1ZXJ5UGFyYW1zKCkgfHwgdXNlUXVlcnlQYXJhbXNJbml0aWFsaXplZCgpKSB7XG4gICAgICAgIDxwLXRhYmxlXG4gICAgICAgICAgICBbdmFsdWVdPVwiZGF0YUxpc3RTZXJ2aWNlLmRhdGEoKVwiXG4gICAgICAgICAgICBbZGF0YUtleV09XCJkZXNjcmlwdG9yKCkudHJhY2tQcm9wZXJ0eVwiXG4gICAgICAgICAgICBbbGF6eV09XCJpc0xhenkoKVwiXG4gICAgICAgICAgICBbbG9hZGluZ109XCJkYXRhTGlzdFNlcnZpY2UubG9hZGluZygpXCJcbiAgICAgICAgICAgIFtwYWdpbmF0b3JdPVwiaXNQYWdpbmF0aW9uKClcIlxuICAgICAgICAgICAgW3Jvd3NdPVwiZGF0YUxpc3RTZXJ2aWNlLnJvd3MoKVwiXG4gICAgICAgICAgICBbZmlyc3RdPVwiZGF0YUxpc3RTZXJ2aWNlLm9mZnNldCgpXCJcbiAgICAgICAgICAgIFt0b3RhbFJlY29yZHNdPVwiZGF0YUxpc3RTZXJ2aWNlLmNvdW50KClcIlxuICAgICAgICAgICAgW3Jvd3NQZXJQYWdlT3B0aW9uc109XCJkYXRhTGlzdFNlcnZpY2Uucm93c1BlclBhZ2VPcHRpb25zKClcIlxuICAgICAgICAgICAgW3Nob3dDdXJyZW50UGFnZVJlcG9ydF09XCJ0cnVlXCJcbiAgICAgICAgICAgIFtjdXJyZW50UGFnZVJlcG9ydFRlbXBsYXRlXT1cIidtbmdUYWJsZS5wYWdpbmF0aW9uTXNnJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICBbbXVsdGlTb3J0TWV0YV09XCJkYXRhTGlzdFNlcnZpY2Uuc29ydE1ldGEoKVwiXG4gICAgICAgICAgICBbZmlsdGVyc109XCJkYXRhTGlzdFNlcnZpY2UuZmlsdGVyTWV0YSgpXCJcbiAgICAgICAgICAgIFtnbG9iYWxGaWx0ZXJGaWVsZHNdPVwiZGF0YUxpc3RTZXJ2aWNlLmdsb2JhbEZpbHRlckZpZWxkcygpXCJcbiAgICAgICAgICAgIHNvcnRNb2RlPVwibXVsdGlwbGVcIlxuICAgICAgICAgICAgW3NlbGVjdGlvbl09XCJbXVwiXG4gICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cIm9uU2VsZWN0aW9uQ2hhbmdlKCRldmVudClcIlxuICAgICAgICAgICAgW3NlbGVjdGlvbk1vZGVdPVwic2VsZWN0aW9uRW5hYmxlZCgpID8gc2VsZWN0aW9uTW9kZSgpIDogbnVsbFwiXG4gICAgICAgICAgICBbc2Nyb2xsYWJsZV09XCJ0cnVlXCJcbiAgICAgICAgICAgIHNjcm9sbEhlaWdodD1cImZsZXhcIlxuICAgICAgICAgICAgW3Jvd0hvdmVyXT1cImRlc2NyaXB0b3IoKS5oYXNIb3ZlclwiXG4gICAgICAgICAgICBbc3R5bGVDbGFzc109XCJjbGFzc05hbWUoKVwiXG4gICAgICAgICAgICBbcmVzaXphYmxlQ29sdW1uc109XCJkZXNjcmlwdG9yKCkuaGFzUmVzaXphYmxlQ29sdW1uc1wiXG4gICAgICAgICAgICBbY29sdW1uUmVzaXplTW9kZV09XCJkZXNjcmlwdG9yKCkuY29sdW1uUmVzaXplTW9kZSA/PyAnZXhwYW5kJ1wiXG4gICAgICAgICAgICBbcmVvcmRlcmFibGVDb2x1bW5zXT1cImFyZUNvbHVtbnNSZW9yZGVyYWJsZSgpXCJcbiAgICAgICAgICAgIHBhZ2luYXRvckRyb3Bkb3duQXBwZW5kVG89XCJib2R5XCJcbiAgICAgICAgICAgIFtjb2x1bW5zXT1cInZpc2libGVDb2x1bW5zKClcIlxuICAgICAgICAgICAgKG9uQ29sUmVzaXplKT1cIm9uVGFibGVDb2x1bW5SZXNpemUoJGV2ZW50KVwiXG4gICAgICAgICAgICAob25Db2xSZW9yZGVyKT1cIm9uQ29sdW1uUmVvcmRlcigkZXZlbnQpXCJcbiAgICAgICAgICAgIChvbkxhenlMb2FkKT1cIm9uVGFibGVMYXp5TG9hZCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChvbkZpbHRlcik9XCJvblRhYmxlRmlsdGVyKCRldmVudClcIlxuICAgICAgICAgICAgKG9uUm93UmVvcmRlcik9XCJvblJvd1Jlb3JkZXIoJGV2ZW50KVwiPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cImNhcHRpb25cIj5cbiAgICAgICAgICAgICAgICBAaWYgKGlzQ2FwdGlvblZpc2libGUoKSkge1xuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFibGUtaGVhZGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKG92ZXJsYXlXaXRoVGFnRmlsdGVycygpLmxlbmd0aCA+IDAgfHwgZGVzY3JpcHRvcigpLnNlYXJjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtbmctZmlsdGVyLW92ZXJsYXktd2l0aC10YWdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3RpdGxlXT1cImRlc2NyaXB0b3IoKS50aXRsZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtkZXNjcmlwdG9yc109XCJvdmVybGF5V2l0aFRhZ0ZpbHRlcnMoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtnZW5lcmljRmlsdGVyRGVzY3JpcHRvcl09XCJnZW5lcmljRmlsdGVyRGVzY3JpcHRvcigpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21vZGVsXT1cImRlc2NyaXB0b3IoKS5tb2RlbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtlbmFibGVTZWFyY2hdPVwiZGVzY3JpcHRvcigpLnNlYXJjaFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzZWFyY2hdPVwiZ2xvYmFsU2VhcmNoUGFyYW1Gcm9tVXJsKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2VhcmNoTGltaXRXb3JkTWF4XT1cImRlc2NyaXB0b3IoKS5zZWFyY2hMaW1pdE1heFdvcmRzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2VuYWJsZUNhc2VTZW5zaXRpdmVdPVwiaXNMYXp5KClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChoYXNUaXRsZURpc3BsYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIG1uZ1RlbXBsYXRlPVwidGl0bGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY2FwdGlvblRlbXBsYXRlT3JDb21wb25lbnRPclRpdGxlXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tbmctZmlsdGVyLW92ZXJsYXktd2l0aC10YWc+XG4gICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY2FwdGlvblRlbXBsYXRlT3JDb21wb25lbnRPclRpdGxlXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI2NhcHRpb25UZW1wbGF0ZU9yQ29tcG9uZW50T3JUaXRsZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGNhcHRpb25UZW1wbGF0ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjYXB0aW9uVGVtcGxhdGUoKVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gQGVsc2UgaWYgKGNhcHRpb25Db21wb25lbnQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyIFttbmdDb21wb25lbnRdPVwiY2FwdGlvbkNvbXBvbmVudCgpXCIgKGluc3RhbmNlQ3JlYXRlZCk9XCJjYXB0aW9uQ29tcG9uZW50SW5zdGFuY2UuZW1pdCgkZXZlbnQpXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBAZWxzZSBpZiAoZGVzY3JpcHRvcigpLnRpdGxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxoNSBjbGFzcz1cInAtMCBtLTBcIj57eyBkZXNjcmlwdG9yKCkudGl0bGUhIHwgdHJhbnNsYXRlIH19PC9oNT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cImhlYWRlclwiPlxuICAgICAgICAgICAgICAgIEBpZiAoIWRlc2NyaXB0b3IoKS5oaWRlSGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIDx0ciBjbGFzcz1cIm1uZy10YWJsZS1oZWFkZXJcIiBbY2xhc3NdPVwiZGVzY3JpcHRvcigpLmhlYWRlckNsYXNzTmFtZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChzZWxlY3Rpb25FbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKHNlbGVjdGlvbk1vZGUoKSA9PT0gJ211bHRpcGxlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc3R5bGU9XCJtaW4td2lkdGg6IDM2cHhcIiBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwiZGVzY3JpcHRvcigpLnNlbGVjdGlvbkNvbHVtbkZyb3plbiA/PyB0cnVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC10YWJsZUhlYWRlckNoZWNrYm94PjwvcC10YWJsZUhlYWRlckNoZWNrYm94PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFdlIG5lZWQgdGhlIGxpbmUgYmVsb3csIGJlY2F1c2Ugb3RoZXJ3aXNlIHAtdGFibGVSYWRpb0J1dHRvbiBzaGlmdHMgdGhlIHJlc3Qgb2YgdGhlIGNvbHVtbnMgaW4gdGFibGUgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBzdHlsZT1cIm1pbi13aWR0aDogMzZweFwiIHBGcm96ZW5Db2x1bW4gW2Zyb3plbl09XCJkZXNjcmlwdG9yKCkuc2VsZWN0aW9uQ29sdW1uRnJvemVuID8/IHRydWVcIj48L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoZGVzY3JpcHRvcigpLnJvd0V4cGFuZGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc2NvcGU9XCJjb2xcIiBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwidHJ1ZVwiPjwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKHJvd1Jlb3JkZXJFbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc2NvcGU9XCJjb2xcIj48L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgQGZvciAoY29sIG9mIHZpc2libGVDb2x1bW5zKCk7IHRyYWNrIGNvbC5pZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjc29ydGFibGVDb2x1bW5USFRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGNvbC5kZXNjcmlwdG9yLnRpdGxlID8/IChjb2wuZGVzY3JpcHRvci5wcm9wZXJ0eSB8IG1uZ0kxOG5Qcm9wZXJ0eTogZGVzY3JpcHRvcigpLm1vZGVsKSB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtc29ydEljb24gW2ZpZWxkXT1cImNvbC5kZXNjcmlwdG9yLnByb3BlcnR5XCI+PC9wLXNvcnRJY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjbm9uU29ydGFibGVDb2x1bW5USFRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBjb2wuZGVzY3JpcHRvci50aXRsZSA/PyAoY29sLmRlc2NyaXB0b3IucHJvcGVydHkgfCBtbmdJMThuUHJvcGVydHk6IGRlc2NyaXB0b3IoKS5tb2RlbCkgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoY29sLmRlc2NyaXB0b3IuaXNSZW9yZGVyYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBSZXNpemFibGVDb2x1bW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBSZW9yZGVyYWJsZUNvbHVtblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cImNvbC5kZXNjcmlwdG9yLnByb3BlcnR5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtwU29ydGFibGVDb2x1bW5dPVwiY29sLnNvcnQ/LnByb3BlcnR5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtwU29ydGFibGVDb2x1bW5EaXNhYmxlZF09XCIhY29sLnNvcnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLndpZHRoXT1cImNvbC53aWR0aCA/IGNvbC53aWR0aCArICdweCcgOiBjb2wuZGVzY3JpcHRvci53aWR0aCArICclJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUubWluLXdpZHRoLnB4XT1cImNvbC53aWR0aCA/IG51bGwgOiBjb2wuZGVzY3JpcHRvci5taW5XaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUubWF4LXdpZHRoLnB4XT1cImNvbC53aWR0aCA/PyBjb2wuZGVzY3JpcHRvci5tYXhXaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3NdPVwiY29sLmRlc2NyaXB0b3IuaGVhZGVyQ2xhc3NOYW1lIHwgbW5nVGFibGVDb2x1bW5GaWx0ZXJDbGFzczogY29sLmZpbHRlciA6IGhhc0NvbHVtbkZpbHRlcnMoKSAmJiAhY29sLndpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY29sLnNvcnQgPyBzb3J0YWJsZUNvbHVtblRIVGVtcGxhdGUgOiBub25Tb3J0YWJsZUNvbHVtblRIVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwUmVzaXphYmxlQ29sdW1uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbaWRdPVwiY29sLmRlc2NyaXB0b3IucHJvcGVydHlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BTb3J0YWJsZUNvbHVtbl09XCJjb2wuc29ydD8ucHJvcGVydHlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BTb3J0YWJsZUNvbHVtbkRpc2FibGVkXT1cIiFjb2wuc29ydFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUud2lkdGhdPVwiY29sLndpZHRoID8gY29sLndpZHRoICsgJ3B4JyA6IGNvbC5kZXNjcmlwdG9yLndpZHRoICsgJyUnXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5taW4td2lkdGgucHhdPVwiY29sLndpZHRoID8gbnVsbCA6IGNvbC5kZXNjcmlwdG9yLm1pbldpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5tYXgtd2lkdGgucHhdPVwiY29sLndpZHRoID8/IGNvbC5kZXNjcmlwdG9yLm1heFdpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzc109XCJjb2wuZGVzY3JpcHRvci5oZWFkZXJDbGFzc05hbWUgfCBtbmdUYWJsZUNvbHVtbkZpbHRlckNsYXNzOiBjb2wuZmlsdGVyIDogaGFzQ29sdW1uRmlsdGVycygpICYmICFjb2wud2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjb2wuc29ydCA/IHNvcnRhYmxlQ29sdW1uVEhUZW1wbGF0ZSA6IG5vblNvcnRhYmxlQ29sdW1uVEhUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoaGFzTGFzdENvbHVtbigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5taW4td2lkdGgucHhdPVwiY29sdW1uTGFzdE1pbldpZHRoKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwRnJvemVuQ29sdW1uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmcm96ZW5dPVwiZGVzY3JpcHRvcigpLmFjdGlvbkNvbHVtbkZyb3plbiA/PyBhcmVDb2x1bW5zVG9nZ2xlYWJsZSgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpZ25Gcm96ZW49XCJyaWdodFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiY29sdW1uLWN1c3RvbS1sYXN0IHRleHQtcmlnaHRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChhcmVDb2x1bW5zVG9nZ2xlYWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC1tdWx0aVNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNjb2x1bW5Ub2dnbGVNdWx0aXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQ2xhc3M9XCJwLWJ1dHRvbi1wcmltYXJ5IG1uZy10YWJsZS1jb2x1bW5zLW11bHRpc2VsZWN0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBlbmRUbz1cImJvZHlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFLZXk9XCJpZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwibGVmdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3Bkb3duSWNvbj1cInBpIHBpLXNsaWRlcnMtaFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2ZpbHRlcl09XCJmYWxzZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW29wdGlvbnNdPVwiY29sdW1ucygpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ2aXNpYmxlQ29sdW1ucygpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcFRvb2x0aXBdPVwiJ21uZ1RhYmxlLmFkanVzdFRhYmxlJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc3BsYXlTZWxlY3RlZExhYmVsXT1cImZhbHNlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAob25DaGFuZ2UpPVwib25Db2x1bW5Ub2dnbGUoJGV2ZW50KVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJmaWx0ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInAtY2hlY2tib3ggcC1jb21wb25lbnQgbWwtMVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInAtaGlkZGVuLWFjY2Vzc2libGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZG9ubHk9XCJyZWFkb25seVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjaGVja2VkXT1cImNvbHVtblRvZ2dsZU11bHRpc2VsZWN0LmFsbFNlbGVjdGVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZvY3VzKT1cImNvbHVtblRvZ2dsZU11bHRpc2VsZWN0Lm9uSGVhZGVyQ2hlY2tib3hGb2N1cygpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJsdXIpPVwiY29sdW1uVG9nZ2xlTXVsdGlzZWxlY3Qub25IZWFkZXJDaGVja2JveEJsdXIoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChrZXlkb3duLnNwYWNlKT1cImNvbHVtblRvZ2dsZU11bHRpc2VsZWN0Lm9uVG9nZ2xlQWxsKCRldmVudClcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJwLWNoZWNrYm94LWJveFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9sZT1cImNoZWNrYm94XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWNoZWNrZWRdPVwiY29sdW1uVG9nZ2xlTXVsdGlzZWxlY3QuYWxsU2VsZWN0ZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3AtaGlnaGxpZ2h0JzogYW55Q29sdW1uVmlzaWJsZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQ29sdW1uVG9nZ2xlQWxsKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInAtY2hlY2tib3gtaWNvblwiIFtuZ0NsYXNzXT1cInsncGkgcGktY2hlY2snOiBhbnlDb2x1bW5WaXNpYmxlKCl9XCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGljb249XCJwaSBwaS1yZXBsYXlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGVDbGFzcz1cInAtYnV0dG9uLXNlY29uZGFyeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcFRvb2x0aXBdPVwiJ21uZ1RhYmxlLnJlc2V0TGF5b3V0JyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sdGlwUG9zaXRpb249XCJsZWZ0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJyZXNldERlZmF1bHRMYXlvdXQoKVwiPjwvcC1idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgbGV0LWl0ZW0gcFRlbXBsYXRlPVwiaXRlbVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBpdGVtLmRlc2NyaXB0b3IudGl0bGUgPz8gKGl0ZW0uZGVzY3JpcHRvci5wcm9wZXJ0eSB8IG1uZ0kxOG5Qcm9wZXJ0eTogZGVzY3JpcHRvcigpLm1vZGVsKSB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3AtbXVsdGlTZWxlY3Q+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBAaWYgKGhhc0NvbHVtbkZpbHRlcnMoKSkge1xuICAgICAgICAgICAgICAgICAgICA8dHIgY2xhc3M9XCJtbmctY29sdW1uLWZpbHRlci1yb3dcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gV2UgbmVlZCB0aGUgbGluZSBiZWxvdywgYmVjYXVzZSBvdGhlcndpc2UgcC10YWJsZVJhZGlvQnV0dG9uIHNoaWZ0cyB0aGUgcmVzdCBvZiB0aGUgY29sdW1ucyBpbiB0YWJsZSAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoc2VsZWN0aW9uRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoIHN0eWxlPVwibWluLXdpZHRoOiAzNnB4XCIgcEZyb3plbkNvbHVtbiBbZnJvemVuXT1cImRlc2NyaXB0b3IoKS5zZWxlY3Rpb25Db2x1bW5Gcm96ZW4gPz8gdHJ1ZVwiPjwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKHJvd1Jlb3JkZXJFbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc2NvcGU9XCJjb2xcIj48L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChkZXNjcmlwdG9yKCkucm93RXhwYW5kYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBzY29wZT1cImNvbFwiPjwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBAZm9yIChjb2wgb2YgdmlzaWJsZUNvbHVtbnMoKTsgdHJhY2sgY29sLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzc109XCJjb2wuZmlsdGVyPy5jb2x1bW5DbGFzc05hbWUgfCBtbmdUYWJsZUNvbHVtbkZpbHRlckNsYXNzOiBjb2wuZmlsdGVyIDogaGFzQ29sdW1uRmlsdGVycygpICYmICFjb2wud2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUud2lkdGgucHhdPVwiY29sLndpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLndpZHRoLiVdPVwiY29sLndpZHRoID8gbnVsbCA6IGNvbC5maWx0ZXI/LmNvbHVtbldpZHRoID8/IGNvbC5kZXNjcmlwdG9yLndpZHRoID8/IG51bGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUubWluLXdpZHRoLnB4XT1cImNvbC53aWR0aCA/IG51bGwgOiBjb2wuZmlsdGVyPy5jb2x1bW5NaW5XaWR0aCA/PyBjb2wuZGVzY3JpcHRvci5taW5XaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5tYXgtd2lkdGgucHhdPVwiY29sLndpZHRoID8/IGNvbC5kZXNjcmlwdG9yLm1heFdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoY29sLmZpbHRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1uZy10YWJsZS1jb2x1bW4tZmlsdGVyIFtkZXNjcmlwdG9yXT1cImNvbC5maWx0ZXJcIj48L21uZy10YWJsZS1jb2x1bW4tZmlsdGVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoaGFzTGFzdENvbHVtbigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwiY29sdW1uLWN1c3RvbS1sYXN0XCIgW3N0eWxlLm1pbi13aWR0aC5weF09XCJjb2x1bW5MYXN0TWluV2lkdGgoKVwiPjwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJib2R5XCIgbGV0LWl0ZW0gbGV0LWlkeD1cInJvd0luZGV4XCIgbGV0LWV4cGFuZGVkPVwiZXhwYW5kZWRcIj5cbiAgICAgICAgICAgICAgICA8dHJcbiAgICAgICAgICAgICAgICAgICAgW3BSZW9yZGVyYWJsZVJvd109XCJpZHhcIlxuICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJkZXNjcmlwdG9yKCkucm93Q2xhc3NOYW1lIHwgbW5nQ2xhc3NNYXA6IGRlc2NyaXB0b3IoKS5yb3dDbGFzc05hbWVNYXBGbiA6IGl0ZW0gfCBtbmdMb2NhbGVEZWZhdWx0Um93Q2xhc3M6IGRlc2NyaXB0b3IoKSA6IGl0ZW1cIj5cbiAgICAgICAgICAgICAgICAgICAgQGlmIChzZWxlY3Rpb25FbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoc2VsZWN0aW9uTW9kZSgpID09PSAnbXVsdGlwbGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkIHN0eWxlPVwibWluLXdpZHRoOiAzNnB4XCIgcEZyb3plbkNvbHVtbiBbZnJvemVuXT1cImRlc2NyaXB0b3IoKS5zZWxlY3Rpb25Db2x1bW5Gcm96ZW4gPz8gdHJ1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC10YWJsZUNoZWNrYm94IFt2YWx1ZV09XCJpdGVtXCI+PC9wLXRhYmxlQ2hlY2tib3g+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBzdHlsZT1cIm1pbi13aWR0aDogMzZweFwiIHBGcm96ZW5Db2x1bW4gW2Zyb3plbl09XCJkZXNjcmlwdG9yKCkuc2VsZWN0aW9uQ29sdW1uRnJvemVuID8/IHRydWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtdGFibGVSYWRpb0J1dHRvbiBbdmFsdWVdPVwiaXRlbVwiPjwvcC10YWJsZVJhZGlvQnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGlmIChkZXNjcmlwdG9yKCkucm93RXhwYW5kYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoIWRlc2NyaXB0b3IoKS5yb3dFeHBhbmRhYmxlUHJvcGVydHkgfHwgaXRlbVtkZXNjcmlwdG9yKCkucm93RXhwYW5kYWJsZVByb3BlcnR5IV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcFJvd1RvZ2dsZXJdPVwiaXRlbVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInAtYnV0dG9uLXRleHQgcC1idXR0b24tcm91bmRlZCBwLWJ1dHRvbi1wbGFpbiBtbmctdGFibGUtcm93LWV4cGFuZC1idXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2ljb25dPVwiZXhwYW5kZWQgPyAncGkgcGktY2hldnJvbi1kb3duJyA6ICdwaSBwaS1jaGV2cm9uLXJpZ2h0J1wiPjwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGlmIChyb3dSZW9yZGVyRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJwaSBwaS1iYXJzXCIgcFJlb3JkZXJhYmxlUm93SGFuZGxlPjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGZvciAoY29sIG9mIHZpc2libGVDb2x1bW5zKCk7IHRyYWNrIGNvbC5pZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPHRkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQ2VsbENsaWNrKCRldmVudCwgY29sLmRlc2NyaXB0b3IsIGl0ZW0sIGlkeClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzc109XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sLmRlc2NyaXB0b3IuY2xhc3NOYW1lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IG1uZ0NsYXNzTWFwOiBjb2wuZGVzY3JpcHRvci5jbGFzc05hbWVNYXBGbiA6IGl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgbW5nVGFibGVDb2x1bW5GaWx0ZXJDbGFzczogY29sLmZpbHRlciA6IGhhc0NvbHVtbkZpbHRlcnMoKSAmJiAhY29sLndpZHRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3MuY2xpY2thYmxlXT1cImlzQ2VsbENsaWNrRW5hYmxlZCgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUud2lkdGhdPVwiY29sLndpZHRoID8gY29sLndpZHRoICsgJ3B4JyA6IGNvbC5kZXNjcmlwdG9yLndpZHRoICsgJyUnXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUubWluLXdpZHRoLnB4XT1cImNvbC53aWR0aCA/IG51bGwgOiBjb2wuZGVzY3JpcHRvci5taW5XaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLm1heC13aWR0aC5weF09XCJjb2wud2lkdGggPz8gY29sLmRlc2NyaXB0b3IubWF4V2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInAtY29sdW1uLXRpdGxlXCI+e3sgY29sLmRlc2NyaXB0b3IudGl0bGUgPz8gKGNvbC5kZXNjcmlwdG9yLnByb3BlcnR5IHwgbW5nSTE4blByb3BlcnR5OiBkZXNjcmlwdG9yKCkubW9kZWwpIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtbmctdGFibGUtY29sdW1uLXZhbHVlIFtkZXNjcmlwdG9yXT1cImNvbC5kZXNjcmlwdG9yXCIgW2l0ZW1dPVwiaXRlbVwiPjwvbW5nLXRhYmxlLWNvbHVtbi12YWx1ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGlmIChoYXNMYXN0Q29sdW1uKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiY29sdW1uLWN1c3RvbS1sYXN0IGp1c3RpZnktY29udGVudC1lbmQgdGV4dC1yaWdodFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLm1pbi13aWR0aC5weF09XCJjb2x1bW5MYXN0TWluV2lkdGgoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcEZyb3plbkNvbHVtblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmcm96ZW5dPVwiZGVzY3JpcHRvcigpLmFjdGlvbkNvbHVtbkZyb3plbiA/PyB0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGlnbkZyb3plbj1cInJpZ2h0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChjb2x1bW5DdXN0b21MYXN0VGVtcGxhdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY29sdW1uQ3VzdG9tTGFzdFRlbXBsYXRlKCk7IGNvbnRleHQ6IHtyb3dJdGVtOiBpdGVtLCByb3dJbmRleDogaWR4fVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gQGVsc2UgaWYgKGNvbHVtbkN1c3RvbUxhc3RDb21wb25lbnQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IFttbmdDb21wb25lbnRdPVwiY29sdW1uQ3VzdG9tTGFzdENvbXBvbmVudCgpXCIgKGluc3RhbmNlQ3JlYXRlZCk9XCJjb2x1bW5DdXN0b21MYXN0Q29tcG9uZW50SW5zdGFuY2UuZW1pdCgkZXZlbnQpXCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cInJvd2V4cGFuc2lvblwiIGxldC1pdGVtPlxuICAgICAgICAgICAgICAgIEBpZiAoZGVzY3JpcHRvcigpLnJvd0V4cGFuZGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgW2NvbFNwYW5dPVwiZGVzY3JpcHRvcigpLnJvd0V4cGFuZGFibGVDb2xTcGFuXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChkZXNjcmlwdG9yKCkucm93RXhwYW5kYWJsZUNvbXBvbmVudFR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyIFttbmdDb21wb25lbnRdPVwiZGVzY3JpcHRvcigpLnJvd0V4cGFuZGFibGVDb21wb25lbnRUeXBlXCIgW2lucHV0c109XCJ7aXRlbX1cIj4gPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJyb3dFeHBhbmRUZW1wbGF0ZSgpOyBjb250ZXh0OiB7cm93SXRlbTogaXRlbX1cIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwibG9hZGluZ2ljb25cIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbHVtbiBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgQGlmIChkZXNjcmlwdG9yKCkubG9hZGluZ0ljb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIFtjbGFzc109XCIndGV4dC13aGl0ZSB0ZXh0LTR4bCBwaS1zcGluICcgKyBkZXNjcmlwdG9yKCkubG9hZGluZ0ljb25cIj48L2k+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGlmIChkZXNjcmlwdG9yKCkubG9hZGluZ1RleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0IHRleHQtd2hpdGUgdGV4dC1sZyBmb250LXNlbWlib2xkXCIgW25nQ2xhc3NdPVwieydtdC0zJzogZGVzY3JpcHRvcigpLmxvYWRpbmdJY29ufVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGRlc2NyaXB0b3IoKS5sb2FkaW5nVGV4dCA/PyAnJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwibG9hZGluZ2JvZHlcIj5cbiAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnNDb2xzcGFuKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nLXRleHRcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxwLXNrZWxldG9uIFtuZ1N0eWxlXT1cInt3aWR0aDogJzEwMCUnfVwiPjwvcC1za2VsZXRvbj5cbiAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJlbXB0eW1lc3NhZ2VcIj5cbiAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnNDb2xzcGFuKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7ICdtbmdUYWJsZS5ub0l0ZW1zJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgQGlmIChmb290ZXJUZW1wbGF0ZSgpKSB7XG4gICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cInN1bW1hcnlcIj5cbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImZvb3RlclRlbXBsYXRlKCk7IGNvbnRleHQ6IHtkYXRhOiBkYXRhTGlzdFNlcnZpY2UuZGF0YSgpLCB0b3RhbENvdW50OiBkYXRhTGlzdFNlcnZpY2UuY291bnQoKX1cIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgfVxuICAgICAgICA8L3AtdGFibGU+XG4gICAgfVxuPC9kaXY+XG4iXX0=
320
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGFibGUvc3JjL2NvbXBvbmVudHMvdGFibGUvdGFibGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vdGFibGUvc3JjL2NvbXBvbmVudHMvdGFibGUvdGFibGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRSxPQUFPLEVBQ0gsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFJVCxlQUFlLEVBQ2YsZ0JBQWdCLEVBQ2hCLFFBQVEsRUFDUixlQUFlLEVBQ2YsTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBQ04sTUFBTSxFQUNOLFNBQVMsRUFDVCxZQUFZLEVBQ2YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLG9CQUFvQixFQUFFLGtCQUFrQixFQUFFLFlBQVksRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBQ2xHLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUMsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFVLE1BQU0sRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRWxJLE9BQU8sRUFBQyxlQUFlLEVBQUUsZ0JBQWdCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RSxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sYUFBYSxDQUFDO0FBQzNDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1QyxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RCxPQUFPLEVBQUMsS0FBSyxFQUF3QyxXQUFXLEVBQXVCLE1BQU0sZUFBZSxDQUFDO0FBQzdHLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM5QyxPQUFPLEVBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUUzRCxPQUFPLEVBQ0gsWUFBWSxFQUNaLGtCQUFrQixFQUdsQixnQkFBZ0IsRUFDaEIsYUFBYSxFQUNiLGlCQUFpQixFQUNqQiwyQkFBMkIsRUFDM0Isd0JBQXdCLEVBQ3hCLGNBQWMsRUFDZCxrQkFBa0IsRUFDbEIsa0JBQWtCLEVBQ2xCLDZCQUE2QixFQUM3Qiw0QkFBNEIsRUFDNUIsZ0JBQWdCLEVBQ2hCLCtCQUErQixFQUNsQyxNQUFNLDZCQUE2QixDQUFDO0FBQ3JDLE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLCtCQUErQixDQUFDO0FBQ3BFLE9BQU8sRUFNSCx1QkFBdUIsRUFFdkIsYUFBYSxFQUNoQixNQUFNLGtDQUFrQyxDQUFDO0FBRTFDLE9BQU8sRUFBQyxzQkFBc0IsRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBQ2xFLE9BQU8sRUFBQyx5QkFBeUIsRUFBQyxNQUFNLDJDQUEyQyxDQUFDO0FBQ3BGLE9BQU8sRUFBQywwQkFBMEIsRUFBQyxNQUFNLDRDQUE0QyxDQUFDO0FBQ3RGLE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLG1DQUFtQyxDQUFDO0FBQ25FLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLHVDQUF1QyxDQUFDO0FBQzNFLE9BQU8sRUFBQyx1QkFBdUIsRUFBQyxNQUFNLDBDQUEwQyxDQUFDO0FBQ2pGLE9BQU8sRUFBQywwQkFBMEIsRUFBQyxNQUFNLDBDQUEwQyxDQUFDO0FBQ3BGLE9BQU8sRUFBQyx5QkFBeUIsRUFBQyxNQUFNLHdDQUF3QyxDQUFDO0FBQ2pGLE9BQU8sRUFBQyxrQ0FBa0MsRUFBQyxNQUFNLHFFQUFxRSxDQUFDOzs7Ozs7Ozs7QUE2QnZILE1BQU0sT0FBTyxjQUFjO0lBOEl2Qix5QkFBeUI7SUFDekIsNkRBQTZEO0lBQzdELDJCQUEyQixDQVF6QjtJQUNGLDZEQUE2RDtJQUM3RCwrQkFBK0IsQ0FTeEI7SUFDUCw2REFBNkQ7SUFDN0QsNkJBQTZCLENBT3RCO0lBQ1AsNkRBQTZEO0lBQzdELHlCQUF5QixDQWNsQjtJQUNQLG1CQUFtQixDQUVoQjtJQUVIO1FBaE1pQixxQkFBZ0IsR0FBRyxJQUFJLENBQUM7UUFFeEIsV0FBTSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDeEUsV0FBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4QixVQUFLLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQy9CLGNBQVMsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNyQyxtQkFBYyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN6QyxhQUFRLEdBQUcsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDeEMsVUFBSyxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3hDLFNBQUksR0FBRyxNQUFNLENBQUMsQ0FBQSxnQkFBc0IsQ0FBQSxDQUFDLENBQUM7UUFFdEQsYUFBYTtRQUNOLG9CQUFlLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBNEMsRUFBQyxLQUFLLEVBQUUsWUFBWSxFQUFDLENBQUMsQ0FBQztRQUUxRyxxQkFBcUI7UUFDZCxVQUFLLEdBQUcsS0FBSyxFQUFVLENBQUM7UUFDeEIsV0FBTSxHQUFHLEtBQUssRUFBd0IsQ0FBQztRQUN2QyxpQkFBWSxHQUFHLEtBQUssQ0FBQyxTQUFTLEVBQUUsRUFBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSwyQkFBMkIsRUFBQyxDQUFDLENBQUM7UUFDNUYsaUJBQVksR0FBRyxLQUFLLEVBQXFELENBQUM7UUFFakYsdUJBQXVCO1FBQ2hCLG1CQUFjLEdBQUcsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBQyxDQUFDLENBQUM7UUFDN0QscUJBQWdCLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBQyxDQUFDLENBQUM7UUFDOUQsa0JBQWEsR0FBRyxLQUFLLENBQXdCLFVBQVUsQ0FBQyxDQUFDO1FBQ3pELHFCQUFnQixHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBQyxTQUFTLEVBQUUsZ0JBQWdCLEVBQUMsQ0FBQyxDQUFDO1FBQy9ELDJCQUFzQixHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsRUFBQyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFDLENBQUMsQ0FBQztRQUNoRyxzQkFBaUIsR0FBRyxRQUFRLENBQVUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN4SCxvQkFBZSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDbkMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUM5QyxJQUFJLE9BQU8sVUFBVSxDQUFDLGFBQWEsS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDL0MsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLEdBQTZCLEVBQUUsSUFBUyxFQUFFLEVBQUU7b0JBQ3pFLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBdUIsQ0FBQyxDQUFDO29CQUNsRixPQUFPLEdBQUcsQ0FBQztnQkFDZixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDWCxDQUFDO2lCQUFNLElBQUksT0FBTyxVQUFVLENBQUMsYUFBYSxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUN4RCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsR0FBNkIsRUFBRSxJQUFTLEVBQUUsRUFBRTtvQkFDekUsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYyxDQUFDLENBQUMsR0FBSSxVQUFVLENBQUMsYUFBeUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDbkcsT0FBTyxHQUFHLENBQUM7Z0JBQ2YsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ1gsQ0FBQztZQUNELE9BQU8sRUFBRSxDQUFDO1FBQ2QsQ0FBQyxDQUFDLENBQUM7UUFFSCxVQUFVO1FBQ0gsdUJBQWtCLEdBQUcsS0FBSyxFQUFVLENBQUM7UUFDckMsbUJBQWMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4SyxvQkFBZSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4SCxxQkFBZ0IsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVqSixtQkFBbUI7UUFDWixxQkFBZ0IsR0FBRyxLQUFLLEVBQWEsQ0FBQztRQUN0Qyw4QkFBeUIsR0FBRyxLQUFLLEVBQWEsQ0FBQztRQUMvQyw0QkFBdUIsR0FBRyxLQUFLLENBQXVCLFNBQVMsRUFBRSxFQUFDLEtBQUssRUFBRSxvQkFBb0IsRUFBQyxDQUFDLENBQUM7UUFFdkcsYUFBYTtRQUNMLHFCQUFnQixHQUFHLElBQUksT0FBTyxFQUE2QixDQUFDO1FBQzdELHdCQUFtQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0QsdUJBQWtCLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7UUFFbEcsZ0JBQWdCO1FBQ1QsY0FBUyxHQUFHLE1BQU0sRUFBa0IsQ0FBQztRQUNyQyxjQUFTLEdBQUcsb0JBQW9CLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDeEQsb0JBQWUsR0FBRyxNQUFNLEVBQWUsQ0FBQztRQUN4Qyw2QkFBd0IsR0FBRyxNQUFNLEVBQU8sQ0FBQztRQUN6QyxzQ0FBaUMsR0FBRyxNQUFNLEVBQU8sQ0FBQztRQUNsRCxlQUFVLEdBQUcsTUFBTSxFQUF3QixDQUFDO1FBRW5ELDJCQUEyQjtRQUNwQixjQUFTLEdBQUcsZUFBZSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDL0MsZUFBVSxHQUFHLFlBQVksQ0FBQyxDQUFBLGtCQUF1QixDQUFBLENBQUMsQ0FBQztRQUNuRCxlQUFVLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXJDLFlBQVk7UUFDTCxvQkFBZSxHQUFvQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDeEgsNkJBQXdCLEdBQW9DLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUsa0JBQWtCLENBQUMsQ0FBQyxDQUFDO1FBQzFJLG1CQUFjLEdBQW9DLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUN0SCxzQkFBaUIsR0FBb0MsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLGtCQUFrQixDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7UUFFMUksMEJBQTBCO1FBQ25CLFdBQU0sR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFLE1BQU0sS0FBSyxJQUFJLENBQUMsQ0FBQztRQUM5RCxpQkFBWSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxLQUFLLHVCQUF1QixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2pHLDhCQUF5QixHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVqRCxTQUFTO1FBQ0YsY0FBUyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDN0IsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDO1lBQzNELFFBQVEsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDdEMsS0FBSyxhQUFhLENBQUMsS0FBSztvQkFDcEIsU0FBUyxJQUFJLGlCQUFpQixDQUFDO29CQUMvQixNQUFNO2dCQUNWLEtBQUssYUFBYSxDQUFDLEtBQUs7b0JBQ3BCLFNBQVMsSUFBSSxpQkFBaUIsQ0FBQztvQkFDL0IsTUFBTTtZQUNkLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQzFDLFNBQVMsSUFBSSx3QkFBd0IsQ0FBQztZQUMxQyxDQUFDO1lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLENBQUM7Z0JBQzNCLFNBQVMsSUFBSSxzQkFBc0IsQ0FBQztZQUN4QyxDQUFDO1lBQ0QsT0FBTyxTQUFTLENBQUM7UUFDckIsQ0FBQyxDQUFDLENBQUM7UUFFSCxVQUFVO1FBQ0gsbUJBQWMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQzVGLDBCQUFxQixHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO1FBQ2hILHlCQUFvQixHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1FBRXJILGVBQWU7UUFDUixxQkFBZ0IsR0FBRyxRQUFRLENBQzlCLEdBQUcsRUFBRSxDQUNELENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyx3QkFBd0IsS0FBSyxxQkFBcUIsQ0FBQyxjQUFjO1lBQzVFLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxLQUFLLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2hHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyx3QkFBd0IsS0FBSyxxQkFBcUIsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLENBQUMsQ0FDdEosQ0FBQztRQUNLLDBCQUFxQixHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDekMsaURBQWlEO1lBQ2pELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRO2lCQUN4QixPQUFPLEVBQUU7aUJBQ1QsTUFBTSxDQUNILENBQUMsQ0FBQyxFQUFFLENBQ0EsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFdBQVcsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyx3QkFBd0IsS0FBSyxxQkFBcUIsQ0FBQyxjQUFjLENBQUM7Z0JBQ3JILENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxLQUFLLHFCQUFxQixDQUFDLGNBQWMsQ0FDeEUsQ0FBQztZQUVOLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7UUFDMUQsQ0FBQyxDQUFDLENBQUM7UUFFSSxxQkFBZ0IsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNwRSx3QkFBbUIsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFLElBQUksSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUMsQ0FBQztRQUMxRyxrQkFBYSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQUFDO1FBTWpJLFFBQVE7UUFDQSxvQkFBZSxHQUFZLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQztRQUMzRCxtQ0FBOEIsR0FBRyxLQUFLLENBQUM7UUFDdkMsZ0NBQTJCLEdBQUcsS0FBSyxDQUFDO1FBRTVDLHlCQUF5QjtRQUN6Qiw2REFBNkQ7UUFDN0QsZ0NBQTJCLEdBQUcsY0FBYyxDQUN4QyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFDbkIsQ0FBQyxDQUFDLFlBQVksQ0FBQyxFQUFFLEVBQUU7WUFDZixJQUFJLFlBQVksRUFBRSxNQUFNLEtBQUssS0FBSyxFQUFFLENBQUM7Z0JBQ2pDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUM7WUFDbEUsQ0FBQztRQUNMLENBQUMsRUFDRCxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUMsQ0FDcEIsQ0FBQztRQUNGLDZEQUE2RDtRQUM3RCxvQ0FBK0IsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQzthQUM1RCxJQUFJLENBQ0QsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLFlBQVksSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFDM0Msa0JBQWtCLEVBQUUsQ0FDdkI7YUFDQSxTQUFTLENBQUM7WUFDUCxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUU7Z0JBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNuQixDQUFDO1NBQ0osQ0FBQyxDQUFDO1FBQ1AsNkRBQTZEO1FBQzdELGtDQUE2QixHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDO2FBQzVELElBQUksQ0FDRCxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQzVELGtCQUFrQixFQUFFLENBQ3ZCO2FBQ0EsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQ1osSUFBSSxDQUFDLHdCQUF3QixDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO1FBQ1AsNkRBQTZEO1FBQzdELDhCQUF5QixHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDO2FBQ3hELElBQUksQ0FDRCxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQ3hELE1BQU0sQ0FDRixDQUFDLENBQUMsRUFBRSxDQUNBLENBQUMsQ0FBQyxZQUFZLGVBQWUsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNuSCxDQUFDLFlBQVksYUFBYTtZQUMxQixDQUFDLFlBQVksZ0JBQWdCO1lBQzdCLENBQUMsWUFBWSxlQUFlLENBQ25DLEVBQ0Qsa0JBQWtCLEVBQUUsQ0FDdkI7YUFDQSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDWCxJQUFJLENBQUMsOEJBQThCLEdBQUcsQ0FBQyxZQUFZLGVBQWUsQ0FBQztRQUN2RSxDQUFDLENBQUMsQ0FBQztRQUNQLHdCQUFtQixHQUFHLGVBQWUsQ0FBQyxHQUFHLEVBQUU7WUFDdkMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDakUsQ0FBQyxDQUFDLENBQUM7UUFHQyxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFDbkYsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzVGLENBQUM7SUFZTSxNQUFNLENBQUMsbUJBQStELEtBQUssRUFBRSxnQkFBZ0IsR0FBRyxLQUFLO1FBQ3hHLE1BQU0sU0FBUyxHQUFHLE9BQU8sZ0JBQWdCLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxTQUFTLElBQUksS0FBSyxDQUFDLENBQUM7UUFDcEgsTUFBTSxXQUFXLEdBQUcsT0FBTyxnQkFBZ0IsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUM7UUFDNUcsTUFBTSxNQUFNLEdBQ1IsT0FBTyxnQkFBZ0IsS0FBSyxRQUFRLElBQUksZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBRSxnQkFBZ0IsRUFBRSxNQUF5QixDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDO1FBQzVLLE1BQU0sWUFBWSxHQUFHLCtCQUErQixDQUFDLE1BQU0sSUFBSSxFQUFFLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQ2xHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxZQUFZLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVNLGVBQWUsQ0FBQyxLQUF5QjtRQUM1QyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDO1FBRS9CLE1BQU0sTUFBTSxHQUFHLDZCQUE2QixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXBELElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLElBQUksQ0FBQyw4QkFBOEIsSUFBSSxDQUFDLElBQUksQ0FBQywyQkFBMkIsRUFBRSxDQUFDO2dCQUM1RSxvSUFBb0k7Z0JBQ3BJLElBQUksQ0FBQywyQkFBMkIsR0FBRyxJQUFJLENBQUM7Z0JBQ3hDLE1BQU0sU0FBUyxHQUFHLHdCQUF3QixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxFQUFFLEVBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixFQUFDLENBQUMsQ0FBQztnQkFDOUgsTUFBTSwyQkFBMkIsR0FBRyxFQUFDLEdBQUcsU0FBUyxFQUFDLENBQUM7Z0JBQ25ELElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO29CQUN2QixNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUM7eUJBQzVCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEtBQUssU0FBUyxDQUFDO3lCQUNwSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLDJCQUEyQixDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQy9ELENBQUM7Z0JBRUQsSUFBSSxDQUFDLE1BQU07cUJBQ04sUUFBUSxDQUFDLEVBQUUsRUFBRTtvQkFDVixVQUFVLEVBQUUsSUFBSSxDQUFDLEtBQUs7b0JBQ3RCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixXQUFXLEVBQUUsMkJBQTJCO29CQUN4QyxtQkFBbUIsRUFBRSxPQUFPO2lCQUMvQixDQUFDO3FCQUNELElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRTtvQkFDUixJQUFJLENBQUMsMkJBQTJCLEdBQUcsS0FBSyxDQUFDO29CQUN6QyxJQUFJLEdBQUcsRUFBRSxDQUFDO3dCQUNOLElBQUksQ0FBQyxlQUFlLEdBQUcsU0FBUyxDQUFDO29CQUNyQyxDQUFDO2dCQUNMLENBQUMsQ0FBQyxDQUFDO1lBQ1gsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ0osTUFBTSxrQkFBa0IsR0FBRywrQkFBK0IsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO1lBQ2xHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFDeEMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDdkQsQ0FBQztJQUNMLENBQUM7SUFFTSxhQUFhLENBQUMsS0FBdUI7UUFDeEMsSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQztZQUN4QixPQUFPO1FBQ1gsQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLDZCQUE2QixDQUFDLEVBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPLEVBQUMsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sa0JBQWtCLEdBQUcsK0JBQStCLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQztRQUVsRyx1RUFBdUU7UUFDdkUsbURBQW1EO1FBQ25ELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzVDLENBQUM7SUFDTCxDQUFDO0lBRU0sV0FBVyxDQUFDLEtBQVksRUFBRSxHQUFnQyxFQUFFLElBQVUsRUFBRSxHQUFXO1FBQ3RGLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO1lBQzdCLE9BQU87UUFDWCxDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQThCO1lBQzFDLE1BQU0sRUFBRSxHQUFHO1lBQ1gsT0FBTyxFQUFFLElBQUk7WUFDYixRQUFRLEVBQUUsR0FBRztZQUNiLEtBQUssRUFBRSxLQUFLO1NBQ2YsQ0FBQztRQUNGLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVNLGlCQUFpQixDQUFDLEtBQWtCO1FBQ3ZDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFTSxZQUFZLENBQUMsS0FBMkI7UUFDM0MsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVPLHlCQUF5QixDQUFDLGtCQUFrQyxFQUFFLFNBQVMsR0FBRyxJQUFJO1FBQ2xGLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxDQUFDLEVBQUU7WUFDMUUsc0JBQXNCLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDL0YsTUFBTSxZQUFZLEdBQUcsa0JBQWtCLENBQUMsS0FBSyxFQUFFLHFCQUFxQixFQUFFO2dCQUNsRSxNQUFNLEVBQUUsa0JBQWtCO2FBQzdCLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1FBQ2xFLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNaLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxrQkFBa0IsQ0FBQztZQUNqRCxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNaLE1BQU0sVUFBVSxHQUFtQjtvQkFDL0IsYUFBYSxFQUFFLElBQUksQ0FBQyxpQkFBaUI7b0JBQ3JDLE1BQU0sRUFBRSxrQkFBa0I7aUJBQzdCLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEMsQ0FBQztRQUNMLENBQUM7SUFDTCxDQUFDO0lBRU8sd0JBQXdCLENBQUMsU0FBaUI7UUFDOUMsTUFBTSxrQkFBa0IsR0FBRywrQkFBK0IsQ0FDdEQsNEJBQTRCLENBQUMsU0FBUyxFQUFFO1lBQ3BDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxnQkFBZ0I7WUFDeEMsY0FBYyxFQUFFLElBQUk7U0FDdkIsQ0FBQyxFQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLENBQ2hDLENBQUM7UUFDRixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMseUJBQXlCLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUN2RCxDQUFDOytHQWpVUSxjQUFjO21HQUFkLGNBQWMscTJFQUhaLENBQUMsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUUsdUJBQXVCLENBQUMsb0RBd0V6QyxpQkFBaUIsNEVBQ25CLENBQUEsa0JBQXVCLENBQUEsNkZBQzFCLEtBQUssZ0VDeEt2Qyw2enFCQTRVQSw0Q0RqUVEsa0JBQWtCLDRLQUNsQixnQkFBZ0Isd0RBQ2hCLE9BQU8sb0ZBQ1AsT0FBTywyRUFDUCxnQkFBZ0Isb0pBQ2hCLHlCQUF5Qiw4RkFDekIsWUFBWSwrQ0FDWix5QkFBeUIsaUVBQ3pCLDBCQUEwQixxRkFDMUIsMEJBQTBCLGlFQUMxQixXQUFXLHk0R0FDWCxpQkFBaUIsbzFDQUNqQixZQUFZLDJrQkFDWixhQUFhLHFYQUNiLGVBQWUsNEZBQ2Ysa0NBQWtDLDhNQUNsQyxXQUFXLCtWQUNYLGlCQUFpQjs7NEZBS1osY0FBYztrQkEzQjFCLFNBQVM7aUNBQ00sSUFBSSxZQUNOLFdBQVcsV0FFWjt3QkFDTCxrQkFBa0I7d0JBQ2xCLGdCQUFnQjt3QkFDaEIsT0FBTzt3QkFDUCxPQUFPO3dCQUNQLGdCQUFnQjt3QkFDaEIseUJBQXlCO3dCQUN6QixZQUFZO3dCQUNaLHlCQUF5Qjt3QkFDekIsMEJBQTBCO3dCQUMxQiwwQkFBMEI7d0JBQzFCLFdBQVc7d0JBQ1gsaUJBQWlCO3dCQUNqQixZQUFZO3dCQUNaLGFBQWE7d0JBQ2IsZUFBZTt3QkFDZixrQ0FBa0M7d0JBQ2xDLFdBQVc7d0JBQ1gsaUJBQWlCO3FCQUNwQixhQUNVLENBQUMsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUUsdUJBQXVCLENBQUMsbUJBQzNELHVCQUF1QixDQUFDLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge05nQ2xhc3MsIE5nU3R5bGUsIE5nVGVtcGxhdGVPdXRsZXR9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICAgIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgIENvbXBvbmVudCxcbiAgICBTaWduYWwsXG4gICAgVGVtcGxhdGVSZWYsXG4gICAgVHlwZSxcbiAgICBhZnRlck5leHRSZW5kZXIsXG4gICAgYm9vbGVhbkF0dHJpYnV0ZSxcbiAgICBjb21wdXRlZCxcbiAgICBjb250ZW50Q2hpbGRyZW4sXG4gICAgaW5qZWN0LFxuICAgIGlucHV0LFxuICAgIG91dHB1dCxcbiAgICBzaWduYWwsXG4gICAgdmlld0NoaWxkLFxuICAgIHZpZXdDaGlsZHJlblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7b3V0cHV0RnJvbU9ic2VydmFibGUsIHRha2VVbnRpbERlc3Ryb3llZCwgdG9PYnNlcnZhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQge0Zvcm1zTW9kdWxlfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge0FjdGl2YXRlZFJvdXRlLCBOYXZpZ2F0aW9uQ2FuY2VsLCBOYXZpZ2F0aW9uRW5kLCBOYXZpZ2F0aW9uRXJyb3IsIE5hdmlnYXRpb25TdGFydCwgUGFyYW1zLCBSb3V0ZXJ9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbmltcG9ydCB7VHJhbnNsYXRlTW9kdWxlLCBUcmFuc2xhdGVTZXJ2aWNlfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7TWVzc2FnZVNlcnZpY2V9IGZyb20gJ3ByaW1lbmcvYXBpJztcbmltcG9ydCB7QnV0dG9uTW9kdWxlfSBmcm9tICdwcmltZW5nL2J1dHRvbic7XG5pbXBvcnQge011bHRpU2VsZWN0TW9kdWxlfSBmcm9tICdwcmltZW5nL211bHRpc2VsZWN0JztcbmltcG9ydCB7VGFibGUsIFRhYmxlRmlsdGVyRXZlbnQsIFRhYmxlTGF6eUxvYWRFdmVudCwgVGFibGVNb2R1bGUsIFRhYmxlUm93UmVvcmRlckV2ZW50fSBmcm9tICdwcmltZW5nL3RhYmxlJztcbmltcG9ydCB7VG9vbHRpcE1vZHVsZX0gZnJvbSAncHJpbWVuZy90b29sdGlwJztcbmltcG9ydCB7TkVWRVIsIFN1YmplY3QsIGZpbHRlciwgb2YsIHN3aXRjaE1hcH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7XG4gICAgQ2xhc3NNYXBQaXBlLFxuICAgIENvbXBvbmVudERpcmVjdGl2ZSxcbiAgICBEYXRhTGlzdFBhcmFtcyxcbiAgICBEYXRhTGlzdFJlc3VsdCxcbiAgICBJMThuUHJvcGVydHlQaXBlLFxuICAgIExvZ2dlclNlcnZpY2UsXG4gICAgVGVtcGxhdGVEaXJlY3RpdmUsXG4gICAgYm9vbGVhbk9yVW5kZWZpbmVkQXR0cmlidXRlLFxuICAgIGRhdGFMaXN0UGFyYW1zVG9VcmxRdWVyeSxcbiAgICBlZmZlY3RXaXRoRGVwcyxcbiAgICBmaW5kVGVtcGxhdGVCeU5hbWUsXG4gICAgZnJvbVN1YnNjcmliZUVycm9yLFxuICAgIGZyb21UYWJsZUxvYWRUb0RhdGFMaXN0UGFyYW1zLFxuICAgIGZyb21VcmxRdWVyeVRvRGF0YUxpc3RQYXJhbXMsXG4gICAgZ2V0RXJyb3JMb2dMZXZlbCxcbiAgICBtZXJnZURhdGFMaXN0UGFyYW1zV2l0aERlZmF1bHRzXG59IGZyb20gJ0BtZWRpdXNpbmMvbW5nLWNvbW1vbnMvY29yZSc7XG5pbXBvcnQge0ZpbHRlckRpc3BsYXlUeXBlRW51bX0gZnJvbSAnQG1lZGl1c2luYy9tbmctY29tbW9ucy9maWx0ZXInO1xuaW1wb3J0IHtcbiAgICBDb2x1bW5EZXNjcmlwdG9yLFxuICAgIElUYWJsZURhdGFQcm92aWRlcixcbiAgICBUYWJsZUNlbGxDbGlja0V2ZW50LFxuICAgIFRhYmxlRGVzY3JpcHRvckluc3QsXG4gICAgVGFibGVMb2FkRXZlbnQsXG4gICAgVGFibGVQYWdpbmF0aW9uTW9kZUVudW0sXG4gICAgVGFibGVSZWxvYWRFdmVudCxcbiAgICBUYWJsZVNpemVFbnVtXG59IGZyb20gJ0BtZWRpdXNpbmMvbW5nLWNvbW1vbnMvdGFibGUvYXBpJztcblxuaW1wb3J0IHt0YWJsZU5vdGlmaWNhdGlvbkVycm9yfSBmcm9tICcuLi8uLi9oZWxwZXJzL25vdGlmaWNhdGlvbic7XG5pbXBvcnQge0xvY2FsZURlZmF1bHRSb3dDbGFzc1BpcGV9IGZyb20gJy4uLy4uL3BpcGVzL2xvY2FsZS1kZWZhdWx0LXJvdy1jbGFzcy5waXBlJztcbmltcG9ydCB7VGFibGVDb2x1bW5GaWx0ZXJDbGFzc1BpcGV9IGZyb20gJy4uLy4uL3BpcGVzL3RhYmxlLWNvbHVtbi1maWx0ZXItY2xhc3MucGlwZSc7XG5pbXBvcnQge1RhYmxlRGF0YVNlcnZpY2V9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3RhYmxlLWRhdGEuc2VydmljZSc7XG5pbXBvcnQge1RhYmxlTWV0YWRhdGFTZXJ2aWNlfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy90YWJsZS1tZXRhZGF0YS5zZXJ2aWNlJztcbmltcG9ydCB7VGFibGVQcmVmZXJlbmNlc1NlcnZpY2V9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3RhYmxlLXByZWZlcmVuY2VzLnNlcnZpY2UnO1xuaW1wb3J0IHtUYWJsZUNvbHVtbkZpbHRlckNvbXBvbmVudH0gZnJvbSAnLi4vY29sdW1uLWZpbHRlci9jb2x1bW4tZmlsdGVyLmNvbXBvbmVudCc7XG5pbXBvcnQge1RhYmxlQ29sdW1uVmFsdWVDb21wb25lbnR9IGZyb20gJy4uL2NvbHVtbi12YWx1ZS9jb2x1bW4tdmFsdWUuY29tcG9uZW50JztcbmltcG9ydCB7VGFibGVGaWx0ZXJPdmVybGF5V2l0aFRhZ0NvbXBvbmVudH0gZnJvbSAnLi4vZmlsdGVyL2ZpbHRlci1vdmVybGF5LXdpdGgtdGFnL2ZpbHRlci1vdmVybGF5LXdpdGgtdGFnLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc2VsZWN0b3I6ICdtbmctdGFibGUnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi90YWJsZS5jb21wb25lbnQuaHRtbCcsXG4gICAgaW1wb3J0czogW1xuICAgICAgICBDb21wb25lbnREaXJlY3RpdmUsXG4gICAgICAgIEkxOG5Qcm9wZXJ0eVBpcGUsXG4gICAgICAgIE5nQ2xhc3MsXG4gICAgICAgIE5nU3R5bGUsXG4gICAgICAgIE5nVGVtcGxhdGVPdXRsZXQsXG4gICAgICAgIFRhYmxlQ29sdW1uVmFsdWVDb21wb25lbnQsXG4gICAgICAgIENsYXNzTWFwUGlwZSxcbiAgICAgICAgTG9jYWxlRGVmYXVsdFJvd0NsYXNzUGlwZSxcbiAgICAgICAgVGFibGVDb2x1bW5GaWx0ZXJDb21wb25lbnQsXG4gICAgICAgIFRhYmxlQ29sdW1uRmlsdGVyQ2xhc3NQaXBlLFxuICAgICAgICBUYWJsZU1vZHVsZSxcbiAgICAgICAgTXVsdGlTZWxlY3RNb2R1bGUsXG4gICAgICAgIEJ1dHRvbk1vZHVsZSxcbiAgICAgICAgVG9vbHRpcE1vZHVsZSxcbiAgICAgICAgVHJhbnNsYXRlTW9kdWxlLFxuICAgICAgICBUYWJsZUZpbHRlck92ZXJsYXlXaXRoVGFnQ29tcG9uZW50LFxuICAgICAgICBGb3Jtc01vZHVsZSxcbiAgICAgICAgVGVtcGxhdGVEaXJlY3RpdmVcbiAgICBdLFxuICAgIHByb3ZpZGVyczogW1RhYmxlTWV0YWRhdGFTZXJ2aWNlLCBUYWJsZURhdGFTZXJ2aWNlLCBUYWJsZVByZWZlcmVuY2VzU2VydmljZV0sXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgVGFibGVDb21wb25lbnQ8SXRlbSA9IGFueSwgU2VydmljZSA9IHVuZGVmaW5lZCwgU29ydHMgPSBhbnksIEZpbHRlcnMgZXh0ZW5kcyBrZXlvZiBhbnkgPSBhbnk+IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGZpbHRlcktleVByZXBlbmQgPSAnZl8nO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXIgPSBpbmplY3QoTG9nZ2VyU2VydmljZSkuY3JlYXRlKFRhYmxlTWV0YWRhdGFTZXJ2aWNlLmNtcFR5cGVOYW1lKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgcm91dGUgPSBpbmplY3QoQWN0aXZhdGVkUm91dGUpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgdHJhbnNsYXRlID0gaW5qZWN0KFRyYW5zbGF0ZVNlcnZpY2UpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbWVzc2FnZVNlcnZpY2UgPSBpbmplY3QoTWVzc2FnZVNlcnZpY2UpO1xuICAgIHB1YmxpYyByZWFkb25seSBtZXRhZGF0YSA9IGluamVjdChUYWJsZU1ldGFkYXRhU2VydmljZSk7XG4gICAgcHVibGljIHJlYWRvbmx5IHByZWZzID0gaW5qZWN0KFRhYmxlUHJlZmVyZW5jZXNTZXJ2aWNlKTtcbiAgICBwdWJsaWMgcmVhZG9ubHkgZGF0YSA9IGluamVjdChUYWJsZURhdGFTZXJ2aWNlPEl0ZW0+KTtcblxuICAgIC8vIGRlc2NyaXB0b3JcbiAgICBwdWJsaWMgZGVzY3JpcHRvcklucHV0ID0gaW5wdXQucmVxdWlyZWQ8VGFibGVEZXNjcmlwdG9ySW5zdDxJdGVtLCBTb3J0cywgRmlsdGVycz4+KHthbGlhczogJ2Rlc2NyaXB0b3InfSk7XG5cbiAgICAvLyBkYXRhIHNvdXJjZSBpbnB1dHNcbiAgICBwdWJsaWMgaXRlbXMgPSBpbnB1dDxJdGVtW10+KCk7XG4gICAgcHVibGljIHJlc3VsdCA9IGlucHV0PERhdGFMaXN0UmVzdWx0PEl0ZW0+PigpO1xuICAgIHB1YmxpYyBsb2FkaW5nSW5wdXQgPSBpbnB1dCh1bmRlZmluZWQsIHthbGlhczogJ2xvYWRpbmcnLCB0cmFuc2Zvcm06IGJvb2xlYW5PclVuZGVmaW5lZEF0dHJpYnV0ZX0pO1xuICAgIHB1YmxpYyBkYXRhUHJvdmlkZXIgPSBpbnB1dDxJVGFibGVEYXRhUHJvdmlkZXI8SXRlbSwgU2VydmljZSwgU29ydHMsIEZpbHRlcnM+PigpO1xuXG4gICAgLy8gZXh0cmEgZmVhdHVyZXMgaW5wdXRcbiAgICBwdWJsaWMgdXNlUXVlcnlQYXJhbXMgPSBpbnB1dChmYWxzZSwge3RyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZX0pO1xuICAgIHB1YmxpYyBjZWxsQ2xpY2tFbmFibGVkID0gaW5wdXQodHJ1ZSwge3RyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZX0pO1xuICAgIHB1YmxpYyBzZWxlY3Rpb25Nb2RlID0gaW5wdXQ8J3NpbmdsZScgfCAnbXVsdGlwbGUnPignbXVsdGlwbGUnKTtcbiAgICBwdWJsaWMgc2VsZWN0aW9uRW5hYmxlZCA9IGlucHV0KGZhbHNlLCB7dHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlfSk7XG4gICAgcHVibGljIHJvd1Jlb3JkZXJFbmFibGVkSW5wdXQgPSBpbnB1dCh0cnVlLCB7YWxpYXM6ICdyb3dSZW9yZGVyRW5hYmxlZCcsIHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZX0pO1xuICAgIHB1YmxpYyByb3dSZW9yZGVyRW5hYmxlZCA9IGNvbXB1dGVkPGJvb2xlYW4+KCgpID0+IHRoaXMucm93UmVvcmRlckVuYWJsZWRJbnB1dCgpICYmIHRoaXMubWV0YWRhdGEuZGVzY3JpcHRvcigpLnJvd1Jlb3JkZXJhYmxlKTtcbiAgICBwdWJsaWMgZXhwYW5kZWRSb3dLZXlzID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gdGhpcy5tZXRhZGF0YS5kZXNjcmlwdG9yKCk7XG4gICAgICAgIGlmICh0eXBlb2YgZGVzY3JpcHRvci5pc1Jvd0V4cGFuZGVkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YS5kYXRhKCk/LnJlZHVjZSgoYWNjOiB7W2tleTogc3RyaW5nXTogYm9vbGVhbn0sIGl0ZW06IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGFjY1tpdGVtW2Rlc2NyaXB0b3IudHJhY2tQcm9wZXJ0eSFdXSA9ICEhaXRlbVtkZXNjcmlwdG9yLmlzUm93RXhwYW5kZWQgYXMgc3RyaW5nXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICAgICAgfSwge30pO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkZXNjcmlwdG9yLmlzUm93RXhwYW5kZWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGEuZGF0YSgpPy5yZWR1Y2UoKGFjYzoge1trZXk6IHN0cmluZ106IGJvb2xlYW59LCBpdGVtOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBhY2NbaXRlbVtkZXNjcmlwdG9yLnRyYWNrUHJvcGVydHkhXV0gPSAoZGVzY3JpcHRvci5pc1Jvd0V4cGFuZGVkIGFzIChpdGVtOiBJdGVtKSA9PiBib29sZWFuKShpdGVtKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICAgICAgfSwge30pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7fTtcbiAgICB9KTtcblxuICAgIC8vIHN0eWxpbmdcbiAgICBwdWJsaWMgY29sdW1uTGFzdE1pbldpZHRoID0gaW5wdXQ8bnVtYmVyPigpO1xuICAgIHB1YmxpYyBjb2x1bW5zQ29sc3BhbiA9IGNvbXB1dGVkKCgpID0+IHRoaXMudmlzaWJsZUNvbHVtbnMoKS5sZW5ndGggKyAodGhpcy5oYXNMYXN0Q29sdW1uKCkgPyAxIDogMCkgKyAodGhpcy5zZWxlY3Rpb25FbmFibGVkKCkgPyAxIDogMCkgKyAodGhpcy5yb3dSZW9yZGVyRW5hYmxlZCgpID8gMSA6IDApKTtcbiAgICBwdWJsaWMgaGFzVGl0bGVEaXNwbGF5ID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5jYXB0aW9uVGVtcGxhdGUoKSB8fCB0aGlzLmNhcHRpb25Db21wb25lbnQoKSB8fCB0aGlzLm1ldGFkYXRhLmRlc2NyaXB0b3IoKS50aXRsZSk7XG4gICAgcHVibGljIGlzQ2FwdGlvblZpc2libGUgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmhhc1RpdGxlRGlzcGxheSgpIHx8IHRoaXMub3ZlcmxheVdpdGhUYWdGaWx0ZXJzKCkubGVuZ3RoID4gMCB8fCB0aGlzLm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5zZWFyY2gpO1xuXG4gICAgLy8gY29tcG9uZW50IGlucHV0c1xuICAgIHB1YmxpYyBjYXB0aW9uQ29tcG9uZW50ID0gaW5wdXQ8VHlwZTxhbnk+PigpO1xuICAgIHB1YmxpYyBjb2x1bW5DdXN0b21MYXN0Q29tcG9uZW50ID0gaW5wdXQ8VHlwZTxhbnk+PigpO1xuICAgIHB1YmxpYyBnbG9iYWxGaWx0ZXJGaWVsZHNJbnB1dCA9IGlucHV0PHN0cmluZ1tdIHwgdW5kZWZpbmVkPih1bmRlZmluZWQsIHthbGlhczogJ2dsb2JhbEZpbHRlckZpZWxkcyd9KTtcblxuICAgIC8vIGNlbGwgY2xpY2tcbiAgICBwcml2YXRlIGNlbGxDbGlja1N1YmplY3QgPSBuZXcgU3ViamVjdDxUYWJsZUNlbGxDbGlja0V2ZW50PEl0ZW0+PigpO1xuICAgIHB1YmxpYyBpc0NlbGxDbGlja09ic2VydmVkID0gc2lnbmFsKHRoaXMuY2VsbENsaWNrU3ViamVjdC5vYnNlcnZlZCk7XG4gICAgcHVibGljIGlzQ2VsbENsaWNrRW5hYmxlZCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuY2VsbENsaWNrRW5hYmxlZCgpICYmIHRoaXMuaXNDZWxsQ2xpY2tPYnNlcnZlZCgpKTtcblxuICAgIC8vIGV2ZW50IG91dHB1dHNcbiAgICBwdWJsaWMgdGFibGVMb2FkID0gb3V0cHV0PFRhYmxlTG9hZEV2ZW50PigpO1xuICAgIHB1YmxpYyBjZWxsQ2xpY2sgPSBvdXRwdXRGcm9tT2JzZXJ2YWJsZSh0aGlzLmNlbGxDbGlja1N1YmplY3QpO1xuICAgIHB1YmxpYyBzZWxlY3Rpb25DaGFuZ2UgPSBvdXRwdXQ8QXJyYXk8SXRlbT4+KCk7XG4gICAgcHVibGljIGNhcHRpb25Db21wb25lbnRJbnN0YW5jZSA9IG91dHB1dDxhbnk+KCk7XG4gICAgcHVibGljIGNvbHVtbkN1c3RvbUxhc3RDb21wb25lbnRJbnN0YW5jZSA9IG91dHB1dDxhbnk+KCk7XG4gICAgcHVibGljIHJvd1Jlb3JkZXIgPSBvdXRwdXQ8VGFibGVSb3dSZW9yZGVyRXZlbnQ+KCk7XG5cbiAgICAvLyBjb250ZW50IGFuZCB2aWV3IHF1ZXJpZXNcbiAgICBwdWJsaWMgdGVtcGxhdGVzID0gY29udGVudENoaWxkcmVuKFRlbXBsYXRlRGlyZWN0aXZlKTtcbiAgICBwdWJsaWMgY29tcG9uZW50cyA9IHZpZXdDaGlsZHJlbihDb21wb25lbnREaXJlY3RpdmU8YW55Pik7XG4gICAgcHVibGljIHByaW1lVGFibGUgPSB2aWV3Q2hpbGQoVGFibGUpO1xuXG4gICAgLy8gdGVtcGxhdGVzXG4gICAgcHVibGljIGNhcHRpb25UZW1wbGF0ZTogU2lnbmFsPFRlbXBsYXRlUmVmPGFueT4gfCBudWxsPiA9IGNvbXB1dGVkKCgpID0+IGZpbmRUZW1wbGF0ZUJ5TmFtZShbLi4udGhpcy50ZW1wbGF0ZXMoKV0sICdjYXB0aW9uJykpO1xuICAgIHB1YmxpYyBjb2x1bW5DdXN0b21MYXN0VGVtcGxhdGU6IFNpZ25hbDxUZW1wbGF0ZVJlZjxhbnk+IHwgbnVsbD4gPSBjb21wdXRlZCgoKSA9PiBmaW5kVGVtcGxhdGVCeU5hbWUoWy4uLnRoaXMudGVtcGxhdGVzKCldLCAnY29sdW1uQ3VzdG9tTGFzdCcpKTtcbiAgICBwdWJsaWMgZm9vdGVyVGVtcGxhdGU6IFNpZ25hbDxUZW1wbGF0ZVJlZjxhbnk+IHwgbnVsbD4gPSBjb21wdXRlZCgoKSA9PiBmaW5kVGVtcGxhdGVCeU5hbWUoWy4uLnRoaXMudGVtcGxhdGVzKCldLCAnZm9vdGVyJykpO1xuICAgIHB1YmxpYyByb3dFeHBhbmRUZW1wbGF0ZTogU2lnbmFsPFRlbXBsYXRlUmVmPGFueT4gfCBudWxsPiA9IGNvbXB1dGVkKCgpID0+IGZpbmRUZW1wbGF0ZUJ5TmFtZShbLi4udGhpcy50ZW1wbGF0ZXMoKV0sICdyb3dFeHBhbmRDb250ZW50JykpO1xuXG4gICAgLy8gZGF0YSBwcm92aWRlciBhbmQgaXRlbXNcbiAgICBwdWJsaWMgaXNMYXp5ID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5kYXRhUHJvdmlkZXIoKT8uaXNMYXp5ID09PSB0cnVlKTtcbiAgICBwdWJsaWMgaXNQYWdpbmF0aW9uID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5kYXRhLnBhZ2luYXRpb25Nb2RlKCkgPT09IFRhYmxlUGFnaW5hdGlvbk1vZGVFbnVtLlBhZ2luYXRpb24pO1xuICAgIHB1YmxpYyB1c2VRdWVyeVBhcmFtc0luaXRpYWxpemVkID0gc2lnbmFsKGZhbHNlKTtcblxuICAgIC8vIHZpc3VhbFxuICAgIHB1YmxpYyBjbGFzc05hbWUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIGxldCBjbGFzc05hbWUgPSB0aGlzLm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5jbGFzc05hbWUgPz8gJyc7XG4gICAgICAgIHN3aXRjaCAodGhpcy5tZXRhZGF0YS5kZXNjcmlwdG9yKCkuc2l6ZSkge1xuICAgICAgICAgICAgY2FzZSBUYWJsZVNpemVFbnVtLlNtYWxsOlxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZSArPSAnIHAtZGF0YXRhYmxlLXNtJztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVGFibGVTaXplRW51bS5MYXJnZTpcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUgKz0gJyBwLWRhdGF0YWJsZS1sZyc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubWV0YWRhdGEuZGVzY3JpcHRvcigpLmhhc0dyaWRsaW5lcykge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9ICcgcC1kYXRhdGFibGUtZ3JpZGxpbmVzJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuaXNDYXB0aW9uVmlzaWJsZSgpKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gJyBkYXRhdGFibGUtbm8taGVhZGVyJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2xhc3NOYW1lO1xuICAgIH0pO1xuXG4gICAgLy8gY29sdW1uc1xuICAgIHB1YmxpYyB2aXNpYmxlQ29sdW1ucyA9IGNvbXB1dGVkKCgpID0+IHRoaXMucHJlZnMuY29sdW1uc1dpdGhQcmVmcygpLmZpbHRlcihjb2wgPT4gY29sLmlzVmlzaWJsZSkpO1xuICAgIHB1YmxpYyBhcmVDb2x1bW5zUmVvcmRlcmFibGUgPSBjb21wdXRlZCgoKSA9PiB0aGlzLnByZWZzLmNvbHVtbnNXaXRoUHJlZnMoKS5zb21lKGNvbCA9PiBjb2wuZGVzY3JpcHRvci5pc1Jlb3JkZXJhYmxlKSk7XG4gICAgcHVibGljIGFyZUNvbHVtbnNUb2dnbGVhYmxlID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5wcmVmcy5jb2x1bW5zV2l0aFByZWZzKCkuc29tZShjb2wgPT4gY29sLmRlc2NyaXB0b3IuaXNUb2dnbGVhYmxlKSk7XG5cbiAgICAvLyBmaWx0ZXIsIHNvcnRcbiAgICBwdWJsaWMgaGFzQ29sdW1uRmlsdGVycyA9IGNvbXB1dGVkKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgICAgKHRoaXMubWV0YWRhdGEuZGVmYXVsdEZpbHRlckRpc3BsYXlUeXBlID09PSBGaWx0ZXJEaXNwbGF5VHlwZUVudW0uT3ZlcmxheVdpdGhUYWcgJiZcbiAgICAgICAgICAgICAgICB0aGlzLm1ldGFkYXRhLmZpbHRlckRlc2NyaXB0b3JzKCkuc29tZShkID0+IGQuZGlzcGxheVR5cGUgPT09IEZpbHRlckRpc3BsYXlUeXBlRW51bS5Db2x1bW4pKSB8fFxuICAgICAgICAgICAgKHRoaXMubWV0YWRhdGEuZGVmYXVsdEZpbHRlckRpc3BsYXlUeXBlID09PSBGaWx0ZXJEaXNwbGF5VHlwZUVudW0uQ29sdW1uICYmIHRoaXMubWV0YWRhdGEuZmlsdGVyRGVzY3JpcHRvcnMoKS5zb21lKGQgPT4gZC5kaXNwbGF5VHlwZSA9PSBudWxsKSlcbiAgICApO1xuICAgIHB1YmxpYyBvdmVybGF5V2l0aFRhZ0ZpbHRlcnMgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIC8vIHN0YXRpY2FsbHkgZGVmaW5lZCBmaWx0ZXJzIEFORCBnZW5lcmljIGZpbHRlcnNcbiAgICAgICAgY29uc3QgZmlsdGVycyA9IHRoaXMubWV0YWRhdGFcbiAgICAgICAgICAgIC5maWx0ZXJzKClcbiAgICAgICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgICAgICAgZCA9PlxuICAgICAgICAgICAgICAgICAgICAoZC5kZXNjcmlwdG9yLmRpc3BsYXlUeXBlID09IG51bGwgJiYgdGhpcy5tZXRhZGF0YS5kZWZhdWx0RmlsdGVyRGlzcGxheVR5cGUgPT09IEZpbHRlckRpc3BsYXlUeXBlRW51bS5PdmVybGF5V2l0aFRhZykgfHxcbiAgICAgICAgICAgICAgICAgICAgZC5kZXNjcmlwdG9yLmRpc3BsYXlUeXBlID09PSBGaWx0ZXJEaXNwbGF5VHlwZUVudW0uT3ZlcmxheVdpdGhUYWdcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIGZpbHRlcnMuY29uY2F0KHRoaXMubWV0YWRhdGEuZ2VuZXJpY0ZpbHRlcnMoKSk7XG4gICAgfSk7XG5cbiAgICBwdWJsaWMgYW55Q29sdW1uVmlzaWJsZSA9IGNvbXB1dGVkKCgpID0+IHRoaXMudmlzaWJsZUNvbHVtbnMoKS5sZW5ndGggPiAwKTtcbiAgICBwdWJsaWMgaGFzQ3VzdG9tTGFzdENvbHVtbiA9IGNvbXB1dGVkKCgpID0+IHRoaXMuY29sdW1uQ3VzdG9tTGFzdENvbXBvbmVudCgpIHx8IHRoaXMuY29sdW1uQ3VzdG9tTGFzdFRlbXBsYXRlKCkpO1xuICAgIHB1YmxpYyBoYXNMYXN0Q29sdW1uID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5oYXNDdXN0b21MYXN0Q29sdW1uKCkgfHwgdGhpcy5hcmVDb2x1bW5zVG9nZ2xlYWJsZSgpIHx8IHRoaXMuYXJlQ29sdW1uc1Jlb3JkZXJhYmxlKCkpO1xuXG4gICAgLy8gdGFibGUgbG9hZCBwYXJhbXNcbiAgICBwcml2YXRlIGxhc3RMYXp5TG9hZEV2ZW50PzogVGFibGVMYXp5TG9hZEV2ZW50O1xuICAgIHByaXZhdGUgbGFzdFBhcmFtc1dpdGhEZWZhdWx0cz86IERhdGFMaXN0UGFyYW1zO1xuXG4gICAgLy8gb3RoZXJcbiAgICBwcml2YXRlIGxhc3RRdWVyeVBhcmFtcz86IFBhcmFtcyA9IHRoaXMucm91dGUuc25hcHNob3QucXVlcnlQYXJhbXM7XG4gICAgcHJpdmF0ZSBuYXZpZ2F0aW9uT3V0T2ZUYWJsZUluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICBwcml2YXRlIG5hdmlnYXRpb25JblRhYmxlSW5Qcm9ncmVzcyA9IGZhbHNlO1xuXG4gICAgLy8gc3Vic2NyaXB0aW9ucyBhbmQgcmVmc1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAjZGF0YVByb3ZpZGVyRWFnZXJGaXJzdExvYWQgPSBlZmZlY3RXaXRoRGVwcyhcbiAgICAgICAgW3RoaXMuZGF0YVByb3ZpZGVyXSxcbiAgICAgICAgKFtkYXRhUHJvdmlkZXJdKSA9PiB7XG4gICAgICAgICAgICBpZiAoZGF0YVByb3ZpZGVyPy5pc0xhenkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkVGFibGVXaXRoRGF0YVByb3ZpZGVyKHRoaXMubWV0YWRhdGEuZGVmYXVsdFBhcmFtcygpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAge2ZpcnN0T25seTogdHJ1ZX1cbiAgICApO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAjZGF0YVByb3ZpZGVyUmVsb2FkU3Vic2NyaXB0aW9uID0gdG9PYnNlcnZhYmxlKHRoaXMuZGF0YVByb3ZpZGVyKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcChkcCA9PiBkcD8udGFibGVSZWxvYWQkID8/IG9mKHt9KSksXG4gICAgICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQoKVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgICAgbmV4dDogZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWxvYWQoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAjcm91dGVRdWVyeVBhcmFtc1N1YnNjcmlwdGlvbiA9IHRvT2JzZXJ2YWJsZSh0aGlzLnVzZVF1ZXJ5UGFyYW1zKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCh1c2VRcCA9PiAodXNlUXAgPyB0aGlzLnJvdXRlLnF1ZXJ5UGFyYW1zIDogTkVWRVIpKSxcbiAgICAgICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCgpXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZShxcCA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvYWRUYWJsZUZyb21Sb3V0ZVVwZGF0ZShxcCk7XG4gICAgICAgIH0pO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAjcm91dGVyRXZlbnRzU3Vic2NyaXB0aW9uID0gdG9PYnNlcnZhYmxlKHRoaXMudXNlUXVlcnlQYXJhbXMpXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKHVzZVFwID0+ICh1c2VRcCA/IHRoaXMucm91dGVyLmV2ZW50cyA6IE5FVkVSKSksXG4gICAgICAgICAgICBmaWx0ZXIoXG4gICAgICAgICAgICAgICAgZSA9PlxuICAgICAgICAgICAgICAgICAgICAoZSBpbnN0YW5jZW9mIE5hdmlnYXRpb25TdGFydCAmJiBlLnVybC5zcGxpdCgnPycpWzBdLnNwbGl0KCcjJylbMF0gIT09IHRoaXMucm91dGVyLnVybC5zcGxpdCgnPycpWzBdLnNwbGl0KCcjJylbMF0pIHx8XG4gICAgICAgICAgICAgICAgICAgIGUgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uRW5kIHx8XG4gICAgICAgICAgICAgICAgICAgIGUgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uQ2FuY2VsIHx8XG4gICAgICAgICAgICAgICAgICAgIGUgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uRXJyb3JcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQoKVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoZSA9PiB7XG4gICAgICAgICAgICB0aGlzLm5hdmlnYXRpb25PdXRPZlRhYmxlSW5Qcm9ncmVzcyA9IGUgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uU3RhcnQ7XG4gICAgICAgIH0pO1xuICAgICNhZnRlck5leHRSZW5kZXJSZWYgPSBhZnRlck5leHRSZW5kZXIoKCkgPT4ge1xuICAgICAgICB0aGlzLmlzQ2VsbENsaWNrT2JzZXJ2ZWQuc2V0KHRoaXMuY2VsbENsaWNrU3ViamVjdC5vYnNlcnZlZCk7XG4gICAgfSk7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5tZXRhZGF0YS5zZXRTaWduYWxTb3VyY2VzKHRoaXMuZGVzY3JpcHRvcklucHV0LCB0aGlzLmdsb2JhbEZpbHRlckZpZWxkc0lucHV0KTtcbiAgICAgICAgdGhpcy5kYXRhLnNldERhdGFTb3VyY2VzKHRoaXMuaXRlbXMsIHRoaXMucmVzdWx0LCB0aGlzLmRhdGFQcm92aWRlciwgdGhpcy5sb2FkaW5nSW5wdXQpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWxvYWQoKTogdm9pZDtcbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBVc2Ugd2l0aCBgVGFibGVSZWxvYWRFdmVudGAgb2JqZWN0IHBhcmFtZXRlci5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVsb2FkKGVtaXRFdmVudDogYm9vbGVhbik6IHZvaWQ7XG4gICAgcHVibGljIHJlbG9hZChlbWl0RXZlbnQ/OiBUYWJsZVJlbG9hZEV2ZW50PFNvcnRzLCBGaWx0ZXJzPik6IHZvaWQ7XG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgVXNlIHdpdGggYFRhYmxlUmVsb2FkRXZlbnRgIG9iamVjdCBwYXJhbWV0ZXIuXG4gICAgICovXG4gICAgcHVibGljIHJlbG9hZChlbWl0RXZlbnQ6IGJvb2xlYW4sIHJlc2V0UGFyYW1zOiBib29sZWFuKTogdm9pZDtcbiAgICBwdWJsaWMgcmVsb2FkKGVtaXRFdmVudE9yRXZlbnQ6IGJvb2xlYW4gfCBUYWJsZVJlbG9hZEV2ZW50PFNvcnRzLCBGaWx0ZXJzPiA9IGZhbHNlLCByZXNldFBhcmFtc1BhcmFtID0gZmFsc2UpIHtcbiAgICAgICAgY29uc3QgZW1pdEV2ZW50ID0gdHlwZW9mIGVtaXRFdmVudE9yRXZlbnQgPT09ICdib29sZWFuJyA/IGVtaXRFdmVudE9yRXZlbnQgOiAoZW1pdEV2ZW50T3JFdmVudD8uZW1pdEV2ZW50ID8/IGZhbHNlKTtcbiAgICAgICAgY29uc3QgcmVzZXRQYXJhbXMgPSB0eXBlb2YgZW1pdEV2ZW50T3JFdmVudCA9PT0gJ29iamVjdCcgPyBlbWl0RXZlbnRPckV2ZW50Py5yZXNldFBhcmFtcyA6IHJlc2V0UGFyYW1zUGFyYW07XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9XG4gICAgICAgICAgICB0eXBlb2YgZW1pdEV2ZW50T3JFdmVudCA9PT0gJ29iamVjdCcgJiYgZW1pdEV2ZW50T3JFdmVudD8ucGFyYW1zID8gKGVtaXRFdmVudE9yRXZlbnQ/LnBhcmFtcyBhcyBEYXRhTGlzdFBhcmFtcykgOiByZXNldFBhcmFtcyA/IHVuZGVmaW5lZCA6IHRoaXMubGFzdFBhcmFtc1dpdGhEZWZhdWx0cztcbiAgICAgICAgY29uc3QgcmVsb2FkUGFyYW1zID0gbWVyZ2VEYXRhTGlzdFBhcmFtc1dpdGhEZWZhdWx0cyhwYXJhbXMgPz8ge30sIHRoaXMubWV0YWRhdGEuZGVmYXVsdFBhcmFtcygpKTtcbiAgICAgICAgdGhpcy5sb2FkVGFibGVXaXRoRGF0YVByb3ZpZGVyKHJlbG9hZFBhcmFtcywgZW1pdEV2ZW50KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25UYWJsZUxhenlMb2FkKGV2ZW50OiBUYWJsZUxhenlMb2FkRXZlbnQpIHtcbiAgICAgICAgdGhpcy5sYXN0TGF6eUxvYWRFdmVudCA9IGV2ZW50O1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IGZyb21UYWJsZUxvYWRUb0RhdGFMaXN0UGFyYW1zKGV2ZW50KTtcblxuICAgICAgICBpZiAodGhpcy51c2VRdWVyeVBhcmFtcygpKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMubmF2aWdhdGlvbk91dE9mVGFibGVJblByb2dyZXNzICYmICF0aGlzLm5hdmlnYXRpb25JblRhYmxlSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgY2hlY2sgaXMgbmVjZXNzYXJ5OiBmcm9tIHNvbWUgcmVhc29uLCBwcmltZU5HIGNvbW1pdHMgb25lIGxhc3QgbGF6eSBsb2FkIGV2ZW50IHdoZW5ldmVyIGFueSBhbmd1bGFyIHJvdXRlciBuYXZpZ2F0aW9uIG9jY3Vyc1xuICAgICAgICAgICAgICAgIHRoaXMubmF2aWdhdGlvbkluVGFibGVJblByb2dyZXNzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdQYXJhbXMgPSBkYXRhTGlzdFBhcmFtc1RvVXJsUXVlcnkocGFyYW1zLCB0aGlzLm1ldGFkYXRhLmRlZmF1bHRQYXJhbXMoKSwge3ByZXBlbmRGaWx0ZXJOYW1lOiB0aGlzLmZpbHRlcktleVByZXBlbmR9KTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdQYXJhbXNXaXRoUGFyYW1zVG9SZW1vdmUgPSB7Li4ubmV3UGFyYW1zfTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5sYXN0UXVlcnlQYXJhbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXModGhpcy5sYXN0UXVlcnlQYXJhbXMpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGsgPT4gKGsuc3RhcnRzV2l0aCh0aGlzLmZpbHRlcktleVByZXBlbmQpIHx8IFsnb2Zmc2V0JywgJ2xpbWl0JywgJ3NvcnQnLCAncSddLmluZGV4T2YoaykgPj0gMCkgJiYgbmV3UGFyYW1zW2tdID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZm9yRWFjaChrID0+IChuZXdQYXJhbXNXaXRoUGFyYW1zVG9SZW1vdmVba10gPSBudWxsKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5yb3V0ZXJcbiAgICAgICAgICAgICAgICAgICAgLm5hdmlnYXRlKFtdLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLnJvdXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZVVybDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zOiBuZXdQYXJhbXNXaXRoUGFyYW1zVG9SZW1vdmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBxdWVyeVBhcmFtc0hhbmRsaW5nOiAnbWVyZ2UnXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdmlnYXRpb25JblRhYmxlSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGFzdFF1ZXJ5UGFyYW1zID0gbmV3UGFyYW1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmFtc1dpdGhEZWZhdWx0cyA9IG1lcmdlRGF0YUxpc3RQYXJhbXNXaXRoRGVmYXVsdHMocGFyYW1zLCB0aGlzLm1ldGFkYXRhLmRlZmF1bHRQYXJhbXMoKSk7XG4gICAgICAgICAgICB0aGlzLmRhdGEuc2V0UGFyYW1zKHBhcmFtc1dpdGhEZWZhdWx0cyk7XG4gICAgICAgICAgICB0aGlzLmxvYWRUYWJsZVdpdGhEYXRhUHJvdmlkZXIocGFyYW1zV2l0aERlZmF1bHRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBvblRhYmxlRmlsdGVyKGV2ZW50OiBUYWJsZUZpbHRlckV2ZW50KSB7XG4gICAgICAgIGlmICh0aGlzLnVzZVF1ZXJ5UGFyYW1zKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXJhbXMgPSBmcm9tVGFibGVMb2FkVG9EYXRhTGlzdFBhcmFtcyh7ZmlsdGVyczogZXZlbnQuZmlsdGVyc30pO1xuICAgICAgICBjb25zdCBwYXJhbXNXaXRoRGVmYXVsdHMgPSBtZXJnZURhdGFMaXN0UGFyYW1zV2l0aERlZmF1bHRzKHBhcmFtcywgdGhpcy5tZXRhZGF0YS5kZWZhdWx0UGFyYW1zKCkpO1xuXG4gICAgICAgIC8vIGlmIHRhYmxlIGRvZXNuJ3QgdXNlIGxhenkgbG9hZGluZywgZmlsdGVyIHBhcmFtcyBuZWVkIHRvIGJlIHNldCBoZXJlXG4gICAgICAgIC8vIGJlY2F1c2UgdGhlIG9uVGFibGVMYXp5TG9hZCBldmVudCBpcyBub3QgZW1pdHRlZFxuICAgICAgICBpZiAoIXRoaXMuaXNMYXp5KCkpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YS5zZXRQYXJhbXMocGFyYW1zV2l0aERlZmF1bHRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBvbkNlbGxDbGljayhldmVudDogRXZlbnQsIGNvbDogQ29sdW1uRGVzY3JpcHRvcjxhbnksIEl0ZW0+LCBpdGVtOiBJdGVtLCBpZHg6IG51bWJlcikge1xuICAgICAgICBpZiAoIXRoaXMuaXNDZWxsQ2xpY2tFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0YWJsZUV2ZW50OiBUYWJsZUNlbGxDbGlja0V2ZW50PEl0ZW0+ID0ge1xuICAgICAgICAgICAgY29sdW1uOiBjb2wsXG4gICAgICAgICAgICByb3dJdGVtOiBpdGVtLFxuICAgICAgICAgICAgcm93SW5kZXg6IGlkeCxcbiAgICAgICAgICAgIGV2ZW50OiBldmVudFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNlbGxDbGlja1N1YmplY3QubmV4dCh0YWJsZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25TZWxlY3Rpb25DaGFuZ2UoZXZlbnQ6IEFycmF5PEl0ZW0+KSB7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uQ2hhbmdlLmVtaXQoZXZlbnQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBvblJvd1Jlb3JkZXIoZXZlbnQ6IFRhYmxlUm93UmVvcmRlckV2ZW50KSB7XG4gICAgICAgIHRoaXMucm93UmVvcmRlci5lbWl0KGV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRUYWJsZVdpdGhEYXRhUHJvdmlkZXIocGFyYW1zV2l0aERlZmF1bHRzOiBEYXRhTGlzdFBhcmFtcywgZW1pdEV2ZW50ID0gdHJ1ZSkge1xuICAgICAgICBjb25zdCBpc0ZldGNoZWQgPSB0aGlzLmRhdGEuZmV0Y2hXaXRoRGF0YVByb3ZpZGVyKHBhcmFtc1dpdGhEZWZhdWx0cywgZXJyb3IgPT4ge1xuICAgICAgICAgICAgdGFibGVOb3RpZmljYXRpb25FcnJvcih0aGlzLnRyYW5zbGF0ZSwgdGhpcy5tZXRhZGF0YS5kZXNjcmlwdG9yKCksIGVycm9yLCB0aGlzLm1lc3NhZ2VTZXJ2aWNlKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbW1vbnNFcnJvciA9IGZyb21TdWJzY3JpYmVFcnJvcihlcnJvciwgJ1RhYmxlQ29tcG9uZW50RXJyb3InLCB7XG4gICAgICAgICAgICAgICAgcGFyYW1zOiBwYXJhbXNXaXRoRGVmYXVsdHNcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nKGNvbW1vbnNFcnJvciwgZ2V0RXJyb3JMb2dMZXZlbChjb21tb25zRXJyb3IpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGlzRmV0Y2hlZCkge1xuICAgICAgICAgICAgdGhpcy5sYXN0UGFyYW1zV2l0aERlZmF1bHRzID0gcGFyYW1zV2l0aERlZmF1bHRzO1xuICAgICAgICAgICAgaWYgKGVtaXRFdmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRhYmxlRXZlbnQ6IFRhYmxlTG9hZEV2ZW50ID0ge1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiB0aGlzLmxhc3RMYXp5TG9hZEV2ZW50LFxuICAgICAgICAgICAgICAgICAgICBwYXJhbXM6IHBhcmFtc1dpdGhEZWZhdWx0c1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YWJsZUxvYWQuZW1pdCh0YWJsZUV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbG9hZFRhYmxlRnJvbVJvdXRlVXBkYXRlKHVybFBhcmFtczogUGFyYW1zKSB7XG4gICAgICAgIGNvbnN0IHBhcmFtc1dpdGhEZWZhdWx0cyA9IG1lcmdlRGF0YUxpc3RQYXJhbXNXaXRoRGVmYXVsdHMoXG4gICAgICAgICAgICBmcm9tVXJsUXVlcnlUb0RhdGFMaXN0UGFyYW1zKHVybFBhcmFtcywge1xuICAgICAgICAgICAgICAgIHByZXBlbmRGaWx0ZXJOYW1lOiB0aGlzLmZpbHRlcktleVByZXBlbmQsXG4gICAgICAgICAgICAgICAgc2VhcmNoQXNHbG9iYWw6IHRydWVcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgdGhpcy5tZXRhZGF0YS5kZWZhdWx0UGFyYW1zKClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5kYXRhLnNldFBhcmFtcyhwYXJhbXNXaXRoRGVmYXVsdHMsIHRydWUpO1xuICAgICAgICB0aGlzLmxvYWRUYWJsZVdpdGhEYXRhUHJvdmlkZXIocGFyYW1zV2l0aERlZmF1bHRzKTtcbiAgICB9XG59XG4iLCI8ZGl2PlxuICAgIDwhLS0gTVVTVCBOT1QgdXNlIG9ic2VydmFibGUgZm9yIHZhbHVlIHdoZW4gdXNpbmcgdmlydHVhbCBzY3JvbGwgLSBkb2VzIG5vdCB3b3JrIGZvciBzb21lIHJlYXNvbiAtLT5cbiAgICBAaWYgKGRhdGEuaXNBbGxQYWdpbmF0aW9uTWV0YUluaXRpYWxpemVkKCkpIHtcbiAgICAgICAgPHAtdGFibGVcbiAgICAgICAgICAgIFt2YWx1ZV09XCJkYXRhLmRhdGEoKVwiXG4gICAgICAgICAgICBbZGF0YUtleV09XCJtZXRhZGF0YS5kZXNjcmlwdG9yKCkudHJhY2tQcm9wZXJ0eVwiXG4gICAgICAgICAgICBbbGF6eV09XCJpc0xhenkoKVwiXG4gICAgICAgICAgICBbbG9hZGluZ109XCJkYXRhLmxvYWRpbmcoKVwiXG4gICAgICAgICAgICBbcGFnaW5hdG9yXT1cImlzUGFnaW5hdGlvbigpXCJcbiAgICAgICAgICAgIFtyb3dzXT1cImRhdGEucm93cygpXCJcbiAgICAgICAgICAgIFtmaXJzdF09XCJkYXRhLm9mZnNldCgpXCJcbiAgICAgICAgICAgIFt0b3RhbFJlY29yZHNdPVwiZGF0YS5jb3VudCgpXCJcbiAgICAgICAgICAgIFtyb3dzUGVyUGFnZU9wdGlvbnNdPVwibWV0YWRhdGEucm93c1BlclBhZ2VPcHRpb25zKClcIlxuICAgICAgICAgICAgW3Nob3dDdXJyZW50UGFnZVJlcG9ydF09XCJ0cnVlXCJcbiAgICAgICAgICAgIFtjdXJyZW50UGFnZVJlcG9ydFRlbXBsYXRlXT1cIidtbmdUYWJsZS5wYWdpbmF0aW9uTXNnJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICBbbXVsdGlTb3J0TWV0YV09XCJkYXRhLnNvcnRNZXRhKClcIlxuICAgICAgICAgICAgW2ZpbHRlcnNdPVwiZGF0YS5maWx0ZXJNZXRhKClcIlxuICAgICAgICAgICAgW2dsb2JhbEZpbHRlckZpZWxkc109XCJtZXRhZGF0YS5zZWFyY2hGaWVsZHMoKVwiXG4gICAgICAgICAgICBzb3J0TW9kZT1cIm11bHRpcGxlXCJcbiAgICAgICAgICAgIFtzZWxlY3Rpb25dPVwiW11cIlxuICAgICAgICAgICAgKHNlbGVjdGlvbkNoYW5nZSk9XCJvblNlbGVjdGlvbkNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgIFtzZWxlY3Rpb25Nb2RlXT1cInNlbGVjdGlvbkVuYWJsZWQoKSA/IHNlbGVjdGlvbk1vZGUoKSA6IG51bGxcIlxuICAgICAgICAgICAgW3Njcm9sbGFibGVdPVwidHJ1ZVwiXG4gICAgICAgICAgICBzY3JvbGxIZWlnaHQ9XCJmbGV4XCJcbiAgICAgICAgICAgIFtyb3dIb3Zlcl09XCJtZXRhZGF0YS5kZXNjcmlwdG9yKCkuaGFzSG92ZXJcIlxuICAgICAgICAgICAgW3N0eWxlQ2xhc3NdPVwiY2xhc3NOYW1lKClcIlxuICAgICAgICAgICAgW3Jlc2l6YWJsZUNvbHVtbnNdPVwibWV0YWRhdGEuZGVzY3JpcHRvcigpLmhhc1Jlc2l6YWJsZUNvbHVtbnNcIlxuICAgICAgICAgICAgW2NvbHVtblJlc2l6ZU1vZGVdPVwibWV0YWRhdGEuZGVzY3JpcHRvcigpLmNvbHVtblJlc2l6ZU1vZGUgPz8gJ2V4cGFuZCdcIlxuICAgICAgICAgICAgW3Jlb3JkZXJhYmxlQ29sdW1uc109XCJhcmVDb2x1bW5zUmVvcmRlcmFibGUoKVwiXG4gICAgICAgICAgICBwYWdpbmF0b3JEcm9wZG93bkFwcGVuZFRvPVwiYm9keVwiXG4gICAgICAgICAgICBbY29sdW1uc109XCJ2aXNpYmxlQ29sdW1ucygpXCJcbiAgICAgICAgICAgIFtleHBhbmRlZFJvd0tleXNdPVwiZXhwYW5kZWRSb3dLZXlzKClcIlxuICAgICAgICAgICAgKG9uQ29sUmVzaXplKT1cInByZWZzLm9uQ29sdW1uUmVzaXplKCRldmVudClcIlxuICAgICAgICAgICAgKG9uQ29sUmVvcmRlcik9XCJwcmVmcy5vbkNvbHVtblJlb3JkZXIoJGV2ZW50KVwiXG4gICAgICAgICAgICAob25MYXp5TG9hZCk9XCJvblRhYmxlTGF6eUxvYWQoJGV2ZW50KVwiXG4gICAgICAgICAgICAob25GaWx0ZXIpPVwib25UYWJsZUZpbHRlcigkZXZlbnQpXCJcbiAgICAgICAgICAgIChvblJvd1Jlb3JkZXIpPVwib25Sb3dSZW9yZGVyKCRldmVudClcIj5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJjYXB0aW9uXCI+XG4gICAgICAgICAgICAgICAgQGlmIChpc0NhcHRpb25WaXNpYmxlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRhYmxlLWhlYWRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChvdmVybGF5V2l0aFRhZ0ZpbHRlcnMoKS5sZW5ndGggPiAwIHx8IG1ldGFkYXRhLmRlc2NyaXB0b3IoKS5zZWFyY2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bW5nLXRhYmxlLWZpbHRlci1vdmVybGF5LXdpdGgtdGFnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0aXRsZV09XCJtZXRhZGF0YS5kZXNjcmlwdG9yKCkudGl0bGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWV0YWRhdGFdPVwib3ZlcmxheVdpdGhUYWdGaWx0ZXJzKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZ2VuZXJpY0ZpbHRlckRlc2NyaXB0b3JdPVwibWV0YWRhdGEuZ2VuZXJpY0ZpbHRlckRlc2NyaXB0b3IoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttb2RlbF09XCJtZXRhZGF0YS5kZXNjcmlwdG9yKCkubW9kZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZW5hYmxlU2VhcmNoXT1cIm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5zZWFyY2hcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2VhcmNoXT1cImRhdGEuc2VhcmNoTWV0YSgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3NlYXJjaExpbWl0V29yZE1heF09XCJtZXRhZGF0YS5kZXNjcmlwdG9yKCkuc2VhcmNoTGltaXRNYXhXb3Jkc1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtlbmFibGVDYXNlU2Vuc2l0aXZlXT1cImlzTGF6eSgpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoaGFzVGl0bGVEaXNwbGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBtbmdUZW1wbGF0ZT1cInRpdGxlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImNhcHRpb25UZW1wbGF0ZU9yQ29tcG9uZW50T3JUaXRsZVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbW5nLXRhYmxlLWZpbHRlci1vdmVybGF5LXdpdGgtdGFnPlxuICAgICAgICAgICAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImNhcHRpb25UZW1wbGF0ZU9yQ29tcG9uZW50T3JUaXRsZVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNjYXB0aW9uVGVtcGxhdGVPckNvbXBvbmVudE9yVGl0bGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChjYXB0aW9uVGVtcGxhdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY2FwdGlvblRlbXBsYXRlKClcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIGlmIChjYXB0aW9uQ29tcG9uZW50KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBbbW5nQ29tcG9uZW50XT1cImNhcHRpb25Db21wb25lbnQoKVwiIChpbnN0YW5jZUNyZWF0ZWQpPVwiY2FwdGlvbkNvbXBvbmVudEluc3RhbmNlLmVtaXQoJGV2ZW50KVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gQGVsc2UgaWYgKG1ldGFkYXRhLmRlc2NyaXB0b3IoKS50aXRsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aDUgY2xhc3M9XCJwLTAgbS0wXCI+e3sgbWV0YWRhdGEuZGVzY3JpcHRvcigpLnRpdGxlISB8IHRyYW5zbGF0ZSB9fTwvaDU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJoZWFkZXJcIj5cbiAgICAgICAgICAgICAgICBAaWYgKCFtZXRhZGF0YS5kZXNjcmlwdG9yKCkuaGlkZUhlYWRlcikge1xuICAgICAgICAgICAgICAgICAgICA8dHIgY2xhc3M9XCJtbmctdGFibGUtaGVhZGVyXCIgW2NsYXNzXT1cIm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5oZWFkZXJDbGFzc05hbWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoc2VsZWN0aW9uRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChzZWxlY3Rpb25Nb2RlKCkgPT09ICdtdWx0aXBsZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoIHN0eWxlPVwibWluLXdpZHRoOiAzNnB4XCIgcEZyb3plbkNvbHVtbiBbZnJvemVuXT1cIm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5zZWxlY3Rpb25Db2x1bW5Gcm96ZW4gPz8gdHJ1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtdGFibGVIZWFkZXJDaGVja2JveD48L3AtdGFibGVIZWFkZXJDaGVja2JveD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBXZSBuZWVkIHRoZSBsaW5lIGJlbG93LCBiZWNhdXNlIG90aGVyd2lzZSBwLXRhYmxlUmFkaW9CdXR0b24gc2hpZnRzIHRoZSByZXN0IG9mIHRoZSBjb2x1bW5zIGluIHRhYmxlIC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc3R5bGU9XCJtaW4td2lkdGg6IDM2cHhcIiBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwibWV0YWRhdGEuZGVzY3JpcHRvcigpLnNlbGVjdGlvbkNvbHVtbkZyb3plbiA/PyB0cnVlXCI+PC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKG1ldGFkYXRhLmRlc2NyaXB0b3IoKS5yb3dFeHBhbmRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoIHNjb3BlPVwiY29sXCIgcEZyb3plbkNvbHVtbiBbZnJvemVuXT1cInRydWVcIj48L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChyb3dSZW9yZGVyRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoIHNjb3BlPVwiY29sXCI+PC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEBmb3IgKGNvbCBvZiB2aXNpYmxlQ29sdW1ucygpOyB0cmFjayBjb2wuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI3NvcnRhYmxlQ29sdW1uVEhUZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBjb2wuZGVzY3JpcHRvci50aXRsZSA/PyAoY29sLmRlc2NyaXB0b3IucHJvcGVydHkgfCBtbmdJMThuUHJvcGVydHk6IG1ldGFkYXRhLmRlc2NyaXB0b3IoKS5tb2RlbCkgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwLXNvcnRJY29uIFtmaWVsZF09XCJjb2wuZGVzY3JpcHRvci5wcm9wZXJ0eVwiPjwvcC1zb3J0SWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI25vblNvcnRhYmxlQ29sdW1uVEhUZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgY29sLmRlc2NyaXB0b3IudGl0bGUgPz8gKGNvbC5kZXNjcmlwdG9yLnByb3BlcnR5IHwgbW5nSTE4blByb3BlcnR5OiBtZXRhZGF0YS5kZXNjcmlwdG9yKCkubW9kZWwpIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGNvbC5kZXNjcmlwdG9yLmlzUmVvcmRlcmFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwUmVzaXphYmxlQ29sdW1uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwUmVvcmRlcmFibGVDb2x1bW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpZF09XCJjb2wuZGVzY3JpcHRvci5wcm9wZXJ0eVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcFNvcnRhYmxlQ29sdW1uXT1cImNvbC5zb3J0Py5wcm9wZXJ0eVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcFNvcnRhYmxlQ29sdW1uRGlzYWJsZWRdPVwiIWNvbC5zb3J0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aF09XCJjb2wud2lkdGggPyBjb2wud2lkdGggKyAncHgnIDogY29sLmRlc2NyaXB0b3Iud2lkdGggKyAnJSdcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLm1pbi13aWR0aC5weF09XCJjb2wud2lkdGggPyBudWxsIDogY29sLmRlc2NyaXB0b3IubWluV2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLm1heC13aWR0aC5weF09XCJjb2wud2lkdGggPz8gY29sLmRlc2NyaXB0b3IubWF4V2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzXT1cImNvbC5kZXNjcmlwdG9yLmhlYWRlckNsYXNzTmFtZSB8IG1uZ1RhYmxlQ29sdW1uRmlsdGVyQ2xhc3M6IGNvbC5maWx0ZXI/LmRlc2NyaXB0b3IgOiBoYXNDb2x1bW5GaWx0ZXJzKCkgJiYgIWNvbC53aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImNvbC5zb3J0ID8gc29ydGFibGVDb2x1bW5USFRlbXBsYXRlIDogbm9uU29ydGFibGVDb2x1bW5USFRlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcFJlc2l6YWJsZUNvbHVtblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cImNvbC5kZXNjcmlwdG9yLnByb3BlcnR5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtwU29ydGFibGVDb2x1bW5dPVwiY29sLnNvcnQ/LnByb3BlcnR5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtwU29ydGFibGVDb2x1bW5EaXNhYmxlZF09XCIhY29sLnNvcnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLndpZHRoXT1cImNvbC53aWR0aCA/IGNvbC53aWR0aCArICdweCcgOiBjb2wuZGVzY3JpcHRvci53aWR0aCArICclJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUubWluLXdpZHRoLnB4XT1cImNvbC53aWR0aCA/IG51bGwgOiBjb2wuZGVzY3JpcHRvci5taW5XaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUubWF4LXdpZHRoLnB4XT1cImNvbC53aWR0aCA/PyBjb2wuZGVzY3JpcHRvci5tYXhXaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3NdPVwiY29sLmRlc2NyaXB0b3IuaGVhZGVyQ2xhc3NOYW1lIHwgbW5nVGFibGVDb2x1bW5GaWx0ZXJDbGFzczogY29sLmZpbHRlcj8uZGVzY3JpcHRvciA6IGhhc0NvbHVtbkZpbHRlcnMoKSAmJiAhY29sLndpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY29sLnNvcnQgPyBzb3J0YWJsZUNvbHVtblRIVGVtcGxhdGUgOiBub25Tb3J0YWJsZUNvbHVtblRIVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGhhc0xhc3RDb2x1bW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUubWluLXdpZHRoLnB4XT1cImNvbHVtbkxhc3RNaW5XaWR0aCgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEZyb3plbkNvbHVtblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZnJvemVuXT1cIm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5hY3Rpb25Db2x1bW5Gcm96ZW4gPz8gYXJlQ29sdW1uc1RvZ2dsZWFibGUoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsaWduRnJvemVuPVwicmlnaHRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNvbHVtbi1jdXN0b20tbGFzdCB0ZXh0LXJpZ2h0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoYXJlQ29sdW1uc1RvZ2dsZWFibGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtbXVsdGlTZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjY29sdW1uVG9nZ2xlTXVsdGlzZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZUNsYXNzPVwicC1idXR0b24tcHJpbWFyeSBtbmctdGFibGUtY29sdW1ucy1tdWx0aXNlbGVjdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwZW5kVG89XCJib2R5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhS2V5PVwiaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2x0aXBQb3NpdGlvbj1cImxlZnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wZG93bkljb249XCJwaSBwaS1zbGlkZXJzLWhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmaWx0ZXJdPVwiZmFsc2VcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtvcHRpb25zXT1cInByZWZzLmNvbHVtbnNXaXRoUHJlZnMoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwidmlzaWJsZUNvbHVtbnMoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BUb29sdGlwXT1cIidtbmdUYWJsZS5hZGp1c3RUYWJsZScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNwbGF5U2VsZWN0ZWRMYWJlbF09XCJmYWxzZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG9uQ2hhbmdlKT1cInByZWZzLm9uQ29sdW1uVG9nZ2xlKCRldmVudClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiZmlsdGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwLWNoZWNrYm94IHAtY29tcG9uZW50IG1sLTFcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwLWhpZGRlbi1hY2Nlc3NpYmxlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRvbmx5PVwicmVhZG9ubHlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2hlY2tlZF09XCJjb2x1bW5Ub2dnbGVNdWx0aXNlbGVjdC5hbGxTZWxlY3RlZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChmb2N1cyk9XCJjb2x1bW5Ub2dnbGVNdWx0aXNlbGVjdC5vbkhlYWRlckNoZWNrYm94Rm9jdXMoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChibHVyKT1cImNvbHVtblRvZ2dsZU11bHRpc2VsZWN0Lm9uSGVhZGVyQ2hlY2tib3hCbHVyKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bi5zcGFjZSk9XCJjb2x1bW5Ub2dnbGVNdWx0aXNlbGVjdC5vblRvZ2dsZUFsbCgkZXZlbnQpXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwicC1jaGVja2JveC1ib3hcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvbGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1jaGVja2VkXT1cImNvbHVtblRvZ2dsZU11bHRpc2VsZWN0LmFsbFNlbGVjdGVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdwLWhpZ2hsaWdodCc6IGFueUNvbHVtblZpc2libGUoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJwcmVmcy5vbkNvbHVtblRvZ2dsZUFsbCgpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJwLWNoZWNrYm94LWljb25cIiBbbmdDbGFzc109XCJ7J3BpIHBpLWNoZWNrJzogYW55Q29sdW1uVmlzaWJsZSgpfVwiPjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtYnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpY29uPVwicGkgcGktcmVwbGF5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQ2xhc3M9XCJwLWJ1dHRvbi1zZWNvbmRhcnlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BUb29sdGlwXT1cIidtbmdUYWJsZS5yZXNldExheW91dCcgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwibGVmdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwicHJlZnMuY2xlYXJMYXlvdXRQcmVmZXJlbmNlcygpXCI+PC9wLWJ1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBsZXQtaXRlbSBwVGVtcGxhdGU9XCJpdGVtXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0uZGVzY3JpcHRvci50aXRsZSA/PyAoaXRlbS5kZXNjcmlwdG9yLnByb3BlcnR5IHwgbW5nSTE4blByb3BlcnR5OiBtZXRhZGF0YS5kZXNjcmlwdG9yKCkubW9kZWwpIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvcC1tdWx0aVNlbGVjdD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIEBpZiAoaGFzQ29sdW1uRmlsdGVycygpKSB7XG4gICAgICAgICAgICAgICAgICAgIDx0ciBjbGFzcz1cIm1uZy1jb2x1bW4tZmlsdGVyLXJvd1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBXZSBuZWVkIHRoZSBsaW5lIGJlbG93LCBiZWNhdXNlIG90aGVyd2lzZSBwLXRhYmxlUmFkaW9CdXR0b24gc2hpZnRzIHRoZSByZXN0IG9mIHRoZSBjb2x1bW5zIGluIHRhYmxlIC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChzZWxlY3Rpb25FbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc3R5bGU9XCJtaW4td2lkdGg6IDM2cHhcIiBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwibWV0YWRhdGEuZGVzY3JpcHRvcigpLnNlbGVjdGlvbkNvbHVtbkZyb3plbiA/PyB0cnVlXCI+PC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAocm93UmVvcmRlckVuYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBzY29wZT1cImNvbFwiPjwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKG1ldGFkYXRhLmRlc2NyaXB0b3IoKS5yb3dFeHBhbmRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRoIHNjb3BlPVwiY29sXCI+PC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEBmb3IgKGNvbCBvZiB2aXNpYmxlQ29sdW1ucygpOyB0cmFjayBjb2wuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzXT1cImNvbC5maWx0ZXI/LmRlc2NyaXB0b3I/LmNvbHVtbkNsYXNzTmFtZSB8IG1uZ1RhYmxlQ29sdW1uRmlsdGVyQ2xhc3M6IGNvbC5maWx0ZXI/LmRlc2NyaXB0b3IgOiBoYXNDb2x1bW5GaWx0ZXJzKCkgJiYgIWNvbC53aWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aC5weF09XCJjb2wud2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUud2lkdGguJV09XCJjb2wud2lkdGggPyBudWxsIDogKGNvbC5maWx0ZXI/LmRlc2NyaXB0b3I/LmNvbHVtbldpZHRoID8/IGNvbC5kZXNjcmlwdG9yLndpZHRoID8/IG51bGwpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLm1pbi13aWR0aC5weF09XCJjb2wud2lkdGggPyBudWxsIDogKGNvbC5maWx0ZXI/LmRlc2NyaXB0b3I/LmNvbHVtbk1pbldpZHRoID8/IGNvbC5kZXNjcmlwdG9yLm1pbldpZHRoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5tYXgtd2lkdGgucHhdPVwiY29sLndpZHRoID8/IGNvbC5kZXNjcmlwdG9yLm1heFdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoY29sLmZpbHRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1uZy10YWJsZS1jb2x1bW4tZmlsdGVyIFttZXRhZGF0YV09XCJjb2wuZmlsdGVyXCI+PC9tbmctdGFibGUtY29sdW1uLWZpbHRlcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGhhc0xhc3RDb2x1bW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImNvbHVtbi1jdXN0b20tbGFzdFwiIFtzdHlsZS5taW4td2lkdGgucHhdPVwiY29sdW1uTGFzdE1pbldpZHRoKClcIj48L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiYm9keVwiIGxldC1pdGVtIGxldC1pZHg9XCJyb3dJbmRleFwiIGxldC1leHBhbmRlZD1cImV4cGFuZGVkXCI+XG4gICAgICAgICAgICAgICAgPHRyXG4gICAgICAgICAgICAgICAgICAgIFtwUmVvcmRlcmFibGVSb3ddPVwiaWR4XCJcbiAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YS5kZXNjcmlwdG9yKCkucm93Q2xhc3NOYW1lIHwgbW5nQ2xhc3NNYXA6IG1ldGFkYXRhLmRlc2NyaXB0b3IoKS5yb3dDbGFzc05hbWVNYXBGbiA6IGl0ZW0gfCBtbmdMb2NhbGVEZWZhdWx0Um93Q2xhc3M6IG1ldGFkYXRhLmRlc2NyaXB0b3IoKSA6IGl0ZW1cbiAgICAgICAgICAgICAgICAgICAgXCI+XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoc2VsZWN0aW9uRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKHNlbGVjdGlvbk1vZGUoKSA9PT0gJ211bHRpcGxlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBzdHlsZT1cIm1pbi13aWR0aDogMzZweFwiIHBGcm96ZW5Db2x1bW4gW2Zyb3plbl09XCJtZXRhZGF0YS5kZXNjcmlwdG9yKCkuc2VsZWN0aW9uQ29sdW1uRnJvemVuID8/IHRydWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtdGFibGVDaGVja2JveCBbdmFsdWVdPVwiaXRlbVwiPjwvcC10YWJsZUNoZWNrYm94PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQgc3R5bGU9XCJtaW4td2lkdGg6IDM2cHhcIiBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwibWV0YWRhdGEuZGVzY3JpcHRvcigpLnNlbGVjdGlvbkNvbHVtbkZyb3plbiA/PyB0cnVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwLXRhYmxlUmFkaW9CdXR0b24gW3ZhbHVlXT1cIml0ZW1cIj48L3AtdGFibGVSYWRpb0J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBpZiAobWV0YWRhdGEuZGVzY3JpcHRvcigpLnJvd0V4cGFuZGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKCFtZXRhZGF0YS5kZXNjcmlwdG9yKCkucm93RXhwYW5kYWJsZVByb3BlcnR5IHx8IGl0ZW1bbWV0YWRhdGEuZGVzY3JpcHRvcigpLnJvd0V4cGFuZGFibGVQcm9wZXJ0eSFdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BSb3dUb2dnbGVyXT1cIml0ZW1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJwLWJ1dHRvbi10ZXh0IHAtYnV0dG9uLXJvdW5kZWQgcC1idXR0b24tcGxhaW4gbW5nLXRhYmxlLXJvdy1leHBhbmQtYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpY29uXT1cImV4cGFuZGVkID8gJ3BpIHBpLWNoZXZyb24tZG93bicgOiAncGkgcGktY2hldnJvbi1yaWdodCdcIj48L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBpZiAocm93UmVvcmRlckVuYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwicGkgcGktYmFyc1wiIHBSZW9yZGVyYWJsZVJvd0hhbmRsZT48L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBmb3IgKGNvbCBvZiB2aXNpYmxlQ29sdW1ucygpOyB0cmFjayBjb2wuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkNlbGxDbGljaygkZXZlbnQsIGNvbC5kZXNjcmlwdG9yLCBpdGVtLCBpZHgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3NdPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbC5kZXNjcmlwdG9yLmNsYXNzTmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBtbmdDbGFzc01hcDogY29sLmRlc2NyaXB0b3IuY2xhc3NOYW1lTWFwRm4gOiBpdGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IG1uZ1RhYmxlQ29sdW1uRmlsdGVyQ2xhc3M6IGNvbC5maWx0ZXI/LmRlc2NyaXB0b3IgOiBoYXNDb2x1bW5GaWx0ZXJzKCkgJiYgIWNvbC53aWR0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzLmNsaWNrYWJsZV09XCJpc0NlbGxDbGlja0VuYWJsZWQoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLndpZHRoXT1cImNvbC53aWR0aCA/IGNvbC53aWR0aCArICdweCcgOiBjb2wuZGVzY3JpcHRvci53aWR0aCArICclJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLm1pbi13aWR0aC5weF09XCJjb2wud2lkdGggPyBudWxsIDogY29sLmRlc2NyaXB0b3IubWluV2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5tYXgtd2lkdGgucHhdPVwiY29sLndpZHRoID8/IGNvbC5kZXNjcmlwdG9yLm1heFdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJwLWNvbHVtbi10aXRsZVwiPnt7IGNvbC5kZXNjcmlwdG9yLnRpdGxlID8/IChjb2wuZGVzY3JpcHRvci5wcm9wZXJ0eSB8IG1uZ0kxOG5Qcm9wZXJ0eTogbWV0YWRhdGEuZGVzY3JpcHRvcigpLm1vZGVsKSB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bW5nLXRhYmxlLWNvbHVtbi12YWx1ZSBbZGVzY3JpcHRvcl09XCJjb2wuZGVzY3JpcHRvclwiIFtpdGVtXT1cIml0ZW1cIj48L21uZy10YWJsZS1jb2x1bW4tdmFsdWU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoaGFzTGFzdENvbHVtbigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNvbHVtbi1jdXN0b20tbGFzdCBqdXN0aWZ5LWNvbnRlbnQtZW5kIHRleHQtcmlnaHRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5taW4td2lkdGgucHhdPVwiY29sdW1uTGFzdE1pbldpZHRoKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBGcm96ZW5Db2x1bW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZnJvemVuXT1cIm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5hY3Rpb25Db2x1bW5Gcm96ZW4gPz8gdHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpZ25Gcm96ZW49XCJyaWdodFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoY29sdW1uQ3VzdG9tTGFzdFRlbXBsYXRlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImNvbHVtbkN1c3RvbUxhc3RUZW1wbGF0ZSgpOyBjb250ZXh0OiB7cm93SXRlbTogaXRlbSwgcm93SW5kZXg6IGlkeH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIGlmIChjb2x1bW5DdXN0b21MYXN0Q29tcG9uZW50KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBbbW5nQ29tcG9uZW50XT1cImNvbHVtbkN1c3RvbUxhc3RDb21wb25lbnQoKVwiIChpbnN0YW5jZUNyZWF0ZWQpPVwiY29sdW1uQ3VzdG9tTGFzdENvbXBvbmVudEluc3RhbmNlLmVtaXQoJGV2ZW50KVwiPjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJyb3dleHBhbnNpb25cIiBsZXQtaXRlbT5cbiAgICAgICAgICAgICAgICBAaWYgKG1ldGFkYXRhLmRlc2NyaXB0b3IoKS5yb3dFeHBhbmRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkIFtjb2xTcGFuXT1cIm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5yb3dFeHBhbmRhYmxlQ29sU3BhblwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAobWV0YWRhdGEuZGVzY3JpcHRvcigpLnJvd0V4cGFuZGFibGVDb21wb25lbnRUeXBlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBbbW5nQ29tcG9uZW50XT1cIm1ldGFkYXRhLmRlc2NyaXB0b3IoKS5yb3dFeHBhbmRhYmxlQ29tcG9uZW50VHlwZVwiIFtpbnB1dHNdPVwie2l0ZW19XCI+IDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwicm93RXhwYW5kVGVtcGxhdGUoKTsgY29udGV4dDoge3Jvd0l0ZW06IGl0ZW19XCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cImxvYWRpbmdpY29uXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC1jb2x1bW4gYWxpZ24taXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgIEBpZiAobWV0YWRhdGEuZGVzY3JpcHRvcigpLmxvYWRpbmdJY29uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8aSBbY2xhc3NdPVwiJ3RleHQtd2hpdGUgdGV4dC00eGwgcGktc3BpbiAnICsgbWV0YWRhdGEuZGVzY3JpcHRvcigpLmxvYWRpbmdJY29uXCI+PC9pPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBpZiAobWV0YWRhdGEuZGVzY3JpcHRvcigpLmxvYWRpbmdUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dCB0ZXh0LXdoaXRlIHRleHQtbGcgZm9udC1zZW1pYm9sZFwiIFtuZ0NsYXNzXT1cInsnbXQtMyc6IG1ldGFkYXRhLmRlc2NyaXB0b3IoKS5sb2FkaW5nSWNvbn1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBtZXRhZGF0YS5kZXNjcmlwdG9yKCkubG9hZGluZ1RleHQgPz8gJycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cImxvYWRpbmdib2R5XCI+XG4gICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICA8dGQgW2F0dHIuY29sc3Bhbl09XCJjb2x1bW5zQ29sc3BhbigpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibG9hZGluZy10ZXh0XCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8cC1za2VsZXRvbiBbbmdTdHlsZV09XCJ7d2lkdGg6ICcxMDAlJ31cIj48L3Atc2tlbGV0b24+XG4gICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiZW1wdHltZXNzYWdlXCI+XG4gICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICA8dGQgW2F0dHIuY29sc3Bhbl09XCJjb2x1bW5zQ29sc3BhbigpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyAnbW5nVGFibGUubm9JdGVtcycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgIEBpZiAoZm9vdGVyVGVtcGxhdGUoKSkge1xuICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJzdW1tYXJ5XCI+XG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJmb290ZXJUZW1wbGF0ZSgpOyBjb250ZXh0OiB7ZGF0YTogZGF0YS5kYXRhKCksIHRvdGFsQ291bnQ6IGRhdGEuY291bnQoKX1cIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgfVxuICAgICAgICA8L3AtdGFibGU+XG4gICAgfVxuPC9kaXY+XG4iXX0=