@decaf-ts/for-angular 0.0.25 → 0.0.26

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 (78) hide show
  1. package/fesm2022/decaf-ts-for-angular.mjs +1465 -1488
  2. package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
  3. package/index.d.ts +7470 -3
  4. package/package.json +14 -17
  5. package/components/component-renderer/component-renderer.component.d.ts +0 -278
  6. package/components/crud-field/crud-field.component.d.ts +0 -611
  7. package/components/crud-form/constants.d.ts +0 -5
  8. package/components/crud-form/crud-form.component.d.ts +0 -288
  9. package/components/crud-form/types.d.ts +0 -17
  10. package/components/empty-state/empty-state.component.d.ts +0 -300
  11. package/components/fieldset/fieldset.component.d.ts +0 -555
  12. package/components/filter/filter.component.d.ts +0 -514
  13. package/components/for-angular-components.module.d.ts +0 -20
  14. package/components/index.d.ts +0 -16
  15. package/components/layout/layout.component.d.ts +0 -110
  16. package/components/list/list.component.d.ts +0 -848
  17. package/components/list-item/list-item.component.d.ts +0 -390
  18. package/components/model-renderer/model-renderer.component.d.ts +0 -97
  19. package/components/pagination/constants.d.ts +0 -7
  20. package/components/pagination/pagination.component.d.ts +0 -264
  21. package/components/searchbar/searchbar.component.d.ts +0 -407
  22. package/components/stepped-form/stepped-form.component.d.ts +0 -255
  23. package/directives/collapsable.directive.d.ts +0 -9
  24. package/directives/index.d.ts +0 -1
  25. package/engine/DynamicModule.d.ts +0 -17
  26. package/engine/NgxBaseComponent.d.ts +0 -541
  27. package/engine/NgxCrudFormField.d.ts +0 -123
  28. package/engine/NgxFormService.d.ts +0 -601
  29. package/engine/NgxRenderingEngine.d.ts +0 -282
  30. package/engine/ValidatorFactory.d.ts +0 -15
  31. package/engine/constants.d.ts +0 -168
  32. package/engine/decorators.d.ts +0 -25
  33. package/engine/index.d.ts +0 -18
  34. package/engine/interfaces.d.ts +0 -271
  35. package/engine/types.d.ts +0 -200
  36. package/esm2022/components/component-renderer/component-renderer.component.mjs +0 -321
  37. package/esm2022/components/crud-field/crud-field.component.mjs +0 -518
  38. package/esm2022/components/crud-form/constants.mjs +0 -14
  39. package/esm2022/components/crud-form/crud-form.component.mjs +0 -259
  40. package/esm2022/components/crud-form/types.mjs +0 -2
  41. package/esm2022/components/empty-state/empty-state.component.mjs +0 -345
  42. package/esm2022/components/fieldset/fieldset.component.mjs +0 -677
  43. package/esm2022/components/filter/filter.component.mjs +0 -700
  44. package/esm2022/components/for-angular-components.module.mjs +0 -84
  45. package/esm2022/components/index.mjs +0 -20
  46. package/esm2022/components/layout/layout.component.mjs +0 -150
  47. package/esm2022/components/list/list.component.mjs +0 -1238
  48. package/esm2022/components/list-item/list-item.component.mjs +0 -405
  49. package/esm2022/components/model-renderer/model-renderer.component.mjs +0 -144
  50. package/esm2022/components/pagination/constants.mjs +0 -2
  51. package/esm2022/components/pagination/pagination.component.mjs +0 -321
  52. package/esm2022/components/searchbar/searchbar.component.mjs +0 -491
  53. package/esm2022/components/stepped-form/stepped-form.component.mjs +0 -306
  54. package/esm2022/decaf-ts-for-angular.mjs +0 -5
  55. package/esm2022/directives/collapsable.directive.mjs +0 -29
  56. package/esm2022/directives/index.mjs +0 -2
  57. package/esm2022/engine/DynamicModule.mjs +0 -18
  58. package/esm2022/engine/NgxBaseComponent.mjs +0 -541
  59. package/esm2022/engine/NgxCrudFormField.mjs +0 -137
  60. package/esm2022/engine/NgxFormService.mjs +0 -917
  61. package/esm2022/engine/NgxRenderingEngine.mjs +0 -376
  62. package/esm2022/engine/ValidatorFactory.mjs +0 -106
  63. package/esm2022/engine/constants.mjs +0 -170
  64. package/esm2022/engine/decorators.mjs +0 -38
  65. package/esm2022/engine/index.mjs +0 -19
  66. package/esm2022/engine/interfaces.mjs +0 -4
  67. package/esm2022/engine/types.mjs +0 -2
  68. package/esm2022/for-angular-common.module.mjs +0 -84
  69. package/esm2022/helpers/index.mjs +0 -13
  70. package/esm2022/helpers/utils.mjs +0 -436
  71. package/esm2022/i18n/Loader.mjs +0 -86
  72. package/esm2022/i18n/data/en.json +0 -85
  73. package/esm2022/public-apis.mjs +0 -15
  74. package/for-angular-common.module.d.ts +0 -50
  75. package/helpers/index.d.ts +0 -12
  76. package/helpers/utils.d.ts +0 -279
  77. package/i18n/Loader.d.ts +0 -43
  78. package/public-apis.d.ts +0 -14
@@ -1,518 +0,0 @@
1
- import { __decorate } from "tslib";
2
- import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, HostListener, Input, ViewChild, } from '@angular/core';
3
- import { FormControl, ReactiveFormsModule } from '@angular/forms';
4
- import { OperationKeys } from '@decaf-ts/db-decorators';
5
- import { NgxCrudFormField } from '../../engine/NgxCrudFormField';
6
- import { Dynamic } from '../../engine/decorators';
7
- import { IonCheckbox, IonIcon, IonInput, IonItem, IonLabel, IonRadio, IonRadioGroup, IonSelect, IonSelectOption, IonText, IonTextarea, } from '@ionic/angular/standalone';
8
- import { HTML5InputTypes } from '@decaf-ts/ui-decorators';
9
- import { addIcons } from 'ionicons';
10
- import { chevronDownOutline, chevronUpOutline } from 'ionicons/icons';
11
- import { generateRandomValue } from '../../helpers';
12
- import { NgxFormService } from '../../engine/NgxFormService';
13
- import { EventConstants } from '../../engine/constants';
14
- import { getLocaleContextByKey } from '../../i18n/Loader';
15
- import { TranslatePipe } from '@ngx-translate/core';
16
- import * as i0 from "@angular/core";
17
- import * as i1 from "@angular/forms";
18
- /**
19
- * @description A dynamic form field component for CRUD operations.
20
- * @summary The CrudFieldComponent is a versatile form field component that adapts to different
21
- * input types and CRUD operations. It extends NgxCrudFormField to inherit form handling capabilities
22
- * and implements lifecycle hooks to properly initialize, render, and clean up. This component
23
- * supports various input types (text, number, date, select, etc.), validation rules, and styling
24
- * options, making it suitable for building dynamic forms for create, read, update, and delete
25
- * operations.
26
- *
27
- * @param {CrudOperations} operation - The CRUD operation being performed (create, read, update, delete)
28
- * @param {string} name - The field name, used as form control identifier
29
- * @param {PossibleInputTypes} type - The input type (text, number, date, select, etc.)
30
- * @param {string|number|Date} value - The initial value of the field
31
- * @param {boolean} disabled - Whether the field is disabled
32
- * @param {string} label - The display label for the field
33
- * @param {string} placeholder - Placeholder text when field is empty
34
- * @param {string} format - Format pattern for the field value
35
- * @param {boolean} hidden - Whether the field should be hidden
36
- * @param {number|Date} max - Maximum allowed value
37
- * @param {number} maxlength - Maximum allowed length
38
- * @param {number|Date} min - Minimum allowed value
39
- * @param {number} minlength - Minimum allowed length
40
- * @param {string} pattern - Validation pattern
41
- * @param {boolean} readonly - Whether the field is read-only
42
- * @param {boolean} required - Whether the field is required
43
- * @param {number} step - Step value for number inputs
44
- * @param {FormGroup} formGroup - The parent form group
45
- * @param {StringOrBoolean} translatable - Whether field labels should be translated
46
- *
47
- * @component CrudFieldComponent
48
- * @example
49
- * <ngx-decaf-crud-field
50
- * operation="create"
51
- * name="firstName"
52
- * type="text"
53
- * label="<NAME>"
54
- * placeholder="<NAME>"
55
- * [value]="model.firstName"
56
- * [disabled]="model.readOnly">
57
- *
58
- *
59
- * @memberOf module:for-angular
60
- */
61
- let CrudFieldComponent = class CrudFieldComponent extends NgxCrudFormField {
62
- constructor() {
63
- super(...arguments);
64
- /**
65
- * @description The parent field path, if this field is nested.
66
- * @summary Specifies the full dot-delimited path of the parent field. This is only set when the field is nested.
67
- *
68
- * @type {string}
69
- * @memberOf CrudFieldComponent
70
- */
71
- /**
72
- * @description The parent field path for nested field structures.
73
- * @summary Specifies the full dot-delimited path of the parent field when this field
74
- * is part of a nested structure. This is used for hierarchical form organization
75
- * and proper form control resolution in complex form structures.
76
- *
77
- * @type {string}
78
- * @default ''
79
- * @memberOf CrudFieldComponent
80
- */
81
- this.childOf = '';
82
- /**
83
- * @description The initial value of the field.
84
- * @summary Sets the initial value of the form field. This can be a string, number, or Date
85
- * depending on the field type. For select fields, this should match one of the option values.
86
- *
87
- * @type {string | number | Date}
88
- * @default ''
89
- * @memberOf CrudFieldComponent
90
- */
91
- this.value = '';
92
- /**
93
- * @description Whether the field should be hidden.
94
- * @summary When true, the field will not be visible in the UI but will still be part of the form model.
95
- * This is useful for fields that need to be included in form submission but should not be displayed to the user.
96
- *
97
- * @type {boolean}
98
- * @memberOf CrudFieldComponent
99
- */
100
- this.hidden = false;
101
- /**
102
- * @description Interface style for select inputs.
103
- * @summary Specifies the interface style for select inputs, such as 'alert', 'action-sheet', or 'popover'.
104
- * This determines how the select options are presented to the user.
105
- *
106
- * @type {SelectInterface}
107
- * @memberOf CrudFieldComponent
108
- */
109
- this.interface = 'popover';
110
- /**
111
- * @description Spellcheck attribute for text inputs.
112
- * @summary Enables or disables spellchecking for text inputs.
113
- * When true, the browser will check the spelling of the input text.
114
- *
115
- * @type {boolean}
116
- * @default false
117
- * @memberOf CrudFieldComponent
118
- */
119
- this.spellcheck = false;
120
- /**
121
- * @description Input mode for text inputs.
122
- * @summary Hints at the type of data that might be entered by the user while editing the element.
123
- * This can affect the virtual keyboard layout on mobile devices.
124
- *
125
- * @type {'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search'}
126
- * @default 'none'
127
- * @memberOf CrudFieldComponent
128
- */
129
- this.inputmode = 'none';
130
- /**
131
- * @description Autocomplete behavior for the field.
132
- * @summary Specifies whether and how the browser should automatically complete the input.
133
- * This can improve user experience by suggesting previously entered values.
134
- *
135
- * @type {AutocompleteTypes}
136
- * @default 'off'
137
- * @memberOf CrudFieldComponent
138
- */
139
- this.autocomplete = 'off';
140
- /**
141
- * @description Fill style for the field.
142
- * @summary Determines the fill style of the field, such as 'outline' or 'solid'.
143
- * This affects the border and background of the field.
144
- *
145
- * @type {'outline' | 'solid'}
146
- * @default 'outline'
147
- * @memberOf CrudFieldComponent
148
- */
149
- this.fill = 'outline';
150
- /**
151
- * @description Placement of the label relative to the field.
152
- * @summary Specifies where the label should be placed relative to the field.
153
- * Options include 'start', 'end', 'floating', 'stacked', and 'fixed'.
154
- *
155
- * @type {'start' | 'end' | 'floating' | 'stacked' | 'fixed'}
156
- * @default 'floating'
157
- * @memberOf CrudFieldComponent
158
- */
159
- this.labelPlacement = 'floating';
160
- /**
161
- * @description Update mode for the field.
162
- * @summary Determines when the field value should be updated in the form model.
163
- * Options include 'change', 'blur', and 'submit'.
164
- *
165
- * @type {FieldUpdateMode}
166
- * @default 'change'
167
- * @memberOf CrudFieldComponent
168
- */
169
- this.updateOn = 'change';
170
- /**
171
- * @description Indicates if this field supports multiple values.
172
- * @summary When true, this field can handle multiple values, typically used in
173
- * multi-select scenarios or when the field is part of a form array structure
174
- * that allows multiple entries of the same field type.
175
- *
176
- * @type {boolean}
177
- * @default false
178
- * @memberOf CrudFieldComponent
179
- */
180
- this.multiple = false;
181
- /**
182
- * @description Unique identifier for the current record.
183
- * @summary A unique identifier for the current record being displayed or manipulated.
184
- * This is typically used in conjunction with the primary key for operations on specific records.
185
- *
186
- * @type {string | number}
187
- */
188
- this.uid = generateRandomValue(12);
189
- /**
190
- * @description Translatability of field labels.
191
- * @summary Indicates whether the field labels should be translated based on the current language settings.
192
- * This is useful for applications supporting multiple languages.
193
- *
194
- * @type {StringOrBoolean}
195
- * @default true
196
- * @memberOf CrudFieldComponent
197
- */
198
- this.translatable = true;
199
- /**
200
- * @description Index of the currently active form group in a form array.
201
- * @summary When working with multiple form groups (form arrays), this indicates
202
- * which form group is currently active or being edited. This is used to manage
203
- * focus and data binding in multi-entry scenarios.
204
- *
205
- * @type {number}
206
- * @default 0
207
- * @memberOf CrudFieldComponent
208
- */
209
- this.activeFormGroup = 0;
210
- }
211
- /**
212
- * @description Gets the currently active form group based on context.
213
- * @summary Returns the appropriate FormGroup based on whether this field supports
214
- * multiple values. For single-value fields, returns the main form group.
215
- * For multi-value fields, returns the form group at the active index from the parent FormArray.
216
- *
217
- * @returns {FormGroup} The currently active FormGroup for this field
218
- * @memberOf CrudFieldComponent
219
- */
220
- get getActiveFormGroup() {
221
- const formGroup = this.formGroup;
222
- return this.multiple
223
- ? formGroup.parent?.at(this.activeFormGroup)
224
- : formGroup;
225
- }
226
- /**
227
- * Returns a list of options for select or radio inputs, with their `text` property
228
- * localized if it does not already include the word 'options'. The localization key
229
- * is generated from the component's label, replacing 'label' with 'options'.
230
- *
231
- * @returns {CrudFieldOption[]} The array of parsed and localized options.
232
- * @memberOf CrudFieldComponent
233
- */
234
- get parsedOptions() {
235
- return this.options.map((option) => {
236
- return {
237
- ...option,
238
- text: !option.text.includes('options') ?
239
- getLocaleContextByKey(`${this.label.toLowerCase().replace('label', 'options')}`, option.text) : option.text
240
- };
241
- });
242
- }
243
- /**
244
- * @description Component initialization lifecycle method.
245
- * @summary Initializes the field component based on the operation type and field configuration.
246
- * For READ and DELETE operations, removes the form group to make fields read-only.
247
- * For other operations, sets up icons, configures multi-value support if needed,
248
- * and sets default values for radio buttons if no value is provided.
249
- *
250
- * @returns {void}
251
- * @memberOf CrudFieldComponent
252
- */
253
- ngOnInit() {
254
- if (this.options?.length)
255
- this.options = this.parsedOptions;
256
- if ([OperationKeys.READ, OperationKeys.DELETE].includes(this.operation)) {
257
- this.formGroup = undefined;
258
- }
259
- else {
260
- addIcons({ chevronDownOutline, chevronUpOutline });
261
- if (this.multiple) {
262
- this.formGroup = this.getActiveFormGroup;
263
- this.formGroupArray = this.formGroup.parent;
264
- this.formControl = this.formGroup.get(this.name);
265
- }
266
- if (this.type === HTML5InputTypes.RADIO && !this.value)
267
- this.formGroup?.get(this.name)?.setValue(this.options[0].value); // TODO: migrate to RenderingEngine
268
- }
269
- }
270
- /**
271
- * @description Component after view initialization lifecycle method.
272
- * @summary Calls the parent afterViewInit method for READ and DELETE operations.
273
- * This ensures proper initialization of read-only fields that don't require
274
- * form functionality but still need view setup.
275
- *
276
- * @returns {void}
277
- * @memberOf CrudFieldComponent
278
- */
279
- ngAfterViewInit() {
280
- if ([OperationKeys.READ, OperationKeys.DELETE].includes(this.operation))
281
- super.afterViewInit();
282
- }
283
- /**
284
- * @description Component cleanup lifecycle method.
285
- * @summary Performs cleanup operations for READ and DELETE operations by calling
286
- * the parent onDestroy method. This ensures proper resource cleanup for
287
- * read-only field components.
288
- *
289
- * @returns {void}
290
- * @memberOf CrudFieldComponent
291
- */
292
- ngOnDestroy() {
293
- if ([OperationKeys.READ, OperationKeys.DELETE].includes(this.operation))
294
- this.onDestroy();
295
- }
296
- /**
297
- * @description Handles fieldset group creation events from parent fieldsets.
298
- * @summary Processes events triggered when a new group needs to be added to a fieldset.
299
- * Validates the current form group, checks for uniqueness if applicable, and either
300
- * creates a new group or provides validation feedback. Updates the active form group
301
- * and resets the field for new input after successful creation.
302
- *
303
- * @param {CustomEvent} event - The fieldset create group event containing group details
304
- * @returns {void}
305
- * @memberOf CrudFieldComponent
306
- */
307
- handleFieldsetCreateGroupEvent(event) {
308
- event.stopImmediatePropagation();
309
- const { parent, component, index, operation } = event.detail;
310
- const formGroup = this.formGroup;
311
- const parentFormGroup = this.formGroup?.parent;
312
- const isValid = NgxFormService.validateFields(formGroup);
313
- const indexToCheck = operation === OperationKeys.CREATE ?
314
- index === 0 ? index : parentFormGroup.length - 1 : index;
315
- const isUnique = NgxFormService.isUniqueOnGroup(formGroup, indexToCheck, operation || OperationKeys.CREATE);
316
- event = new CustomEvent(EventConstants.FIELDSET_ADD_GROUP, {
317
- detail: { isValid: isValid && isUnique, value: formGroup.value, formGroup: parentFormGroup, formService: NgxFormService },
318
- });
319
- component.dispatchEvent(event);
320
- if (isValid && isUnique) {
321
- const newIndex = parentFormGroup?.length;
322
- if (operation === OperationKeys.CREATE) {
323
- NgxFormService.addGroupToParent(parentFormGroup?.parent, parent, newIndex);
324
- this.activeFormGroup = newIndex;
325
- }
326
- else {
327
- this.activeFormGroup = newIndex - 1;
328
- }
329
- this.formGroup = this.getActiveFormGroup;
330
- // NgxFormService.reset(this.formGroup as FormGroup);
331
- this.formControl = this.formGroup.get(this.name);
332
- // NgxFormService.reset(this.formControl);
333
- // this.component.nativeElement.setFocus();
334
- }
335
- else {
336
- if (isUnique)
337
- this.component.nativeElement.setFocus();
338
- }
339
- }
340
- /**
341
- * @description Handles fieldset group update events from parent fieldsets.
342
- * @summary Processes events triggered when an existing group needs to be updated.
343
- * Updates the active form group index and refreshes the form group and form control
344
- * references to point to the group being edited.
345
- *
346
- * @param {CustomEvent} event - The fieldset update group event containing update details
347
- * @returns {void}
348
- * @memberOf CrudFieldComponent
349
- */
350
- handleFieldsetUpdateGroupEvent(event) {
351
- const { index } = event.detail;
352
- this.activeFormGroup = index;
353
- this.formGroup = this.getActiveFormGroup;
354
- this.formControl = this.formGroup.get(this.name);
355
- this.value = this.formControl.value;
356
- }
357
- /**
358
- * @description Handles fieldset group removal events from parent fieldsets.
359
- * @summary Processes events triggered when a group needs to be removed from a fieldset.
360
- * Removes the specified group from the form array, updates the active form group index,
361
- * and refreshes the form references. Dispatches a confirmation event back to the component.
362
- *
363
- * @param {CustomEvent} event - The fieldset remove group event containing removal details
364
- * @returns {void}
365
- * @memberOf CrudFieldComponent
366
- */
367
- handleFieldsetRemoveGroupEvent(event) {
368
- const { component, index } = event.detail;
369
- const formArray = this.formGroup?.parent;
370
- formArray.removeAt(index);
371
- this.activeFormGroup = formArray.length === 1 ? 0 : formArray.length - 1;
372
- this.formGroup = this.getActiveFormGroup;
373
- this.formControl = this.formGroup.get(this.name);
374
- this.formGroupArray = formArray;
375
- event = new CustomEvent(EventConstants.FIELDSET_REMOVE_GROUP, {
376
- detail: { value: true },
377
- });
378
- component.dispatchEvent(event);
379
- }
380
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CrudFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
381
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CrudFieldComponent, isStandalone: true, selector: "ngx-decaf-crud-field", inputs: { operation: "operation", name: "name", path: "path", childOf: "childOf", type: "type", value: "value", disabled: "disabled", label: "label", placeholder: "placeholder", format: "format", hidden: "hidden", max: "max", maxlength: "maxlength", min: "min", minlength: "minlength", pattern: "pattern", readonly: "readonly", required: "required", step: "step", equals: "equals", different: "different", lessThan: "lessThan", lessThanOrEqual: "lessThanOrEqual", greaterThan: "greaterThan", greaterThanOrEqual: "greaterThanOrEqual", cols: "cols", rows: "rows", alignment: "alignment", checked: "checked", justify: "justify", cancelText: "cancelText", interface: "interface", options: "options", mode: "mode", spellcheck: "spellcheck", inputmode: "inputmode", autocomplete: "autocomplete", fill: "fill", labelPlacement: "labelPlacement", updateOn: "updateOn", formGroup: "formGroup", formControl: "formControl", multiple: "multiple", uid: "uid", page: "page", translatable: "translatable", activeFormGroup: "activeFormGroup", pk: "pk" }, host: { listeners: { "window:fieldsetAddGroupEvent": "handleFieldsetCreateGroupEvent($event)", "window:fieldsetUpdateGroupEvent": "handleFieldsetUpdateGroupEvent($event)", "window:fieldsetRemoveGroupEvent": "handleFieldsetRemoveGroupEvent($event)" }, properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "@if(operation === 'read' || operation === 'delete') {\n <ng-container #component>\n <div [class]=\"'dcf-input-item ' + operation\">\n <ion-item>\n <ion-label>\n {{ label | translate }}<br />\n @if(value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n <br />\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n <ng-container [formGroup]=\"getActiveFormGroup\">\n <div #container [class]=\"'dcf-input-item ' + (operation || 'create')\" (createGroupEvent)=\"multiple ? handleFieldsetCreateGroupEvent($event) : ''\">\n @if(type === 'textarea') {\n <ion-textarea\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [required]=\"required !== undefined ? required : null\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if(type === 'checkbox') {\n <ion-item>\n <ion-checkbox\n #checkboxElement\n [mode]=\"mode\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span [innerHTML]=\"label | translate\"></span>\n </ion-checkbox>\n </ion-item>\n }\n @else if(type === 'radio') {\n <ion-radio-group [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track option) {\n <ion-item>\n <ion-radio\n [errorText]=\"getErrors(container)\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ translatable ? (option?.text | translate) : option?.text }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if(type === 'select') {\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"translatable ? (label | translate) : label\"\n [value]=\"value\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [interface]=\"interface\" #component>\n @for(option of options; track option.value) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n </ion-select>\n }\n @else {\n <ion-input\n [type]=\"type\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [required]=\"required !== undefined ? required : false\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n}\n\n", styles: [".dcf-input-item.create,.dcf-input-item.update{margin-bottom:1.8rem;margin-top:0!important}.dcf-input-item.create.checkbox+.checkbox,.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}.dcf-input-item.create ion-item,.dcf-input-item.update ion-item{--border-color: transparent}.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{font-weight:600}@media (prefers-color-scheme: light){.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{color:var(--dcf-color-gray-7)}}.dcf-input-item.read ion-text,.dcf-input-item.delete ion-text{display:block;margin-top:.5rem!important}.dcf-input-item ion-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15}@media (prefers-color-scheme: dark){.dcf-input-item ion-item{--border-color: var(--dcf-color-gray-6)}}@media (prefers-color-scheme: light){.dcf-input-item ion-item{--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}}.dcf-input-item ion-item span,.dcf-input-item ion-item ion-text{font-weight:400!important;font-size:.925rem;min-height:.5rem!important}.dcf-input-item ion-item span:not(.dcf-display-block),.dcf-input-item ion-item ion-text:not(.dcf-display-block){display:inline-block}.dcf-input-item ion-item span.dcf-display-block,.dcf-input-item ion-item ion-text.dcf-display-block{display:block!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-item{--inner-padding-start: .75rem}ion-checkbox::part(container){border-radius:50%;padding:3px}@media (prefers-color-scheme: light){ion-checkbox::part(container){border:2px solid var(--dcf-color-primary)}}ion-item .dcf-radio-group-label,ion-radio-group .dcf-radio-group-label{font-weight:600}ion-item .dcf-radio-group-label~ion-item,ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-item+.dcf-helper,ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:600!important;line-height:1.1rem;box-sizing:border-box;z-index:9999;margin-top:0;animation-duration:.1s;animation-timing-function:ease-out;animation-fill-mode:both;animation-name:fadeTopSmallAnimation;display:flex;align-items:flex-start;gap:.25rem}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;color:var(--dcf-color-gray-7)!important;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}@keyframes fadeTopSmallAnimation{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeBottomSmallAnimation{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeTopMediumAnimation{0%{opacity:0;transform:translateY(-50px)}to{opacity:1;transform:translateY(0)}}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }] }); }
382
- };
383
- CrudFieldComponent = __decorate([
384
- Dynamic()
385
- ], CrudFieldComponent);
386
- export { CrudFieldComponent };
387
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CrudFieldComponent, decorators: [{
388
- type: Component,
389
- args: [{ standalone: true, imports: [
390
- ReactiveFormsModule,
391
- TranslatePipe,
392
- IonInput,
393
- IonItem,
394
- IonCheckbox,
395
- IonRadioGroup,
396
- IonRadio,
397
- IonSelect,
398
- IonSelectOption,
399
- IonLabel,
400
- IonText,
401
- IonTextarea,
402
- IonIcon
403
- ], selector: 'ngx-decaf-crud-field', schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { '[attr.id]': 'uid' }, template: "@if(operation === 'read' || operation === 'delete') {\n <ng-container #component>\n <div [class]=\"'dcf-input-item ' + operation\">\n <ion-item>\n <ion-label>\n {{ label | translate }}<br />\n @if(value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n <br />\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n <ng-container [formGroup]=\"getActiveFormGroup\">\n <div #container [class]=\"'dcf-input-item ' + (operation || 'create')\" (createGroupEvent)=\"multiple ? handleFieldsetCreateGroupEvent($event) : ''\">\n @if(type === 'textarea') {\n <ion-textarea\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [required]=\"required !== undefined ? required : null\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if(type === 'checkbox') {\n <ion-item>\n <ion-checkbox\n #checkboxElement\n [mode]=\"mode\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span [innerHTML]=\"label | translate\"></span>\n </ion-checkbox>\n </ion-item>\n }\n @else if(type === 'radio') {\n <ion-radio-group [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track option) {\n <ion-item>\n <ion-radio\n [errorText]=\"getErrors(container)\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ translatable ? (option?.text | translate) : option?.text }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if(type === 'select') {\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"translatable ? (label | translate) : label\"\n [value]=\"value\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [interface]=\"interface\" #component>\n @for(option of options; track option.value) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n </ion-select>\n }\n @else {\n <ion-input\n [type]=\"type\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [required]=\"required !== undefined ? required : false\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n}\n\n", styles: [".dcf-input-item.create,.dcf-input-item.update{margin-bottom:1.8rem;margin-top:0!important}.dcf-input-item.create.checkbox+.checkbox,.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}.dcf-input-item.create ion-item,.dcf-input-item.update ion-item{--border-color: transparent}.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{font-weight:600}@media (prefers-color-scheme: light){.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{color:var(--dcf-color-gray-7)}}.dcf-input-item.read ion-text,.dcf-input-item.delete ion-text{display:block;margin-top:.5rem!important}.dcf-input-item ion-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15}@media (prefers-color-scheme: dark){.dcf-input-item ion-item{--border-color: var(--dcf-color-gray-6)}}@media (prefers-color-scheme: light){.dcf-input-item ion-item{--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}}.dcf-input-item ion-item span,.dcf-input-item ion-item ion-text{font-weight:400!important;font-size:.925rem;min-height:.5rem!important}.dcf-input-item ion-item span:not(.dcf-display-block),.dcf-input-item ion-item ion-text:not(.dcf-display-block){display:inline-block}.dcf-input-item ion-item span.dcf-display-block,.dcf-input-item ion-item ion-text.dcf-display-block{display:block!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-item{--inner-padding-start: .75rem}ion-checkbox::part(container){border-radius:50%;padding:3px}@media (prefers-color-scheme: light){ion-checkbox::part(container){border:2px solid var(--dcf-color-primary)}}ion-item .dcf-radio-group-label,ion-radio-group .dcf-radio-group-label{font-weight:600}ion-item .dcf-radio-group-label~ion-item,ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-item+.dcf-helper,ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:600!important;line-height:1.1rem;box-sizing:border-box;z-index:9999;margin-top:0;animation-duration:.1s;animation-timing-function:ease-out;animation-fill-mode:both;animation-name:fadeTopSmallAnimation;display:flex;align-items:flex-start;gap:.25rem}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;color:var(--dcf-color-gray-7)!important;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}@keyframes fadeTopSmallAnimation{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeBottomSmallAnimation{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeTopMediumAnimation{0%{opacity:0;transform:translateY(-50px)}to{opacity:1;transform:translateY(0)}}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"] }]
404
- }], propDecorators: { operation: [{
405
- type: Input,
406
- args: [{ required: true }]
407
- }], name: [{
408
- type: Input,
409
- args: [{ required: true }]
410
- }], path: [{
411
- type: Input,
412
- args: [{ required: true }]
413
- }], childOf: [{
414
- type: Input
415
- }], type: [{
416
- type: Input,
417
- args: [{ required: true }]
418
- }], value: [{
419
- type: Input
420
- }], disabled: [{
421
- type: Input
422
- }], label: [{
423
- type: Input,
424
- args: [{ required: true }]
425
- }], placeholder: [{
426
- type: Input
427
- }], format: [{
428
- type: Input
429
- }], hidden: [{
430
- type: Input
431
- }], max: [{
432
- type: Input
433
- }], maxlength: [{
434
- type: Input
435
- }], min: [{
436
- type: Input
437
- }], minlength: [{
438
- type: Input
439
- }], pattern: [{
440
- type: Input
441
- }], readonly: [{
442
- type: Input
443
- }], required: [{
444
- type: Input
445
- }], step: [{
446
- type: Input
447
- }], equals: [{
448
- type: Input
449
- }], different: [{
450
- type: Input
451
- }], lessThan: [{
452
- type: Input
453
- }], lessThanOrEqual: [{
454
- type: Input
455
- }], greaterThan: [{
456
- type: Input
457
- }], greaterThanOrEqual: [{
458
- type: Input
459
- }], cols: [{
460
- type: Input
461
- }], rows: [{
462
- type: Input
463
- }], alignment: [{
464
- type: Input
465
- }], checked: [{
466
- type: Input
467
- }], justify: [{
468
- type: Input
469
- }], cancelText: [{
470
- type: Input
471
- }], interface: [{
472
- type: Input
473
- }], options: [{
474
- type: Input
475
- }], mode: [{
476
- type: Input
477
- }], spellcheck: [{
478
- type: Input
479
- }], inputmode: [{
480
- type: Input
481
- }], autocomplete: [{
482
- type: Input
483
- }], fill: [{
484
- type: Input
485
- }], labelPlacement: [{
486
- type: Input
487
- }], updateOn: [{
488
- type: Input
489
- }], component: [{
490
- type: ViewChild,
491
- args: ['component', { read: ElementRef }]
492
- }], formGroup: [{
493
- type: Input
494
- }], formControl: [{
495
- type: Input
496
- }], multiple: [{
497
- type: Input
498
- }], uid: [{
499
- type: Input
500
- }], page: [{
501
- type: Input
502
- }], translatable: [{
503
- type: Input
504
- }], activeFormGroup: [{
505
- type: Input
506
- }], pk: [{
507
- type: Input
508
- }], handleFieldsetCreateGroupEvent: [{
509
- type: HostListener,
510
- args: ['window:fieldsetAddGroupEvent', ['$event']]
511
- }], handleFieldsetUpdateGroupEvent: [{
512
- type: HostListener,
513
- args: ['window:fieldsetUpdateGroupEvent', ['$event']]
514
- }], handleFieldsetRemoveGroupEvent: [{
515
- type: HostListener,
516
- args: ['window:fieldsetRemoveGroupEvent', ['$event']]
517
- }] } });
518
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3J1ZC1maWVsZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvY3J1ZC1maWVsZC9jcnVkLWZpZWxkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9jcnVkLWZpZWxkL2NydWQtZmllbGQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1Qsc0JBQXNCLEVBQ3RCLFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUdMLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQWEsV0FBVyxFQUFhLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEYsT0FBTyxFQUFrQixhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNqRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFbEQsT0FBTyxFQUNMLFdBQVcsRUFDWCxPQUFPLEVBQ1AsUUFBUSxFQUNSLE9BQU8sRUFDUCxRQUFRLEVBQ1IsUUFBUSxFQUNSLGFBQWEsRUFDYixTQUFTLEVBQ1QsZUFBZSxFQUNmLE9BQU8sRUFDUCxXQUFXLEdBQ1osTUFBTSwyQkFBMkIsQ0FBQztBQUNuQyxPQUFPLEVBQXFCLGVBQWUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzdFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDcEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM3RCxP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QUFTO3NCQURSLEtBQUs7Z0JBWU4sT0FBTztzQkFETixLQUFLO2dCQVlOLElBQUk7c0JBREgsS0FBSztnQkFhTixVQUFVO3NCQURULEtBQUs7Z0JBYU4sU0FBUztzQkFEUixLQUFLO2dCQXFCTixZQUFZO3NCQURYLEtBQUs7Z0JBYU4sSUFBSTtzQkFESCxLQUFLO2dCQWFOLGNBQWM7c0JBRGIsS0FBSztnQkFjTixRQUFRO3NCQURQLEtBQUs7Z0JBV0csU0FBUztzQkFEakIsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO2dCQVluQyxTQUFTO3NCQURqQixLQUFLO2dCQWNHLFdBQVc7c0JBRG5CLEtBQUs7Z0JBY0csUUFBUTtzQkFEaEIsS0FBSztnQkFXRyxHQUFHO3NCQURYLEtBQUs7Z0JBS0csSUFBSTtzQkFEWixLQUFLO2dCQWFOLFlBQVk7c0JBRFgsS0FBSztnQkFnQk4sZUFBZTtzQkFEZCxLQUFLO2dCQXdCTixFQUFFO3NCQURELEtBQUs7Z0JBMkdOLDhCQUE4QjtzQkFEN0IsWUFBWTt1QkFBQyw4QkFBOEIsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFnRHhELDhCQUE4QjtzQkFEN0IsWUFBWTt1QkFBQyxpQ0FBaUMsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFxQjNELDhCQUE4QjtzQkFEN0IsWUFBWTt1QkFBQyxpQ0FBaUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENvbXBvbmVudCxcbiAgQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQSxcbiAgRWxlbWVudFJlZixcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQXJyYXksIEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBdXRvY29tcGxldGVUeXBlcywgU2VsZWN0SW50ZXJmYWNlIH0gZnJvbSAnQGlvbmljL2NvcmUnO1xuaW1wb3J0IHsgQ3J1ZE9wZXJhdGlvbnMsIE9wZXJhdGlvbktleXMgfSBmcm9tICdAZGVjYWYtdHMvZGItZGVjb3JhdG9ycyc7XG5pbXBvcnQgeyBOZ3hDcnVkRm9ybUZpZWxkIH0gZnJvbSAnLi4vLi4vZW5naW5lL05neENydWRGb3JtRmllbGQnO1xuaW1wb3J0IHsgRHluYW1pYyB9IGZyb20gJy4uLy4uL2VuZ2luZS9kZWNvcmF0b3JzJztcbmltcG9ydCB7IENydWRGaWVsZE9wdGlvbiwgRmllbGRVcGRhdGVNb2RlLCBQb3NzaWJsZUlucHV0VHlwZXMsIFN0cmluZ09yQm9vbGVhbiB9IGZyb20gJy4uLy4uL2VuZ2luZS90eXBlcyc7XG5pbXBvcnQge1xuICBJb25DaGVja2JveCxcbiAgSW9uSWNvbixcbiAgSW9uSW5wdXQsXG4gIElvbkl0ZW0sXG4gIElvbkxhYmVsLFxuICBJb25SYWRpbyxcbiAgSW9uUmFkaW9Hcm91cCxcbiAgSW9uU2VsZWN0LFxuICBJb25TZWxlY3RPcHRpb24sXG4gIElvblRleHQsXG4gIElvblRleHRhcmVhLFxufSBmcm9tICdAaW9uaWMvYW5ndWxhci9zdGFuZGFsb25lJztcbmltcG9ydCB7IENydWRPcGVyYXRpb25LZXlzLCBIVE1MNUlucHV0VHlwZXMgfSBmcm9tICdAZGVjYWYtdHMvdWktZGVjb3JhdG9ycyc7XG5pbXBvcnQgeyBhZGRJY29ucyB9IGZyb20gJ2lvbmljb25zJztcbmltcG9ydCB7IGNoZXZyb25Eb3duT3V0bGluZSwgY2hldnJvblVwT3V0bGluZSB9IGZyb20gJ2lvbmljb25zL2ljb25zJztcbmltcG9ydCB7IGdlbmVyYXRlUmFuZG9tVmFsdWUgfSBmcm9tICcuLi8uLi9oZWxwZXJzJztcbmltcG9ydCB7IE5neEZvcm1TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vZW5naW5lL05neEZvcm1TZXJ2aWNlJztcbmltcG9ydCB7IEV2ZW50Q29uc3RhbnRzIH0gZnJvbSAnLi4vLi4vZW5naW5lL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBnZXRMb2NhbGVDb250ZXh0QnlLZXkgfSBmcm9tICcuLi8uLi9pMThuL0xvYWRlcic7XG5pbXBvcnQgeyBUcmFuc2xhdGVQaXBlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgZHluYW1pYyBmb3JtIGZpZWxkIGNvbXBvbmVudCBmb3IgQ1JVRCBvcGVyYXRpb25zLlxuICogQHN1bW1hcnkgVGhlIENydWRGaWVsZENvbXBvbmVudCBpcyBhIHZlcnNhdGlsZSBmb3JtIGZpZWxkIGNvbXBvbmVudCB0aGF0IGFkYXB0cyB0byBkaWZmZXJlbnRcbiAqIGlucHV0IHR5cGVzIGFuZCBDUlVEIG9wZXJhdGlvbnMuIEl0IGV4dGVuZHMgTmd4Q3J1ZEZvcm1GaWVsZCB0byBpbmhlcml0IGZvcm0gaGFuZGxpbmcgY2FwYWJpbGl0aWVzXG4gKiBhbmQgaW1wbGVtZW50cyBsaWZlY3ljbGUgaG9va3MgdG8gcHJvcGVybHkgaW5pdGlhbGl6ZSwgcmVuZGVyLCBhbmQgY2xlYW4gdXAuIFRoaXMgY29tcG9uZW50XG4gKiBzdXBwb3J0cyB2YXJpb3VzIGlucHV0IHR5cGVzICh0ZXh0LCBudW1iZXIsIGRhdGUsIHNlbGVjdCwgZXRjLiksIHZhbGlkYXRpb24gcnVsZXMsIGFuZCBzdHlsaW5nXG4gKiBvcHRpb25zLCBtYWtpbmcgaXQgc3VpdGFibGUgZm9yIGJ1aWxkaW5nIGR5bmFtaWMgZm9ybXMgZm9yIGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBhbmQgZGVsZXRlXG4gKiBvcGVyYXRpb25zLlxuICpcbiAqIEBwYXJhbSB7Q3J1ZE9wZXJhdGlvbnN9IG9wZXJhdGlvbiAtIFRoZSBDUlVEIG9wZXJhdGlvbiBiZWluZyBwZXJmb3JtZWQgKGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBkZWxldGUpXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBmaWVsZCBuYW1lLCB1c2VkIGFzIGZvcm0gY29udHJvbCBpZGVudGlmaWVyXG4gKiBAcGFyYW0ge1Bvc3NpYmxlSW5wdXRUeXBlc30gdHlwZSAtIFRoZSBpbnB1dCB0eXBlICh0ZXh0LCBudW1iZXIsIGRhdGUsIHNlbGVjdCwgZXRjLilcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcnxEYXRlfSB2YWx1ZSAtIFRoZSBpbml0aWFsIHZhbHVlIG9mIHRoZSBmaWVsZFxuICogQHBhcmFtIHtib29sZWFufSBkaXNhYmxlZCAtIFdoZXRoZXIgdGhlIGZpZWxkIGlzIGRpc2FibGVkXG4gKiBAcGFyYW0ge3N0cmluZ30gbGFiZWwgLSBUaGUgZGlzcGxheSBsYWJlbCBmb3IgdGhlIGZpZWxkXG4gKiBAcGFyYW0ge3N0cmluZ30gcGxhY2Vob2xkZXIgLSBQbGFjZWhvbGRlciB0ZXh0IHdoZW4gZmllbGQgaXMgZW1wdHlcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgLSBGb3JtYXQgcGF0dGVybiBmb3IgdGhlIGZpZWxkIHZhbHVlXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGhpZGRlbiAtIFdoZXRoZXIgdGhlIGZpZWxkIHNob3VsZCBiZSBoaWRkZW5cbiAqIEBwYXJhbSB7bnVtYmVyfERhdGV9IG1heCAtIE1heGltdW0gYWxsb3dlZCB2YWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IG1heGxlbmd0aCAtIE1heGltdW0gYWxsb3dlZCBsZW5ndGhcbiAqIEBwYXJhbSB7bnVtYmVyfERhdGV9IG1pbiAtIE1pbmltdW0gYWxsb3dlZCB2YWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IG1pbmxlbmd0aCAtIE1pbmltdW0gYWxsb3dlZCBsZW5ndGhcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXR0ZXJuIC0gVmFsaWRhdGlvbiBwYXR0ZXJuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IHJlYWRvbmx5IC0gV2hldGhlciB0aGUgZmllbGQgaXMgcmVhZC1vbmx5XG4gKiBAcGFyYW0ge2Jvb2xlYW59IHJlcXVpcmVkIC0gV2hldGhlciB0aGUgZmllbGQgaXMgcmVxdWlyZWRcbiAqIEBwYXJhbSB7bnVtYmVyfSBzdGVwIC0gU3RlcCB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0c1xuICogQHBhcmFtIHtGb3JtR3JvdXB9IGZvcm1Hcm91cCAtIFRoZSBwYXJlbnQgZm9ybSBncm91cFxuICogQHBhcmFtIHtTdHJpbmdPckJvb2xlYW59IHRyYW5zbGF0YWJsZSAtIFdoZXRoZXIgZmllbGQgbGFiZWxzIHNob3VsZCBiZSB0cmFuc2xhdGVkXG4gKlxuICogQGNvbXBvbmVudCBDcnVkRmllbGRDb21wb25lbnRcbiAqIEBleGFtcGxlXG4gKiA8bmd4LWRlY2FmLWNydWQtZmllbGRcbiAqICAgb3BlcmF0aW9uPVwiY3JlYXRlXCJcbiAqICAgbmFtZT1cImZpcnN0TmFtZVwiXG4gKiAgIHR5cGU9XCJ0ZXh0XCJcbiAqICAgbGFiZWw9XCI8TkFNRT5cIlxuICogICBwbGFjZWhvbGRlcj1cIjxOQU1FPlwiXG4gKiAgIFt2YWx1ZV09XCJtb2RlbC5maXJzdE5hbWVcIlxuICogICBbZGlzYWJsZWRdPVwibW9kZWwucmVhZE9ubHlcIj5cbiAqXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItYW5ndWxhclxuICovXG5ARHluYW1pYygpXG5AQ29tcG9uZW50KHtcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgVHJhbnNsYXRlUGlwZSxcbiAgICBJb25JbnB1dCxcbiAgICBJb25JdGVtLFxuICAgIElvbkNoZWNrYm94LFxuICAgIElvblJhZGlvR3JvdXAsXG4gICAgSW9uUmFkaW8sXG4gICAgSW9uU2VsZWN0LFxuICAgIElvblNlbGVjdE9wdGlvbixcbiAgICBJb25MYWJlbCxcbiAgICBJb25UZXh0LFxuICAgIElvblRleHRhcmVhLFxuICAgIElvbkljb25cbiAgXSxcbiAgc2VsZWN0b3I6ICduZ3gtZGVjYWYtY3J1ZC1maWVsZCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9jcnVkLWZpZWxkLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2NydWQtZmllbGQuY29tcG9uZW50LnNjc3MnLFxuICBzY2hlbWFzOiBbQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQV0sXG4gIGhvc3Q6IHsnW2F0dHIuaWRdJzogJ3VpZCd9LFxufSlcbmV4cG9ydCBjbGFzcyBDcnVkRmllbGRDb21wb25lbnQgZXh0ZW5kcyBOZ3hDcnVkRm9ybUZpZWxkIGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIENSVUQgb3BlcmF0aW9uIGJlaW5nIHBlcmZvcm1lZC5cbiAgICogQHN1bW1hcnkgU3BlY2lmaWVzIHdoaWNoIENSVUQgb3BlcmF0aW9uIChDcmVhdGUsIFJlYWQsIFVwZGF0ZSwgRGVsZXRlKSB0aGUgZmllbGQgaXMgYmVpbmcgdXNlZCBmb3IuXG4gICAqIFRoaXMgYWZmZWN0cyBob3cgdGhlIGZpZWxkIGJlaGF2ZXMgYW5kIGlzIHJlbmRlcmVkLiBGb3IgZXhhbXBsZSwgZmllbGRzIG1pZ2h0IGJlIHJlYWQtb25seSBpblxuICAgKiAncmVhZCcgbW9kZSBidXQgZWRpdGFibGUgaW4gJ2NyZWF0ZScgb3IgJ3VwZGF0ZScgbW9kZXMuXG4gICAqXG4gICAqIEB0eXBlIHtDcnVkT3BlcmF0aW9uc31cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcbiAgb3ZlcnJpZGUgb3BlcmF0aW9uITogQ3J1ZE9wZXJhdGlvbnM7XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5ICBUaGUgZmxhdCBmaWVsZCBuYW1lIHVzZWQgYXMgdGhlIGZvcm0gY29udHJvbCBpZGVudGlmaWVyIGluIGltbWVkaWF0ZSBwYXJlbnQgRm9ybUdyb3VwLlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogU3BlY2lmaWVzIHRoZSBuYW1lIG9mIHRoZSBmaWVsZCwgd2hpY2ggaXMgdXNlZCBhcyB0aGUgRm9ybUNvbnRyb2wgaWRlbnRpZmllciBpbiBpbW1lZGlhdGUgcGFyZW50IEZvcm1Hcm91cC5cbiAgICogVGhpcyB2YWx1ZSBtdXN0IGJlIHVuaXF1ZSB3aXRoaW4gdGhlIGltbWVkaWF0ZSBwYXJlbnQgRm9ybUdyb3VwIGNvbnRleHQgYW5kIHNob3VsZCBub3QgY29udGFpbiBkb3RzIG9yIG5lc3RpbmcuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXG4gIG92ZXJyaWRlIG5hbWUhOiBzdHJpbmc7XG5cblxuICAvKipcbiAgICogQHN1bW1hcnkgVGhlIGZ1bGwgZmllbGQgcGF0aCB1c2VkIGZvciBmb3JtIGNvbnRyb2wgcmVzb2x1dGlvbi5cbiAgICogQGRlc2NyaXB0aW9uIFNwZWNpZmllcyB0aGUgaGllcmFyY2hpY2FsIHBhdGggb2YgdGhlIGZpZWxkLCB1c2VkIHRvIHJlc29sdmUgaXRzIGxvY2F0aW9uIHdpdGhpbiB0aGUgcGFyZW50IEZvcm1Hcm91cCAob3IgbmVzdGVkIEZvcm1Hcm91cHMpLlxuICAgKiBJdCBpcyB1c2VkIGFzIHRoZSBpZGVudGlmaWVyIGluIHRoZSByZW5kZXJlZCBIVE1MLCBhbmQgbWF5IGluY2x1ZGUgbmVzdGluZyAoZS5nLiwgJ2FkZHJlc3MuYmlsbGluZy5zdHJlZXQnKSBhbmRcbiAgICogc2hvdWxkIG1hdGNoIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEgbW9kZWxcbiAgICpcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcbiAgb3ZlcnJpZGUgcGF0aCE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBwYXJlbnQgZmllbGQgcGF0aCwgaWYgdGhpcyBmaWVsZCBpcyBuZXN0ZWQuXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB0aGUgZnVsbCBkb3QtZGVsaW1pdGVkIHBhdGggb2YgdGhlIHBhcmVudCBmaWVsZC4gVGhpcyBpcyBvbmx5IHNldCB3aGVuIHRoZSBmaWVsZCBpcyBuZXN0ZWQuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHBhcmVudCBmaWVsZCBwYXRoIGZvciBuZXN0ZWQgZmllbGQgc3RydWN0dXJlcy5cbiAgICogQHN1bW1hcnkgU3BlY2lmaWVzIHRoZSBmdWxsIGRvdC1kZWxpbWl0ZWQgcGF0aCBvZiB0aGUgcGFyZW50IGZpZWxkIHdoZW4gdGhpcyBmaWVsZFxuICAgKiBpcyBwYXJ0IG9mIGEgbmVzdGVkIHN0cnVjdHVyZS4gVGhpcyBpcyB1c2VkIGZvciBoaWVyYXJjaGljYWwgZm9ybSBvcmdhbml6YXRpb25cbiAgICogYW5kIHByb3BlciBmb3JtIGNvbnRyb2wgcmVzb2x1dGlvbiBpbiBjb21wbGV4IGZvcm0gc3RydWN0dXJlcy5cbiAgICpcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQGRlZmF1bHQgJydcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgY2hpbGRPZjogc3RyaW5nID0gJyc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgaW5wdXQgdHlwZSBvZiB0aGUgZmllbGQuXG4gICAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIHR5cGUgb2YgaW5wdXQgdG8gcmVuZGVyLCBzdWNoIGFzIHRleHQsIG51bWJlciwgZGF0ZSwgc2VsZWN0LCBldGMuXG4gICAqIFRoaXMgZGV0ZXJtaW5lcyB3aGljaCBJb25pYyBmb3JtIGNvbXBvbmVudCB3aWxsIGJlIHVzZWQgdG8gcmVuZGVyIHRoZSBmaWVsZCBhbmQgaG93XG4gICAqIHRoZSBkYXRhIHdpbGwgYmUgZm9ybWF0dGVkIGFuZCB2YWxpZGF0ZWQuXG4gICAqXG4gICAqIEB0eXBlIHtQb3NzaWJsZUlucHV0VHlwZXN9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXG4gIG92ZXJyaWRlIHR5cGUhOiBQb3NzaWJsZUlucHV0VHlwZXM7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgaW5pdGlhbCB2YWx1ZSBvZiB0aGUgZmllbGQuXG4gICAqIEBzdW1tYXJ5IFNldHMgdGhlIGluaXRpYWwgdmFsdWUgb2YgdGhlIGZvcm0gZmllbGQuIFRoaXMgY2FuIGJlIGEgc3RyaW5nLCBudW1iZXIsIG9yIERhdGVcbiAgICogZGVwZW5kaW5nIG9uIHRoZSBmaWVsZCB0eXBlLiBGb3Igc2VsZWN0IGZpZWxkcywgdGhpcyBzaG91bGQgbWF0Y2ggb25lIG9mIHRoZSBvcHRpb24gdmFsdWVzLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nIHwgbnVtYmVyIHwgRGF0ZX1cbiAgICogQGRlZmF1bHQgJydcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgdmFsdWU6IHN0cmluZyB8IG51bWJlciB8IERhdGUgPSAnJztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdGhlIGZpZWxkIGlzIGRpc2FibGVkLlxuICAgKiBAc3VtbWFyeSBXaGVuIHRydWUsIHRoZSBmaWVsZCB3aWxsIGJlIHJlbmRlcmVkIGluIGEgZGlzYWJsZWQgc3RhdGUsIHByZXZlbnRpbmcgdXNlciBpbnRlcmFjdGlvbi5cbiAgICogRGlzYWJsZWQgZmllbGRzIGFyZSBzdGlsbCBpbmNsdWRlZCBpbiB0aGUgZm9ybSBtb2RlbCBidXQgY2Fubm90IGJlIGVkaXRlZCBieSB0aGUgdXNlci5cbiAgICpcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIGRpc2FibGVkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBkaXNwbGF5IGxhYmVsIGZvciB0aGUgZmllbGQuXG4gICAqIEBzdW1tYXJ5IFRoZSB0ZXh0IGxhYmVsIGRpc3BsYXllZCBhbG9uZ3NpZGUgdGhlIGZpZWxkIHRvIGlkZW50aWZ5IGl0IHRvIHRoZSB1c2VyLlxuICAgKiBUaGlzIGxhYmVsIGNhbiBiZSB0cmFuc2xhdGVkIGlmIHRoZSB0cmFuc2xhdGFibGUgcHJvcGVydHkgaXMgc2V0IHRvIHRydWUuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXG4gIGxhYmVsITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGxhY2Vob2xkZXIgdGV4dCB3aGVuIGZpZWxkIGlzIGVtcHR5LlxuICAgKiBAc3VtbWFyeSBUZXh0IHRoYXQgYXBwZWFycyBpbiB0aGUgaW5wdXQgd2hlbiBpdCBoYXMgbm8gdmFsdWUuIFRoaXMgcHJvdmlkZXMgYSBoaW50IHRvIHRoZSB1c2VyXG4gICAqIGFib3V0IHdoYXQga2luZCBvZiBkYXRhIGlzIGV4cGVjdGVkLiBUaGUgcGxhY2Vob2xkZXIgZGlzYXBwZWFycyB3aGVuIHRoZSB1c2VyIHN0YXJ0cyB0eXBpbmcuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHBsYWNlaG9sZGVyITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRm9ybWF0IHBhdHRlcm4gZm9yIHRoZSBmaWVsZCB2YWx1ZS5cbiAgICogQHN1bW1hcnkgU3BlY2lmaWVzIGEgZm9ybWF0IHBhdHRlcm4gZm9yIHRoZSBmaWVsZCB2YWx1ZSwgd2hpY2ggY2FuIGJlIHVzZWQgZm9yIGRhdGUgZm9ybWF0dGluZyxcbiAgICogbnVtYmVyIGZvcm1hdHRpbmcsIG9yIG90aGVyIHR5cGUtc3BlY2lmaWMgZm9ybWF0dGluZyByZXF1aXJlbWVudHMuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIGZvcm1hdD86IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdGhlIGZpZWxkIHNob3VsZCBiZSBoaWRkZW4uXG4gICAqIEBzdW1tYXJ5IFdoZW4gdHJ1ZSwgdGhlIGZpZWxkIHdpbGwgbm90IGJlIHZpc2libGUgaW4gdGhlIFVJIGJ1dCB3aWxsIHN0aWxsIGJlIHBhcnQgb2YgdGhlIGZvcm0gbW9kZWwuXG4gICAqIFRoaXMgaXMgdXNlZnVsIGZvciBmaWVsZHMgdGhhdCBuZWVkIHRvIGJlIGluY2x1ZGVkIGluIGZvcm0gc3VibWlzc2lvbiBidXQgc2hvdWxkIG5vdCBiZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKiBAbWVtYmVyT2YgQ3J1ZEZpZWxkQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBvdmVycmlkZSBoaWRkZW46IGJvb2xlYW4gfCBDcnVkT3BlcmF0aW9uS2V5c1tdID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBNYXhpbXVtIGFsbG93ZWQgdmFsdWUgZm9yIHRoZSBmaWVsZC5cbiAgICogQHN1bW1hcnkgRm9yIG51bWJlciBpbnB1dHMsIHRoaXMgc2V0cyB0aGUgbWF4aW11bSBhbGxvd2VkIG51bWVyaWMgdmFsdWUuXG4gICAqIEZvciBkYXRlIGlucHV0cywgdGhpcyBzZXRzIHRoZSBsYXRlc3QgYWxsb3dlZCBkYXRlLlxuICAgKlxuICAgKiBAdHlwZSB7bnVtYmVyIHwgRGF0ZX1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgbWF4PzogbnVtYmVyIHwgRGF0ZTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE1heGltdW0gYWxsb3dlZCBsZW5ndGggZm9yIHRleHQgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IEZvciB0ZXh0IGlucHV0cywgdGhpcyBzZXRzIHRoZSBtYXhpbXVtIG51bWJlciBvZiBjaGFyYWN0ZXJzIGFsbG93ZWQuXG4gICAqIFRoaXMgaXMgdXNlZCBmb3IgdmFsaWRhdGlvbiBhbmQgbWF5IGFsc28gYmUgdXNlZCB0byBsaW1pdCBpbnB1dCBpbiB0aGUgVUkuXG4gICAqXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIG1heGxlbmd0aD86IG51bWJlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE1pbmltdW0gYWxsb3dlZCB2YWx1ZSBmb3IgdGhlIGZpZWxkLlxuICAgKiBAc3VtbWFyeSBGb3IgbnVtYmVyIGlucHV0cywgdGhpcyBzZXRzIHRoZSBtaW5pbXVtIGFsbG93ZWQgbnVtZXJpYyB2YWx1ZS5cbiAgICogRm9yIGRhdGUgaW5wdXRzLCB0aGlzIHNldHMgdGhlIGVhcmxpZXN0IGFsbG93ZWQgZGF0ZS5cbiAgICpcbiAgICogQHR5cGUge251bWJlciB8IERhdGV9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIG1pbj86IG51bWJlciB8IERhdGU7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBNaW5pbXVtIGFsbG93ZWQgbGVuZ3RoIGZvciB0ZXh0IGlucHV0LlxuICAgKiBAc3VtbWFyeSBGb3IgdGV4dCBpbnB1dHMsIHRoaXMgc2V0cyB0aGUgbWluaW11bSBudW1iZXIgb2YgY2hhcmFjdGVycyByZXF1aXJlZC5cbiAgICogVGhpcyBpcyB1c2VkIGZvciB2YWxpZGF0aW9uIHRvIGVuc3VyZSB0aGUgaW5wdXQgbWVldHMgYSBtaW5pbXVtIGxlbmd0aCByZXF1aXJlbWVudC5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgbWlubGVuZ3RoPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVmFsaWRhdGlvbiBwYXR0ZXJuIGZvciB0ZXh0IGlucHV0LlxuICAgKiBAc3VtbWFyeSBBIHJlZ3VsYXIgZXhwcmVzc2lvbiBwYXR0ZXJuIHVzZWQgdG8gdmFsaWRhdGUgdGV4dCBpbnB1dC5cbiAgICogVGhlIGlucHV0IHZhbHVlIG11c3QgbWF0Y2ggdGhpcyBwYXR0ZXJuIHRvIGJlIGNvbnNpZGVyZWQgdmFsaWQuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIHBhdHRlcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRoZSBmaWVsZCBpcyByZWFkLW9ubHkuXG4gICAqIEBzdW1tYXJ5IFdoZW4gdHJ1ZSwgdGhlIGZpZWxkIHdpbGwgYmUgcmVuZGVyZWQgaW4gYSByZWFkLW9ubHkgc3RhdGUuIFVubGlrZSBkaXNhYmxlZCBmaWVsZHMsXG4gICAqIHJlYWQtb25seSBmaWVsZHMgYXJlIHN0aWxsIGZvY3VzYWJsZSBidXQgY2Fubm90IGJlIG1vZGlmaWVkIGJ5IHRoZSB1c2VyLlxuICAgKlxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgcmVhZG9ubHk/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0aGUgZmllbGQgaXMgcmVxdWlyZWQuXG4gICAqIEBzdW1tYXJ5IFdoZW4gdHJ1ZSwgdGhlIGZpZWxkIG11c3QgaGF2ZSBhIHZhbHVlIGZvciB0aGUgZm9ybSB0byBiZSB2YWxpZC5cbiAgICogUmVxdWlyZWQgZmllbGRzIGFyZSB0eXBpY2FsbHkgbWFya2VkIHdpdGggYW4gaW5kaWNhdG9yIGluIHRoZSBVSS5cbiAgICpcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIHJlcXVpcmVkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0ZXAgdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IEZvciBudW1iZXIgaW5wdXRzLCB0aGlzIHNldHMgdGhlIGluY3JlbWVudC9kZWNyZW1lbnQgc3RlcCB3aGVuIHVzaW5nXG4gICAqIHRoZSB1cC9kb3duIGFycm93cyBvciB3aGVuIHVzaW5nIGEgcmFuZ2Ugc2xpZGVyLlxuICAgKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAbWVtYmVyT2YgQ3J1ZEZpZWxkQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBvdmVycmlkZSBzdGVwPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmllbGQgbmFtZSBmb3IgZXF1YWxpdHkgdmFsaWRhdGlvbiBjb21wYXJpc29uLlxuICAgKiBAc3VtbWFyeSBTcGVjaWZpZXMgYW5vdGhlciBmaWVsZCBuYW1lIHRoYXQgdGhpcyBmaWVsZCdzIHZhbHVlIG11c3QgYmUgZXF1YWwgdG8gZm9yIHZhbGlkYXRpb24uXG4gICAqIFRoaXMgaXMgY29tbW9ubHkgdXNlZCBmb3IgcGFzc3dvcmQgY29uZmlybWF0aW9uIGZpZWxkcyBvciBvdGhlciBzY2VuYXJpb3Mgd2hlcmVcbiAgICogdHdvIGZpZWxkcyBtdXN0IGNvbnRhaW4gdGhlIHNhbWUgdmFsdWUuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmcgfCB1bmRlZmluZWR9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIGVxdWFscz86IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZpZWxkIG5hbWUgZm9yIGluZXF1YWxpdHkgdmFsaWRhdGlvbiBjb21wYXJpc29uLlxuICAgKiBAc3VtbWFyeSBTcGVjaWZpZXMgYW5vdGhlciBmaWVsZCBuYW1lIHRoYXQgdGhpcyBmaWVsZCdzIHZhbHVlIG11c3QgYmUgZGlmZmVyZW50IGZyb20gZm9yIHZhbGlkYXRpb24uXG4gICAqIFRoaXMgaXMgdXNlZCB0byBlbnN1cmUgdGhhdCB0d28gZmllbGRzIGRvIG5vdCBjb250YWluIHRoZSBzYW1lIHZhbHVlLCB3aGljaCBtaWdodCBiZVxuICAgKiByZXF1aXJlZCBmb3IgY2VydGFpbiBidXNpbmVzcyBydWxlcyBvciBzZWN1cml0eSBjb25zdHJhaW50cy5cbiAgICpcbiAgICogQHR5cGUge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgZGlmZmVyZW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmllbGQgbmFtZSBmb3IgbGVzcy10aGFuIHZhbGlkYXRpb24gY29tcGFyaXNvbi5cbiAgICogQHN1bW1hcnkgU3BlY2lmaWVzIGFub3RoZXIgZmllbGQgbmFtZSB0aGF0IHRoaXMgZmllbGQncyB2YWx1ZSBtdXN0IGJlIGxlc3MgdGhhbiBmb3IgdmFsaWRhdGlvbi5cbiAgICogVGhpcyBpcyBjb21tb25seSB1c2VkIGZvciBkYXRlIHJhbmdlcywgbnVtZXJpYyByYW5nZXMsIG9yIG90aGVyIHNjZW5hcmlvcyB3aGVyZVxuICAgKiBvbmUgZmllbGQgbXVzdCBoYXZlIGEgc21hbGxlciB2YWx1ZSB0aGFuIGFub3RoZXIuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmcgfCB1bmRlZmluZWR9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIGxlc3NUaGFuPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmllbGQgbmFtZSBmb3IgbGVzcy10aGFuLW9yLWVxdWFsIHZhbGlkYXRpb24gY29tcGFyaXNvbi5cbiAgICogQHN1bW1hcnkgU3BlY2lmaWVzIGFub3RoZXIgZmllbGQgbmFtZSB0aGF0IHRoaXMgZmllbGQncyB2YWx1ZSBtdXN0IGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0b1xuICAgKiBmb3IgdmFsaWRhdGlvbi4gVGhpcyBwcm92aWRlcyBpbmNsdXNpdmUgdXBwZXIgYm91bmQgdmFsaWRhdGlvbiBmb3IgbnVtZXJpYyBvciBkYXRlIGNvbXBhcmlzb25zLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKiBAbWVtYmVyT2YgQ3J1ZEZpZWxkQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBvdmVycmlkZSBsZXNzVGhhbk9yRXF1YWw/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBGaWVsZCBuYW1lIGZvciBncmVhdGVyLXRoYW4gdmFsaWRhdGlvbiBjb21wYXJpc29uLlxuICAgKiBAc3VtbWFyeSBTcGVjaWZpZXMgYW5vdGhlciBmaWVsZCBuYW1lIHRoYXQgdGhpcyBmaWVsZCdzIHZhbHVlIG11c3QgYmUgZ3JlYXRlciB0aGFuIGZvciB2YWxpZGF0aW9uLlxuICAgKiBUaGlzIGlzIGNvbW1vbmx5IHVzZWQgZm9yIGRhdGUgcmFuZ2VzLCBudW1lcmljIHJhbmdlcywgb3Igb3RoZXIgc2NlbmFyaW9zIHdoZXJlXG4gICAqIG9uZSBmaWVsZCBtdXN0IGhhdmUgYSBsYXJnZXIgdmFsdWUgdGhhbiBhbm90aGVyLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKiBAbWVtYmVyT2YgQ3J1ZEZpZWxkQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBvdmVycmlkZSBncmVhdGVyVGhhbj86IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZpZWxkIG5hbWUgZm9yIGdyZWF0ZXItdGhhbi1vci1lcXVhbCB2YWxpZGF0aW9uIGNvbXBhcmlzb24uXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyBhbm90aGVyIGZpZWxkIG5hbWUgdGhhdCB0aGlzIGZpZWxkJ3MgdmFsdWUgbXVzdCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG9cbiAgICogZm9yIHZhbGlkYXRpb24uIFRoaXMgcHJvdmlkZXMgaW5jbHVzaXZlIGxvd2VyIGJvdW5kIHZhbGlkYXRpb24gZm9yIG51bWVyaWMgb3IgZGF0ZSBjb21wYXJpc29ucy5cbiAgICpcbiAgICogQHR5cGUge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgZ3JlYXRlclRoYW5PckVxdWFsPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTnVtYmVyIG9mIGNvbHVtbnMgZm9yIHRleHRhcmVhIGlucHV0cy5cbiAgICogQHN1bW1hcnkgRm9yIHRleHRhcmVhIGlucHV0cywgdGhpcyBzZXRzIHRoZSB2aXNpYmxlIHdpZHRoIG9mIHRoZSB0ZXh0IGFyZWEgaW4gYXZlcmFnZSBjaGFyYWN0ZXIgd2lkdGhzLlxuICAgKiBUaGlzIGlzIHVzZWQgYWxvbmdzaWRlIHJvd3MgdG8gZGVmaW5lIHRoZSBkaW1lbnNpb25zIG9mIHRoZSB0ZXh0YXJlYS5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgY29scz86IG51bWJlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE51bWJlciBvZiByb3dzIGZvciB0ZXh0YXJlYSBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IEZvciB0ZXh0YXJlYSBpbnB1dHMsIHRoaXMgc2V0cyB0aGUgdmlzaWJsZSBoZWlnaHQgb2YgdGhlIHRleHQgYXJlYSBpbiBsaW5lcyBvZiB0ZXh0LlxuICAgKiBUaGlzIGlzIHVzZWQgYWxvbmdzaWRlIGNvbHMgdG8gZGVmaW5lIHRoZSBkaW1lbnNpb25zIG9mIHRoZSB0ZXh0YXJlYS5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgcm93cz86IG51bWJlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFsaWdubWVudCBvZiB0aGUgZmllbGQgY29udGVudC5cbiAgICogQHN1bW1hcnkgQ29udHJvbHMgdGhlIGhvcml6b250YWwgYWxpZ25tZW50IG9mIHRoZSBmaWVsZCBjb250ZW50LlxuICAgKiBUaGlzIGFmZmVjdHMgaG93IHRoZSBjb250ZW50IGlzIHBvc2l0aW9uZWQgd2l0aGluIHRoZSBmaWVsZCBjb250YWluZXIuXG4gICAqXG4gICAqIEB0eXBlIHsnc3RhcnQnIHwgJ2NlbnRlcid9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGFsaWdubWVudD86ICdzdGFydCcgfCAnY2VudGVyJztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWwgY2hlY2tlZCBzdGF0ZSBmb3IgY2hlY2tib3ggb3IgdG9nZ2xlIGlucHV0cy5cbiAgICogQHN1bW1hcnkgRm9yIGNoZWNrYm94IG9yIHRvZ2dsZSBpbnB1dHMsIHRoaXMgc2V0cyB0aGUgaW5pdGlhbCBjaGVja2VkIHN0YXRlLlxuICAgKiBXaGVuIHRydWUsIHRoZSBjaGVja2JveCBvciB0b2dnbGUgd2lsbCBiZSBpbml0aWFsbHkgY2hlY2tlZC5cbiAgICpcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGNoZWNrZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSnVzdGlmaWNhdGlvbiBvZiBpdGVtcyB3aXRoaW4gdGhlIGZpZWxkLlxuICAgKiBAc3VtbWFyeSBDb250cm9scyBob3cgaXRlbXMgYXJlIGp1c3RpZmllZCB3aXRoaW4gdGhlIGZpZWxkIGNvbnRhaW5lci5cbiAgICogVGhpcyBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBmaWVsZHMgd2l0aCBtdWx0aXBsZSBlbGVtZW50cywgc3VjaCBhcyByYWRpbyBncm91cHMuXG4gICAqXG4gICAqIEB0eXBlIHsnc3RhcnQnIHwgJ2VuZCcgfCAnc3BhY2UtYmV0d2Vlbid9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGp1c3RpZnk/OiAnc3RhcnQnIHwgJ2VuZCcgfCAnc3BhY2UtYmV0d2Vlbic7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUZXh0IGZvciB0aGUgY2FuY2VsIGJ1dHRvbiBpbiBzZWxlY3QgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBGb3Igc2VsZWN0IGlucHV0cyB3aXRoIGEgY2FuY2VsIGJ1dHRvbiwgdGhpcyBzZXRzIHRoZSB0ZXh0IGRpc3BsYXllZCBvbiB0aGUgY2FuY2VsIGJ1dHRvbi5cbiAgICogVGhpcyBpcyB0eXBpY2FsbHkgdXNlZCBpbiBzZWxlY3QgZGlhbG9ncyB0byBwcm92aWRlIGEgd2F5IGZvciB1c2VycyB0byBkaXNtaXNzIHRoZSBzZWxlY3Rpb24gd2l0aG91dCBtYWtpbmcgYSBjaGFuZ2UuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGNhbmNlbFRleHQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbnRlcmZhY2Ugc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB0aGUgaW50ZXJmYWNlIHN0eWxlIGZvciBzZWxlY3QgaW5wdXRzLCBzdWNoIGFzICdhbGVydCcsICdhY3Rpb24tc2hlZXQnLCBvciAncG9wb3ZlcicuXG4gICAqIFRoaXMgZGV0ZXJtaW5lcyBob3cgdGhlIHNlbGVjdCBvcHRpb25zIGFyZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEB0eXBlIHtTZWxlY3RJbnRlcmZhY2V9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGludGVyZmFjZTogU2VsZWN0SW50ZXJmYWNlID0gJ3BvcG92ZXInO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gT3B0aW9ucyBmb3Igc2VsZWN0IG9yIHJhZGlvIGlucHV0cy5cbiAgICogQHN1bW1hcnkgUHJvdmlkZXMgdGhlIGxpc3Qgb2Ygb3B0aW9ucyBmb3Igc2VsZWN0IG9yIHJhZGlvIGlucHV0cy4gRWFjaCBvcHRpb24gY2FuIGhhdmUgYSB2YWx1ZSBhbmQgYSBsYWJlbC5cbiAgICogVGhpcyBpcyB1c2VkIHRvIHBvcHVsYXRlIHRoZSBkcm9wZG93biBvciByYWRpbyBncm91cCB3aXRoIGNob2ljZXMuXG4gICAqXG4gICAqIEB0eXBlIHtDcnVkRmllbGRPcHRpb25bXX1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3B0aW9ucyE6IENydWRGaWVsZE9wdGlvbltdO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTW9kZSBvZiB0aGUgZmllbGQuXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB0aGUgdmlzdWFsIG1vZGUgb2YgdGhlIGZpZWxkLCBzdWNoIGFzICdpb3MnIG9yICdtZCcuXG4gICAqIFRoaXMgYWZmZWN0cyB0aGUgc3R5bGluZyBhbmQgYXBwZWFyYW5jZSBvZiB0aGUgZmllbGQgdG8gbWF0Y2ggdGhlIHBsYXRmb3JtIHN0eWxlLlxuICAgKlxuICAgKiBAdHlwZSB7J2lvcycgfCAnbWQnfVxuICAgKiBAbWVtYmVyT2YgQ3J1ZEZpZWxkQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBtb2RlPzogJ2lvcycgfCAnbWQnO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3BlbGxjaGVjayBhdHRyaWJ1dGUgZm9yIHRleHQgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBFbmFibGVzIG9yIGRpc2FibGVzIHNwZWxsY2hlY2tpbmcgZm9yIHRleHQgaW5wdXRzLlxuICAgKiBXaGVuIHRydWUsIHRoZSBicm93c2VyIHdpbGwgY2hlY2sgdGhlIHNwZWxsaW5nIG9mIHRoZSBpbnB1dCB0ZXh0LlxuICAgKlxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgc3BlbGxjaGVjazogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5wdXQgbW9kZSBmb3IgdGV4dCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IEhpbnRzIGF0IHRoZSB0eXBlIG9mIGRhdGEgdGhhdCBtaWdodCBiZSBlbnRlcmVkIGJ5IHRoZSB1c2VyIHdoaWxlIGVkaXRpbmcgdGhlIGVsZW1lbnQuXG4gICAqIFRoaXMgY2FuIGFmZmVjdCB0aGUgdmlydHVhbCBrZXlib2FyZCBsYXlvdXQgb24gbW9iaWxlIGRldmljZXMuXG4gICAqXG4gICAqIEB0eXBlIHsnbm9uZScgfCAndGV4dCcgfCAndGVsJyB8ICd1cmwnIHwgJ2VtYWlsJyB8ICdudW1lcmljJyB8ICdkZWNpbWFsJyB8ICdzZWFyY2gnfVxuICAgKiBAZGVmYXVsdCAnbm9uZSdcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgaW5wdXRtb2RlOlxuICAgIHwgJ25vbmUnXG4gICAgfCAndGV4dCdcbiAgICB8ICd0ZWwnXG4gICAgfCAndXJsJ1xuICAgIHwgJ2VtYWlsJ1xuICAgIHwgJ251bWVyaWMnXG4gICAgfCAnZGVjaW1hbCdcbiAgICB8ICdzZWFyY2gnID0gJ25vbmUnO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXV0b2NvbXBsZXRlIGJlaGF2aW9yIGZvciB0aGUgZmllbGQuXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB3aGV0aGVyIGFuZCBob3cgdGhlIGJyb3dzZXIgc2hvdWxkIGF1dG9tYXRpY2FsbHkgY29tcGxldGUgdGhlIGlucHV0LlxuICAgKiBUaGlzIGNhbiBpbXByb3ZlIHVzZXIgZXhwZXJpZW5jZSBieSBzdWdnZXN0aW5nIHByZXZpb3VzbHkgZW50ZXJlZCB2YWx1ZXMuXG4gICAqXG4gICAqIEB0eXBlIHtBdXRvY29tcGxldGVUeXBlc31cbiAgICogQGRlZmF1bHQgJ29mZidcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgYXV0b2NvbXBsZXRlOiBBdXRvY29tcGxldGVUeXBlcyA9ICdvZmYnO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmlsbCBzdHlsZSBmb3IgdGhlIGZpZWxkLlxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIHRoZSBmaWxsIHN0eWxlIG9mIHRoZSBmaWVsZCwgc3VjaCBhcyAnb3V0bGluZScgb3IgJ3NvbGlkJy5cbiAgICogVGhpcyBhZmZlY3RzIHRoZSBib3JkZXIgYW5kIGJhY2tncm91bmQgb2YgdGhlIGZpZWxkLlxuICAgKlxuICAgKiBAdHlwZSB7J291dGxpbmUnIHwgJ3NvbGlkJ31cbiAgICogQGRlZmF1bHQgJ291dGxpbmUnXG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGZpbGw6ICdvdXRsaW5lJyB8ICdzb2xpZCcgPSAnb3V0bGluZSc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQbGFjZW1lbnQgb2YgdGhlIGxhYmVsIHJlbGF0aXZlIHRvIHRoZSBmaWVsZC5cbiAgICogQHN1bW1hcnkgU3BlY2lmaWVzIHdoZXJlIHRoZSBsYWJlbCBzaG91bGQgYmUgcGxhY2VkIHJlbGF0aXZlIHRvIHRoZSBmaWVsZC5cbiAgICogT3B0aW9ucyBpbmNsdWRlICdzdGFydCcsICdlbmQnLCAnZmxvYXRpbmcnLCAnc3RhY2tlZCcsIGFuZCAnZml4ZWQnLlxuICAgKlxuICAgKiBAdHlwZSB7J3N0YXJ0JyB8ICdlbmQnIHwgJ2Zsb2F0aW5nJyB8ICdzdGFja2VkJyB8ICdmaXhlZCd9XG4gICAqIEBkZWZhdWx0ICdmbG9hdGluZydcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbGFiZWxQbGFjZW1lbnQ6ICdzdGFydCcgfCAnZW5kJyB8ICdmbG9hdGluZycgfCAnc3RhY2tlZCcgfCAnZml4ZWQnID1cbiAgICAnZmxvYXRpbmcnO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlIG1vZGUgZm9yIHRoZSBmaWVsZC5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB3aGVuIHRoZSBmaWVsZCB2YWx1ZSBzaG91bGQgYmUgdXBkYXRlZCBpbiB0aGUgZm9ybSBtb2RlbC5cbiAgICogT3B0aW9ucyBpbmNsdWRlICdjaGFuZ2UnLCAnYmx1cicsIGFuZCAnc3VibWl0Jy5cbiAgICpcbiAgICogQHR5cGUge0ZpZWxkVXBkYXRlTW9kZX1cbiAgICogQGRlZmF1bHQgJ2NoYW5nZSdcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgdXBkYXRlT246IEZpZWxkVXBkYXRlTW9kZSA9ICdjaGFuZ2UnO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVmZXJlbmNlIHRvIHRoZSBmaWVsZCBjb21wb25lbnQuXG4gICAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgcmVmZXJlbmNlIHRvIHRoZSBmaWVsZCBjb21wb25lbnQgZWxlbWVudCwgYWxsb3dpbmcgZGlyZWN0IGFjY2VzcyB0byBpdHMgcHJvcGVydGllcyBhbmQgbWV0aG9kcy5cbiAgICpcbiAgICogQHR5cGUge0VsZW1lbnRSZWZ9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBWaWV3Q2hpbGQoJ2NvbXBvbmVudCcsIHsgcmVhZDogRWxlbWVudFJlZiB9KVxuICBvdmVycmlkZSBjb21wb25lbnQhOiBFbGVtZW50UmVmO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyZW50IGZvcm0gZ3JvdXAuXG4gICAqIEBzdW1tYXJ5IFJlZmVyZW5jZXMgdGhlIHBhcmVudCBmb3JtIGdyb3VwIHRvIHdoaWNoIHRoaXMgZmllbGQgYmVsb25ncy5cbiAgICogVGhpcyBpcyBuZWNlc3NhcnkgZm9yIGludGVncmF0aW5nIHRoZSBmaWVsZCB3aXRoIEFuZ3VsYXIncyByZWFjdGl2ZSBmb3Jtcy5cbiAgICpcbiAgICogQHR5cGUge0Zvcm1Hcm91cH1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgZm9ybUdyb3VwOiBGb3JtR3JvdXAgfCB1bmRlZmluZWQ7XG5cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFuZ3VsYXIgRm9ybUNvbnRyb2wgaW5zdGFuY2UgZm9yIHRoaXMgZmllbGQuXG4gICAqIEBzdW1tYXJ5IFRoZSBzcGVjaWZpYyBGb3JtQ29udHJvbCBpbnN0YW5jZSB0aGF0IG1hbmFnZXMgdGhpcyBmaWVsZCdzIHN0YXRlLCB2YWxpZGF0aW9uLFxuICAgKiBhbmQgdmFsdWUuIFRoaXMgcHJvdmlkZXMgZGlyZWN0IGFjY2VzcyB0byBBbmd1bGFyJ3MgcmVhY3RpdmUgZm9ybXMgZnVuY3Rpb25hbGl0eVxuICAgKiBmb3IgdGhpcyBpbmRpdmlkdWFsIGZpZWxkIHdpdGhpbiB0aGUgYnJvYWRlciBmb3JtIHN0cnVjdHVyZS5cbiAgICpcbiAgICogQHR5cGUge0Zvcm1Db250cm9sfVxuICAgKiBAbWVtYmVyT2YgQ3J1ZEZpZWxkQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBvdmVycmlkZSBmb3JtQ29udHJvbCE6IEZvcm1Db250cm9sO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5kaWNhdGVzIGlmIHRoaXMgZmllbGQgc3VwcG9ydHMgbXVsdGlwbGUgdmFsdWVzLlxuICAgKiBAc3VtbWFyeSBXaGVuIHRydWUsIHRoaXMgZmllbGQgY2FuIGhhbmRsZSBtdWx0aXBsZSB2YWx1ZXMsIHR5cGljYWxseSB1c2VkIGluXG4gICAqIG11bHRpLXNlbGVjdCBzY2VuYXJpb3Mgb3Igd2hlbiB0aGUgZmllbGQgaXMgcGFydCBvZiBhIGZvcm0gYXJyYXkgc3RydWN0dXJlXG4gICAqIHRoYXQgYWxsb3dzIG11bHRpcGxlIGVudHJpZXMgb2YgdGhlIHNhbWUgZmllbGQgdHlwZS5cbiAgICpcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG92ZXJyaWRlIG11bHRpcGxlOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIGN1cnJlbnQgcmVjb3JkLlxuICAgKiBAc3VtbWFyeSBBIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgY3VycmVudCByZWNvcmQgYmVpbmcgZGlzcGxheWVkIG9yIG1hbmlwdWxhdGVkLlxuICAgKiBUaGlzIGlzIHR5cGljYWxseSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggdGhlIHByaW1hcnkga2V5IGZvciBvcGVyYXRpb25zIG9uIHNwZWNpZmljIHJlY29yZHMuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmcgfCBudW1iZXJ9XG4gICAqL1xuICBASW5wdXQoKVxuICBvdmVycmlkZSB1aWQ6IHN0cmluZyA9IGdlbmVyYXRlUmFuZG9tVmFsdWUoMTIpO1xuXG5cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgcGFnZSE6IG51bWJlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRyYW5zbGF0YWJpbGl0eSBvZiBmaWVsZCBsYWJlbHMuXG4gICAqIEBzdW1tYXJ5IEluZGljYXRlcyB3aGV0aGVyIHRoZSBmaWVsZCBsYWJlbHMgc2hvdWxkIGJlIHRyYW5zbGF0ZWQgYmFzZWQgb24gdGhlIGN1cnJlbnQgbGFuZ3VhZ2Ugc2V0dGluZ3MuXG4gICAqIFRoaXMgaXMgdXNlZnVsIGZvciBhcHBsaWNhdGlvbnMgc3VwcG9ydGluZyBtdWx0aXBsZSBsYW5ndWFnZXMuXG4gICAqXG4gICAqIEB0eXBlIHtTdHJpbmdPckJvb2xlYW59XG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgdHJhbnNsYXRhYmxlOiBTdHJpbmdPckJvb2xlYW4gPSB0cnVlO1xuXG5cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluZGV4IG9mIHRoZSBjdXJyZW50bHkgYWN0aXZlIGZvcm0gZ3JvdXAgaW4gYSBmb3JtIGFycmF5LlxuICAgKiBAc3VtbWFyeSBXaGVuIHdvcmtpbmcgd2l0aCBtdWx0aXBsZSBmb3JtIGdyb3VwcyAoZm9ybSBhcnJheXMpLCB0aGlzIGluZGljYXRlc1xuICAgKiB3aGljaCBmb3JtIGdyb3VwIGlzIGN1cnJlbnRseSBhY3RpdmUgb3IgYmVpbmcgZWRpdGVkLiBUaGlzIGlzIHVzZWQgdG8gbWFuYWdlXG4gICAqIGZvY3VzIGFuZCBkYXRhIGJpbmRpbmcgaW4gbXVsdGktZW50cnkgc2NlbmFyaW9zLlxuICAgKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAZGVmYXVsdCAwXG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGFjdGl2ZUZvcm1Hcm91cDogbnVtYmVyID0gMDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZvcm1BcnJheSBjb250YWluaW5nIG11bHRpcGxlIGZvcm0gZ3JvdXBzIGZvciB0aGlzIGZpZWxkLlxuICAgKiBAc3VtbWFyeSBXaGVuIHRoaXMgZmllbGQgaXMgcGFydCBvZiBhIG11bHRpLWVudHJ5IHN0cnVjdHVyZSwgdGhpcyBGb3JtQXJyYXlcbiAgICogY29udGFpbnMgYWxsIHRoZSBmb3JtIGdyb3Vwcy4gVGhpcyBlbmFibGVzIG1hbmFnZW1lbnQgb2YgbXVsdGlwbGUgaW5zdGFuY2VzXG4gICAqIG9mIHRoZSBzYW1lIGZpZWxkIHN0cnVjdHVyZSB3aXRoaW4gYSBzaW5nbGUgZm9ybS5cbiAgICpcbiAgICogQHR5cGUge0Zvcm1BcnJheX1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgZm9ybUdyb3VwQXJyYXkhOiBGb3JtQXJyYXk7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmltYXJ5IGtleSBmaWVsZCBuYW1lIGZvciB1bmlxdWVuZXNzIHZhbGlkYXRpb24uXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB0aGUgZmllbGQgbmFtZSB0aGF0IHNlcnZlcyBhcyB0aGUgcHJpbWFyeSBrZXkgZm9yIHVuaXF1ZW5lc3NcbiAgICogdmFsaWRhdGlvbiB3aXRoaW4gZm9ybSBhcnJheXMuIFRoaXMgaXMgdXNlZCB0byBwcmV2ZW50IGR1cGxpY2F0ZSBlbnRyaWVzXG4gICAqIGFuZCBlbnN1cmUgZGF0YSBpbnRlZ3JpdHkgaW4gbXVsdGktZW50cnkgZm9ybXMuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHBrITogc3RyaW5nO1xuXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSBjdXJyZW50bHkgYWN0aXZlIGZvcm0gZ3JvdXAgYmFzZWQgb24gY29udGV4dC5cbiAgICogQHN1bW1hcnkgUmV0dXJucyB0aGUgYXBwcm9wcmlhdGUgRm9ybUdyb3VwIGJhc2VkIG9uIHdoZXRoZXIgdGhpcyBmaWVsZCBzdXBwb3J0c1xuICAgKiBtdWx0aXBsZSB2YWx1ZXMuIEZvciBzaW5nbGUtdmFsdWUgZmllbGRzLCByZXR1cm5zIHRoZSBtYWluIGZvcm0gZ3JvdXAuXG4gICAqIEZvciBtdWx0aS12YWx1ZSBmaWVsZHMsIHJldHVybnMgdGhlIGZvcm0gZ3JvdXAgYXQgdGhlIGFjdGl2ZSBpbmRleCBmcm9tIHRoZSBwYXJlbnQgRm9ybUFycmF5LlxuICAgKlxuICAgKiBAcmV0dXJucyB7Rm9ybUdyb3VwfSBUaGUgY3VycmVudGx5IGFjdGl2ZSBGb3JtR3JvdXAgZm9yIHRoaXMgZmllbGRcbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgZ2V0IGdldEFjdGl2ZUZvcm1Hcm91cCgpOiBGb3JtR3JvdXAge1xuICAgIGNvbnN0IGZvcm1Hcm91cCA9IHRoaXMuZm9ybUdyb3VwIGFzIEZvcm1Hcm91cDtcbiAgICByZXR1cm4gdGhpcy5tdWx0aXBsZVxuICAgICAgPyAoKGZvcm1Hcm91cC5wYXJlbnQgYXMgRm9ybUFycmF5KT8uYXQodGhpcy5hY3RpdmVGb3JtR3JvdXApIGFzIEZvcm1Hcm91cClcbiAgICAgIDogZm9ybUdyb3VwO1xuXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2Ygb3B0aW9ucyBmb3Igc2VsZWN0IG9yIHJhZGlvIGlucHV0cywgd2l0aCB0aGVpciBgdGV4dGAgcHJvcGVydHlcbiAgICogbG9jYWxpemVkIGlmIGl0IGRvZXMgbm90IGFscmVhZHkgaW5jbHVkZSB0aGUgd29yZCAnb3B0aW9ucycuIFRoZSBsb2NhbGl6YXRpb24ga2V5XG4gICAqIGlzIGdlbmVyYXRlZCBmcm9tIHRoZSBjb21wb25lbnQncyBsYWJlbCwgcmVwbGFjaW5nICdsYWJlbCcgd2l0aCAnb3B0aW9ucycuXG4gICAqXG4gICAqIEByZXR1cm5zIHtDcnVkRmllbGRPcHRpb25bXX0gVGhlIGFycmF5IG9mIHBhcnNlZCBhbmQgbG9jYWxpemVkIG9wdGlvbnMuXG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIGdldCBwYXJzZWRPcHRpb25zKCk6IENydWRGaWVsZE9wdGlvbltdIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLm1hcCgob3B0aW9uKSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5vcHRpb24sXG4gICAgICAgIHRleHQ6ICFvcHRpb24udGV4dC5pbmNsdWRlcygnb3B0aW9ucycpID9cbiAgICAgICAgICBnZXRMb2NhbGVDb250ZXh0QnlLZXkoYCR7dGhpcy5sYWJlbC50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoJ2xhYmVsJywgJ29wdGlvbnMnKX1gLCBvcHRpb24udGV4dCkgOiBvcHRpb24udGV4dFxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29tcG9uZW50IGluaXRpYWxpemF0aW9uIGxpZmVjeWNsZSBtZXRob2QuXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIHRoZSBmaWVsZCBjb21wb25lbnQgYmFzZWQgb24gdGhlIG9wZXJhdGlvbiB0eXBlIGFuZCBmaWVsZCBjb25maWd1cmF0aW9uLlxuICAgKiBGb3IgUkVBRCBhbmQgREVMRVRFIG9wZXJhdGlvbnMsIHJlbW92ZXMgdGhlIGZvcm0gZ3JvdXAgdG8gbWFrZSBmaWVsZHMgcmVhZC1vbmx5LlxuICAgKiBGb3Igb3RoZXIgb3BlcmF0aW9ucywgc2V0cyB1cCBpY29ucywgY29uZmlndXJlcyBtdWx0aS12YWx1ZSBzdXBwb3J0IGlmIG5lZWRlZCxcbiAgICogYW5kIHNldHMgZGVmYXVsdCB2YWx1ZXMgZm9yIHJhZGlvIGJ1dHRvbnMgaWYgbm8gdmFsdWUgaXMgcHJvdmlkZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgQ3J1ZEZpZWxkQ29tcG9uZW50XG4gICAqL1xuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZih0aGlzLm9wdGlvbnM/Lmxlbmd0aClcbiAgICAgIHRoaXMub3B0aW9ucyA9IHRoaXMucGFyc2VkT3B0aW9ucztcbiAgICBpZiAoW09wZXJhdGlvbktleXMuUkVBRCwgT3BlcmF0aW9uS2V5cy5ERUxFVEVdLmluY2x1ZGVzKHRoaXMub3BlcmF0aW9uKSkge1xuICAgICAgdGhpcy5mb3JtR3JvdXAgPSB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFkZEljb25zKHtjaGV2cm9uRG93bk91dGxpbmUsIGNoZXZyb25VcE91dGxpbmV9KVxuICAgICAgaWYodGhpcy5tdWx0aXBsZSkge1xuICAgICAgICB0aGlzLmZvcm1Hcm91cCA9IHRoaXMuZ2V0QWN0aXZlRm9ybUdyb3VwIGFzIEZvcm1Hcm91cDtcbiAgICAgICAgdGhpcy5mb3JtR3JvdXBBcnJheSA9IHRoaXMuZm9ybUdyb3VwLnBhcmVudCBhcyBGb3JtQXJyYXk7XG4gICAgICAgIHRoaXMuZm9ybUNvbnRyb2wgPSAodGhpcy5mb3JtR3JvdXAgYXMgRm9ybUdyb3VwKS5nZXQodGhpcy5uYW1lKSBhcyBGb3JtQ29udHJvbDtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnR5cGUgPT09IEhUTUw1SW5wdXRUeXBlcy5SQURJTyAmJiAhdGhpcy52YWx1ZSlcbiAgICAgICAgdGhpcy5mb3JtR3JvdXA/LmdldCh0aGlzLm5hbWUpPy5zZXRWYWx1ZSh0aGlzLm9wdGlvbnNbMF0udmFsdWUpOyAvLyBUT0RPOiBtaWdyYXRlIHRvIFJlbmRlcmluZ0VuZ2luZVxuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb21wb25lbnQgYWZ0ZXIgdmlldyBpbml0aWFsaXphdGlvbiBsaWZlY3ljbGUgbWV0aG9kLlxuICAgKiBAc3VtbWFyeSBDYWxscyB0aGUgcGFyZW50IGFmdGVyVmlld0luaXQgbWV0aG9kIGZvciBSRUFEIGFuZCBERUxFVEUgb3BlcmF0aW9ucy5cbiAgICogVGhpcyBlbnN1cmVzIHByb3BlciBpbml0aWFsaXphdGlvbiBvZiByZWFkLW9ubHkgZmllbGRzIHRoYXQgZG9uJ3QgcmVxdWlyZVxuICAgKiBmb3JtIGZ1bmN0aW9uYWxpdHkgYnV0IHN0aWxsIG5lZWQgdmlldyBzZXR1cC5cbiAgICpcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBpZiAoW09wZXJhdGlvbktleXMuUkVBRCwgT3BlcmF0aW9uS2V5cy5ERUxFVEVdLmluY2x1ZGVzKHRoaXMub3BlcmF0aW9uKSlcbiAgICAgIHN1cGVyLmFmdGVyVmlld0luaXQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29tcG9uZW50IGNsZWFudXAgbGlmZWN5Y2xlIG1ldGhvZC5cbiAgICogQHN1bW1hcnkgUGVyZm9ybXMgY2xlYW51cCBvcGVyYXRpb25zIGZvciBSRUFEIGFuZCBERUxFVEUgb3BlcmF0aW9ucyBieSBjYWxsaW5nXG4gICAqIHRoZSBwYXJlbnQgb25EZXN0cm95IG1ldGhvZC4gVGhpcyBlbnN1cmVzIHByb3BlciByZXNvdXJjZSBjbGVhbnVwIGZvclxuICAgKiByZWFkLW9ubHkgZmllbGQgY29tcG9uZW50cy5cbiAgICpcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGlmIChbT3BlcmF0aW9uS2V5cy5SRUFELCBPcGVyYXRpb25LZXlzLkRFTEVURV0uaW5jbHVkZXModGhpcy5vcGVyYXRpb24pKVxuICAgICAgdGhpcy5vbkRlc3Ryb3koKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBmaWVsZHNldCBncm91cCBjcmVhdGlvbiBldmVudHMgZnJvbSBwYXJlbnQgZmllbGRzZXRzLlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgZXZlbnRzIHRyaWdnZXJlZCB3aGVuIGEgbmV3IGdyb3VwIG5lZWRzIHRvIGJlIGFkZGVkIHRvIGEgZmllbGRzZXQuXG4gICAqIFZhbGlkYXRlcyB0aGUgY3VycmVudCBmb3JtIGdyb3VwLCBjaGVja3MgZm9yIHVuaXF1ZW5lc3MgaWYgYXBwbGljYWJsZSwgYW5kIGVpdGhlclxuICAgKiBjcmVhdGVzIGEgbmV3IGdyb3VwIG9yIHByb3ZpZGVzIHZhbGlkYXRpb24gZmVlZGJhY2suIFVwZGF0ZXMgdGhlIGFjdGl2ZSBmb3JtIGdyb3VwXG4gICAqIGFuZCByZXNldHMgdGhlIGZpZWxkIGZvciBuZXcgaW5wdXQgYWZ0ZXIgc3VjY2Vzc2Z1bCBjcmVhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtDdXN0b21FdmVudH0gZXZlbnQgLSBUaGUgZmllbGRzZXQgY3JlYXRlIGdyb3VwIGV2ZW50IGNvbnRhaW5pbmcgZ3JvdXAgZGV0YWlsc1xuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmZpZWxkc2V0QWRkR3JvdXBFdmVudCcsIFsnJGV2ZW50J10pXG4gIGhhbmRsZUZpZWxkc2V0Q3JlYXRlR3JvdXBFdmVudChldmVudDogQ3VzdG9tRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICBjb25zdCB7IHBhcmVudCwgY29tcG9uZW50LCBpbmRleCwgb3BlcmF0aW9uIH0gPSBldmVudC5kZXRhaWw7XG4gICAgY29uc3QgZm9ybUdyb3VwID0gdGhpcy5mb3JtR3JvdXAgYXMgRm9ybUdyb3VwO1xuICAgIGNvbnN0IHBhcmVudEZvcm1Hcm91cCA9IHRoaXMuZm9ybUdyb3VwPy5wYXJlbnQgYXMgRm9ybUFycmF5O1xuICAgIGNvbnN0IGlzVmFsaWQgPSBOZ3hGb3JtU2VydmljZS52YWxpZGF0ZUZpZWxkcyhmb3JtR3JvdXAgYXMgRm9ybUdyb3VwKTtcbiAgICBjb25zdCBpbmRleFRvQ2hlY2sgPSBvcGVyYXRpb24gPT09IE9wZXJhdGlvbktleXMuQ1JFQVRFID9cbiAgICAgIGluZGV4ID09PSAwID8gaW5kZXggOiBwYXJlbnRGb3JtR3JvdXAubGVuZ3RoIC0gMSA6IGluZGV4O1xuXG4gICAgY29uc3QgaXNVbmlxdWUgPSBOZ3hGb3JtU2VydmljZS5pc1VuaXF1ZU9uR3JvdXAoZm9ybUdyb3VwLCBpbmRleFRvQ2hlY2ssIG9wZXJhdGlvbiB8fCBPcGVyYXRpb25LZXlzLkNSRUFURSk7XG4gICAgZXZlbnQgPSBuZXcgQ3VzdG9tRXZlbnQoRXZlbnRDb25zdGFudHMuRklFTERTRVRfQUREX0dST1VQLCB7XG4gICAgICBkZXRhaWw6IHtpc1ZhbGlkOiBpc1ZhbGlkICYmIGlzVW5pcXVlLCB2YWx1ZTogZm9ybUdyb3VwLnZhbHVlLCBmb3JtR3JvdXA6IHBhcmVudEZvcm1Hcm91cCwgZm9ybVNlcnZpY2U6IE5neEZvcm1TZXJ2aWNlfSxcbiAgICB9KTtcbiAgICBjb21wb25lbnQuZGlzcGF0Y2hFdmVudChldmVudCk7XG5cbiAgICBpZihpc1ZhbGlkICYmIGlzVW5pcXVlKSB7XG4gICAgICBjb25zdCBuZXdJbmRleCA9IHBhcmVudEZvcm1Hcm91cD8ubGVuZ3RoO1xuXG4gICAgICBpZihvcGVyYXRpb24gPT09IE9wZXJhdGlvbktleXMuQ1JFQVRFKSB7XG4gICAgICAgIE5neEZvcm1TZXJ2aWNlLmFkZEdyb3VwVG9QYXJlbnQocGFyZW50Rm9ybUdyb3VwPy5wYXJlbnQgYXMgRm9ybUdyb3VwLCBwYXJlbnQsIG5ld0luZGV4KTtcbiAgICAgICAgdGhpcy5hY3RpdmVGb3JtR3JvdXAgPSBuZXdJbmRleDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWN0aXZlRm9ybUdyb3VwID0gbmV3SW5kZXggLSAxO1xuICAgICAgfVxuICAgICAgdGhpcy5mb3JtR3JvdXAgPSB0aGlzLmdldEFjdGl2ZUZvcm1Hcm91cDtcbiAgICAgIC8vIE5neEZvcm1TZXJ2aWNlLnJlc2V0KHRoaXMuZm9ybUdyb3VwIGFzIEZvcm1Hcm91cCk7XG4gICAgICB0aGlzLmZvcm1Db250cm9sID0gKHRoaXMuZm9ybUdyb3VwIGFzIEZvcm1Hcm91cCkuZ2V0KHRoaXMubmFtZSkgYXMgRm9ybUNvbnRyb2w7XG4gICAgICAvLyBOZ3hGb3JtU2VydmljZS5yZXNldCh0aGlzLmZvcm1Db250cm9sKTtcbiAgICAgIC8vIHRoaXMuY29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuc2V0Rm9jdXMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYoaXNVbmlxdWUpXG4gICAgICAgIHRoaXMuY29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuc2V0Rm9jdXMoKTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBmaWVsZHNldCBncm91cCB1cGRhdGUgZXZlbnRzIGZyb20gcGFyZW50IGZpZWxkc2V0cy5cbiAgICogQHN1bW1hcnkgUHJvY2Vzc2VzIGV2ZW50cyB0cmlnZ2VyZWQgd2hlbiBhbiBleGlzdGluZyBncm91cCBuZWVkcyB0byBiZSB1cGRhdGVkLlxuICAgKiBVcGRhdGVzIHRoZSBhY3RpdmUgZm9ybSBncm91cCBpbmRleCBhbmQgcmVmcmVzaGVzIHRoZSBmb3JtIGdyb3VwIGFuZCBmb3JtIGNvbnRyb2xcbiAgICogcmVmZXJlbmNlcyB0byBwb2ludCB0byB0aGUgZ3JvdXAgYmVpbmcgZWRpdGVkLlxuICAgKlxuICAgKiBAcGFyYW0ge0N1c3RvbUV2ZW50fSBldmVudCAtIFRoZSBmaWVsZHNldCB1cGRhdGUgZ3JvdXAgZXZlbnQgY29udGFpbmluZyB1cGRhdGUgZGV0YWlsc1xuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICogQG1lbWJlck9mIENydWRGaWVsZENvbXBvbmVudFxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmZpZWxkc2V0VXBkYXRlR3JvdXBFdmVudCcsIFsnJGV2ZW50J10pXG4gIGhhbmRsZUZpZWxkc2V0VXBkYXRlR3JvdXBFdmVudChldmVudDogQ3VzdG9tRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCB7aW5kZXh9ID0gZXZlbnQuZGV0YWlsO1xuICAgIHRoaXMuYWN0aXZlRm9ybUdyb3VwID0gaW5kZXg7XG4gICAgdGhpcy5mb3JtR3JvdXAgPSB0aGlzLmdldEFjdGl2ZUZvcm1Hcm91cDtcbiAgICB0aGlzLmZvcm1Db250cm9sID0gdGhpcy5mb3JtR3JvdXAuZ2V0KHRoaXMubmFtZSkgYXMgRm9ybUNvbnRyb2w7XG4gICAgdGhpcy52YWx1ZSA9IHRoaXMuZm9ybUNvbnRyb2wudmFsdWU7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBmaWVsZHNldCBncm91cCByZW1vdmFsIGV2ZW50cyBmcm9tIHBhcmVudCBmaWVsZHNldHMuXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBldmVudHMgdHJpZ2dlcmVkIHdoZW4gYSBncm91cCBuZWVkcyB0byBiZSByZW1vdmVkIGZyb20gYSBmaWVsZHNldC5cbiAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIGdyb3VwIGZyb20gdGhlIGZvcm0gYXJyYXksIHVwZGF0ZXMgdGhlIGFjdGl2ZSBmb3JtIGdyb3VwIGluZGV4LFxuICAgKiBhbmQgcmVmcmVzaGVzIHRoZSBmb3JtIHJlZmVyZW5jZXMuIERpc3BhdGNoZXMgYSBjb25maXJtYXRpb24gZXZlbnQgYmFjayB0byB0aGUgY29tcG9uZW50LlxuICAgKlxuICAgKiBAcGFyYW0ge0N1c3RvbUV2ZW50fSBldmVudCAtIFRoZSBmaWVsZHNldCByZW1vdmUgZ3JvdXAgZXZlbnQgY29udGFpbmluZyByZW1vdmFsIGRldGFpbHNcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqIEBtZW1iZXJPZiBDcnVkRmllbGRDb21wb25lbnRcbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpmaWVsZHNldFJlbW92ZUdyb3VwRXZlbnQnLCBbJyRldmVudCddKVxuICBoYW5kbGVGaWVsZHNldFJlbW92ZUdyb3VwRXZlbnQoZXZlbnQ6IEN1c3RvbUV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgeyBjb21wb25lbnQsIGluZGV4IH0gPSBldmVudC5kZXRhaWw7XG4gICAgY29uc3QgZm9ybUFycmF5ID0gdGhpcy5mb3JtR3JvdXA/LnBhcmVudCBhcyBGb3JtQXJyYXk7XG4gICAgZm9ybUFycmF5LnJlbW92ZUF0KGluZGV4KTtcbiAgICB0aGlzLmFjdGl2ZUZvcm1Hcm91cCA9IGZvcm1BcnJheS5sZW5ndGggPT09IDEgPyAwIDogZm9ybUFycmF5Lmxlbmd0aCAtIDE7XG4gICAgdGhpcy5mb3JtR3JvdXAgPSB0aGlzLmdldEFjdGl2ZUZvcm1Hcm91cDtcbiAgICB0aGlzLmZvcm1Db250cm9sID0gdGhpcy5mb3JtR3JvdXAuZ2V0KHRoaXMubmFtZSkgYXMgRm9ybUNvbnRyb2w7XG4gICAgdGhpcy5mb3JtR3JvdXBBcnJheSA9IGZvcm1BcnJheVxuICAgIGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KEV2ZW50Q29uc3RhbnRzLkZJRUxEU0VUX1JFTU9WRV9HUk9VUCwge1xuICAgICAgZGV0YWlsOiB7dmFsdWU6IHRydWV9LFxuICAgIH0pO1xuICAgIGNvbXBvbmVudC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgfVxufVxuIiwiQGlmKG9wZXJhdGlvbiA9PT0gJ3JlYWQnIHx8IG9wZXJhdGlvbiA9PT0gJ2RlbGV0ZScpIHtcbiAgPG5nLWNvbnRhaW5lciAjY29tcG9uZW50PlxuICAgIDxkaXYgW2NsYXNzXT1cIidkY2YtaW5wdXQtaXRlbSAnICsgb3BlcmF0aW9uXCI+XG4gICAgICA8aW9uLWl0ZW0+XG4gICAgICAgIDxpb24tbGFiZWw+XG4gICAgICAgICAge3sgbGFiZWwgfCB0cmFuc2xhdGUgfX08YnIgLz5cbiAgICAgICAgICBAaWYodmFsdWUpIHtcbiAgICAgICAgICAgIDxpb24tdGV4dCAgW2lubmVySFRNTF09XCJ0eXBlID09PSAncGFzc3dvcmQnID8gJyoqKioqKioqJyA6IHZhbHVlXCI+PC9pb24tdGV4dD5cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIDxiciAvPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9pb24tbGFiZWw+XG4gICAgICA8L2lvbi1pdGVtPlxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbn0gQGVsc2Uge1xuICA8bmctY29udGFpbmVyIFtmb3JtR3JvdXBdPVwiZ2V0QWN0aXZlRm9ybUdyb3VwXCI+XG4gICAgPGRpdiAjY29udGFpbmVyIFtjbGFzc109XCInZGNmLWlucHV0LWl0ZW0gJyArIChvcGVyYXRpb24gfHwgJ2NyZWF0ZScpXCIgKGNyZWF0ZUdyb3VwRXZlbnQpPVwibXVsdGlwbGUgPyBoYW5kbGVGaWVsZHNldENyZWF0ZUdyb3VwRXZlbnQoJGV2ZW50KSA6ICcnXCI+XG4gICAgICAgIEBpZih0eXBlID09PSAndGV4dGFyZWEnKSB7XG4gICAgICAgICAgPGlvbi10ZXh0YXJlYVxuICAgICAgICAgICAgW21vZGVdPVwibW9kZVwiXG4gICAgICAgICAgICBbaGlkZGVuXT1cImhpZGRlblwiXG4gICAgICAgICAgICBbYXV0b0dyb3ddPVwidHJ1ZVwiXG4gICAgICAgICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWQgIT09IHVuZGVmaW5lZCA/IHJlcXVpcmVkIDogbnVsbFwiXG4gICAgICAgICAgICBbbWlubGVuZ3RoXT1cIm1pbmxlbmd0aCAhPT0gdW5kZWZpbmVkID8gbWlubGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICBbbWF4bGVuZ3RoXT1cIm1heGxlbmd0aCAhPT0gdW5kZWZpbmVkID8gbWF4bGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHkgIT09IHVuZGVmaW5lZCA/IHJlYWRvbmx5IDogbnVsbFwiXG4gICAgICAgICAgICBbaW5wdXRtb2RlXT1cImlucHV0bW9kZVwiXG4gICAgICAgICAgICBbc3BlbGxjaGVja109XCJzcGVsbGNoZWNrXCJcbiAgICAgICAgICAgIFtyb3dzXT1cInJvd3NcIlxuICAgICAgICAgICAgW2xhYmVsUGxhY2VtZW50XT1cImxhYmVsUGxhY2VtZW50XCJcbiAgICAgICAgICAgIFt2YWx1ZV09XCJ2YWx1ZVwiXG4gICAgICAgICAgICBbZmlsbF09XCJmaWxsXCJcbiAgICAgICAgICAgIFtlcnJvclRleHRdPVwiZ2V0RXJyb3JzKGNvbnRhaW5lcilcIlxuICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgIFtmb3JtQ29udHJvbE5hbWVdPVwibmFtZVwiXG4gICAgICAgICAgICBbbGFiZWxdPVwibGFiZWwgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAjY29tcG9uZW50PlxuICAgICAgICAgIDwvaW9uLXRleHRhcmVhPlxuICAgICAgICB9XG4gICAgICAgIEBlbHNlIGlmKHR5cGUgPT09ICdjaGVja2JveCcpIHtcbiAgICAgICAgICA8aW9uLWl0ZW0+XG4gICAgICAgICAgICA8aW9uLWNoZWNrYm94XG4gICAgICAgICAgICAgICNjaGVja2JveEVsZW1lbnRcbiAgICAgICAgICAgICAgW21vZGVdPVwibW9kZVwiXG4gICAgICAgICAgICAgIFtlcnJvclRleHRdPVwiZ2V0RXJyb3JzKGNvbnRhaW5lcilcIlxuICAgICAgICAgICAgICBbaGlkZGVuXT1cImhpZGRlblwiXG4gICAgICAgICAgICAgIFtsYWJlbFBsYWNlbWVudF09XCJsYWJlbFBsYWNlbWVudFwiXG4gICAgICAgICAgICAgIFtqdXN0aWZ5XT1cImp1c3RpZnlcIlxuICAgICAgICAgICAgICBbdmFsdWVdPVwidmFsdWVcIlxuICAgICAgICAgICAgICBbY2hlY2tlZF09XCJjaGVja2VkXCJcbiAgICAgICAgICAgICAgW3JlYWRvbmx5XT1cInJlYWRvbmx5XCJcbiAgICAgICAgICAgICAgKGlvbkNoYW5nZSk9XCJjaGVja2VkID0gIWNoZWNrZWRcIlxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xOYW1lXT1cIm5hbWVcIlxuICAgICAgICAgICAgICAjY29tcG9uZW50PlxuICAgICAgICAgICAgICA8c3BhbiBbaW5uZXJIVE1MXT1cImxhYmVsIHwgdHJhbnNsYXRlXCI+PC9zcGFuPlxuICAgICAgICAgICAgPC9pb24tY2hlY2tib3g+XG4gICAgICAgICAgPC9pb24taXRlbT5cbiAgICAgICAgfVxuICAgICAgICBAZWxzZSBpZih0eXBlID09PSAncmFkaW8nKSB7XG4gICAgICAgICAgPGlvbi1yYWRpby1ncm91cCBbZm9ybUNvbnRyb2xOYW1lXT1cIm5hbWVcIiBbdmFsdWVdPVwidmFsdWVcIiAjY29tcG9uZW50PlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZGNmLXJhZGlvLWdyb3VwLWxhYmVsXCIgW2Zvcl09XCJwYXRoXCI+e3tsYWJlbCB8IHRyYW5zbGF0ZX19PC9sYWJlbD5cbiAgICAgICAgICAgIEBmb3Iob3B0aW9uIG9mIG9wdGlvbnM7IHRyYWNrIG9wdGlvbikge1xuICAgICAgICAgICAgICA8aW9uLWl0ZW0+XG4gICAgICAgICAgICAgICAgPGlvbi1yYWRpb1xuICAgICAgICAgICAgICAgICAgW2Vycm9yVGV4dF09XCJnZXRFcnJvcnMoY29udGFpbmVyKVwiXG4gICAgICAgICAgICAgICAgICBbbW9kZV09XCJtb2RlXCJcbiAgICAgICAgICAgICAgICAgIFtoaWRkZW5dPVwiaGlkZGVuXCJcbiAgICAgICAgICAgICAgICAgIFtsYWJlbFBsYWNlbWVudF09XCJsYWJlbFBsYWNlbWVudFwiXG4gICAgICAgICAgICAgICAgICBbYWxpZ25tZW50XT1cImFsaWdubWVudFwiXG4gICAgICAgICAgICAgICAgICBbanVzdGlmeV09XCJqdXN0aWZ5XCJcbiAgICAgICAgICAgICAgICAgIFtyZWFkb25seV09XCJyZWFkb25seVwiXG4gICAgICAgICAgICAgICAgICBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCJcbiAgICAgICAgICAgICAgICA+e3sgdHJhbnNsYXRhYmxlID8gIChvcHRpb24/LnRleHQgfCB0cmFuc2xhdGUpIDogb3B0aW9uPy50ZXh0IH19PC9pb24tcmFkaW8+XG4gICAgICAgICAgICAgIDwvaW9uLWl0ZW0+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9pb24tcmFkaW8tZ3JvdXA+XG4gICAgICAgIH1cbiAgICAgICAgQGVsc2UgaWYodHlwZSA9PT0gJ3NlbGVjdCcpIHtcbiAgICAgICAgICAgIDxpb24tc2VsZWN0XG4gICAgICAgICAgICAgIHRvZ2dsZUljb249XCJjaGV2cm9uLWRvd24tb3V0bGluZVwiXG4gICAgICAgICAgICAgIGV4cGFuZGVkSWNvbj1cImNoZXZyb24tdXAtb3V0bGluZVwiXG4gICAgICAgICAgICAgIFttb2RlXT1cIm1vZGVcIlxuICAgICAgICAgICAgICBbaGlkZGVuXT1cImhpZGRlblwiXG4gICAgICAgICAgICAgIFtsYWJlbFBsYWNlbWVudF09XCJsYWJlbFBsYWNlbWVudFwiXG4gICAgICAgICAgICAgIFtsYWJlbF09XCJ0cmFuc2xhdGFibGUgPyAobGFiZWwgfCB0cmFuc2xhdGUpIDogbGFiZWxcIlxuICAgICAgICAgICAgICBbdmFsdWVdPVwidmFsdWVcIlxuICAgICAgICAgICAgICBbZmlsbF09XCJmaWxsXCJcbiAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJuYW1lXCJcbiAgICAgICAgICAgICAgW2Vycm9yVGV4dF09XCJnZXRFcnJvcnMoY29udGFpbmVyKVwiXG4gICAgICAgICAgICAgIFtpbnRlcmZhY2VdPVwiaW50ZXJmYWNlXCIgI2NvbXBvbmVudD5cbiAgICAgICAgICAgICAgQGZvcihvcHRpb24gb2Ygb3B0aW9uczsgdHJhY2sgb3B0aW9uLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgPGlvbi1zZWxlY3Qtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi50ZXh0IHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgPC9pb24tc2VsZWN0LW9wdGlvbj5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9pb24tc2VsZWN0PlxuICAgICAgICB9XG4gICAgICAgIEBlbHNlIHtcbiAgICAgICAgICA8aW9uLWlucHV0XG4gICAgICAgICAgICBbdHlwZV09XCJ0eXBlXCJcbiAgICAgICAgICAgIFttb2RlXT1cIm1vZGVcIlxuICAgICAgICAgICAgW2hpZGRlbl09XCJoaWRkZW5cIlxuICAgICAgICAgICAgW2lucHV0bW9kZV09XCJpbnB1dG1vZGVcIlxuICAgICAgICAgICAgW2xhYmVsUGxhY2VtZW50XT1cImxhYmVsUGxhY2VtZW50XCJcbiAgICAgICAgICAgIFtyZXF1aXJlZF09XCJyZXF1aXJlZCAhPT0gdW5kZWZpbmVkID8gcmVxdWlyZWQgOiBmYWxzZVwiXG4gICAgICAgICAgICBbbWlubGVuZ3RoXT1cIm1pbmxlbmd0aCAhPT0gdW5kZWZpbmVkID8gbWlubGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICBbbWF4bGVuZ3RoXT1cIm1heGxlbmd0aCAhPT0gdW5kZWZpbmVkID8gbWF4bGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHkgIT09IHVuZGVmaW5lZCA/IHJlYWRvbmx5IDogbnVsbFwiXG4gICAgICAgICAgICBbbWF4XT1cIm1heCAhPT0gdW5kZWZpbmVkID8gbWF4IDogbnVsbFwiXG4gICAgICAgICAgICBbbWluXT1cIm1pbiAhPT0gdW5kZWZpbmVkID8gbWluIDogbnVsbFwiXG4gICAgICAgICAgICBbcGF0dGVybl09XCJwYXR0ZXJuICE9PSB1bmRlZmluZWQgPyBwYXR0ZXJuIDogbnVsbFwiXG4gICAgICAgICAgICBbc3RlcF09XCJzdGVwICE9PSB1bmRlZmluZWQgPyBzdGVwIDogbnVsbFwiXG4gICAgICAgICAgICBbZmlsbF09XCJmaWxsXCJcbiAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlciB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICBbZm9ybUNvbnRyb2xOYW1lXT1cIm5hbWVcIlxuICAgICAgICAgICAgW2Vycm9yVGV4dF09XCJnZXRFcnJvcnMoY29udGFpbmVyKVwiXG4gICAgICAgICAgICBbbGFiZWxdPVwibGFiZWwgfCB0cmFuc2xhdGVcIiAjY29tcG9uZW50IC8+XG4gICAgICAgIH1cbiAgICA8L2Rpdj5cbiAgPC9uZy1jb250YWluZXI+XG59XG5cbiJdfQ==