ngx-material-entity 0.1.1 → 0.1.4

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 (133) hide show
  1. package/CONTRIBUTING.md +7 -1
  2. package/README.md +536 -328
  3. package/classes/base.builder.d.ts +35 -0
  4. package/classes/date.utilities.d.ts +58 -0
  5. package/classes/entity.model.d.ts +13 -0
  6. package/classes/{entity-service.class.d.ts → entity.service.d.ts} +35 -20
  7. package/classes/entity.utilities.d.ts +153 -0
  8. package/components/confirm-dialog/confirm-dialog-data.builder.d.ts +23 -0
  9. package/components/confirm-dialog/confirm-dialog-data.d.ts +18 -8
  10. package/components/confirm-dialog/confirm-dialog.component.d.ts +15 -5
  11. package/components/get-validation-error-message.function.d.ts +3 -2
  12. package/components/input/add-array-item-dialog-data.builder.d.ts +20 -0
  13. package/components/input/add-array-item-dialog-data.d.ts +19 -0
  14. package/components/input/input.component.d.ts +151 -30
  15. package/components/input/input.module.d.ts +7 -4
  16. package/components/table/create-dialog/create-dialog-data.builder.d.ts +21 -0
  17. package/components/table/create-dialog/create-entity-dialog-data.builder.d.ts +21 -0
  18. package/components/table/create-dialog/create-entity-dialog-data.d.ts +4 -5
  19. package/components/table/create-dialog/create-entity-dialog.component.d.ts +21 -8
  20. package/components/table/edit-dialog/edit-dialog-data.builder.d.ts +24 -0
  21. package/components/table/edit-dialog/edit-entity-dialog-data.d.ts +7 -8
  22. package/components/table/edit-dialog/edit-entity-dialog.builder.d.ts +22 -0
  23. package/components/table/edit-dialog/edit-entity-dialog.component.d.ts +25 -8
  24. package/components/table/table-data.builder.d.ts +51 -0
  25. package/components/table/table-data.d.ts +46 -30
  26. package/components/table/table.component.d.ts +53 -7
  27. package/components/table/table.module.d.ts +3 -1
  28. package/decorators/array/array-decorator-internal.data.d.ts +45 -0
  29. package/decorators/array/array-decorator.data.d.ts +129 -0
  30. package/decorators/array/array.decorator.d.ts +9 -0
  31. package/decorators/base/base-property.decorator.d.ts +7 -6
  32. package/decorators/base/decorator-types.enum.d.ts +12 -9
  33. package/decorators/base/dropdown-value.interface.d.ts +14 -0
  34. package/decorators/base/property-decorator-internal.data.d.ts +24 -0
  35. package/decorators/base/property-decorator.data.d.ts +70 -0
  36. package/decorators/boolean/boolean-decorator-internal.data.d.ts +25 -0
  37. package/decorators/boolean/boolean-decorator.data.d.ts +37 -0
  38. package/decorators/boolean/boolean.decorator.d.ts +8 -0
  39. package/decorators/date/date-decorator-internal.data.d.ts +44 -0
  40. package/decorators/date/date-decorator.data.d.ts +129 -0
  41. package/decorators/number/number-decorator-internal.data.d.ts +20 -0
  42. package/decorators/number/number-decorator.data.d.ts +36 -0
  43. package/decorators/number/number.decorator.d.ts +8 -0
  44. package/decorators/object/object-decorator-internal.data.d.ts +11 -0
  45. package/decorators/object/object-decorator.data.d.ts +25 -0
  46. package/decorators/object/object.decorator.d.ts +8 -0
  47. package/decorators/string/string-decorator-internal.data.d.ts +41 -0
  48. package/decorators/string/string-decorator.data.d.ts +77 -0
  49. package/decorators/string/string.decorator.d.ts +8 -0
  50. package/esm2020/classes/base.builder.mjs +43 -0
  51. package/esm2020/classes/date.utilities.mjs +138 -0
  52. package/esm2020/classes/entity.model.mjs +19 -0
  53. package/esm2020/classes/entity.service.mjs +83 -0
  54. package/esm2020/classes/entity.utilities.mjs +538 -0
  55. package/esm2020/components/confirm-dialog/confirm-dialog-data.builder.mjs +44 -0
  56. package/esm2020/components/confirm-dialog/confirm-dialog-data.mjs +1 -1
  57. package/esm2020/components/confirm-dialog/confirm-dialog.component.mjs +18 -22
  58. package/esm2020/components/get-validation-error-message.function.mjs +8 -3
  59. package/esm2020/components/input/add-array-item-dialog-data.builder.mjs +30 -0
  60. package/esm2020/components/input/add-array-item-dialog-data.mjs +2 -0
  61. package/esm2020/components/input/input.component.mjs +240 -36
  62. package/esm2020/components/input/input.module.mjs +23 -9
  63. package/esm2020/components/table/create-dialog/create-dialog-data.builder.mjs +32 -0
  64. package/esm2020/components/table/create-dialog/create-entity-dialog-data.builder.mjs +26 -0
  65. package/esm2020/components/table/create-dialog/create-entity-dialog-data.mjs +1 -1
  66. package/esm2020/components/table/create-dialog/create-entity-dialog.component.mjs +31 -31
  67. package/esm2020/components/table/create-dialog/create-entity-dialog.module.mjs +20 -4
  68. package/esm2020/components/table/edit-dialog/edit-dialog-data.builder.mjs +41 -0
  69. package/esm2020/components/table/edit-dialog/edit-entity-dialog-data.mjs +1 -1
  70. package/esm2020/components/table/edit-dialog/edit-entity-dialog.builder.mjs +27 -0
  71. package/esm2020/components/table/edit-dialog/edit-entity-dialog.component.mjs +45 -49
  72. package/esm2020/components/table/table-data.builder.mjs +105 -0
  73. package/esm2020/components/table/table-data.mjs +1 -1
  74. package/esm2020/components/table/table.component.mjs +91 -83
  75. package/esm2020/components/table/table.module.mjs +12 -4
  76. package/esm2020/decorators/array/array-decorator-internal.data.mjs +51 -0
  77. package/esm2020/decorators/array/array-decorator.data.mjs +7 -0
  78. package/esm2020/decorators/array/array.decorator.mjs +24 -0
  79. package/esm2020/decorators/base/base-property.decorator.mjs +6 -5
  80. package/esm2020/decorators/base/decorator-types.enum.mjs +4 -1
  81. package/esm2020/decorators/base/dropdown-value.interface.mjs +2 -0
  82. package/esm2020/decorators/base/property-decorator-internal.data.mjs +38 -0
  83. package/esm2020/decorators/base/property-decorator.data.mjs +6 -0
  84. package/esm2020/decorators/boolean/boolean-decorator-internal.data.mjs +33 -0
  85. package/esm2020/decorators/boolean/boolean-decorator.data.mjs +7 -0
  86. package/esm2020/decorators/boolean/boolean.decorator.mjs +21 -0
  87. package/esm2020/decorators/date/date-decorator-internal.data.mjs +48 -0
  88. package/esm2020/decorators/date/date-decorator.data.mjs +7 -0
  89. package/esm2020/decorators/number/number-decorator-internal.data.mjs +23 -0
  90. package/esm2020/decorators/number/number-decorator.data.mjs +7 -0
  91. package/esm2020/decorators/number/number.decorator.mjs +18 -0
  92. package/esm2020/decorators/object/object-decorator-internal.data.mjs +12 -0
  93. package/esm2020/decorators/object/object-decorator.data.mjs +7 -0
  94. package/esm2020/decorators/object/object.decorator.mjs +13 -0
  95. package/esm2020/decorators/string/string-decorator-internal.data.mjs +48 -0
  96. package/esm2020/decorators/string/string-decorator.data.mjs +7 -0
  97. package/esm2020/decorators/string/string.decorator.mjs +24 -0
  98. package/esm2020/public-api.mjs +20 -13
  99. package/fesm2015/ngx-material-entity.mjs +1664 -944
  100. package/fesm2015/ngx-material-entity.mjs.map +1 -1
  101. package/fesm2020/ngx-material-entity.mjs +1667 -941
  102. package/fesm2020/ngx-material-entity.mjs.map +1 -1
  103. package/package.json +7 -1
  104. package/public-api.d.ts +21 -10
  105. package/classes/entity-model.class.d.ts +0 -9
  106. package/classes/entity-utilities.class.d.ts +0 -95
  107. package/components/input/array-table/add-array-item-dialog/add-array-item-dialog.component.d.ts +0 -35
  108. package/components/input/array-table/add-array-item-dialog/add-array-item-dialog.module.d.ts +0 -12
  109. package/components/input/array-table/array-table.component.d.ts +0 -34
  110. package/components/input/array-table/array-table.module.d.ts +0 -19
  111. package/components/input/internal-input/internal-input.component.d.ts +0 -57
  112. package/components/input/internal-input/internal-input.module.d.ts +0 -16
  113. package/decorators/array.decorator.d.ts +0 -125
  114. package/decorators/base/property-decorator-config.interface.d.ts +0 -50
  115. package/decorators/boolean.decorator.d.ts +0 -42
  116. package/decorators/number.decorator.d.ts +0 -40
  117. package/decorators/object.decorator.d.ts +0 -27
  118. package/decorators/string.decorator.d.ts +0 -76
  119. package/esm2020/classes/entity-model.class.mjs +0 -19
  120. package/esm2020/classes/entity-service.class.mjs +0 -70
  121. package/esm2020/classes/entity-utilities.class.mjs +0 -296
  122. package/esm2020/components/input/array-table/add-array-item-dialog/add-array-item-dialog.component.mjs +0 -43
  123. package/esm2020/components/input/array-table/add-array-item-dialog/add-array-item-dialog.module.mjs +0 -22
  124. package/esm2020/components/input/array-table/array-table.component.mjs +0 -116
  125. package/esm2020/components/input/array-table/array-table.module.mjs +0 -66
  126. package/esm2020/components/input/internal-input/internal-input.component.mjs +0 -73
  127. package/esm2020/components/input/internal-input/internal-input.module.mjs +0 -54
  128. package/esm2020/decorators/array.decorator.mjs +0 -70
  129. package/esm2020/decorators/base/property-decorator-config.interface.mjs +0 -31
  130. package/esm2020/decorators/boolean.decorator.mjs +0 -44
  131. package/esm2020/decorators/number.decorator.mjs +0 -36
  132. package/esm2020/decorators/object.decorator.mjs +0 -23
  133. package/esm2020/decorators/string.decorator.mjs +0 -61
@@ -1,30 +1,52 @@
1
- import { Component, Input } from '@angular/core';
2
- import { EntityUtilities } from '../../classes/entity-utilities.class';
1
+ import { Component, Input, TemplateRef, ViewChild } from '@angular/core';
2
+ import { EntityUtilities } from '../../classes/entity.utilities';
3
3
  import { DecoratorTypes } from '../../decorators/base/decorator-types.enum';
4
4
  import { getValidationErrorMessage } from '../get-validation-error-message.function';
5
5
  import { cloneDeep } from 'lodash';
6
+ import { MatTableDataSource } from '@angular/material/table';
7
+ import { SelectionModel } from '@angular/cdk/collections';
8
+ import { AddArrayItemDialogDataBuilder } from './add-array-item-dialog-data.builder';
9
+ import { MatDialog } from '@angular/material/dialog';
10
+ import { DateUtilities } from '../../classes/date.utilities';
6
11
  import * as i0 from "@angular/core";
7
- import * as i1 from "@angular/material/form-field";
8
- import * as i2 from "@angular/material/autocomplete";
9
- import * as i3 from "@angular/material/core";
10
- import * as i4 from "@angular/material/select";
11
- import * as i5 from "@angular/material/checkbox";
12
- import * as i6 from "@angular/material/slide-toggle";
13
- import * as i7 from "./array-table/array-table.component";
14
- import * as i8 from "@angular/material/chips";
15
- import * as i9 from "@angular/material/icon";
16
- import * as i10 from "@angular/common";
17
- import * as i11 from "@angular/material/input";
18
- import * as i12 from "@angular/forms";
19
- import * as i13 from "@angular/cdk/text-field";
12
+ import * as i1 from "@angular/material/dialog";
13
+ import * as i2 from "@angular/material/form-field";
14
+ import * as i3 from "@angular/material/autocomplete";
15
+ import * as i4 from "@angular/material/core";
16
+ import * as i5 from "@angular/material/select";
17
+ import * as i6 from "@angular/material/checkbox";
18
+ import * as i7 from "@angular/material/slide-toggle";
19
+ import * as i8 from "@angular/material/button";
20
+ import * as i9 from "@angular/material/table";
21
+ import * as i10 from "@angular/material/chips";
22
+ import * as i11 from "@angular/material/datepicker";
23
+ import * as i12 from "@angular/common";
24
+ import * as i13 from "@angular/material/input";
25
+ import * as i14 from "@angular/forms";
26
+ import * as i15 from "@angular/cdk/text-field";
27
+ /**
28
+ * The default input component. It gets the metadata of the property from the given @Input "entity" and @Input "propertyKey"
29
+ * and displays the input field accordingly.
30
+ *
31
+ * You can also define a method that generates error-messages and if the input should be hidden when its metadata says
32
+ * that it should be omitted for creating or updating.
33
+ * The last part being mostly relevant if you want to use this component inside an ngFor.
34
+ */
20
35
  export class NgxMatEntityInputComponent {
21
- constructor() {
36
+ constructor(dialog) {
37
+ this.dialog = dialog;
22
38
  this.chipsInput = '';
39
+ this.selection = new SelectionModel(true, []);
23
40
  this.DecoratorTypes = DecoratorTypes;
24
- this.getWidth = EntityUtilities.getWidth;
41
+ this.EntityUtilities = EntityUtilities;
42
+ this.DateUtilities = DateUtilities;
43
+ this.defaultDateFilter = () => true;
25
44
  }
26
45
  /**
27
- * Helper method needed to recursively generate property input components (used eg. with the object)
46
+ * This is needed for the inputs to work inside an ngFor.
47
+ *
48
+ * @param index - The index of the element in the ngFor.
49
+ * @returns The index.
28
50
  */
29
51
  trackByFn(index) {
30
52
  return index;
@@ -45,12 +67,19 @@ export class NgxMatEntityInputComponent {
45
67
  this.filteredAutocompleteStrings = cloneDeep(this.autocompleteStrings);
46
68
  this.metadataDropdownString = this.metadata;
47
69
  this.metadataDropdownBoolean = this.metadata;
70
+ if ((this.type === DecoratorTypes.BOOLEAN_CHECKBOX || this.type === DecoratorTypes.BOOLEAN_TOGGLE)
71
+ && this.entity[this.propertyKey] === undefined) {
72
+ this.entity[this.propertyKey] = false;
73
+ }
48
74
  this.metadataDefaultNumber = this.metadata;
49
75
  this.metadataDropdownNumber = this.metadata;
50
76
  this.metadataDefaultObject = this.metadata;
51
77
  this.objectProperty = this.entity[this.propertyKey];
78
+ if (this.type === DecoratorTypes.OBJECT) {
79
+ this.objectPropertyRows = EntityUtilities.getEntityRows(this.objectProperty, this.hideOmitForCreate, this.hideOmitForEdit);
80
+ }
52
81
  this.metadataEntityArray = this.metadata;
53
- if (this.metadataEntityArray.EntityClass) {
82
+ if (this.type === DecoratorTypes.ARRAY) {
54
83
  if (!this.entity[this.propertyKey]) {
55
84
  this.entity[this.propertyKey] = [];
56
85
  }
@@ -63,9 +92,27 @@ export class NgxMatEntityInputComponent {
63
92
  title: 'Add'
64
93
  };
65
94
  }
95
+ const givenDisplayColumns = this.metadataEntityArray.displayColumns.map((v) => v.displayName);
96
+ if (givenDisplayColumns.find(s => s === 'select')) {
97
+ throw new Error(`The name "select" for a display column is reserved.
98
+ Please choose a different name.`);
99
+ }
100
+ this.displayedColumns = ['select'].concat(givenDisplayColumns);
101
+ this.dataSource = new MatTableDataSource();
102
+ this.dataSource.data = this.entityArrayValues;
103
+ this.arrayItem = new this.metadataEntityArray.EntityClass();
104
+ this.arrayItemInlineRows = EntityUtilities.getEntityRows(this.arrayItem, this.hideOmitForCreate === false ? false : true, this.hideOmitForEdit ? true : false);
105
+ this.arrayItemPriorChanges = cloneDeep(this.arrayItem);
106
+ this.dialogInputData = {
107
+ entity: this.arrayItem,
108
+ createDialogData: this.metadataEntityArray.createDialogData,
109
+ getValidationErrorMessage: this.getValidationErrorMessage
110
+ };
111
+ this.dialogData = new AddArrayItemDialogDataBuilder(this.dialogInputData).getResult();
112
+ this.arrayItemDialogRows = EntityUtilities.getEntityRows(this.dialogData.entity, true);
66
113
  }
67
114
  this.metadataStringChipsArray = this.metadata;
68
- if (this.metadataStringChipsArray.itemType
115
+ if ((this.type === DecoratorTypes.ARRAY_STRING_CHIPS || this.type === DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS)
69
116
  && this.entity[this.propertyKey]?.length) {
70
117
  this.stringChipsArrayValues = this.entity[this.propertyKey];
71
118
  }
@@ -73,18 +120,149 @@ export class NgxMatEntityInputComponent {
73
120
  if (!this.getValidationErrorMessage) {
74
121
  this.getValidationErrorMessage = getValidationErrorMessage;
75
122
  }
76
- }
77
- getObjectProperties() {
78
- const res = [];
79
- for (const property in this.objectProperty) {
80
- const metadata = EntityUtilities.getPropertyMetadata(this.objectProperty, property, EntityUtilities.getPropertyType(this.objectProperty, property));
81
- if (!(this.hideOmitForCreate && metadata.omitForCreate)
82
- && !(this.hideOmitForEdit && metadata.omitForUpdate)) {
83
- res.push(property);
123
+ this.metadataDefaultDate = this.metadata;
124
+ this.metadataDateRangeDate = this.metadata;
125
+ this.metadataDateTimeDate = this.metadata;
126
+ if (this.type === DecoratorTypes.DATE_RANGE) {
127
+ this.dateRange = cloneDeep(this.entity[this.propertyKey]);
128
+ if (!this.dateRange) {
129
+ this.dateRange = {
130
+ start: undefined,
131
+ end: undefined,
132
+ values: undefined
133
+ };
134
+ }
135
+ this.dateRangeStart = new Date(this.dateRange.start);
136
+ this.dateRangeEnd = new Date(this.dateRange.end);
137
+ this.setDateRangeValues();
138
+ }
139
+ if (this.type === DecoratorTypes.DATE_TIME) {
140
+ this.time = DateUtilities.getTimeFromDate(DateUtilities.asDate(this.entity[this.propertyKey]));
141
+ this.timeDropdownValues = this.metadataDateTimeDate.times;
142
+ if (this.entity[this.propertyKey]) {
143
+ this.dateTime = new Date(this.entity[this.propertyKey]);
84
144
  }
85
145
  }
86
- return res.sort((a, b) => EntityUtilities.compareOrder(a, b, this.objectProperty));
87
146
  }
147
+ /**
148
+ * Checks if two times are equal. Is needed for the dropdown.
149
+ *
150
+ * @param time1 - The first time to compare.
151
+ * @param time2 - The second time to compare.
152
+ * @returns Whether or not the time objects are the same.
153
+ */
154
+ compareTimes(time1, time2) {
155
+ return time1 && time2 && time1.hours === time2.hours && time1.minutes === time2.minutes;
156
+ }
157
+ /**
158
+ * Updates the date range values based on the start and end date.
159
+ */
160
+ setDateRangeValues() {
161
+ if (this.dateRangeStart && this.dateRangeEnd) {
162
+ this.dateRange.start = new Date(this.dateRangeStart);
163
+ this.dateRange.end = new Date(this.dateRangeEnd);
164
+ const values = DateUtilities.getDatesBetween(new Date(this.dateRange.start), new Date(this.dateRange.end), this.metadataDateRangeDate);
165
+ this.dateRange.values = values.length ? values : undefined;
166
+ }
167
+ else {
168
+ this.dateRange.values = undefined;
169
+ }
170
+ this.entity[this.propertyKey] = this.dateRange;
171
+ }
172
+ /**
173
+ * Sets the time on a datetime property.
174
+ */
175
+ setTime() {
176
+ if (!this.dateTime) {
177
+ this.entity[this.propertyKey] = undefined;
178
+ return;
179
+ }
180
+ this.entity[this.propertyKey] = new Date(this.dateTime);
181
+ if (this.time?.hours != null && this.time?.minutes != null) {
182
+ DateUtilities.asDate(this.entity[this.propertyKey]).setHours(this.time.hours, this.time.minutes, 0, 0);
183
+ }
184
+ else {
185
+ DateUtilities.asDate(this.entity[this.propertyKey]).setHours(0, 0, 0, 0);
186
+ }
187
+ }
188
+ /**
189
+ * Tries to add an item to the array.
190
+ * Does this either inline if the "createInline"-metadata is set to true
191
+ * or in a separate dialog if it is set to false.
192
+ */
193
+ add() {
194
+ if (this.metadataEntityArray.createInline) {
195
+ this.entityArrayValues.push(cloneDeep(this.arrayItem));
196
+ this.dataSource.data = this.entityArrayValues;
197
+ EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
198
+ }
199
+ else {
200
+ this.addArrayItemDialogRef = this.dialog.open(this.addArrayItemDialog, {
201
+ data: this.dialogData,
202
+ autoFocus: false,
203
+ restoreFocus: false
204
+ });
205
+ }
206
+ }
207
+ /**
208
+ * Adds the array item defined in the dialog.
209
+ */
210
+ addArrayItem() {
211
+ this.addArrayItemDialogRef.close();
212
+ this.entityArrayValues.push(cloneDeep(this.arrayItem));
213
+ this.dataSource.data = this.entityArrayValues;
214
+ EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
215
+ }
216
+ /**
217
+ * Cancels adding the array item defined in the dialog.
218
+ */
219
+ cancelAddArrayItem() {
220
+ this.addArrayItemDialogRef.close();
221
+ EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
222
+ }
223
+ /**
224
+ * Removes all selected entries from the array.
225
+ */
226
+ remove() {
227
+ this.selection.selected.forEach(s => {
228
+ this.entityArrayValues.splice(this.entityArrayValues.indexOf(s), 1);
229
+ });
230
+ this.dataSource.data = this.entityArrayValues;
231
+ this.selection.clear();
232
+ }
233
+ /**
234
+ * Toggles all array-items in the table.
235
+ */
236
+ masterToggle() {
237
+ if (this.isAllSelected()) {
238
+ this.selection.clear();
239
+ }
240
+ else {
241
+ this.dataSource.data.forEach(row => this.selection.select(row));
242
+ }
243
+ }
244
+ /**
245
+ * Checks if all array-items in the table have been selected.
246
+ * This is needed to display the "masterToggle"-checkbox correctly.
247
+ *
248
+ * @returns Whether or not all array-items in the table have been selected.
249
+ */
250
+ isAllSelected() {
251
+ const numSelected = this.selection.selected.length;
252
+ const numRows = this.dataSource.data.length;
253
+ return numSelected === numRows;
254
+ }
255
+ /**
256
+ * Handles adding strings to the chipsArray.
257
+ * Checks validation and also creates a new array if it is undefined.
258
+ * This is needed because two things are validated: The array itself
259
+ * and the contents of the array. And we need a way to display an
260
+ * mat-error. As the only validation for the array is whether or not
261
+ * it contains values, we can set it to undefined when the last element is removed
262
+ * (removeStringChipArrayValue). That way we can use the "required" validator.
263
+ *
264
+ * @param event - The event that fires when a new chip is completed.
265
+ */
88
266
  addStringChipArrayValue(event) {
89
267
  const value = (event.value || '').trim();
90
268
  if (value) {
@@ -107,6 +285,16 @@ export class NgxMatEntityInputComponent {
107
285
  }
108
286
  event.chipInput.clear();
109
287
  }
288
+ /**
289
+ * Removes the given value from the array.
290
+ * Sets the array to undefined if it is now empty.
291
+ * This is needed because two things are validated: The array itself
292
+ * and the contents of the array. And we need a way to display an
293
+ * mat-error. As the only validation for the array is whether or not
294
+ * it is empty, setting it to undefined here enables us to use the "required" validator.
295
+ *
296
+ * @param value - The string to remove from the array.
297
+ */
110
298
  removeStringChipArrayValue(value) {
111
299
  this.stringChipsArrayValues.splice(this.stringChipsArrayValues.indexOf(value), 1);
112
300
  if (!this.stringChipsArrayValues.length) {
@@ -114,6 +302,12 @@ export class NgxMatEntityInputComponent {
114
302
  this.stringChipsArrayValues = this.entity[this.propertyKey];
115
303
  }
116
304
  }
305
+ /**
306
+ * Handles adding a string to the array when an autocomplete value has been selected.
307
+ *
308
+ * @param event - The autocomplete selected event.
309
+ * @param chipsInput - The element where the user typed the value.
310
+ */
117
311
  selected(event, chipsInput) {
118
312
  const value = (event.option.viewValue || '').trim();
119
313
  if (this.metadataStringChipsArray.minLength && value.length < this.metadataStringChipsArray.minLength) {
@@ -134,17 +328,24 @@ export class NgxMatEntityInputComponent {
134
328
  this.stringChipsArrayValues.push(value);
135
329
  chipsInput.value = '';
136
330
  }
331
+ /**
332
+ * Dynamically filters the Autocomplete options when the user inputs something.
333
+ *
334
+ * @param input - The input of the user.
335
+ */
137
336
  filterAutocompleteStrings(input) {
138
- const filterValue = input.toLowerCase();
139
- this.filteredAutocompleteStrings = this.autocompleteStrings.filter(s => s.toLowerCase().includes(filterValue));
337
+ if (input) {
338
+ const filterValue = input.toLowerCase();
339
+ this.filteredAutocompleteStrings = this.autocompleteStrings.filter(s => s.toLowerCase().includes(filterValue));
340
+ }
140
341
  }
141
342
  }
142
- NgxMatEntityInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
143
- NgxMatEntityInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: { entity: "entity", propertyKey: "propertyKey", getValidationErrorMessage: "getValidationErrorMessage", hideOmitForCreate: "hideOmitForCreate", hideOmitForEdit: "hideOmitForEdit" }, ngImport: i0, template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required ? metadata.required : false\"\n [pattern]=\"metadataDefaultString.regex ? metadataDefaultString.regex : '[\\\\s\\\\S]*'\"\n [minlength]=\"metadataDefaultString.minLength ? metadataDefaultString.minLength : null\"\n [maxlength]=\"metadataDefaultString.maxLength ? metadataDefaultString.maxLength : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required ? metadata.required : false\"\n [minlength]=\"metadataTextboxString.minLength ? metadataTextboxString.minLength : null\"\n [maxlength]=\"metadataTextboxString.maxLength ? metadataTextboxString.maxLength : null\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[propertyKey])\"\n [required]=\"metadata.required ? metadata.required : false\"\n [minlength]=\"metadataAutocompleteString.minLength ? metadataAutocompleteString.minLength : null\"\n [maxlength]=\"metadataAutocompleteString.maxLength ? metadataAutocompleteString.maxLength : null\"\n [pattern]=\"metadataAutocompleteString.regex ? metadataAutocompleteString.regex : '[\\\\s\\\\S]*'\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n <mat-option *ngFor=\"let value of metadataDropdownString.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <mat-form-field>\n <mat-checkbox [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n {{metadata.displayName}}\n </mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <textarea matInput hidden></textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <mat-form-field>\n <mat-slide-toggle [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n {{metadata.displayName}}\n </mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <textarea matInput hidden></textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadataDropdownBoolean.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadataDropdownBoolean.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required ? metadata.required : false\"\n [min]=\"metadataDefaultNumber.min ? metadataDefaultNumber.min : null\"\n [max]=\"metadataDefaultNumber.max ? metadataDefaultNumber.max : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n <mat-option *ngFor=\"let value of metadataDropdownNumber.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n <div class=\"row\">\n <!--\n displays another ngx-material-entity with the:\n object as the entity,\n the current key in the loop received by the keyvalue direction as the propertyKey\n and the getValidationErrorMessage of the current component\n -->\n <ngx-mat-entity-input\n *ngFor=\"let key of getObjectProperties(); let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{getWidth(objectProperty, key, 'lg')}} col-md-{{getWidth(objectProperty, key, 'md')}} col-sm-{{getWidth(objectProperty, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <ngx-mat-entity-array-table\n [arrayItems]=\"entityArrayValues\"\n [metadata]=\"metadataEntityArray\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [omit]=\"hideOmitForCreate ? 'create' : 'edit'\"\n >\n </ngx-mat-entity-array-table>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required ? metadata.required : false\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove *ngIf=\"metadataStringChipsArray.deleteHtml\" [innerHtml]=\"metadataStringChipsArray.deleteHtml\">\n </button>\n <button matChipRemove *ngIf=\"!metadataStringChipsArray.deleteHtml\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required ? metadata.required : false\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove *ngIf=\"metadataStringChipsArray.deleteHtml\" [innerHtml]=\"metadataStringChipsArray.deleteHtml\">\n </button>\n <button matChipRemove *ngIf=\"!metadataStringChipsArray.deleteHtml\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}}is not known.</div>\n</div>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["disableRipple"], exportAs: ["matAutocomplete"] }, { type: i3.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { type: i4.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i6.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"] }, { type: i7.NgxMatEntityArrayTableComponent, selector: "ngx-mat-entity-array-table", inputs: ["arrayItems", "metadata", "getValidationErrorMessage", "omit"] }, { type: i8.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { type: i9.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i10.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i10.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i10.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i1.MatLabel, selector: "mat-label" }, { type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i12.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i12.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i12.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i12.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i12.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i12.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i12.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i1.MatError, selector: "mat-error", inputs: ["id"] }, { type: i13.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { type: i2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { type: i10.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.MatCheckboxRequiredValidator, selector: "mat-checkbox[required][formControlName], mat-checkbox[required][formControl], mat-checkbox[required][ngModel]" }, { type: i6.MatSlideToggleRequiredValidator, selector: "mat-slide-toggle[required][formControlName], mat-slide-toggle[required][formControl], mat-slide-toggle[required][ngModel]" }, { type: i12.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i12.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i12.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i8.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disableRipple", "tabIndex", "selected", "value", "selectable", "disabled", "removable"], outputs: ["selectionChange", "destroyed", "removed"], exportAs: ["matChip"] }, { type: i8.MatChipRemove, selector: "[matChipRemove]" }, { type: i8.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i10.NgSwitchDefault, selector: "[ngSwitchDefault]" }] });
343
+ NgxMatEntityInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
344
+ NgxMatEntityInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: { entity: "entity", propertyKey: "propertyKey", getValidationErrorMessage: "getValidationErrorMessage", hideOmitForCreate: "hideOmitForCreate", hideOmitForEdit: "hideOmitForEdit" }, viewQueries: [{ propertyName: "addArrayItemDialog", first: true, predicate: ["addArrayItemDialog"], descendants: true }], ngImport: i0, template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [pattern]=\"metadataDefaultString.regex ? metadataDefaultString.regex : '[\\\\s\\\\S]*'\"\n [minlength]=\"metadataDefaultString.minLength ? metadataDefaultString.minLength : null\"\n [maxlength]=\"metadataDefaultString.maxLength ? metadataDefaultString.maxLength : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataTextboxString.minLength ? metadataTextboxString.minLength : null\"\n [maxlength]=\"metadataTextboxString.maxLength ? metadataTextboxString.maxLength : null\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[propertyKey])\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataAutocompleteString.minLength ? metadataAutocompleteString.minLength : null\"\n [maxlength]=\"metadataAutocompleteString.maxLength ? metadataAutocompleteString.maxLength : null\"\n [pattern]=\"metadataAutocompleteString.regex ? metadataAutocompleteString.regex : '[\\\\s\\\\S]*'\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownString.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadataDropdownBoolean.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadataDropdownBoolean.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultNumber.min ? metadataDefaultNumber.min : null\"\n [max]=\"metadataDefaultNumber.max ? metadataDefaultNumber.max : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownNumber.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n\n <div class=\"row\" *ngFor=\"let row of objectPropertyRows\">\n <!--\n displays another ngx-material-entity with the:\n object as the entity,\n the current key in the loop received by the keyvalue direction as the propertyKey\n and the getValidationErrorMessage of the current component\n -->\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{EntityUtilities.getWidth(objectProperty, key, 'lg')}} col-md-{{EntityUtilities.getWidth(objectProperty, key, 'md')}} col-sm-{{EntityUtilities.getWidth(objectProperty, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n\n <div style=\"padding-bottom: 10px\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(arrayItem, key, 'lg')}} col-md-{{EntityUtilities.getWidth(arrayItem, key, 'md')}} col-sm-{{EntityUtilities.getWidth(arrayItem, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !EntityUtilities.isEntityValid(arrayItem, 'create')\"\n (click)=\"add()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadataEntityArray.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required && !dataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultDate.min ? metadataDefaultDate.min(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [max]=\"metadataDefaultDate.max ? metadataDefaultDate.max(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [matDatepickerFilter]=\"metadataDefaultDate.filter ? metadataDefaultDate.filter : defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadataDateRangeDate.filter ? metadataDateRangeDate.filter : defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"propertyKey.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minStart ? metadataDateRangeDate.minStart(dateRange.start) : undefined\"\n [max]=\"metadataDateRangeDate.maxStart ? metadataDateRangeDate.maxStart(dateRange.start) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderStart ? metadataDateRangeDate.placeholderStart : 'Start'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"propertyKey.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minEnd ? metadataDateRangeDate.minEnd(dateRange.end) : undefined\"\n [max]=\"metadataDateRangeDate.maxEnd ? metadataDateRangeDate.maxEnd(dateRange.end) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderEnd ? metadataDateRangeDate.placeholderEnd : 'End'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\" class=\"date-time\">\n <mat-form-field appearance=\"standard\" class=\"datepicker\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"dateTime\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateTimeDate.minDate ? metadataDateTimeDate.minDate(dateTime) : undefined\"\n [max]=\"metadataDateTimeDate.maxDate ? metadataDateTimeDate.maxDate(dateTime) : undefined\"\n [matDatepickerFilter]=\"metadataDateTimeDate.filterDate ? metadataDateTimeDate.filterDate : defaultDateFilter\"\n (dateInput)=\"setTime()\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadataDateTimeDate.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"propertyKey.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n [compareWith]=\"compareTimes\"\n (ngModelChange)=\"setTime()\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(entity[propertyKey]),\n metadataDateTimeDate.times,\n metadataDateTimeDate.minTime,\n metadataDateTimeDate.maxTime,\n metadataDateTimeDate.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <h2 mat-dialog-title>{{dialogData.createDialogData.title}}</h2>\n\n <mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"dialogData.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"dialogData.getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(dialogData.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(dialogData.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(dialogData.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!EntityUtilities.isEntityValid(dialogData.entity, 'create')\">\n {{dialogData.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancelAddArrayItem()\" class=\"cancel-button\">\n {{dialogData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n\n</ng-template>", styles: ["mat-form-field{width:100%}::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}.entityArray .buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}.entityArray mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.entityArray .mat-column-select{flex:0 0 75px}.entityArray .array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"], components: [{ type: i2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3.MatAutocomplete, selector: "mat-autocomplete", inputs: ["disableRipple"], exportAs: ["matAutocomplete"] }, { type: i4.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { type: i5.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"] }, { type: i8.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { type: i10.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { type: i11.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i11.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i11.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i11.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }], directives: [{ type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i12.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i12.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i2.MatLabel, selector: "mat-label" }, { type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i14.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i14.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i14.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i14.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i2.MatError, selector: "mat-error", inputs: ["id"] }, { type: i15.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { type: i3.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i14.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i14.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i14.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i9.MatCellDef, selector: "[matCellDef]" }, { type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { type: i10.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disableRipple", "tabIndex", "selected", "value", "selectable", "disabled", "removable"], outputs: ["selectionChange", "destroyed", "removed"], exportAs: ["matChip"] }, { type: i10.MatChipRemove, selector: "[matChipRemove]" }, { type: i10.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i11.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i2.MatSuffix, selector: "[matSuffix]" }, { type: i11.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i11.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i12.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i14.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
144
345
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, decorators: [{
145
346
  type: Component,
146
- args: [{ selector: 'ngx-mat-entity-input', template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required ? metadata.required : false\"\n [pattern]=\"metadataDefaultString.regex ? metadataDefaultString.regex : '[\\\\s\\\\S]*'\"\n [minlength]=\"metadataDefaultString.minLength ? metadataDefaultString.minLength : null\"\n [maxlength]=\"metadataDefaultString.maxLength ? metadataDefaultString.maxLength : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required ? metadata.required : false\"\n [minlength]=\"metadataTextboxString.minLength ? metadataTextboxString.minLength : null\"\n [maxlength]=\"metadataTextboxString.maxLength ? metadataTextboxString.maxLength : null\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[propertyKey])\"\n [required]=\"metadata.required ? metadata.required : false\"\n [minlength]=\"metadataAutocompleteString.minLength ? metadataAutocompleteString.minLength : null\"\n [maxlength]=\"metadataAutocompleteString.maxLength ? metadataAutocompleteString.maxLength : null\"\n [pattern]=\"metadataAutocompleteString.regex ? metadataAutocompleteString.regex : '[\\\\s\\\\S]*'\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n <mat-option *ngFor=\"let value of metadataDropdownString.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <mat-form-field>\n <mat-checkbox [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n {{metadata.displayName}}\n </mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <textarea matInput hidden></textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <mat-form-field>\n <mat-slide-toggle [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n {{metadata.displayName}}\n </mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <textarea matInput hidden></textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadataDropdownBoolean.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadataDropdownBoolean.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required ? metadata.required : false\"\n [min]=\"metadataDefaultNumber.min ? metadataDefaultNumber.min : null\"\n [max]=\"metadataDefaultNumber.max ? metadataDefaultNumber.max : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required ? metadata.required : false\">\n <mat-option *ngFor=\"let value of metadataDropdownNumber.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n <div class=\"row\">\n <!--\n displays another ngx-material-entity with the:\n object as the entity,\n the current key in the loop received by the keyvalue direction as the propertyKey\n and the getValidationErrorMessage of the current component\n -->\n <ngx-mat-entity-input\n *ngFor=\"let key of getObjectProperties(); let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{getWidth(objectProperty, key, 'lg')}} col-md-{{getWidth(objectProperty, key, 'md')}} col-sm-{{getWidth(objectProperty, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <ngx-mat-entity-array-table\n [arrayItems]=\"entityArrayValues\"\n [metadata]=\"metadataEntityArray\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [omit]=\"hideOmitForCreate ? 'create' : 'edit'\"\n >\n </ngx-mat-entity-array-table>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required ? metadata.required : false\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove *ngIf=\"metadataStringChipsArray.deleteHtml\" [innerHtml]=\"metadataStringChipsArray.deleteHtml\">\n </button>\n <button matChipRemove *ngIf=\"!metadataStringChipsArray.deleteHtml\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required ? metadata.required : false\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove *ngIf=\"metadataStringChipsArray.deleteHtml\" [innerHtml]=\"metadataStringChipsArray.deleteHtml\">\n </button>\n <button matChipRemove *ngIf=\"!metadataStringChipsArray.deleteHtml\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}}is not known.</div>\n</div>", styles: ["mat-form-field{width:100%}\n"] }]
147
- }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
347
+ args: [{ selector: 'ngx-mat-entity-input', template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [pattern]=\"metadataDefaultString.regex ? metadataDefaultString.regex : '[\\\\s\\\\S]*'\"\n [minlength]=\"metadataDefaultString.minLength ? metadataDefaultString.minLength : null\"\n [maxlength]=\"metadataDefaultString.maxLength ? metadataDefaultString.maxLength : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataTextboxString.minLength ? metadataTextboxString.minLength : null\"\n [maxlength]=\"metadataTextboxString.maxLength ? metadataTextboxString.maxLength : null\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[propertyKey])\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataAutocompleteString.minLength ? metadataAutocompleteString.minLength : null\"\n [maxlength]=\"metadataAutocompleteString.maxLength ? metadataAutocompleteString.maxLength : null\"\n [pattern]=\"metadataAutocompleteString.regex ? metadataAutocompleteString.regex : '[\\\\s\\\\S]*'\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownString.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadataDropdownBoolean.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadataDropdownBoolean.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultNumber.min ? metadataDefaultNumber.min : null\"\n [max]=\"metadataDefaultNumber.max ? metadataDefaultNumber.max : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownNumber.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n\n <div class=\"row\" *ngFor=\"let row of objectPropertyRows\">\n <!--\n displays another ngx-material-entity with the:\n object as the entity,\n the current key in the loop received by the keyvalue direction as the propertyKey\n and the getValidationErrorMessage of the current component\n -->\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{EntityUtilities.getWidth(objectProperty, key, 'lg')}} col-md-{{EntityUtilities.getWidth(objectProperty, key, 'md')}} col-sm-{{EntityUtilities.getWidth(objectProperty, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n\n <div style=\"padding-bottom: 10px\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(arrayItem, key, 'lg')}} col-md-{{EntityUtilities.getWidth(arrayItem, key, 'md')}} col-sm-{{EntityUtilities.getWidth(arrayItem, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !EntityUtilities.isEntityValid(arrayItem, 'create')\"\n (click)=\"add()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadataEntityArray.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required && !dataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultDate.min ? metadataDefaultDate.min(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [max]=\"metadataDefaultDate.max ? metadataDefaultDate.max(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [matDatepickerFilter]=\"metadataDefaultDate.filter ? metadataDefaultDate.filter : defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadataDateRangeDate.filter ? metadataDateRangeDate.filter : defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"propertyKey.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minStart ? metadataDateRangeDate.minStart(dateRange.start) : undefined\"\n [max]=\"metadataDateRangeDate.maxStart ? metadataDateRangeDate.maxStart(dateRange.start) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderStart ? metadataDateRangeDate.placeholderStart : 'Start'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"propertyKey.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minEnd ? metadataDateRangeDate.minEnd(dateRange.end) : undefined\"\n [max]=\"metadataDateRangeDate.maxEnd ? metadataDateRangeDate.maxEnd(dateRange.end) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderEnd ? metadataDateRangeDate.placeholderEnd : 'End'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\" class=\"date-time\">\n <mat-form-field appearance=\"standard\" class=\"datepicker\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"dateTime\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateTimeDate.minDate ? metadataDateTimeDate.minDate(dateTime) : undefined\"\n [max]=\"metadataDateTimeDate.maxDate ? metadataDateTimeDate.maxDate(dateTime) : undefined\"\n [matDatepickerFilter]=\"metadataDateTimeDate.filterDate ? metadataDateTimeDate.filterDate : defaultDateFilter\"\n (dateInput)=\"setTime()\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadataDateTimeDate.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"propertyKey.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n [compareWith]=\"compareTimes\"\n (ngModelChange)=\"setTime()\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(entity[propertyKey]),\n metadataDateTimeDate.times,\n metadataDateTimeDate.minTime,\n metadataDateTimeDate.maxTime,\n metadataDateTimeDate.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <h2 mat-dialog-title>{{dialogData.createDialogData.title}}</h2>\n\n <mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"dialogData.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"dialogData.getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(dialogData.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(dialogData.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(dialogData.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!EntityUtilities.isEntityValid(dialogData.entity, 'create')\">\n {{dialogData.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancelAddArrayItem()\" class=\"cancel-button\">\n {{dialogData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n\n</ng-template>", styles: ["mat-form-field{width:100%}::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}.entityArray .buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}.entityArray mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.entityArray .mat-column-select{flex:0 0 75px}.entityArray .array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"] }]
348
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
148
349
  type: Input
149
350
  }], propertyKey: [{
150
351
  type: Input
@@ -154,5 +355,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
154
355
  type: Input
155
356
  }], hideOmitForEdit: [{
156
357
  type: Input
358
+ }], addArrayItemDialog: [{
359
+ type: ViewChild,
360
+ args: ['addArrayItemDialog']
157
361
  }] } });
158
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LW1hdGVyaWFsLWVudGl0eS9zcmMvY29tcG9uZW50cy9pbnB1dC9pbnB1dC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtbWF0ZXJpYWwtZW50aXR5L3NyYy9jb21wb25lbnRzL2lucHV0L2lucHV0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBRXpELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUV2RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFFNUUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFRckYsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFFBQVEsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7O0FBT25DLE1BQU0sT0FBTywwQkFBMEI7SUFpRW5DO1FBUkEsZUFBVSxHQUFXLEVBQUUsQ0FBQztRQUlmLG1CQUFjLEdBQUcsY0FBYyxDQUFDO1FBRXpDLGFBQVEsR0FBRyxlQUFlLENBQUMsUUFBUSxDQUFDO0lBRXJCLENBQUM7SUFFaEI7O09BRUc7SUFDSCxTQUFTLENBQUMsS0FBYztRQUNwQixPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBRUQsUUFBUTtRQUNKLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2QsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO1NBQzNEO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1NBQ2hFO1FBQ0QsSUFBSSxDQUFDLElBQUksR0FBRyxlQUFl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THRDLFNBQVM7K0JBQ0ksc0JBQXNCOzBFQVVoQyxNQUFNO3NCQURMLEtBQUs7Z0JBT04sV0FBVztzQkFEVixLQUFLO2dCQU9OLHlCQUF5QjtzQkFEeEIsS0FBSztnQkFRTixpQkFBaUI7c0JBRGhCLEtBQUs7Z0JBUU4sZUFBZTtzQkFEZCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZ01vZGVsIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgRW50aXR5VXRpbGl0aWVzIH0gZnJvbSAnLi4vLi4vY2xhc3Nlcy9lbnRpdHktdXRpbGl0aWVzLmNsYXNzJztcbmltcG9ydCB7IEVudGl0eSB9IGZyb20gJy4uLy4uL2NsYXNzZXMvZW50aXR5LW1vZGVsLmNsYXNzJztcbmltcG9ydCB7IERlY29yYXRvclR5cGVzIH0gZnJvbSAnLi4vLi4vZGVjb3JhdG9ycy9iYXNlL2RlY29yYXRvci10eXBlcy5lbnVtJztcbmltcG9ydCB7IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnIH0gZnJvbSAnLi4vLi4vZGVjb3JhdG9ycy9iYXNlL3Byb3BlcnR5LWRlY29yYXRvci1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IGdldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UgfSBmcm9tICcuLi9nZXQtdmFsaWRhdGlvbi1lcnJvci1tZXNzYWdlLmZ1bmN0aW9uJztcbmltcG9ydCB7IEF1dG9jb21wbGV0ZVN0cmluZ0RlY29yYXRvckNvbmZpZywgRGVmYXVsdFN0cmluZ0RlY29yYXRvckNvbmZpZywgRHJvcGRvd25TdHJpbmdEZWNvcmF0b3JDb25maWcsIFRleHRib3hTdHJpbmdEZWNvcmF0b3JDb25maWcgfSBmcm9tICcuLi8uLi9kZWNvcmF0b3JzL3N0cmluZy5kZWNvcmF0b3InO1xuaW1wb3J0IHsgRHJvcGRvd25Cb29sZWFuRGVjb3JhdG9yQ29uZmlnIH0gZnJvbSAnLi4vLi4vZGVjb3JhdG9ycy9ib29sZWFuLmRlY29yYXRvcic7XG5pbXBvcnQgeyBEZWZhdWx0TnVtYmVyRGVjb3JhdG9yQ29uZmlnLCBEcm9wZG93bk51bWJlckRlY29yYXRvckNvbmZpZyB9IGZyb20gJy4uLy4uL2RlY29yYXRvcnMvbnVtYmVyLmRlY29yYXRvcic7XG5pbXBvcnQgeyBEZWZhdWx0T2JqZWN0RGVjb3JhdG9yQ29uZmlnIH0gZnJvbSAnLi4vLi4vZGVjb3JhdG9ycy9vYmplY3QuZGVjb3JhdG9yJztcbmltcG9ydCB7IEF1dG9jb21wbGV0ZVN0cmluZ0NoaXBzQXJyYXlEZWNvcmF0b3JDb25maWcsIEVudGl0eUFycmF5RGVjb3JhdG9yQ29uZmlnLCBTdHJpbmdDaGlwc0FycmF5RGVjb3JhdG9yQ29uZmlnIH0gZnJvbSAnLi4vLi4vZGVjb3JhdG9ycy9hcnJheS5kZWNvcmF0b3InO1xuaW1wb3J0IHsgTWF0Q2hpcElucHV0RXZlbnQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jaGlwcyc7XG5pbXBvcnQgeyBNYXRBdXRvY29tcGxldGVTZWxlY3RlZEV2ZW50IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYXV0b2NvbXBsZXRlJztcbmltcG9ydCB7IGNsb25lRGVlcCB9IGZyb20gJ2xvZGFzaCc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnbmd4LW1hdC1lbnRpdHktaW5wdXQnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9pbnB1dC5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vaW5wdXQuY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hNYXRFbnRpdHlJbnB1dENvbXBvbmVudDxFbnRpdHlUeXBlIGV4dGVuZHMgRW50aXR5PiBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gICAgLyoqXG4gICAgICogVGhlIGVudGl0eSBvbiB3aGljaCB0aGUgcHJvcGVydHkgZXhpc3RzLiBVc2VkIGluIGNvbmp1Y3Rpb24gd2l0aCB0aGUgXCJwcm9wZXJ0eUtleVwiXG4gICAgICogdG8gZGV0ZXJtaW5lIHRoZSBwcm9wZXJ0eSBmb3Igd2hpY2ggdGhlIGlucHV0IHNob3VsZCBiZSBnZW5lcmF0ZWQuXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBlbnRpdHkhOiBFbnRpdHlUeXBlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIGdlbmVyYXRlIHRoZSBpbnB1dCBmb3IuIFVzZWQgaW4gY29uanVjdGlvbiB3aXRoIHRoZSBcImVudGl0eVwiLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHJvcGVydHlLZXkhOiBrZXlvZiBFbnRpdHlUeXBlO1xuXG4gICAgLyoqXG4gICAgICogKG9wdGlvbmFsKSBBIGN1c3RvbSBmdW5jdGlvbiB0byBnZW5lcmF0ZSB0aGUgZXJyb3ItbWVzc2FnZSBmb3IgaW52YWxpZCBpbnB1dHMuXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlITogKG1vZGVsOiBOZ01vZGVsKSA9PiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRvIGhpZGUgYSB2YWx1ZSBpZiBpdCBpcyBvbWl0dGVkIGZvciBjcmVhdGlvbi5cbiAgICAgKiBJcyB1c2VkIGludGVybmFsbHkgZm9yIHRoZSBvYmplY3QgcHJvcGVydHkuXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBoaWRlT21pdEZvckNyZWF0ZT86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRvIGhpZGUgYSB2YWx1ZSBpZiBpdCBpcyBvbWl0dGVkIGZvciBlZGl0aW5nLlxuICAgICAqIElzIHVzZWQgaW50ZXJuYWxseSBmb3IgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGhpZGVPbWl0Rm9yRWRpdD86IGJvb2xlYW47XG5cbiAgICB0eXBlITogRGVjb3JhdG9yVHlwZXM7XG5cbiAgICBtZXRhZGF0YSE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnO1xuXG4gICAgbWV0YWRhdGFEZWZhdWx0U3RyaW5nITogRGVmYXVsdFN0cmluZ0RlY29yYXRvckNvbmZpZztcbiAgICBtZXRhZGF0YVRleHRib3hTdHJpbmchOiBUZXh0Ym94U3RyaW5nRGVjb3JhdG9yQ29uZmlnO1xuICAgIG1ldGFkYXRhQXV0b2NvbXBsZXRlU3RyaW5nITogQXV0b2NvbXBsZXRlU3RyaW5nRGVjb3JhdG9yQ29uZmlnO1xuICAgIGF1dG9jb21wbGV0ZVN0cmluZ3MhOiBzdHJpbmdbXTtcbiAgICBmaWx0ZXJlZEF1dG9jb21wbGV0ZVN0cmluZ3MhOiBzdHJpbmdbXTtcbiAgICBtZXRhZGF0YURyb3Bkb3duU3RyaW5nITogRHJvcGRvd25TdHJpbmdEZWNvcmF0b3JDb25maWc7XG5cbiAgICBtZXRhZGF0YURyb3Bkb3duQm9vbGVhbiE6IERyb3Bkb3duQm9vbGVhbkRlY29yYXRvckNvbmZpZztcblxuICAgIG1ldGFkYXRhRGVmYXVsdE51bWJlciE6IERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWc7XG4gICAgbWV0YWRhdGFEcm9wZG93bk51bWJlciE6IERyb3Bkb3duTnVtYmVyRGVjb3JhdG9yQ29uZmlnO1xuXG4gICAgbWV0YWRhdGFEZWZhdWx0T2JqZWN0ITogRGVmYXVsdE9iamVjdERlY29yYXRvckNvbmZpZztcbiAgICBvYmplY3RQcm9wZXJ0eSE6IEVudGl0eTtcblxuICAgIG1ldGFkYXRhRW50aXR5QXJyYXkhOiBFbnRpdHlBcnJheURlY29yYXRvckNvbmZpZzxFbnRpdHk+O1xuICAgIGVudGl0eUFycmF5VmFsdWVzITogRW50aXR5W107XG4gICAgbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5ITogU3RyaW5nQ2hpcHNBcnJheURlY29yYXRvckNvbmZpZztcbiAgICBzdHJpbmdDaGlwc0FycmF5VmFsdWVzITogc3RyaW5nW107XG4gICAgY2hpcHNJbnB1dDogc3RyaW5nID0gJyc7XG5cbiAgICBtZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZ0NoaXBzQXJyYXkhOiBBdXRvY29tcGxldGVTdHJpbmdDaGlwc0FycmF5RGVjb3JhdG9yQ29uZmlnO1xuXG4gICAgcmVhZG9ubHkgRGVjb3JhdG9yVHlwZXMgPSBEZWNvcmF0b3JUeXBlcztcblxuICAgIGdldFdpZHRoID0gRW50aXR5VXRpbGl0aWVzLmdldFdpZHRoO1xuXG4gICAgY29uc3RydWN0b3IoKSB7fVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCBuZWVkZWQgdG8gcmVjdXJzaXZlbHkgZ2VuZXJhdGUgcHJvcGVydHkgaW5wdXQgY29tcG9uZW50cyAodXNlZCBlZy4gd2l0aCB0aGUgb2JqZWN0KVxuICAgICAqL1xuICAgIHRyYWNrQnlGbihpbmRleDogdW5rbm93bik6IHVua25vd24ge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxuXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5lbnRpdHkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBJbnB1dCBkYXRhIFwiZW50aXR5XCInKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucHJvcGVydHlLZXkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBJbnB1dCBkYXRhIFwicHJvcGVydHlLZXlcIicpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudHlwZSA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eVR5cGUodGhpcy5lbnRpdHksIHRoaXMucHJvcGVydHlLZXkpO1xuICAgICAgICB0aGlzLm1ldGFkYXRhID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEodGhpcy5lbnRpdHksIHRoaXMucHJvcGVydHlLZXksIHRoaXMudHlwZSk7XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YURlZmF1bHRTdHJpbmcgPSB0aGlzLm1ldGFkYXRhIGFzIERlZmF1bHRTdHJpbmdEZWNvcmF0b3JDb25maWc7XG4gICAgICAgIHRoaXMubWV0YWRhdGFUZXh0Ym94U3RyaW5nID0gdGhpcy5tZXRhZGF0YSBhcyBUZXh0Ym94U3RyaW5nRGVjb3JhdG9yQ29uZmlnO1xuXG4gICAgICAgIHRoaXMubWV0YWRhdGFBdXRvY29tcGxldGVTdHJpbmcgPSB0aGlzLm1ldGFkYXRhIGFzIEF1dG9jb21wbGV0ZVN0cmluZ0RlY29yYXRvckNvbmZpZztcbiAgICAgICAgdGhpcy5hdXRvY29tcGxldGVTdHJpbmdzID0gdGhpcy5tZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZy5hdXRvY29tcGxldGVWYWx1ZXM7XG4gICAgICAgIHRoaXMuZmlsdGVyZWRBdXRvY29tcGxldGVTdHJpbmdzID0gY2xvbmVEZWVwKHRoaXMuYXV0b2NvbXBsZXRlU3RyaW5ncyk7XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YURyb3Bkb3duU3RyaW5nID0gdGhpcy5tZXRhZGF0YSBhcyBEcm9wZG93blN0cmluZ0RlY29yYXRvckNvbmZpZztcblxuICAgICAgICB0aGlzLm1ldGFkYXRhRHJvcGRvd25Cb29sZWFuID0gdGhpcy5tZXRhZGF0YSBhcyBEcm9wZG93bkJvb2xlYW5EZWNvcmF0b3JDb25maWc7XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YURlZmF1bHROdW1iZXIgPSB0aGlzLm1ldGFkYXRhIGFzIERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWc7XG4gICAgICAgIHRoaXMubWV0YWRhdGFEcm9wZG93bk51bWJlciA9IHRoaXMubWV0YWRhdGEgYXMgRHJvcGRvd25OdW1iZXJEZWNvcmF0b3JDb25maWc7XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YURlZmF1bHRPYmplY3QgPSB0aGlzLm1ldGFkYXRhIGFzIERlZmF1bHRPYmplY3REZWNvcmF0b3JDb25maWc7XG4gICAgICAgIHRoaXMub2JqZWN0UHJvcGVydHkgPSB0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIEVudGl0eTtcblxuICAgICAgICB0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkgPSB0aGlzLm1ldGFkYXRhIGFzIEVudGl0eUFycmF5RGVjb3JhdG9yQ29uZmlnPEVudGl0eT47XG4gICAgICAgIGlmICh0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkuRW50aXR5Q2xhc3MpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0pIHtcbiAgICAgICAgICAgICAgICAodGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBFbnRpdHlbXSkgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW50aXR5QXJyYXlWYWx1ZXMgPSB0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIEVudGl0eVtdO1xuICAgICAgICAgICAgaWYgKHRoaXMubWV0YWRhdGFFbnRpdHlBcnJheS5jcmVhdGVJbmxpbmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWV0YWRhdGFFbnRpdHlBcnJheS5jcmVhdGVJbmxpbmUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkuY3JlYXRlSW5saW5lICYmICF0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkuY3JlYXRlRGlhbG9nRGF0YSkge1xuICAgICAgICAgICAgICAgIHRoaXMubWV0YWRhdGFFbnRpdHlBcnJheS5jcmVhdGVEaWFsb2dEYXRhID0ge1xuICAgICAgICAgICAgICAgICAgICB0aXRsZTogJ0FkZCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheSA9IHRoaXMubWV0YWRhdGEgYXMgU3RyaW5nQ2hpcHNBcnJheURlY29yYXRvckNvbmZpZztcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5tZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkuaXRlbVR5cGVcbiAgICAgICAgICAgICYmICh0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIHN0cmluZ1tdKT8ubGVuZ3RoXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzID0gKHRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldIGFzIHVua25vd24gYXMgc3RyaW5nW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZ0NoaXBzQXJyYXkgPSB0aGlzLm1ldGFkYXRhIGFzIEF1dG9jb21wbGV0ZVN0cmluZ0NoaXBzQXJyYXlEZWNvcmF0b3JDb25maWc7XG5cbiAgICAgICAgaWYgKCF0aGlzLmdldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UpIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZSA9IGdldFZhbGlkYXRpb25FcnJvck1lc3NhZ2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRPYmplY3RQcm9wZXJ0aWVzKCk6IChrZXlvZiBFbnRpdHkpW10ge1xuICAgICAgICBjb25zdCByZXM6IChrZXlvZiBFbnRpdHkpW10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBwcm9wZXJ0eSBpbiB0aGlzLm9iamVjdFByb3BlcnR5KSB7XG4gICAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKFxuICAgICAgICAgICAgICAgIHRoaXMub2JqZWN0UHJvcGVydHksXG4gICAgICAgICAgICAgICAgcHJvcGVydHkgYXMga2V5b2YgRW50aXR5LFxuICAgICAgICAgICAgICAgIEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eVR5cGUodGhpcy5vYmplY3RQcm9wZXJ0eSwgcHJvcGVydHkgYXMga2V5b2YgRW50aXR5KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAhKHRoaXMuaGlkZU9taXRGb3JDcmVhdGUgJiYgbWV0YWRhdGEub21pdEZvckNyZWF0ZSlcbiAgICAgICAgICAgICAgICAmJiAhKHRoaXMuaGlkZU9taXRGb3JFZGl0ICYmIG1ldGFkYXRhLm9taXRGb3JVcGRhdGUpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChwcm9wZXJ0eSBhcyBrZXlvZiBFbnRpdHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXMuc29ydCgoYSwgYikgPT4gRW50aXR5VXRpbGl0aWVzLmNvbXBhcmVPcmRlcihhLCBiLCB0aGlzLm9iamVjdFByb3BlcnR5KSk7XG4gICAgfVxuXG4gICAgYWRkU3RyaW5nQ2hpcEFycmF5VmFsdWUoZXZlbnQ6IE1hdENoaXBJbnB1dEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gKGV2ZW50LnZhbHVlIHx8ICcnKS50cmltKCk7XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1pbkxlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPCB0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5taW5MZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5tZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWF4TGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA+IHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1heExlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCAgJiYgIXZhbHVlLm1hdGNoKHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5LnJlZ2V4KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIHN0cmluZ1tdKSB7XG4gICAgICAgICAgICAgICAgICAgICh0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIHN0cmluZ1tdKSA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnN0cmluZ0NoaXBzQXJyYXlWYWx1ZXMgPSB0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIHN0cmluZ1tdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGV2ZW50LmNoaXBJbnB1dCEuY2xlYXIoKTtcbiAgICB9XG5cbiAgICByZW1vdmVTdHJpbmdDaGlwQXJyYXlWYWx1ZSh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyaW5nQ2hpcHNBcnJheVZhbHVlcy5zcGxpY2UodGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzLmluZGV4T2YodmFsdWUpLCAxKTtcbiAgICAgICAgaWYgKCF0aGlzLnN0cmluZ0NoaXBzQXJyYXlWYWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAodGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93bikgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnN0cmluZ0NoaXBzQXJyYXlWYWx1ZXMgPSB0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIHN0cmluZ1tdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2VsZWN0ZWQoZXZlbnQ6IE1hdEF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnQsIGNoaXBzSW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSAoZXZlbnQub3B0aW9uLnZpZXdWYWx1ZSB8fCAnJykudHJpbSgpO1xuICAgICAgICBpZiAodGhpcy5tZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWluTGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA8IHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1pbkxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5tYXhMZW5ndGggJiYgdmFsdWUubGVuZ3RoID4gdGhpcy5tZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWF4TGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5LnJlZ2V4ICAmJiAhdmFsdWUubWF0Y2godGhpcy5tZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkucmVnZXgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnN0cmluZ0NoaXBzQXJyYXlWYWx1ZXMpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBzdHJpbmdbXSkge1xuICAgICAgICAgICAgICAgICh0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIHN0cmluZ1tdKSA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzID0gdGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBzdHJpbmdbXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0cmluZ0NoaXBzQXJyYXlWYWx1ZXMucHVzaCh2YWx1ZSk7XG4gICAgICAgIGNoaXBzSW5wdXQudmFsdWUgPSAnJztcbiAgICB9XG5cbiAgICBmaWx0ZXJBdXRvY29tcGxldGVTdHJpbmdzKGlucHV0OiB1bmtub3duKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGZpbHRlclZhbHVlID0gKGlucHV0IGFzIHN0cmluZykudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgdGhpcy5maWx0ZXJlZEF1dG9jb21wbGV0ZVN0cmluZ3MgPSB0aGlzLmF1dG9jb21wbGV0ZVN0cmluZ3MuZmlsdGVyKHMgPT4gcy50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKGZpbHRlclZhbHVlKSk7XG4gICAgfVxufSIsIjxkaXYgW25nU3dpdGNoXT1cInR5cGVcIiAqbmdJZj1cIiEoaGlkZU9taXRGb3JDcmVhdGUgJiYgbWV0YWRhdGEub21pdEZvckNyZWF0ZSkgJiYgIShoaWRlT21pdEZvckVkaXQgJiYgbWV0YWRhdGEub21pdEZvclVwZGF0ZSlcIj5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS1TdHJpbmdzLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5TVFJJTkdcIj5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57e21ldGFkYXRhLmRpc3BsYXlOYW1lfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJlbnRpdHlbcHJvcGVydHlLZXldXCJcbiAgICAgICAgICAgICAgICBbbmFtZV09XCJwcm9wZXJ0eUtleS50b1N0cmluZygpXCJcbiAgICAgICAgICAgICAgICAjbW9kZWw9XCJuZ01vZGVsXCJcbiAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWQgPyBtZXRhZGF0YS5yZXF1aXJlZCA6IGZhbHNlXCJcbiAgICAgICAgICAgICAgICBbcGF0dGVybl09XCJtZXRhZGF0YURlZmF1bHRTdHJpbmcucmVnZXggPyBtZXRhZGF0YURlZmF1bHRTdHJpbmcucmVnZXggOiAnW1xcXFxzXFxcXFNdKidcIlxuICAgICAgICAgICAgICAgIFttaW5sZW5ndGhdPVwibWV0YWRhdGFEZWZhdWx0U3RyaW5nLm1pbkxlbmd0aCA/IG1ldGFkYXRhRGVmYXVsdFN0cmluZy5taW5MZW5ndGggOiBudWxsXCJcbiAgICAgICAgICAgICAgICBbbWF4bGVuZ3RoXT1cIm1ldGFkYXRhRGVmYXVsdFN0cmluZy5tYXhMZW5ndGggPyBtZXRhZGF0YURlZmF1bHRTdHJpbmcubWF4TGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLlNUUklOR19URVhUQk9YXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8dGV4dGFyZWFcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZW50aXR5W3Byb3BlcnR5S2V5XVwiXG4gICAgICAgICAgICAgICAgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiXG4gICAgICAgICAgICAgICAgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgY2RrVGV4dGFyZWFBdXRvc2l6ZVxuICAgICAgICAgICAgICAgIGNka0F1dG9zaXplTWluUm93cz1cIjEwXCJcbiAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWQgPyBtZXRhZGF0YS5yZXF1aXJlZCA6IGZhbHNlXCJcbiAgICAgICAgICAgICAgICBbbWlubGVuZ3RoXT1cIm1ldGFkYXRhVGV4dGJveFN0cmluZy5taW5MZW5ndGggPyBtZXRhZGF0YVRleHRib3hTdHJpbmcubWluTGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgW21heGxlbmd0aF09XCJtZXRhZGF0YVRleHRib3hTdHJpbmcubWF4TGVuZ3RoID8gbWV0YWRhdGFUZXh0Ym94U3RyaW5nLm1heExlbmd0aCA6IG51bGxcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgPC90ZXh0YXJlYT5cbiAgICAgICAgICAgIDxtYXQtZXJyb3I+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKG1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5TVFJJTkdfQVVUT0NPTVBMRVRFXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZW50aXR5W3Byb3BlcnR5S2V5XVwiXG4gICAgICAgICAgICAgICAgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiXG4gICAgICAgICAgICAgICAgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgW21hdEF1dG9jb21wbGV0ZV09XCJhdXRvXCJcbiAgICAgICAgICAgICAgICAoa2V5dXApPVwiZmlsdGVyQXV0b2NvbXBsZXRlU3RyaW5ncyhlbnRpdHlbcHJvcGVydHlLZXldKVwiXG4gICAgICAgICAgICAgICAgW3JlcXVpcmVkXT1cIm1ldGFkYXRhLnJlcXVpcmVkID8gbWV0YWRhdGEucmVxdWlyZWQgOiBmYWxzZVwiXG4gICAgICAgICAgICAgICAgW21pbmxlbmd0aF09XCJtZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZy5taW5MZW5ndGggPyBtZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZy5taW5MZW5ndGggOiBudWxsXCJcbiAgICAgICAgICAgICAgICBbbWF4bGVuZ3RoXT1cIm1ldGFkYXRhQXV0b2NvbXBsZXRlU3RyaW5nLm1heExlbmd0aCA/IG1ldGFkYXRhQXV0b2NvbXBsZXRlU3RyaW5nLm1heExlbmd0aCA6IG51bGxcIlxuICAgICAgICAgICAgICAgIFtwYXR0ZXJuXT1cIm1ldGFkYXRhQXV0b2NvbXBsZXRlU3RyaW5nLnJlZ2V4ID8gbWV0YWRhdGFBdXRvY29tcGxldGVTdHJpbmcucmVnZXggOiAnW1xcXFxzXFxcXFNdKidcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxtYXQtYXV0b2NvbXBsZXRlICNhdXRvPVwibWF0QXV0b2NvbXBsZXRlXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gKm5nRm9yPVwibGV0IHZhbHVlIG9mIGZpbHRlcmVkQXV0b2NvbXBsZXRlU3RyaW5nc1wiIFt2YWx1ZV09XCJ2YWx1ZVwiPlxuICAgICAgICAgICAgICAgICAgICB7e3ZhbHVlfX1cbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICA8L21hdC1hdXRvY29tcGxldGU+XG4gICAgICAgICAgICA8bWF0LWVycm9yPnt7Z2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZShtb2RlbCl9fTwvbWF0LWVycm9yPlxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiRGVjb3JhdG9yVHlwZXMuU1RSSU5HX0RST1BET1dOXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LXNlbGVjdCBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIiBbbmFtZV09XCJwcm9wZXJ0eUtleS50b1N0cmluZygpXCIgI21vZGVsPVwibmdNb2RlbFwiIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZCA/IG1ldGFkYXRhLnJlcXVpcmVkIDogZmFsc2VcIj5cbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgdmFsdWUgb2YgbWV0YWRhdGFEcm9wZG93blN0cmluZy5kcm9wZG93blZhbHVlc1wiIFt2YWx1ZV09XCJ2YWx1ZS52YWx1ZVwiPnt7dmFsdWUuZGlzcGxheU5hbWV9fTwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgIDxtYXQtZXJyb3I+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKG1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS1Cb29sZWFucy0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5CT09MRUFOX0NIRUNLQk9YXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtY2hlY2tib3ggWyhuZ01vZGVsKV09XCJlbnRpdHlbcHJvcGVydHlLZXldXCIgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiICNtb2RlbD1cIm5nTW9kZWxcIiBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWQgPyBtZXRhZGF0YS5yZXF1aXJlZCA6IGZhbHNlXCI+XG4gICAgICAgICAgICAgICAge3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19XG4gICAgICAgICAgICA8L21hdC1jaGVja2JveD5cbiAgICAgICAgICAgIDwhLS0gaGlkZGVuIGlucHV0IGlzIG5lZWRlZCBzbyB0aGF0IHRoZSBjaGVja2JveCBjYW4gYmUgdXNlZCBpbnNpZGUgYSBtYXQtZm9ybS1maWVsZCAtLT5cbiAgICAgICAgICAgIDx0ZXh0YXJlYSBtYXRJbnB1dCBoaWRkZW4+PC90ZXh0YXJlYT5cbiAgICAgICAgICAgIDxtYXQtZXJyb3I+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKG1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5CT09MRUFOX1RPR0dMRVwiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LXNsaWRlLXRvZ2dsZSBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIiBbbmFtZV09XCJwcm9wZXJ0eUtleS50b1N0cmluZygpXCIgI21vZGVsPVwibmdNb2RlbFwiIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZCA/IG1ldGFkYXRhLnJlcXVpcmVkIDogZmFsc2VcIj5cbiAgICAgICAgICAgICAgICB7e21ldGFkYXRhLmRpc3BsYXlOYW1lfX1cbiAgICAgICAgICAgIDwvbWF0LXNsaWRlLXRvZ2dsZT5cbiAgICAgICAgICAgIDwhLS0gaGlkZGVuIGlucHV0IGlzIG5lZWRlZCBzbyB0aGF0IHRoZSB0b2dnbGUgY2FuIGJlIHVzZWQgaW5zaWRlIGEgbWF0LWZvcm0tZmllbGQgLS0+XG4gICAgICAgICAgICA8dGV4dGFyZWEgbWF0SW5wdXQgaGlkZGVuPjwvdGV4dGFyZWE+XG4gICAgICAgICAgICA8bWF0LWVycm9yPnt7Z2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZShtb2RlbCl9fTwvbWF0LWVycm9yPlxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiRGVjb3JhdG9yVHlwZXMuQk9PTEVBTl9EUk9QRE9XTlwiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7bWV0YWRhdGEuZGlzcGxheU5hbWV9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPG1hdC1zZWxlY3QgWyhuZ01vZGVsKV09XCJlbnRpdHlbcHJvcGVydHlLZXldXCIgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiICNtb2RlbD1cIm5nTW9kZWxcIiBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWQgPyBtZXRhZGF0YS5yZXF1aXJlZCA6IGZhbHNlXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cInVuZGVmaW5lZFwiPi08L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cInRydWVcIj57e21ldGFkYXRhRHJvcGRvd25Cb29sZWFuLmRyb3Bkb3duVHJ1ZX19PC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJmYWxzZVwiPnt7bWV0YWRhdGFEcm9wZG93bkJvb2xlYW4uZHJvcGRvd25GYWxzZX19PC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS1OdW1iZXJzLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLk5VTUJFUlwiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7bWV0YWRhdGEuZGlzcGxheU5hbWV9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIlxuICAgICAgICAgICAgICAgIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKClcIlxuICAgICAgICAgICAgICAgICNtb2RlbD1cIm5nTW9kZWxcIlxuICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZCA/IG1ldGFkYXRhLnJlcXVpcmVkIDogZmFsc2VcIlxuICAgICAgICAgICAgICAgIFttaW5dPVwibWV0YWRhdGFEZWZhdWx0TnVtYmVyLm1pbiA/IG1ldGFkYXRhRGVmYXVsdE51bWJlci5taW4gOiBudWxsXCJcbiAgICAgICAgICAgICAgICBbbWF4XT1cIm1ldGFkYXRhRGVmYXVsdE51bWJlci5tYXggPyBtZXRhZGF0YURlZmF1bHROdW1iZXIubWF4IDogbnVsbFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLk5VTUJFUl9EUk9QRE9XTlwiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7bWV0YWRhdGEuZGlzcGxheU5hbWV9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPG1hdC1zZWxlY3QgWyhuZ01vZGVsKV09XCJlbnRpdHlbcHJvcGVydHlLZXldXCIgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiICNtb2RlbD1cIm5nTW9kZWxcIiBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWQgPyBtZXRhZGF0YS5yZXF1aXJlZCA6IGZhbHNlXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gKm5nRm9yPVwibGV0IHZhbHVlIG9mIG1ldGFkYXRhRHJvcGRvd25OdW1iZXIuZHJvcGRvd25WYWx1ZXNcIiBbdmFsdWVdPVwidmFsdWUudmFsdWVcIj57e3ZhbHVlLmRpc3BsYXlOYW1lfX08L21hdC1vcHRpb24+XG4gICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICA8bWF0LWVycm9yPnt7Z2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZShtb2RlbCl9fTwvbWF0LWVycm9yPlxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS1PYmplY3QtLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiRGVjb3JhdG9yVHlwZXMuT0JKRUNUXCI+XG4gICAgICAgIDxiPnt7bWV0YWRhdGFEZWZhdWx0T2JqZWN0LmRpc3BsYXlOYW1lfX08L2I+XG4gICAgICAgIDwhLS0gaXRlcmF0ZXMgb3ZlciB0aGUgb2JqZWN0IHByb3BlcnRpZXMgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICAgICAgICAgIDwhLS1cbiAgICAgICAgICAgICAgICBkaXNwbGF5cyBhbm90aGVyIG5neC1tYXRlcmlhbC1lbnRpdHkgd2l0aCB0aGU6XG4gICAgICAgICAgICAgICAgb2JqZWN0IGFzIHRoZSBlbnRpdHksXG4gICAgICAgICAgICAgICAgdGhlIGN1cnJlbnQga2V5IGluIHRoZSBsb29wIHJlY2VpdmVkIGJ5IHRoZSBrZXl2YWx1ZSBkaXJlY3Rpb24gYXMgdGhlIHByb3BlcnR5S2V5XG4gICAgICAgICAgICAgICAgYW5kIHRoZSBnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlIG9mIHRoZSBjdXJyZW50IGNvbXBvbmVudFxuICAgICAgICAgICAgLS0+XG4gICAgICAgICAgICA8bmd4LW1hdC1lbnRpdHktaW5wdXRcbiAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQga2V5IG9mIGdldE9iamVjdFByb3BlcnRpZXMoKTsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogdHJhY2tCeUZuXCJcbiAgICAgICAgICAgICAgICBbZW50aXR5XT1cIm9iamVjdFByb3BlcnR5XCJcbiAgICAgICAgICAgICAgICBbcHJvcGVydHlLZXldPVwia2V5XCJcbiAgICAgICAgICAgICAgICBbZ2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZV09XCJnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlXCJcbiAgICAgICAgICAgICAgICBbaGlkZU9taXRGb3JDcmVhdGVdPVwiaGlkZU9taXRGb3JDcmVhdGVcIlxuICAgICAgICAgICAgICAgIFtoaWRlT21pdEZvckVkaXRdPVwiaGlkZU9taXRGb3JFZGl0XCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImNvbC1sZy17e2dldFdpZHRoKG9iamVjdFByb3BlcnR5LCBrZXksICdsZycpfX0gY29sLW1kLXt7Z2V0V2lkdGgob2JqZWN0UHJvcGVydHksIGtleSwgJ21kJyl9fSBjb2wtc20te3tnZXRXaWR0aChvYmplY3RQcm9wZXJ0eSwga2V5LCAnc20nKX19XCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgIDwvbmd4LW1hdC1lbnRpdHktaW5wdXQ+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS1BcnJheS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiRGVjb3JhdG9yVHlwZXMuQVJSQVlcIj5cbiAgICAgICAgPG5neC1tYXQtZW50aXR5LWFycmF5LXRhYmxlXG4gICAgICAgICAgICBbYXJyYXlJdGVtc109XCJlbnRpdHlBcnJheVZhbHVlc1wiXG4gICAgICAgICAgICBbbWV0YWRhdGFdPVwibWV0YWRhdGFFbnRpdHlBcnJheVwiXG4gICAgICAgICAgICBbZ2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZV09XCJnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlXCJcbiAgICAgICAgICAgIFtvbWl0XT1cImhpZGVPbWl0Rm9yQ3JlYXRlID8gJ2NyZWF0ZScgOiAnZWRpdCdcIlxuICAgICAgICA+XG4gICAgICAgIDwvbmd4LW1hdC1lbnRpdHktYXJyYXktdGFibGU+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5BUlJBWV9TVFJJTkdfQ0hJUFNcIj5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57e21ldGFkYXRhLmRpc3BsYXlOYW1lfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxtYXQtY2hpcC1saXN0ICNjaGlwTGlzdFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZW50aXR5W3Byb3BlcnR5S2V5XVwiIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKClcIiAjbW9kZWw9XCJuZ01vZGVsXCJcbiAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWQgPyBtZXRhZGF0YS5yZXF1aXJlZCA6IGZhbHNlXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LWNoaXAgKm5nRm9yPVwibGV0IHZhbHVlIG9mIHN0cmluZ0NoaXBzQXJyYXlWYWx1ZXNcIiAocmVtb3ZlZCk9XCJyZW1vdmVTdHJpbmdDaGlwQXJyYXlWYWx1ZSh2YWx1ZSlcIj5cbiAgICAgICAgICAgICAgICAgICAge3t2YWx1ZX19XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gbWF0Q2hpcFJlbW92ZSAqbmdJZj1cIm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5kZWxldGVIdG1sXCIgW2lubmVySHRtbF09XCJtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkuZGVsZXRlSHRtbFwiPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXRDaGlwUmVtb3ZlICpuZ0lmPVwiIW1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5kZWxldGVIdG1sXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+Y2FuY2VsPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9tYXQtY2hpcD5cbiAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgW21hdENoaXBJbnB1dEZvcl09XCJjaGlwTGlzdFwiXG4gICAgICAgICAgICAgICAgICAgIFttYXRDaGlwSW5wdXRBZGRPbkJsdXJdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgIChtYXRDaGlwSW5wdXRUb2tlbkVuZCk9XCJhZGRTdHJpbmdDaGlwQXJyYXlWYWx1ZSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjaGlwc0lucHV0XCIgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiICNjaGlwc01vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgICAgIFttaW5sZW5ndGhdPSdtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWluTGVuZ3RoID8gbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1pbkxlbmd0aCA6IG51bGwnXG4gICAgICAgICAgICAgICAgICAgIFttYXhsZW5ndGhdPSdtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWF4TGVuZ3RoID8gbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1heExlbmd0aCA6IG51bGwnXG4gICAgICAgICAgICAgICAgICAgIFtwYXR0ZXJuXT1cIm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCA/IG1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCA6ICdbXFxcXHNcXFxcU10qJ1wiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJjaGlwc01vZGVsLmVycm9yc1wiPnt7Z2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZShjaGlwc01vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8L21hdC1jaGlwLWxpc3Q+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiIWNoaXBzTW9kZWwuZXJyb3JzXCI+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKG1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5BUlJBWV9TVFJJTkdfQVVUT0NPTVBMRVRFX0NISVBTXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LWNoaXAtbGlzdCAjY2hpcExpc3RcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIiBbbmFtZV09XCJwcm9wZXJ0eUtleS50b1N0cmluZygpXCIgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgW3JlcXVpcmVkXT1cIm1ldGFkYXRhLnJlcXVpcmVkID8gbWV0YWRhdGEucmVxdWlyZWQgOiBmYWxzZVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1jaGlwICpuZ0Zvcj1cImxldCB2YWx1ZSBvZiBzdHJpbmdDaGlwc0FycmF5VmFsdWVzXCIgKHJlbW92ZWQpPVwicmVtb3ZlU3RyaW5nQ2hpcEFycmF5VmFsdWUodmFsdWUpXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7dmFsdWV9fVxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdENoaXBSZW1vdmUgKm5nSWY9XCJtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkuZGVsZXRlSHRtbFwiIFtpbm5lckh0bWxdPVwibWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5LmRlbGV0ZUh0bWxcIj5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gbWF0Q2hpcFJlbW92ZSAqbmdJZj1cIiFtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkuZGVsZXRlSHRtbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmNhbmNlbDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvbWF0LWNoaXA+XG4gICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIFttYXRDaGlwSW5wdXRGb3JdPVwiY2hpcExpc3RcIlxuICAgICAgICAgICAgICAgICAgICBbbWF0QXV0b2NvbXBsZXRlXT1cImF1dG9cIlxuICAgICAgICAgICAgICAgICAgICBbbWF0Q2hpcElucHV0QWRkT25CbHVyXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAobWF0Q2hpcElucHV0VG9rZW5FbmQpPVwiYWRkU3RyaW5nQ2hpcEFycmF5VmFsdWUoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgIChrZXl1cCk9XCJmaWx0ZXJBdXRvY29tcGxldGVTdHJpbmdzKGNoaXBzSW5wdXQpXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjaGlwc0lucHV0XCIgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiICNjaGlwc01vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgICAgICNjaGlwc0VsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgW21pbmxlbmd0aF09J21ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5taW5MZW5ndGggPyBtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWluTGVuZ3RoIDogbnVsbCdcbiAgICAgICAgICAgICAgICAgICAgW21heGxlbmd0aF09J21ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5tYXhMZW5ndGggPyBtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWF4TGVuZ3RoIDogbnVsbCdcbiAgICAgICAgICAgICAgICAgICAgW3BhdHRlcm5dPVwibWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5LnJlZ2V4ID8gbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5LnJlZ2V4IDogJ1tcXFxcc1xcXFxTXSonXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cImNoaXBzTW9kZWwuZXJyb3JzXCI+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKGNoaXBzTW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgICAgIDwvbWF0LWNoaXAtbGlzdD5cbiAgICAgICAgICAgIDxtYXQtYXV0b2NvbXBsZXRlICNhdXRvPVwibWF0QXV0b2NvbXBsZXRlXCIgKG9wdGlvblNlbGVjdGVkKT1cInNlbGVjdGVkKCRldmVudCwgY2hpcHNFbGVtZW50KVwiPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCB2YWx1ZSBvZiBmaWx0ZXJlZEF1dG9jb21wbGV0ZVN0cmluZ3NcIiBbdmFsdWVdPVwidmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgIHt7dmFsdWV9fVxuICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgIDwvbWF0LWF1dG9jb21wbGV0ZT5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCIhY2hpcHNNb2RlbC5lcnJvcnNcIj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoRGVmYXVsdD5FUlJPUjogVGhlIHR5cGUge3t0eXBlfX1pcyBub3Qga25vd24uPC9kaXY+XG48L2Rpdj4iXX0=
362
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LW1hdGVyaWFsLWVudGl0eS9zcmMvY29tcG9uZW50cy9pbnB1dC9pbnB1dC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtbWF0ZXJpYWwtZW50aXR5L3NyYy9jb21wb25lbnRzL2lucHV0L2lucHV0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFVLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFakYsT0FBTyxFQUFhLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQUM1RSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUdyRixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBT25DLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzdELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsNkJBQTZCLEVBQWtDLE1BQU0sc0NBQXNDLENBQUM7QUFFckgsT0FBTyxFQUFFLFNBQVMsRUFBZ0IsTUFBTSwwQkFBMEIsQ0FBQztBQUVuRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sOEJBQThCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBTTdEOzs7Ozs7O0dBT0c7QUFNSCxNQUFNLE9BQU8sMEJBQTBCO0lBOEZuQyxZQUNxQixNQUFpQjtRQUFqQixXQUFNLEdBQU4sTUFBTSxDQUFXO1FBakN0QyxlQUFVLEdBQVcsRUFBRSxDQUFDO1FBb0J4QixjQUFTLEdBQStCLElBQUksY0FBYyxDQUFhLElBQUksRUFBRSxF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QUFJLENBQUMsMkJBQTJCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztTQUNsSDtJQUNMLENBQUM7O3dIQXpiUSwwQkFBMEI7NEdBQTFCLDBCQUEwQixvWEN2Q3ZDLHFqdkJBMGJjLDJ2RERuWkQsMEJBQTBCOzRGQUExQiwwQkFBMEI7a0JBTHRDLFNBQVM7K0JBQ0ksc0JBQXNCO2dHQVVoQyxNQUFNO3NCQURMLEtBQUs7Z0JBT04sV0FBVztzQkFEVixLQUFLO2dCQU9OLHlCQUF5QjtzQkFEeEIsS0FBSztnQkFRTixpQkFBaUI7c0JBRGhCLEtBQUs7Z0JBUU4sZUFBZTtzQkFEZCxLQUFLO2dCQUlOLGtCQUFrQjtzQkFEakIsU0FBUzt1QkFBQyxvQkFBb0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPbkluaXQsIFRlbXBsYXRlUmVmLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5nTW9kZWwgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBFbnRpdHlSb3csIEVudGl0eVV0aWxpdGllcyB9IGZyb20gJy4uLy4uL2NsYXNzZXMvZW50aXR5LnV0aWxpdGllcyc7XG5pbXBvcnQgeyBEZWNvcmF0b3JUeXBlcyB9IGZyb20gJy4uLy4uL2RlY29yYXRvcnMvYmFzZS9kZWNvcmF0b3ItdHlwZXMuZW51bSc7XG5pbXBvcnQgeyBnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlIH0gZnJvbSAnLi4vZ2V0LXZhbGlkYXRpb24tZXJyb3ItbWVzc2FnZS5mdW5jdGlvbic7XG5pbXBvcnQgeyBNYXRDaGlwSW5wdXRFdmVudCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NoaXBzJztcbmltcG9ydCB7IE1hdEF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9hdXRvY29tcGxldGUnO1xuaW1wb3J0IHsgY2xvbmVEZWVwIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IEF1dG9jb21wbGV0ZVN0cmluZ0NoaXBzQXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCwgRW50aXR5QXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCwgU3RyaW5nQ2hpcHNBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsIH0gZnJvbSAnLi4vLi4vZGVjb3JhdG9ycy9hcnJheS9hcnJheS1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBEcm9wZG93bkJvb2xlYW5EZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uLy4uL2RlY29yYXRvcnMvYm9vbGVhbi9ib29sZWFuLWRlY29yYXRvci1pbnRlcm5hbC5kYXRhJztcbmltcG9ydCB7IERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbCwgRHJvcGRvd25OdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uLy4uL2RlY29yYXRvcnMvbnVtYmVyL251bWJlci1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBEZWZhdWx0T2JqZWN0RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9kZWNvcmF0b3JzL29iamVjdC9vYmplY3QtZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgQXV0b2NvbXBsZXRlU3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIERlZmF1bHRTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbCwgRHJvcGRvd25TdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbCwgVGV4dGJveFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsIH0gZnJvbSAnLi4vLi4vZGVjb3JhdG9ycy9zdHJpbmcvc3RyaW5nLWRlY29yYXRvci1pbnRlcm5hbC5kYXRhJztcbmltcG9ydCB7IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9kZWNvcmF0b3JzL2Jhc2UvcHJvcGVydHktZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgTWF0VGFibGVEYXRhU291cmNlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFibGUnO1xuaW1wb3J0IHsgU2VsZWN0aW9uTW9kZWwgfSBmcm9tICdAYW5ndWxhci9jZGsvY29sbGVjdGlvbnMnO1xuaW1wb3J0IHsgQWRkQXJyYXlJdGVtRGlhbG9nRGF0YUJ1aWxkZXIsIEFkZEFycmF5SXRlbURpYWxvZ0RhdGFJbnRlcm5hbCB9IGZyb20gJy4vYWRkLWFycmF5LWl0ZW0tZGlhbG9nLWRhdGEuYnVpbGRlcic7XG5pbXBvcnQgeyBBZGRBcnJheUl0ZW1EaWFsb2dEYXRhIH0gZnJvbSAnLi9hZGQtYXJyYXktaXRlbS1kaWFsb2ctZGF0YSc7XG5pbXBvcnQgeyBNYXREaWFsb2csIE1hdERpYWxvZ1JlZiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RpYWxvZyc7XG5pbXBvcnQgeyBEYXRlUmFuZ2VEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIERhdGVUaW1lRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsLCBEZWZhdWx0RGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsIH0gZnJvbSAnLi4vLi4vZGVjb3JhdG9ycy9kYXRlL2RhdGUtZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgRGF0ZVV0aWxpdGllcyB9IGZyb20gJy4uLy4uL2NsYXNzZXMvZGF0ZS51dGlsaXRpZXMnO1xuaW1wb3J0IHsgRGF0ZUZpbHRlckZuIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGF0ZXBpY2tlcic7XG5pbXBvcnQgeyBEYXRlUmFuZ2UgfSBmcm9tICcuLi8uLi9kZWNvcmF0b3JzL2RhdGUvZGF0ZS1kZWNvcmF0b3IuZGF0YSc7XG5pbXBvcnQgeyBUaW1lIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IERyb3Bkb3duVmFsdWUgfSBmcm9tICcuLi8uLi9kZWNvcmF0b3JzL2Jhc2UvZHJvcGRvd24tdmFsdWUuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBpbnB1dCBjb21wb25lbnQuIEl0IGdldHMgdGhlIG1ldGFkYXRhIG9mIHRoZSBwcm9wZXJ0eSBmcm9tIHRoZSBnaXZlbiBASW5wdXQgXCJlbnRpdHlcIiBhbmQgQElucHV0IFwicHJvcGVydHlLZXlcIlxuICogYW5kIGRpc3BsYXlzIHRoZSBpbnB1dCBmaWVsZCBhY2NvcmRpbmdseS5cbiAqXG4gKiBZb3UgY2FuIGFsc28gZGVmaW5lIGEgbWV0aG9kIHRoYXQgZ2VuZXJhdGVzIGVycm9yLW1lc3NhZ2VzIGFuZCBpZiB0aGUgaW5wdXQgc2hvdWxkIGJlIGhpZGRlbiB3aGVuIGl0cyBtZXRhZGF0YSBzYXlzXG4gKiB0aGF0IGl0IHNob3VsZCBiZSBvbWl0dGVkIGZvciBjcmVhdGluZyBvciB1cGRhdGluZy5cbiAqIFRoZSBsYXN0IHBhcnQgYmVpbmcgbW9zdGx5IHJlbGV2YW50IGlmIHlvdSB3YW50IHRvIHVzZSB0aGlzIGNvbXBvbmVudCBpbnNpZGUgYW4gbmdGb3IuXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnbmd4LW1hdC1lbnRpdHktaW5wdXQnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9pbnB1dC5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vaW5wdXQuY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hNYXRFbnRpdHlJbnB1dENvbXBvbmVudDxFbnRpdHlUeXBlIGV4dGVuZHMgb2JqZWN0PiBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gICAgLyoqXG4gICAgICogVGhlIGVudGl0eSBvbiB3aGljaCB0aGUgcHJvcGVydHkgZXhpc3RzLiBVc2VkIGluIGNvbmp1bmN0aW9uIHdpdGggdGhlIFwicHJvcGVydHlLZXlcIlxuICAgICAqIHRvIGRldGVybWluZSB0aGUgcHJvcGVydHkgZm9yIHdoaWNoIHRoZSBpbnB1dCBzaG91bGQgYmUgZ2VuZXJhdGVkLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgZW50aXR5ITogRW50aXR5VHlwZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBnZW5lcmF0ZSB0aGUgaW5wdXQgZm9yLiBVc2VkIGluIGNvbmp1bmN0aW9uIHdpdGggdGhlIFwiZW50aXR5XCIuXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwcm9wZXJ0eUtleSE6IGtleW9mIEVudGl0eVR5cGU7XG5cbiAgICAvKipcbiAgICAgKiAob3B0aW9uYWwpIEEgY3VzdG9tIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIHRoZSBlcnJvci1tZXNzYWdlIGZvciBpbnZhbGlkIGlucHV0cy5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGdldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UhOiAobW9kZWw6IE5nTW9kZWwpID0+IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdG8gaGlkZSBhIHZhbHVlIGlmIGl0IGlzIG9taXR0ZWQgZm9yIGNyZWF0aW9uLlxuICAgICAqIElzIHVzZWQgaW50ZXJuYWxseSBmb3IgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGhpZGVPbWl0Rm9yQ3JlYXRlPzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdG8gaGlkZSBhIHZhbHVlIGlmIGl0IGlzIG9taXR0ZWQgZm9yIGVkaXRpbmcuXG4gICAgICogSXMgdXNlZCBpbnRlcm5hbGx5IGZvciB0aGUgb2JqZWN0IHByb3BlcnR5LlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgaGlkZU9taXRGb3JFZGl0PzogYm9vbGVhbjtcblxuICAgIEBWaWV3Q2hpbGQoJ2FkZEFycmF5SXRlbURpYWxvZycpXG4gICAgYWRkQXJyYXlJdGVtRGlhbG9nITogVGVtcGxhdGVSZWY8dW5rbm93bj47XG4gICAgYWRkQXJyYXlJdGVtRGlhbG9nUmVmITogTWF0RGlhbG9nUmVmPHVua25vd24+O1xuXG4gICAgdHlwZSE6IERlY29yYXRvclR5cGVzO1xuXG4gICAgbWV0YWRhdGEhOiBQcm9wZXJ0eURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuXG4gICAgbWV0YWRhdGFEZWZhdWx0U3RyaW5nITogRGVmYXVsdFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgIG1ldGFkYXRhVGV4dGJveFN0cmluZyE6IFRleHRib3hTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICBtZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZyE6IEF1dG9jb21wbGV0ZVN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgIGF1dG9jb21wbGV0ZVN0cmluZ3MhOiBzdHJpbmdbXTtcbiAgICBmaWx0ZXJlZEF1dG9jb21wbGV0ZVN0cmluZ3MhOiBzdHJpbmdbXTtcbiAgICBtZXRhZGF0YURyb3Bkb3duU3RyaW5nITogRHJvcGRvd25TdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcblxuICAgIG1ldGFkYXRhRHJvcGRvd25Cb29sZWFuITogRHJvcGRvd25Cb29sZWFuRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG5cbiAgICBtZXRhZGF0YURlZmF1bHROdW1iZXIhOiBEZWZhdWx0TnVtYmVyRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgbWV0YWRhdGFEcm9wZG93bk51bWJlciE6IERyb3Bkb3duTnVtYmVyRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG5cbiAgICBtZXRhZGF0YURlZmF1bHRPYmplY3QhOiBEZWZhdWx0T2JqZWN0RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw8RW50aXR5VHlwZT47XG4gICAgb2JqZWN0UHJvcGVydHkhOiBFbnRpdHlUeXBlO1xuICAgIG9iamVjdFByb3BlcnR5Um93cyE6IEVudGl0eVJvdzxFbnRpdHlUeXBlPltdO1xuXG4gICAgbWV0YWRhdGFFbnRpdHlBcnJheSE6IEVudGl0eUFycmF5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw8RW50aXR5VHlwZT47XG4gICAgZW50aXR5QXJyYXlWYWx1ZXMhOiBFbnRpdHlUeXBlW107XG4gICAgbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5ITogU3RyaW5nQ2hpcHNBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgIHN0cmluZ0NoaXBzQXJyYXlWYWx1ZXMhOiBzdHJpbmdbXTtcbiAgICBjaGlwc0lucHV0OiBzdHJpbmcgPSAnJztcblxuICAgIG1ldGFkYXRhQXV0b2NvbXBsZXRlU3RyaW5nQ2hpcHNBcnJheSE6IEF1dG9jb21wbGV0ZVN0cmluZ0NoaXBzQXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcblxuICAgIG1ldGFkYXRhRGVmYXVsdERhdGUhOiBEZWZhdWx0RGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgIG1ldGFkYXRhRGF0ZVJhbmdlRGF0ZSE6IERhdGVSYW5nZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICBtZXRhZGF0YURhdGVUaW1lRGF0ZSE6IERhdGVUaW1lRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuXG4gICAgZGF0ZVJhbmdlITogRGF0ZVJhbmdlO1xuICAgIGRhdGVSYW5nZVN0YXJ0ITogRGF0ZTtcbiAgICBkYXRlUmFuZ2VFbmQhOiBEYXRlO1xuXG4gICAgZGF0ZVRpbWUhOiBEYXRlO1xuICAgIHRpbWUhOiBUaW1lO1xuICAgIHRpbWVEcm9wZG93blZhbHVlcyE6IERyb3Bkb3duVmFsdWU8VGltZT5bXTtcblxuICAgIGFycmF5SXRlbSE6IEVudGl0eVR5cGU7XG4gICAgcHJpdmF0ZSBhcnJheUl0ZW1QcmlvckNoYW5nZXMhOiBFbnRpdHlUeXBlO1xuICAgIGFycmF5SXRlbUlubGluZVJvd3MhOiBFbnRpdHlSb3c8RW50aXR5VHlwZT5bXTtcbiAgICBkYXRhU291cmNlITogTWF0VGFibGVEYXRhU291cmNlPEVudGl0eVR5cGU+O1xuICAgIHNlbGVjdGlvbjogU2VsZWN0aW9uTW9kZWw8RW50aXR5VHlwZT4gPSBuZXcgU2VsZWN0aW9uTW9kZWw8RW50aXR5VHlwZT4odHJ1ZSwgW10pO1xuICAgIGRpc3BsYXllZENvbHVtbnMhOiBzdHJpbmdbXTtcblxuICAgIGRpYWxvZ0lucHV0RGF0YSE6IEFkZEFycmF5SXRlbURpYWxvZ0RhdGE8RW50aXR5VHlwZT47XG4gICAgZGlhbG9nRGF0YSE6IEFkZEFycmF5SXRlbURpYWxvZ0RhdGFJbnRlcm5hbDxFbnRpdHlUeXBlPjtcbiAgICBhcnJheUl0ZW1EaWFsb2dSb3dzITogRW50aXR5Um93PEVudGl0eVR5cGU+W107XG5cbiAgICByZWFkb25seSBEZWNvcmF0b3JUeXBlcyA9IERlY29yYXRvclR5cGVzO1xuXG4gICAgRW50aXR5VXRpbGl0aWVzID0gRW50aXR5VXRpbGl0aWVzO1xuICAgIERhdGVVdGlsaXRpZXMgPSBEYXRlVXRpbGl0aWVzO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgZGlhbG9nOiBNYXREaWFsb2dcbiAgICApIHt9XG5cbiAgICBkZWZhdWx0RGF0ZUZpbHRlcjogRGF0ZUZpbHRlckZuPERhdGUgfCBudWxsIHwgdW5kZWZpbmVkPiA9ICgpOiBib29sZWFuID0+IHRydWU7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGlzIG5lZWRlZCBmb3IgdGhlIGlucHV0cyB0byB3b3JrIGluc2lkZSBhbiBuZ0Zvci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCBpbiB0aGUgbmdGb3IuXG4gICAgICogQHJldHVybnMgVGhlIGluZGV4LlxuICAgICAqL1xuICAgIHRyYWNrQnlGbihpbmRleDogdW5rbm93bik6IHVua25vd24ge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxuXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5lbnRpdHkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBJbnB1dCBkYXRhIFwiZW50aXR5XCInKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucHJvcGVydHlLZXkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBJbnB1dCBkYXRhIFwicHJvcGVydHlLZXlcIicpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudHlwZSA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eVR5cGUodGhpcy5lbnRpdHksIHRoaXMucHJvcGVydHlLZXkpO1xuICAgICAgICB0aGlzLm1ldGFkYXRhID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEodGhpcy5lbnRpdHksIHRoaXMucHJvcGVydHlLZXksIHRoaXMudHlwZSk7XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YURlZmF1bHRTdHJpbmcgPSB0aGlzLm1ldGFkYXRhIGFzIERlZmF1bHRTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgdGhpcy5tZXRhZGF0YVRleHRib3hTdHJpbmcgPSB0aGlzLm1ldGFkYXRhIGFzIFRleHRib3hTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcblxuICAgICAgICB0aGlzLm1ldGFkYXRhQXV0b2NvbXBsZXRlU3RyaW5nID0gdGhpcy5tZXRhZGF0YSBhcyBBdXRvY29tcGxldGVTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgdGhpcy5hdXRvY29tcGxldGVTdHJpbmdzID0gdGhpcy5tZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZy5hdXRvY29tcGxldGVWYWx1ZXM7XG4gICAgICAgIHRoaXMuZmlsdGVyZWRBdXRvY29tcGxldGVTdHJpbmdzID0gY2xvbmVEZWVwKHRoaXMuYXV0b2NvbXBsZXRlU3RyaW5ncyk7XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YURyb3Bkb3duU3RyaW5nID0gdGhpcy5tZXRhZGF0YSBhcyBEcm9wZG93blN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuXG4gICAgICAgIHRoaXMubWV0YWRhdGFEcm9wZG93bkJvb2xlYW4gPSB0aGlzLm1ldGFkYXRhIGFzIERyb3Bkb3duQm9vbGVhbkRlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICAodGhpcy50eXBlID09PSBEZWNvcmF0b3JUeXBlcy5CT09MRUFOX0NIRUNLQk9YIHx8IHRoaXMudHlwZSA9PT0gRGVjb3JhdG9yVHlwZXMuQk9PTEVBTl9UT0dHTEUpXG4gICAgICAgICAgICAmJiB0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSA9PT0gdW5kZWZpbmVkXG4gICAgICAgICkge1xuICAgICAgICAgICAgKHRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldIGFzIHVua25vd24gYXMgYm9vbGVhbikgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWV0YWRhdGFEZWZhdWx0TnVtYmVyID0gdGhpcy5tZXRhZGF0YSBhcyBEZWZhdWx0TnVtYmVyRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgIHRoaXMubWV0YWRhdGFEcm9wZG93bk51bWJlciA9IHRoaXMubWV0YWRhdGEgYXMgRHJvcGRvd25OdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcblxuICAgICAgICB0aGlzLm1ldGFkYXRhRGVmYXVsdE9iamVjdCA9IHRoaXMubWV0YWRhdGEgYXMgRGVmYXVsdE9iamVjdERlY29yYXRvckNvbmZpZ0ludGVybmFsPEVudGl0eVR5cGU+O1xuICAgICAgICB0aGlzLm9iamVjdFByb3BlcnR5ID0gdGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBFbnRpdHlUeXBlO1xuICAgICAgICBpZiAodGhpcy50eXBlID09PSBEZWNvcmF0b3JUeXBlcy5PQkpFQ1QpIHtcbiAgICAgICAgICAgIHRoaXMub2JqZWN0UHJvcGVydHlSb3dzID0gRW50aXR5VXRpbGl0aWVzLmdldEVudGl0eVJvd3ModGhpcy5vYmplY3RQcm9wZXJ0eSwgdGhpcy5oaWRlT21pdEZvckNyZWF0ZSwgdGhpcy5oaWRlT21pdEZvckVkaXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YUVudGl0eUFycmF5ID0gdGhpcy5tZXRhZGF0YSBhcyBFbnRpdHlBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsPEVudGl0eVR5cGU+O1xuICAgICAgICBpZiAodGhpcy50eXBlID09PSBEZWNvcmF0b3JUeXBlcy5BUlJBWSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSkge1xuICAgICAgICAgICAgICAgICh0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIEVudGl0eVR5cGVbXSkgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW50aXR5QXJyYXlWYWx1ZXMgPSB0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIEVudGl0eVR5cGVbXTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkuY3JlYXRlSW5saW5lID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkuY3JlYXRlSW5saW5lID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5tZXRhZGF0YUVudGl0eUFycmF5LmNyZWF0ZUlubGluZSAmJiAhdGhpcy5tZXRhZGF0YUVudGl0eUFycmF5LmNyZWF0ZURpYWxvZ0RhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkuY3JlYXRlRGlhbG9nRGF0YSA9IHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6ICdBZGQnXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZ2l2ZW5EaXNwbGF5Q29sdW1uczogc3RyaW5nW10gPSB0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkuZGlzcGxheUNvbHVtbnMubWFwKCh2KSA9PiB2LmRpc3BsYXlOYW1lKTtcbiAgICAgICAgICAgIGlmIChnaXZlbkRpc3BsYXlDb2x1bW5zLmZpbmQocyA9PiBzID09PSAnc2VsZWN0JykpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGBUaGUgbmFtZSBcInNlbGVjdFwiIGZvciBhIGRpc3BsYXkgY29sdW1uIGlzIHJlc2VydmVkLlxuICAgICAgICAgICAgICAgICAgICBQbGVhc2UgY2hvb3NlIGEgZGlmZmVyZW50IG5hbWUuYFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMgPSBbJ3NlbGVjdCddLmNvbmNhdChnaXZlbkRpc3BsYXlDb2x1bW5zKTtcbiAgICAgICAgICAgIHRoaXMuZGF0YVNvdXJjZSA9IG5ldyBNYXRUYWJsZURhdGFTb3VyY2UoKTtcbiAgICAgICAgICAgIHRoaXMuZGF0YVNvdXJjZS5kYXRhID0gdGhpcy5lbnRpdHlBcnJheVZhbHVlcztcbiAgICAgICAgICAgIHRoaXMuYXJyYXlJdGVtID0gbmV3IHRoaXMubWV0YWRhdGFFbnRpdHlBcnJheS5FbnRpdHlDbGFzcygpO1xuICAgICAgICAgICAgdGhpcy5hcnJheUl0ZW1JbmxpbmVSb3dzID0gRW50aXR5VXRpbGl0aWVzLmdldEVudGl0eVJvd3MoXG4gICAgICAgICAgICAgICAgdGhpcy5hcnJheUl0ZW0sXG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlT21pdEZvckNyZWF0ZSA9PT0gZmFsc2UgPyBmYWxzZSA6IHRydWUsXG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlT21pdEZvckVkaXQgPyB0cnVlIDogZmFsc2VcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmFycmF5SXRlbVByaW9yQ2hhbmdlcyA9IGNsb25lRGVlcCh0aGlzLmFycmF5SXRlbSk7XG5cbiAgICAgICAgICAgIHRoaXMuZGlhbG9nSW5wdXREYXRhID0ge1xuICAgICAgICAgICAgICAgIGVudGl0eTogdGhpcy5hcnJheUl0ZW0sXG4gICAgICAgICAgICAgICAgY3JlYXRlRGlhbG9nRGF0YTogdGhpcy5tZXRhZGF0YUVudGl0eUFycmF5LmNyZWF0ZURpYWxvZ0RhdGEsXG4gICAgICAgICAgICAgICAgZ2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZTogdGhpcy5nZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmRpYWxvZ0RhdGEgPSBuZXcgQWRkQXJyYXlJdGVtRGlhbG9nRGF0YUJ1aWxkZXIodGhpcy5kaWFsb2dJbnB1dERhdGEpLmdldFJlc3VsdCgpO1xuICAgICAgICAgICAgdGhpcy5hcnJheUl0ZW1EaWFsb2dSb3dzID0gRW50aXR5VXRpbGl0aWVzLmdldEVudGl0eVJvd3ModGhpcy5kaWFsb2dEYXRhLmVudGl0eSwgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheSA9IHRoaXMubWV0YWRhdGEgYXMgU3RyaW5nQ2hpcHNBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICAodGhpcy50eXBlID09PSBEZWNvcmF0b3JUeXBlcy5BUlJBWV9TVFJJTkdfQ0hJUFMgfHwgdGhpcy50eXBlID09PSBEZWNvcmF0b3JUeXBlcy5BUlJBWV9TVFJJTkdfQVVUT0NPTVBMRVRFX0NISVBTKVxuICAgICAgICAgICAgJiYgKHRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldIGFzIHVua25vd24gYXMgc3RyaW5nW10pPy5sZW5ndGhcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnN0cmluZ0NoaXBzQXJyYXlWYWx1ZXMgPSAodGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBzdHJpbmdbXSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1ldGFkYXRhQXV0b2NvbXBsZXRlU3RyaW5nQ2hpcHNBcnJheSA9IHRoaXMubWV0YWRhdGEgYXMgQXV0b2NvbXBsZXRlU3RyaW5nQ2hpcHNBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuXG4gICAgICAgIGlmICghdGhpcy5nZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKSB7XG4gICAgICAgICAgICB0aGlzLmdldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UgPSBnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tZXRhZGF0YURlZmF1bHREYXRlID0gdGhpcy5tZXRhZGF0YSBhcyBEZWZhdWx0RGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICB0aGlzLm1ldGFkYXRhRGF0ZVJhbmdlRGF0ZSA9IHRoaXMubWV0YWRhdGEgYXMgRGF0ZVJhbmdlRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICB0aGlzLm1ldGFkYXRhRGF0ZVRpbWVEYXRlID0gdGhpcy5tZXRhZGF0YSBhcyBEYXRlVGltZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcblxuICAgICAgICBpZiAodGhpcy50eXBlID09PSBEZWNvcmF0b3JUeXBlcy5EQVRFX1JBTkdFKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGVSYW5nZSA9IGNsb25lRGVlcCh0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duIGFzIERhdGVSYW5nZSk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZGF0ZVJhbmdlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlUmFuZ2UgPSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBEYXRlLFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IHVuZGVmaW5lZCBhcyB1bmtub3duIGFzIERhdGUsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlczogdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5kYXRlUmFuZ2VTdGFydCA9IG5ldyBEYXRlKHRoaXMuZGF0ZVJhbmdlLnN0YXJ0KTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZVJhbmdlRW5kID0gbmV3IERhdGUodGhpcy5kYXRlUmFuZ2UuZW5kKTtcbiAgICAgICAgICAgIHRoaXMuc2V0RGF0ZVJhbmdlVmFsdWVzKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy50eXBlID09PSBEZWNvcmF0b3JUeXBlcy5EQVRFX1RJTUUpIHtcbiAgICAgICAgICAgIHRoaXMudGltZSA9IERhdGVVdGlsaXRpZXMuZ2V0VGltZUZyb21EYXRlKERhdGVVdGlsaXRpZXMuYXNEYXRlKHRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldKSk7XG4gICAgICAgICAgICB0aGlzLnRpbWVEcm9wZG93blZhbHVlcyA9IHRoaXMubWV0YWRhdGFEYXRlVGltZURhdGUudGltZXM7XG4gICAgICAgICAgICBpZiAodGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGVUaW1lID0gbmV3IERhdGUodGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBEYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiB0d28gdGltZXMgYXJlIGVxdWFsLiBJcyBuZWVkZWQgZm9yIHRoZSBkcm9wZG93bi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0aW1lMSAtIFRoZSBmaXJzdCB0aW1lIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHRpbWUyIC0gVGhlIHNlY29uZCB0aW1lIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgdGhlIHRpbWUgb2JqZWN0cyBhcmUgdGhlIHNhbWUuXG4gICAgICovXG4gICAgY29tcGFyZVRpbWVzKHRpbWUxOiBUaW1lLCB0aW1lMjogVGltZSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGltZTEgJiYgdGltZTIgJiYgdGltZTEuaG91cnMgPT09IHRpbWUyLmhvdXJzICYmIHRpbWUxLm1pbnV0ZXMgPT09IHRpbWUyLm1pbnV0ZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgZGF0ZSByYW5nZSB2YWx1ZXMgYmFzZWQgb24gdGhlIHN0YXJ0IGFuZCBlbmQgZGF0ZS5cbiAgICAgKi9cbiAgICBzZXREYXRlUmFuZ2VWYWx1ZXMoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmRhdGVSYW5nZVN0YXJ0ICYmIHRoaXMuZGF0ZVJhbmdlRW5kKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGVSYW5nZS5zdGFydCA9IG5ldyBEYXRlKHRoaXMuZGF0ZVJhbmdlU3RhcnQpO1xuICAgICAgICAgICAgdGhpcy5kYXRlUmFuZ2UuZW5kID0gbmV3IERhdGUodGhpcy5kYXRlUmFuZ2VFbmQpO1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzOiBEYXRlW10gPSBEYXRlVXRpbGl0aWVzLmdldERhdGVzQmV0d2VlbihcbiAgICAgICAgICAgICAgICBuZXcgRGF0ZSh0aGlzLmRhdGVSYW5nZS5zdGFydCksXG4gICAgICAgICAgICAgICAgbmV3IERhdGUodGhpcy5kYXRlUmFuZ2UuZW5kKSxcbiAgICAgICAgICAgICAgICB0aGlzLm1ldGFkYXRhRGF0ZVJhbmdlRGF0ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZVJhbmdlLnZhbHVlcyA9IHZhbHVlcy5sZW5ndGggPyB2YWx1ZXMgOiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRhdGVSYW5nZS52YWx1ZXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gPSB0aGlzLmRhdGVSYW5nZSBhcyB1bmtub3duIGFzIEVudGl0eVR5cGVba2V5b2YgRW50aXR5VHlwZV1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB0aW1lIG9uIGEgZGF0ZXRpbWUgcHJvcGVydHkuXG4gICAgICovXG4gICAgc2V0VGltZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLmRhdGVUaW1lKSB7XG4gICAgICAgICAgICB0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSA9IHVuZGVmaW5lZCBhcyB1bmtub3duIGFzIEVudGl0eVR5cGVba2V5b2YgRW50aXR5VHlwZV07XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gPSBuZXcgRGF0ZSh0aGlzLmRhdGVUaW1lKSBhcyB1bmtub3duIGFzIEVudGl0eVR5cGVba2V5b2YgRW50aXR5VHlwZV07XG4gICAgICAgIGlmICh0aGlzLnRpbWU/LmhvdXJzICE9IG51bGwgJiYgdGhpcy50aW1lPy5taW51dGVzICE9IG51bGwpIHtcbiAgICAgICAgICAgIERhdGVVdGlsaXRpZXMuYXNEYXRlKHRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldKS5zZXRIb3Vycyh0aGlzLnRpbWUuaG91cnMsIHRoaXMudGltZS5taW51dGVzLCAwLCAwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIERhdGVVdGlsaXRpZXMuYXNEYXRlKHRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldKS5zZXRIb3VycygwLCAwLCAwLCAwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRyaWVzIHRvIGFkZCBhbiBpdGVtIHRvIHRoZSBhcnJheS5cbiAgICAgKiBEb2VzIHRoaXMgZWl0aGVyIGlubGluZSBpZiB0aGUgXCJjcmVhdGVJbmxpbmVcIi1tZXRhZGF0YSBpcyBzZXQgdG8gdHJ1ZVxuICAgICAqIG9yIGluIGEgc2VwYXJhdGUgZGlhbG9nIGlmIGl0IGlzIHNldCB0byBmYWxzZS5cbiAgICAgKi9cbiAgICBhZGQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm1ldGFkYXRhRW50aXR5QXJyYXkuY3JlYXRlSW5saW5lKSB7XG4gICAgICAgICAgICB0aGlzLmVudGl0eUFycmF5VmFsdWVzLnB1c2goY2xvbmVEZWVwKHRoaXMuYXJyYXlJdGVtKSk7XG4gICAgICAgICAgICB0aGlzLmRhdGFTb3VyY2UuZGF0YSA9IHRoaXMuZW50aXR5QXJyYXlWYWx1ZXM7XG4gICAgICAgICAgICBFbnRpdHlVdGlsaXRpZXMucmVzZXRDaGFuZ2VzT25FbnRpdHkodGhpcy5hcnJheUl0ZW0sIHRoaXMuYXJyYXlJdGVtUHJpb3JDaGFuZ2VzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYWRkQXJyYXlJdGVtRGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEFycmF5SXRlbURpYWxvZyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IHRoaXMuZGlhbG9nRGF0YSxcbiAgICAgICAgICAgICAgICAgICAgYXV0b0ZvY3VzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgcmVzdG9yZUZvY3VzOiBmYWxzZVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgdGhlIGFycmF5IGl0ZW0gZGVmaW5lZCBpbiB0aGUgZGlhbG9nLlxuICAgICAqL1xuICAgIGFkZEFycmF5SXRlbSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hZGRBcnJheUl0ZW1EaWFsb2dSZWYuY2xvc2UoKTtcbiAgICAgICAgdGhpcy5lbnRpdHlBcnJheVZhbHVlcy5wdXNoKGNsb25lRGVlcCh0aGlzLmFycmF5SXRlbSkpO1xuICAgICAgICB0aGlzLmRhdGFTb3VyY2UuZGF0YSA9IHRoaXMuZW50aXR5QXJyYXlWYWx1ZXM7XG4gICAgICAgIEVudGl0eVV0aWxpdGllcy5yZXNldENoYW5nZXNPbkVudGl0eSh0aGlzLmFycmF5SXRlbSwgdGhpcy5hcnJheUl0ZW1QcmlvckNoYW5nZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbmNlbHMgYWRkaW5nIHRoZSBhcnJheSBpdGVtIGRlZmluZWQgaW4gdGhlIGRpYWxvZy5cbiAgICAgKi9cbiAgICBjYW5jZWxBZGRBcnJheUl0ZW0oKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYWRkQXJyYXlJdGVtRGlhbG9nUmVmLmNsb3NlKCk7XG4gICAgICAgIEVudGl0eVV0aWxpdGllcy5yZXNldENoYW5nZXNPbkVudGl0eSh0aGlzLmFycmF5SXRlbSwgdGhpcy5hcnJheUl0ZW1QcmlvckNoYW5nZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIHNlbGVjdGVkIGVudHJpZXMgZnJvbSB0aGUgYXJyYXkuXG4gICAgICovXG4gICAgcmVtb3ZlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNlbGVjdGlvbi5zZWxlY3RlZC5mb3JFYWNoKHMgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbnRpdHlBcnJheVZhbHVlcy5zcGxpY2UodGhpcy5lbnRpdHlBcnJheVZhbHVlcy5pbmRleE9mKHMpLCAxKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZGF0YVNvdXJjZS5kYXRhID0gdGhpcy5lbnRpdHlBcnJheVZhbHVlcztcbiAgICAgICAgdGhpcy5zZWxlY3Rpb24uY2xlYXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIGFsbCBhcnJheS1pdGVtcyBpbiB0aGUgdGFibGUuXG4gICAgICovXG4gICAgbWFzdGVyVG9nZ2xlKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5pc0FsbFNlbGVjdGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uLmNsZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFTb3VyY2UuZGF0YS5mb3JFYWNoKHJvdyA9PiB0aGlzLnNlbGVjdGlvbi5zZWxlY3Qocm93KSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYWxsIGFycmF5LWl0ZW1zIGluIHRoZSB0YWJsZSBoYXZlIGJlZW4gc2VsZWN0ZWQuXG4gICAgICogVGhpcyBpcyBuZWVkZWQgdG8gZGlzcGxheSB0aGUgXCJtYXN0ZXJUb2dnbGVcIi1jaGVja2JveCBjb3JyZWN0bHkuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIG9yIG5vdCBhbGwgYXJyYXktaXRlbXMgaW4gdGhlIHRhYmxlIGhhdmUgYmVlbiBzZWxlY3RlZC5cbiAgICAgKi9cbiAgICBpc0FsbFNlbGVjdGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBudW1TZWxlY3RlZCA9IHRoaXMuc2VsZWN0aW9uLnNlbGVjdGVkLmxlbmd0aDtcbiAgICAgICAgY29uc3QgbnVtUm93cyA9IHRoaXMuZGF0YVNvdXJjZS5kYXRhLmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIG51bVNlbGVjdGVkID09PSBudW1Sb3dzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgYWRkaW5nIHN0cmluZ3MgdG8gdGhlIGNoaXBzQXJyYXkuXG4gICAgICogQ2hlY2tzIHZhbGlkYXRpb24gYW5kIGFsc28gY3JlYXRlcyBhIG5ldyBhcnJheSBpZiBpdCBpcyB1bmRlZmluZWQuXG4gICAgICogVGhpcyBpcyBuZWVkZWQgYmVjYXVzZSB0d28gdGhpbmdzIGFyZSB2YWxpZGF0ZWQ6IFRoZSBhcnJheSBpdHNlbGZcbiAgICAgKiBhbmQgdGhlIGNvbnRlbnRzIG9mIHRoZSBhcnJheS4gQW5kIHdlIG5lZWQgYSB3YXkgdG8gZGlzcGxheSBhblxuICAgICAqIG1hdC1lcnJvci4gQXMgdGhlIG9ubHkgdmFsaWRhdGlvbiBmb3IgdGhlIGFycmF5IGlzIHdoZXRoZXIgb3Igbm90XG4gICAgICogaXQgY29udGFpbnMgdmFsdWVzLCB3ZSBjYW4gc2V0IGl0IHRvIHVuZGVmaW5lZCB3aGVuIHRoZSBsYXN0IGVsZW1lbnQgaXMgcmVtb3ZlZFxuICAgICAqIChyZW1vdmVTdHJpbmdDaGlwQXJyYXlWYWx1ZSkuIFRoYXQgd2F5IHdlIGNhbiB1c2UgdGhlIFwicmVxdWlyZWRcIiB2YWxpZGF0b3IuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBUaGUgZXZlbnQgdGhhdCBmaXJlcyB3aGVuIGEgbmV3IGNoaXAgaXMgY29tcGxldGVkLlxuICAgICAqL1xuICAgIGFkZFN0cmluZ0NoaXBBcnJheVZhbHVlKGV2ZW50OiBNYXRDaGlwSW5wdXRFdmVudCk6IHZvaWQge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IChldmVudC52YWx1ZSB8fCAnJykudHJpbSgpO1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5taW5MZW5ndGggJiYgdmFsdWUubGVuZ3RoIDwgdGhpcy5tZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWluTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1heExlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPiB0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5tYXhMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5tZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkucmVnZXggICYmICF2YWx1ZS5tYXRjaCh0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuc3RyaW5nQ2hpcHNBcnJheVZhbHVlcykge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBzdHJpbmdbXSkge1xuICAgICAgICAgICAgICAgICAgICAodGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBzdHJpbmdbXSkgPSBbXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzID0gdGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBzdHJpbmdbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc3RyaW5nQ2hpcHNBcnJheVZhbHVlcy5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBldmVudC5jaGlwSW5wdXQhLmNsZWFyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgZ2l2ZW4gdmFsdWUgZnJvbSB0aGUgYXJyYXkuXG4gICAgICogU2V0cyB0aGUgYXJyYXkgdG8gdW5kZWZpbmVkIGlmIGl0IGlzIG5vdyBlbXB0eS5cbiAgICAgKiBUaGlzIGlzIG5lZWRlZCBiZWNhdXNlIHR3byB0aGluZ3MgYXJlIHZhbGlkYXRlZDogVGhlIGFycmF5IGl0c2VsZlxuICAgICAqIGFuZCB0aGUgY29udGVudHMgb2YgdGhlIGFycmF5LiBBbmQgd2UgbmVlZCBhIHdheSB0byBkaXNwbGF5IGFuXG4gICAgICogbWF0LWVycm9yLiBBcyB0aGUgb25seSB2YWxpZGF0aW9uIGZvciB0aGUgYXJyYXkgaXMgd2hldGhlciBvciBub3RcbiAgICAgKiBpdCBpcyBlbXB0eSwgc2V0dGluZyBpdCB0byB1bmRlZmluZWQgaGVyZSBlbmFibGVzIHVzIHRvIHVzZSB0aGUgXCJyZXF1aXJlZFwiIHZhbGlkYXRvci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBzdHJpbmcgdG8gcmVtb3ZlIGZyb20gdGhlIGFycmF5LlxuICAgICAqL1xuICAgIHJlbW92ZVN0cmluZ0NoaXBBcnJheVZhbHVlKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzLnNwbGljZSh0aGlzLnN0cmluZ0NoaXBzQXJyYXlWYWx1ZXMuaW5kZXhPZih2YWx1ZSksIDEpO1xuICAgICAgICBpZiAoIXRoaXMuc3RyaW5nQ2hpcHNBcnJheVZhbHVlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICh0aGlzLmVudGl0eVt0aGlzLnByb3BlcnR5S2V5XSBhcyB1bmtub3duKSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuc3RyaW5nQ2hpcHNBcnJheVZhbHVlcyA9IHRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldIGFzIHVua25vd24gYXMgc3RyaW5nW107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGFkZGluZyBhIHN0cmluZyB0byB0aGUgYXJyYXkgd2hlbiBhbiBhdXRvY29tcGxldGUgdmFsdWUgaGFzIGJlZW4gc2VsZWN0ZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBUaGUgYXV0b2NvbXBsZXRlIHNlbGVjdGVkIGV2ZW50LlxuICAgICAqIEBwYXJhbSBjaGlwc0lucHV0IC0gVGhlIGVsZW1lbnQgd2hlcmUgdGhlIHVzZXIgdHlwZWQgdGhlIHZhbHVlLlxuICAgICAqL1xuICAgIHNlbGVjdGVkKGV2ZW50OiBNYXRBdXRvY29tcGxldGVTZWxlY3RlZEV2ZW50LCBjaGlwc0lucHV0OiBIVE1MSW5wdXRFbGVtZW50KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gKGV2ZW50Lm9wdGlvbi52aWV3VmFsdWUgfHwgJycpLnRyaW0oKTtcbiAgICAgICAgaWYgKHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1pbkxlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPCB0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5taW5MZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5tZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWF4TGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA+IHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1heExlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCAgJiYgIXZhbHVlLm1hdGNoKHRoaXMubWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5LnJlZ2V4KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldIGFzIHVua25vd24gYXMgc3RyaW5nW10pIHtcbiAgICAgICAgICAgICAgICAodGhpcy5lbnRpdHlbdGhpcy5wcm9wZXJ0eUtleV0gYXMgdW5rbm93biBhcyBzdHJpbmdbXSkgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc3RyaW5nQ2hpcHNBcnJheVZhbHVlcyA9IHRoaXMuZW50aXR5W3RoaXMucHJvcGVydHlLZXldIGFzIHVua25vd24gYXMgc3RyaW5nW107XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdHJpbmdDaGlwc0FycmF5VmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgICBjaGlwc0lucHV0LnZhbHVlID0gJyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRHluYW1pY2FsbHkgZmlsdGVycyB0aGUgQXV0b2NvbXBsZXRlIG9wdGlvbnMgd2hlbiB0aGUgdXNlciBpbnB1dHMgc29tZXRoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIGlucHV0IC0gVGhlIGlucHV0IG9mIHRoZSB1c2VyLlxuICAgICAqL1xuICAgIGZpbHRlckF1dG9jb21wbGV0ZVN0cmluZ3MoaW5wdXQ6IHVua25vd24pOiB2b2lkIHtcbiAgICAgICAgaWYgKGlucHV0KSB7XG4gICAgICAgICAgICBjb25zdCBmaWx0ZXJWYWx1ZSA9IChpbnB1dCBhcyBzdHJpbmcpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICB0aGlzLmZpbHRlcmVkQXV0b2NvbXBsZXRlU3RyaW5ncyA9IHRoaXMuYXV0b2NvbXBsZXRlU3RyaW5ncy5maWx0ZXIocyA9PiBzLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoZmlsdGVyVmFsdWUpKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCI8ZGl2IFtuZ1N3aXRjaF09XCJ0eXBlXCIgKm5nSWY9XCIhKGhpZGVPbWl0Rm9yQ3JlYXRlICYmIG1ldGFkYXRhLm9taXRGb3JDcmVhdGUpICYmICEoaGlkZU9taXRGb3JFZGl0ICYmIG1ldGFkYXRhLm9taXRGb3JVcGRhdGUpXCI+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tU3RyaW5ncy0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiRGVjb3JhdG9yVHlwZXMuU1RSSU5HXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZW50aXR5W3Byb3BlcnR5S2V5XVwiXG4gICAgICAgICAgICAgICAgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiXG4gICAgICAgICAgICAgICAgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgW3JlcXVpcmVkXT1cIm1ldGFkYXRhLnJlcXVpcmVkXCJcbiAgICAgICAgICAgICAgICBbcGF0dGVybl09XCJtZXRhZGF0YURlZmF1bHRTdHJpbmcucmVnZXggPyBtZXRhZGF0YURlZmF1bHRTdHJpbmcucmVnZXggOiAnW1xcXFxzXFxcXFNdKidcIlxuICAgICAgICAgICAgICAgIFttaW5sZW5ndGhdPVwibWV0YWRhdGFEZWZhdWx0U3RyaW5nLm1pbkxlbmd0aCA/IG1ldGFkYXRhRGVmYXVsdFN0cmluZy5taW5MZW5ndGggOiBudWxsXCJcbiAgICAgICAgICAgICAgICBbbWF4bGVuZ3RoXT1cIm1ldGFkYXRhRGVmYXVsdFN0cmluZy5tYXhMZW5ndGggPyBtZXRhZGF0YURlZmF1bHRTdHJpbmcubWF4TGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLlNUUklOR19URVhUQk9YXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8dGV4dGFyZWFcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZW50aXR5W3Byb3BlcnR5S2V5XVwiXG4gICAgICAgICAgICAgICAgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiXG4gICAgICAgICAgICAgICAgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgY2RrVGV4dGFyZWFBdXRvc2l6ZVxuICAgICAgICAgICAgICAgIGNka0F1dG9zaXplTWluUm93cz1cIjEwXCJcbiAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWRcIlxuICAgICAgICAgICAgICAgIFttaW5sZW5ndGhdPVwibWV0YWRhdGFUZXh0Ym94U3RyaW5nLm1pbkxlbmd0aCA/IG1ldGFkYXRhVGV4dGJveFN0cmluZy5taW5MZW5ndGggOiBudWxsXCJcbiAgICAgICAgICAgICAgICBbbWF4bGVuZ3RoXT1cIm1ldGFkYXRhVGV4dGJveFN0cmluZy5tYXhMZW5ndGggPyBtZXRhZGF0YVRleHRib3hTdHJpbmcubWF4TGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICA8L3RleHRhcmVhPlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLlNUUklOR19BVVRPQ09NUExFVEVcIj5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57e21ldGFkYXRhLmRpc3BsYXlOYW1lfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJlbnRpdHlbcHJvcGVydHlLZXldXCJcbiAgICAgICAgICAgICAgICBbbmFtZV09XCJwcm9wZXJ0eUtleS50b1N0cmluZygpXCJcbiAgICAgICAgICAgICAgICAjbW9kZWw9XCJuZ01vZGVsXCJcbiAgICAgICAgICAgICAgICBbbWF0QXV0b2NvbXBsZXRlXT1cImF1dG9cIlxuICAgICAgICAgICAgICAgIChrZXl1cCk9XCJmaWx0ZXJBdXRvY29tcGxldGVTdHJpbmdzKGVudGl0eVtwcm9wZXJ0eUtleV0pXCJcbiAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWRcIlxuICAgICAgICAgICAgICAgIFttaW5sZW5ndGhdPVwibWV0YWRhdGFBdXRvY29tcGxldGVTdHJpbmcubWluTGVuZ3RoID8gbWV0YWRhdGFBdXRvY29tcGxldGVTdHJpbmcubWluTGVuZ3RoIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgW21heGxlbmd0aF09XCJtZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZy5tYXhMZW5ndGggPyBtZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZy5tYXhMZW5ndGggOiBudWxsXCJcbiAgICAgICAgICAgICAgICBbcGF0dGVybl09XCJtZXRhZGF0YUF1dG9jb21wbGV0ZVN0cmluZy5yZWdleCA/IG1ldGFkYXRhQXV0b2NvbXBsZXRlU3RyaW5nLnJlZ2V4IDogJ1tcXFxcc1xcXFxTXSonXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bWF0LWF1dG9jb21wbGV0ZSAjYXV0bz1cIm1hdEF1dG9jb21wbGV0ZVwiPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCB2YWx1ZSBvZiBmaWx0ZXJlZEF1dG9jb21wbGV0ZVN0cmluZ3NcIiBbdmFsdWVdPVwidmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAge3t2YWx1ZX19XG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgPC9tYXQtYXV0b2NvbXBsZXRlPlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLlNUUklOR19EUk9QRE9XTlwiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7bWV0YWRhdGEuZGlzcGxheU5hbWV9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPG1hdC1zZWxlY3QgWyhuZ01vZGVsKV09XCJlbnRpdHlbcHJvcGVydHlLZXldXCIgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiICNtb2RlbD1cIm5nTW9kZWxcIiBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWRcIj5cbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgdmFsdWUgb2YgbWV0YWRhdGFEcm9wZG93blN0cmluZy5kcm9wZG93blZhbHVlc1wiIFt2YWx1ZV09XCJ2YWx1ZS52YWx1ZVwiPnt7dmFsdWUuZGlzcGxheU5hbWV9fTwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgIDxtYXQtZXJyb3I+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKG1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS1Cb29sZWFucy0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5CT09MRUFOX0NIRUNLQk9YXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImhpZGVVbmRlcmxpbmVcIj5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LWNoZWNrYm94IChjbGljayk9XCJtb2RlbC5jb250cm9sLm1hcmtBc1RvdWNoZWQoKVwiIFsobmdNb2RlbCldPVwiZW50aXR5W3Byb3BlcnR5S2V5XVwiIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKClcIj48L21hdC1jaGVja2JveD5cbiAgICAgICAgICAgIDwhLS0gaGlkZGVuIGlucHV0IGlzIG5lZWRlZCBzbyB0aGF0IHRoZSBjaGVja2JveCBjYW4gYmUgdXNlZCBpbnNpZGUgYSBtYXQtZm9ybS1maWVsZCAtLT5cbiAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBoaWRkZW5cbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIlxuICAgICAgICAgICAgICAgIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKCkgKyAnSGVscGVyJ1wiXG4gICAgICAgICAgICAgICAgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgW3BhdHRlcm5dPVwibWV0YWRhdGEucmVxdWlyZWQgPyAndHJ1ZScgOiAnW1xcXFxzXFxcXFNdKidcIlxuICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZFwiPlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLkJPT0xFQU5fVE9HR0xFXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImhpZGVVbmRlcmxpbmVcIj5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LXNsaWRlLXRvZ2dsZSAoY2xpY2spPVwibW9kZWwuY29udHJvbC5tYXJrQXNUb3VjaGVkKClcIiBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIiBbbmFtZV09XCJwcm9wZXJ0eUtleS50b1N0cmluZygpXCI+PC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgPCEtLSBoaWRkZW4gaW5wdXQgaXMgbmVlZGVkIHNvIHRoYXQgdGhlIHRvZ2dsZSBjYW4gYmUgdXNlZCBpbnNpZGUgYSBtYXQtZm9ybS1maWVsZCAtLT5cbiAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBoaWRkZW5cbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIlxuICAgICAgICAgICAgICAgIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKCkgKyAnSGVscGVyJ1wiXG4gICAgICAgICAgICAgICAgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgW3BhdHRlcm5dPVwibWV0YWRhdGEucmVxdWlyZWQgPyAndHJ1ZScgOiAnW1xcXFxzXFxcXFNdKidcIlxuICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZFwiPlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLkJPT0xFQU5fRFJPUERPV05cIj5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57e21ldGFkYXRhLmRpc3BsYXlOYW1lfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxtYXQtc2VsZWN0IFsobmdNb2RlbCldPVwiZW50aXR5W3Byb3BlcnR5S2V5XVwiIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKClcIiAjbW9kZWw9XCJuZ01vZGVsXCIgW3JlcXVpcmVkXT1cIm1ldGFkYXRhLnJlcXVpcmVkXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cInVuZGVmaW5lZFwiPi08L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cInRydWVcIj57e21ldGFkYXRhRHJvcGRvd25Cb29sZWFuLmRyb3Bkb3duVHJ1ZX19PC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJmYWxzZVwiPnt7bWV0YWRhdGFEcm9wZG93bkJvb2xlYW4uZHJvcGRvd25GYWxzZX19PC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS1OdW1iZXJzLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLk5VTUJFUlwiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7bWV0YWRhdGEuZGlzcGxheU5hbWV9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIlxuICAgICAgICAgICAgICAgIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKClcIlxuICAgICAgICAgICAgICAgICNtb2RlbD1cIm5nTW9kZWxcIlxuICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZFwiXG4gICAgICAgICAgICAgICAgW21pbl09XCJtZXRhZGF0YURlZmF1bHROdW1iZXIubWluID8gbWV0YWRhdGFEZWZhdWx0TnVtYmVyLm1pbiA6IG51bGxcIlxuICAgICAgICAgICAgICAgIFttYXhdPVwibWV0YWRhdGFEZWZhdWx0TnVtYmVyLm1heCA/IG1ldGFkYXRhRGVmYXVsdE51bWJlci5tYXggOiBudWxsXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bWF0LWVycm9yPnt7Z2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZShtb2RlbCl9fTwvbWF0LWVycm9yPlxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiRGVjb3JhdG9yVHlwZXMuTlVNQkVSX0RST1BET1dOXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LXNlbGVjdCBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIiBbbmFtZV09XCJwcm9wZXJ0eUtleS50b1N0cmluZygpXCIgI21vZGVsPVwibmdNb2RlbFwiIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCB2YWx1ZSBvZiBtZXRhZGF0YURyb3Bkb3duTnVtYmVyLmRyb3Bkb3duVmFsdWVzXCIgW3ZhbHVlXT1cInZhbHVlLnZhbHVlXCI+e3t2YWx1ZS5kaXNwbGF5TmFtZX19PC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tT2JqZWN0LS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLk9CSkVDVFwiPlxuICAgICAgICA8Yj57e21ldGFkYXRhRGVmYXVsdE9iamVjdC5kaXNwbGF5TmFtZX19PC9iPlxuICAgICAgICA8IS0tIGl0ZXJhdGVzIG92ZXIgdGhlIG9iamVjdCBwcm9wZXJ0aWVzIC0tPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIiAqbmdGb3I9XCJsZXQgcm93IG9mIG9iamVjdFByb3BlcnR5Um93c1wiPlxuICAgICAgICAgICAgPCEtLVxuICAgICAgICAgICAgICAgIGRpc3BsYXlzIGFub3RoZXIgbmd4LW1hdGVyaWFsLWVudGl0eSB3aXRoIHRoZTpcbiAgICAgICAgICAgICAgICBvYmplY3QgYXMgdGhlIGVudGl0eSxcbiAgICAgICAgICAgICAgICB0aGUgY3VycmVudCBrZXkgaW4gdGhlIGxvb3AgcmVjZWl2ZWQgYnkgdGhlIGtleXZhbHVlIGRpcmVjdGlvbiBhcyB0aGUgcHJvcGVydHlLZXlcbiAgICAgICAgICAgICAgICBhbmQgdGhlIGdldFZhbGlkYXRpb25FcnJvck1lc3NhZ2Ugb2YgdGhlIGN1cnJlbnQgY29tcG9uZW50XG4gICAgICAgICAgICAtLT5cbiAgICAgICAgICAgIDxuZ3gtbWF0LWVudGl0eS1pbnB1dFxuICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBrZXkgb2Ygcm93LmtleXM7IGxldCBpID0gaW5kZXg7IHRyYWNrQnk6IHRyYWNrQnlGblwiXG4gICAgICAgICAgICAgICAgW2VudGl0eV09XCJvYmplY3RQcm9wZXJ0eVwiXG4gICAgICAgICAgICAgICAgW3Byb3BlcnR5S2V5XT1cImtleVwiXG4gICAgICAgICAgICAgICAgW2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2VdPVwiZ2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZVwiXG4gICAgICAgICAgICAgICAgW2hpZGVPbWl0Rm9yQ3JlYXRlXT1cImhpZGVPbWl0Rm9yQ3JlYXRlXCJcbiAgICAgICAgICAgICAgICBbaGlkZU9taXRGb3JFZGl0XT1cImhpZGVPbWl0Rm9yRWRpdFwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJjb2wtbGcte3tFbnRpdHlVdGlsaXRpZXMuZ2V0V2lkdGgob2JqZWN0UHJvcGVydHksIGtleSwgJ2xnJyl9fSBjb2wtbWQte3tFbnRpdHlVdGlsaXRpZXMuZ2V0V2lkdGgob2JqZWN0UHJvcGVydHksIGtleSwgJ21kJyl9fSBjb2wtc20te3tFbnRpdHlVdGlsaXRpZXMuZ2V0V2lkdGgob2JqZWN0UHJvcGVydHksIGtleSwgJ3NtJyl9fVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICA8L25neC1tYXQtZW50aXR5LWlucHV0PlxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tQXJyYXktLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDxkaXYgY2xhc3M9XCJlbnRpdHlBcnJheVwiICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5BUlJBWVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibWF0LWVsZXZhdGlvbi16OFwiIHN0eWxlPVwiYm9yZGVyLXJhZGl1czogNXB4O3BhZGRpbmc6IDE1cHg7bWFyZ2luLWJvdHRvbTogMTVweDttYXJnaW4tdG9wOiAxNXB4O1wiPlxuXG4gICAgICAgICAgICA8ZGl2IHN0eWxlPVwicGFkZGluZy1ib3R0b206IDEwcHhcIj5cbiAgICAgICAgICAgICAgICA8Yj57e21ldGFkYXRhRW50aXR5QXJyYXkuZGlzcGxheU5hbWV9fTwvYj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cIm1ldGFkYXRhRW50aXR5QXJyYXkuY3JlYXRlSW5saW5lXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvd1wiICpuZ0Zvcj1cImxldCByb3cgb2YgYXJyYXlJdGVtSW5saW5lUm93c1wiPlxuICAgICAgICAgICAgICAgICAgICA8bmd4LW1hdC1lbnRpdHktaW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBrZXkgb2Ygcm93LmtleXM7IGxldCBpID0gaW5kZXg7IHRyYWNrQnk6IHRyYWNrQnlGblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbZW50aXR5XT1cImFycmF5SXRlbVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbcHJvcGVydHlLZXldPVwia2V5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtoaWRlT21pdEZvckNyZWF0ZV09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlXT1cImdldFZhbGlkYXRpb25FcnJvck1lc3NhZ2VcIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJjb2wtbGcte3tFbnRpdHlVdGlsaXRpZXMuZ2V0V2lkdGgoYXJyYXlJdGVtLCBrZXksICdsZycpfX0gY29sLW1kLXt7RW50aXR5VXRpbGl0aWVzLmdldFdpZHRoKGFycmF5SXRlbSwga2V5LCAnbWQnKX19IGNvbC1zbS17e0VudGl0eVV0aWxpdGllcy5nZXRXaWR0aChhcnJheUl0ZW0sIGtleSwgJ3NtJyl9fVwiXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPC9uZ3gtbWF0LWVudGl0eS1pbnB1dD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYnV0dG9uc1wiPlxuICAgICAgICAgICAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIm1ldGFkYXRhRW50aXR5QXJyYXkuY3JlYXRlSW5saW5lICYmICFFbnRpdHlVdGlsaXRpZXMuaXNFbnRpdHlWYWxpZChhcnJheUl0ZW0sICdjcmVhdGUnKVwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJhZGQoKVwiPlxuICAgICAgICAgICAgICAgICAgICB7e21ldGFkYXRhRW50aXR5QXJyYXkuYWRkQnV0dG9uTGFiZWx9fVxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFzZWxlY3Rpb24uc2VsZWN0ZWQubGVuZ3RoXCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZSgpXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7bWV0YWRhdGFFbnRpdHlBcnJheS5yZW1vdmVCdXR0b25MYWJlbH19XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgXG4gICAgICAgICAgICA8bWF0LXRhYmxlIFtkYXRhU291cmNlXT1cImRhdGFTb3VyY2VcIj5cbiAgICAgICAgICAgICAgICA8IS0tIHNlbGVjdCBDb2x1bW4gLS0+XG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJzZWxlY3RcIj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtY2hlY2tib3ggW2Rpc2FibGVkXT1cIiFkYXRhU291cmNlLmRhdGEubGVuZ3RoXCIgKGNoYW5nZSk9XCIkZXZlbnQgPyBtYXN0ZXJUb2dnbGUoKSA6IG51bGxcIiBbY2hlY2tlZF09XCJzZWxlY3Rpb24uaGFzVmFsdWUoKSAmJiBpc0FsbFNlbGVjdGVkKClcIiBbaW5kZXRlcm1pbmF0ZV09XCJzZWxlY3Rpb24uaGFzVmFsdWUoKSAmJiAhaXNBbGxTZWxlY3RlZCgpXCI+PC9tYXQtY2hlY2tib3g+XG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWhlYWRlci1jZWxsPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgbW9kdWxlXCIgY2xhc3M9XCJtb2R1bGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtY2hlY2tib3ggKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiIChjaGFuZ2UpPVwiJGV2ZW50ID8gc2VsZWN0aW9uLnRvZ2dsZShtb2R1bGUpIDogbnVsbFwiIFtjaGVja2VkXT1cInNlbGVjdGlvbi5pc1NlbGVjdGVkKG1vZHVsZSlcIj48L21hdC1jaGVja2JveD5cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtY2VsbD5cbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGRDb2wgb2YgbWV0YWRhdGFFbnRpdHlBcnJheS5kaXNwbGF5Q29sdW1uc1wiIFttYXRDb2x1bW5EZWZdPVwiZENvbC5kaXNwbGF5TmFtZVwiPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPlxuICAgICAgICAgICAgICAgICAgICAgICAge3tkQ29sLmRpc3BsYXlOYW1lfX1cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtaGVhZGVyLWNlbGw+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtY2VsbCBjbGFzcz1cImVudGl0eVwiICptYXRDZWxsRGVmPVwibGV0IGVudGl0eVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3tkQ29sLnZhbHVlKGVudGl0eSl9fVxuICAgICAgICAgICAgICAgICAgICA8L21hdC1jZWxsPlxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgPG1hdC1oZWFkZXItcm93ICptYXRIZWFkZXJSb3dEZWY9XCJkaXNwbGF5ZWRDb2x1bW5zXCI+PC9tYXQtaGVhZGVyLXJvdz5cbiAgICAgICAgICAgICAgICA8bWF0LXJvdyAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogZGlzcGxheWVkQ29sdW1uc1wiPjwvbWF0LXJvdz5cbiAgICAgICAgICAgIDwvbWF0LXRhYmxlPlxuICAgICAgICBcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhcnJheS1lcnJvclwiICpuZ0lmPVwibWV0YWRhdGFFbnRpdHlBcnJheS5yZXF1aXJlZCAmJiAhZGF0YVNvdXJjZS5kYXRhLmxlbmd0aFwiPlxuICAgICAgICAgICAgICAgIHt7bWV0YWRhdGFFbnRpdHlBcnJheS5taXNzaW5nRXJyb3JNZXNzYWdlfX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLkFSUkFZX1NUUklOR19DSElQU1wiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7bWV0YWRhdGEuZGlzcGxheU5hbWV9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPG1hdC1jaGlwLWxpc3QgI2NoaXBMaXN0XG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJlbnRpdHlbcHJvcGVydHlLZXldXCIgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiICNtb2RlbD1cIm5nTW9kZWxcIlxuICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1jaGlwICpuZ0Zvcj1cImxldCB2YWx1ZSBvZiBzdHJpbmdDaGlwc0FycmF5VmFsdWVzXCIgKHJlbW92ZWQpPVwicmVtb3ZlU3RyaW5nQ2hpcEFycmF5VmFsdWUodmFsdWUpXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7dmFsdWV9fVxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdENoaXBSZW1vdmU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cInt7bWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5LmRlbGV0ZUljb259fVwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9tYXQtY2hpcD5cbiAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgW21hdENoaXBJbnB1dEZvcl09XCJjaGlwTGlzdFwiXG4gICAgICAgICAgICAgICAgICAgIFttYXRDaGlwSW5wdXRBZGRPbkJsdXJdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgIChtYXRDaGlwSW5wdXRUb2tlbkVuZCk9XCJhZGRTdHJpbmdDaGlwQXJyYXlWYWx1ZSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjaGlwc0lucHV0XCIgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiICNjaGlwc01vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgICAgIFttaW5sZW5ndGhdPSdtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWluTGVuZ3RoID8gbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1pbkxlbmd0aCA6IG51bGwnXG4gICAgICAgICAgICAgICAgICAgIFttYXhsZW5ndGhdPSdtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWF4TGVuZ3RoID8gbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1heExlbmd0aCA6IG51bGwnXG4gICAgICAgICAgICAgICAgICAgIFtwYXR0ZXJuXT1cIm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCA/IG1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCA6ICdbXFxcXHNcXFxcU10qJ1wiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJjaGlwc01vZGVsLmVycm9yc1wiPnt7Z2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZShjaGlwc01vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8L21hdC1jaGlwLWxpc3Q+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiIWNoaXBzTW9kZWwuZXJyb3JzXCI+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKG1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5BUlJBWV9TVFJJTkdfQVVUT0NPTVBMRVRFX0NISVBTXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LWNoaXAtbGlzdCAjY2hpcExpc3RcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVudGl0eVtwcm9wZXJ0eUtleV1cIiBbbmFtZV09XCJwcm9wZXJ0eUtleS50b1N0cmluZygpXCIgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgW3JlcXVpcmVkXT1cIm1ldGFkYXRhLnJlcXVpcmVkXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LWNoaXAgKm5nRm9yPVwibGV0IHZhbHVlIG9mIHN0cmluZ0NoaXBzQXJyYXlWYWx1ZXNcIiAocmVtb3ZlZCk9XCJyZW1vdmVTdHJpbmdDaGlwQXJyYXlWYWx1ZSh2YWx1ZSlcIj5cbiAgICAgICAgICAgICAgICAgICAge3t2YWx1ZX19XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gbWF0Q2hpcFJlbW92ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwie3ttZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkuZGVsZXRlSWNvbn19XCI+PC9pPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICA8L21hdC1jaGlwPlxuICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICBbbWF0Q2hpcElucHV0Rm9yXT1cImNoaXBMaXN0XCJcbiAgICAgICAgICAgICAgICAgICAgW21hdEF1dG9jb21wbGV0ZV09XCJhdXRvXCJcbiAgICAgICAgICAgICAgICAgICAgW21hdENoaXBJbnB1dEFkZE9uQmx1cl09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgKG1hdENoaXBJbnB1dFRva2VuRW5kKT1cImFkZFN0cmluZ0NoaXBBcnJheVZhbHVlKCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAoa2V5dXApPVwiZmlsdGVyQXV0b2NvbXBsZXRlU3RyaW5ncyhjaGlwc0lucHV0KVwiXG4gICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiY2hpcHNJbnB1dFwiIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKClcIiAjY2hpcHNNb2RlbD1cIm5nTW9kZWxcIlxuICAgICAgICAgICAgICAgICAgICAjY2hpcHNFbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIFttaW5sZW5ndGhdPSdtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWluTGVuZ3RoID8gbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1pbkxlbmd0aCA6IG51bGwnXG4gICAgICAgICAgICAgICAgICAgIFttYXhsZW5ndGhdPSdtZXRhZGF0YVN0cmluZ0NoaXBzQXJyYXkubWF4TGVuZ3RoID8gbWV0YWRhdGFTdHJpbmdDaGlwc0FycmF5Lm1heExlbmd0aCA6IG51bGwnXG4gICAgICAgICAgICAgICAgICAgIFtwYXR0ZXJuXT1cIm1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCA/IG1ldGFkYXRhU3RyaW5nQ2hpcHNBcnJheS5yZWdleCA6ICdbXFxcXHNcXFxcU10qJ1wiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJjaGlwc01vZGVsLmVycm9yc1wiPnt7Z2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZShjaGlwc01vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8L21hdC1jaGlwLWxpc3Q+XG4gICAgICAgICAgICA8bWF0LWF1dG9jb21wbGV0ZSAjYXV0bz1cIm1hdEF1dG9jb21wbGV0ZVwiIChvcHRpb25TZWxlY3RlZCk9XCJzZWxlY3RlZCgkZXZlbnQsIGNoaXBzRWxlbWVudClcIj5cbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgdmFsdWUgb2YgZmlsdGVyZWRBdXRvY29tcGxldGVTdHJpbmdzXCIgW3ZhbHVlXT1cInZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICB7e3ZhbHVlfX1cbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICA8L21hdC1hdXRvY29tcGxldGU+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiIWNoaXBzTW9kZWwuZXJyb3JzXCI+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKG1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgIDwhLS0tLS0tLS0tLS0tLS0tLS0tLURhdGVzLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5EQVRFXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwic3RhbmRhcmRcIj5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZW50aXR5W3Byb3BlcnR5S2V5XVwiXG4gICAgICAgICAgICAgICAgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKVwiXG4gICAgICAgICAgICAgICAgI21vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgW21hdERhdGVwaWNrZXJdPVwicGlja2VyXCJcbiAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwibWV0YWRhdGEucmVxdWlyZWRcIlxuICAgICAgICAgICAgICAgIFttaW5dPVwibWV0YWRhdGFEZWZhdWx0RGF0ZS5taW4gPyBtZXRhZGF0YURlZmF1bHREYXRlLm1pbihEYXRlVXRpbGl0aWVzLmFzRGF0ZShlbnRpdHlbcHJvcGVydHlLZXldKSkgOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgICAgIFttYXhdPVwibWV0YWRhdGFEZWZhdWx0RGF0ZS5tYXggPyBtZXRhZGF0YURlZmF1bHREYXRlLm1heChEYXRlVXRpbGl0aWVzLmFzRGF0ZShlbnRpdHlbcHJvcGVydHlLZXldKSkgOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgICAgIFttYXREYXRlcGlja2VyRmlsdGVyXT1cIm1ldGFkYXRhRGVmYXVsdERhdGUuZmlsdGVyID8gbWV0YWRhdGFEZWZhdWx0RGF0ZS5maWx0ZXIgOiBkZWZhdWx0RGF0ZUZpbHRlclwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICA8bWF0LWRhdGVwaWNrZXItdG9nZ2xlIG1hdFN1ZmZpeCBbZm9yXT1cInBpY2tlclwiPjwvbWF0LWRhdGVwaWNrZXItdG9nZ2xlPlxuICAgICAgICAgICAgPG1hdC1kYXRlcGlja2VyICNwaWNrZXI+PC9tYXQtZGF0ZXBpY2tlcj5cbiAgICAgICAgICAgIDxtYXQtZXJyb3I+e3tnZXRWYWxpZGF0aW9uRXJyb3JNZXNzYWdlKG1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCJEZWNvcmF0b3JUeXBlcy5EQVRFX1JBTkdFXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwic3RhbmRhcmRcIj5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIDxtYXQtZGF0ZS1yYW5nZS1pbnB1dCBbcmFuZ2VQaWNrZXJdPVwicGlja2VyXCIgW3JlcXVpcmVkXT1cIm1ldGFkYXRhLnJlcXVpcmVkXCIgW2RhdGVGaWx0ZXJdPVwibWV0YWRhdGFEYXRlUmFuZ2VEYXRlLmZpbHRlciA/IG1ldGFkYXRhRGF0ZVJhbmdlRGF0ZS5maWx0ZXIgOiBkZWZhdWx0RGF0ZUZpbHRlclwiPlxuICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRTdGFydERhdGVcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJkYXRlUmFuZ2VTdGFydFwiXG4gICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKCkgKyAnc3RhcnQnXCJcbiAgICAgICAgICAgICAgICAgICAgI3N0YXJ0TW9kZWw9XCJuZ01vZGVsXCJcbiAgICAgICAgICAgICAgICAgICAgW3JlcXVpcmVkXT1cIm1ldGFkYXRhLnJlcXVpcmVkXCJcbiAgICAgICAgICAgICAgICAgICAgW21pbl09XCJtZXRhZGF0YURhdGVSYW5nZURhdGUubWluU3RhcnQgPyBtZXRhZGF0YURhdGVSYW5nZURhdGUubWluU3RhcnQoZGF0ZVJhbmdlLnN0YXJ0KSA6IHVuZGVmaW5lZFwiXG4gICAgICAgICAgICAgICAgICAgIFttYXhdPVwibWV0YWRhdGFEYXRlUmFuZ2VEYXRlLm1heFN0YXJ0ID8gbWV0YWRhdGFEYXRlUmFuZ2VEYXRlLm1heFN0YXJ0KGRhdGVSYW5nZS5zdGFydCkgOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwibWV0YWRhdGFEYXRlUmFuZ2VEYXRlLnBsYWNlaG9sZGVyU3RhcnQgPyBtZXRhZGF0YURhdGVSYW5nZURhdGUucGxhY2Vob2xkZXJTdGFydCA6ICdTdGFydCdcIlxuICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzZXREYXRlUmFuZ2VWYWx1ZXMoKVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRFbmREYXRlXG4gICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZGF0ZVJhbmdlRW5kXCJcbiAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKSArICdlbmQnXCJcbiAgICAgICAgICAgICAgICAgICAgI2VuZE1vZGVsPVwibmdNb2RlbFwiXG4gICAgICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZFwiXG4gICAgICAgICAgICAgICAgICAgIFttaW5dPVwibWV0YWRhdGFEYXRlUmFuZ2VEYXRlLm1pbkVuZCA/IG1ldGFkYXRhRGF0ZVJhbmdlRGF0ZS5taW5FbmQoZGF0ZVJhbmdlLmVuZCkgOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgICAgICAgICBbbWF4XT1cIm1ldGFkYXRhRGF0ZVJhbmdlRGF0ZS5tYXhFbmQgPyBtZXRhZGF0YURhdGVSYW5nZURhdGUubWF4RW5kKGRhdGVSYW5nZS5lbmQpIDogdW5kZWZpbmVkXCJcbiAgICAgICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIm1ldGFkYXRhRGF0ZVJhbmdlRGF0ZS5wbGFjZWhvbGRlckVuZCA/IG1ldGFkYXRhRGF0ZVJhbmdlRGF0ZS5wbGFjZWhvbGRlckVuZCA6ICdFbmQnXCJcbiAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic2V0RGF0ZVJhbmdlVmFsdWVzKClcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgIDwvbWF0LWRhdGUtcmFuZ2UtaW5wdXQ+XG4gICAgICAgICAgICA8bWF0LWRhdGVwaWNrZXItdG9nZ2xlIG1hdFN1ZmZpeCBbZm9yXT1cInBpY2tlclwiPjwvbWF0LWRhdGVwaWNrZXItdG9nZ2xlPlxuICAgICAgICAgICAgPG1hdC1kYXRlLXJhbmdlLXBpY2tlciAjcGlja2VyPjwvbWF0LWRhdGUtcmFuZ2UtcGlja2VyPlxuXG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwic3RhcnRNb2RlbC5lcnJvcnNcIj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2Uoc3RhcnRNb2RlbCl9fTwvbWF0LWVycm9yPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cIiFzdGFydE1vZGVsLmVycm9ycyAmJiBlbmRNb2RlbC5lcnJvcnNcIj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UoZW5kTW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIkRlY29yYXRvclR5cGVzLkRBVEVfVElNRVwiIGNsYXNzPVwiZGF0ZS10aW1lXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwic3RhbmRhcmRcIiBjbGFzcz1cImRhdGVwaWNrZXJcIj5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3ttZXRhZGF0YS5kaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZGF0ZVRpbWVcIlxuICAgICAgICAgICAgICAgIFtuYW1lXT1cInByb3BlcnR5S2V5LnRvU3RyaW5nKClcIlxuICAgICAgICAgICAgICAgICNtb2RlbD1cIm5nTW9kZWxcIlxuICAgICAgICAgICAgICAgIFttYXREYXRlcGlja2VyXT1cInBpY2tlclwiXG4gICAgICAgICAgICAgICAgW3JlcXVpcmVkXT1cIm1ldGFkYXRhLnJlcXVpcmVkXCJcbiAgICAgICAgICAgICAgICBbbWluXT1cIm1ldGFkYXRhRGF0ZVRpbWVEYXRlLm1pbkRhdGUgPyBtZXRhZGF0YURhdGVUaW1lRGF0ZS5taW5EYXRlKGRhdGVUaW1lKSA6IHVuZGVmaW5lZFwiXG4gICAgICAgICAgICAgICAgW21heF09XCJtZXRhZGF0YURhdGVUaW1lRGF0ZS5tYXhEYXRlID8gbWV0YWRhdGFEYXRlVGltZURhdGUubWF4RGF0ZShkYXRlVGltZSkgOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgICAgIFttYXREYXRlcGlja2VyRmlsdGVyXT1cIm1ldGFkYXRhRGF0ZVRpbWVEYXRlLmZpbHRlckRhdGUgPyBtZXRhZGF0YURhdGVUaW1lRGF0ZS5maWx0ZXJEYXRlIDogZGVmYXVsdERhdGVGaWx0ZXJcIlxuICAgICAgICAgICAgICAgIChkYXRlSW5wdXQpPVwic2V0VGltZSgpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgIDxtYXQtZGF0ZXBpY2tlci10b2dnbGUgbWF0U3VmZml4IFtmb3JdPVwicGlja2VyXCI+PC9tYXQtZGF0ZXBpY2tlci10b2dnbGU+XG4gICAgICAgICAgICA8bWF0LWRhdGVwaWNrZXIgI3BpY2tlcj48L21hdC1kYXRlcGlja2VyPlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UobW9kZWwpfX08L21hdC1lcnJvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwidGltZXBpY2tlclwiPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57e21ldGFkYXRhRGF0ZVRpbWVEYXRlLnRpbWVEaXNwbGF5TmFtZX19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwidGltZVwiXG4gICAgICAgICAgICAgICAgW25hbWVdPVwicHJvcGVydHlLZXkudG9TdHJpbmcoKSArICd0aW1lJ1wiXG4gICAgICAgICAgICAgICAgI3RpbWVNb2RlbD1cIm5nTW9kZWxcIlxuICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJtZXRhZGF0YS5yZXF1aXJlZFwiXG4gICAgICAgICAgICAgICAgW2NvbXBhcmVXaXRoXT1cImNvbXBhcmVUaW1lc1wiXG4gICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic2V0VGltZSgpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgdmFsaWRUaW1lIG9mIERhdGVVdGlsaXRpZXMuZ2V0VmFsaWRUaW1lc0ZvckRyb3Bkb3duKFxuICAgICAgICAgICAgICAgICAgICAgICAgRGF0ZVV0aWxpdGllcy5hc0RhdGUoZW50aXR5W3Byb3BlcnR5S2V5XSksXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YURhdGVUaW1lRGF0ZS50aW1lcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhRGF0ZVRpbWVEYXRlLm1pblRpbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YURhdGVUaW1lRGF0ZS5tYXhUaW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGFEYXRlVGltZURhdGUuZmlsdGVyVGltZVxuICAgICAgICAgICAgICAgICAgICApXCJcbiAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cInZhbGlkVGltZS52YWx1ZVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICB7e3ZhbGlkVGltZS5kaXNwbGF5TmFtZX19XG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgPG1hdC1lcnJvcj57e2dldFZhbGlkYXRpb25FcnJvck1lc3NhZ2UodGltZU1vZGVsKX19PC9tYXQtZXJyb3I+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2ICpuZ1N3aXRjaERlZmF1bHQ+RVJST1I6IFRoZSB0eXBlIHt7dHlwZX19IGlzIG5vdCBrbm93bi48L2Rpdj5cbjwvZGl2PlxuXG48IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbjwhLS0tLS0tLS0tLS0tLS0tLS0tLS1BZGQgQXJyYXkgSXRlbSBEaWFsb2ctLS0tLS0tLS0tLS0tLS0tPlxuPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG48bmctdGVtcGxhdGUgI2FkZEFycmF5SXRlbURpYWxvZz5cbiAgICA8aDIgbWF0LWRpYWxvZy10aXRsZT57e2RpYWxvZ0RhdGEuY3JlYXRlRGlhbG9nRGF0YS50aXRsZX19PC9oMj5cblxuICAgIDxtYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgICAgIDxmb3JtICNmb3JtPVwibmdGb3JtXCIgY2xhc3M9XCJyb3dcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIiAqbmdGb3I9XCJsZXQgcm93IG9mIGFycmF5SXRlbURpYWxvZ1Jvd3NcIj5cbiAgICAgICAgICAgICAgICA8bmd4LW1hdC1lbnRpdHktaW5wdXRcbiAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGtleSBvZiByb3cua2V5c1wiXG4gICAgICAgICAgICAgICAgICAgIFtlbnRpdHldPVwiZGlhbG9nRGF0YS5lbnRpdHlcIlxuICAgICAgICAgICAgICAgICAgICBbcHJvcGVydHlLZXldPVwia2V5XCJcbiAgICAgICAgICAgICAgICAgICAgW2hpZGVPbWl0Rm9yQ3JlYXRlXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICBbZ2V0VmFsaWRhdGlvbkVycm9yTWVzc2FnZV09XCJkaWFsb2dEYXRhLmdldFZhbGlkYXRpb25FcnJvck1lc3NhZ2VcIlxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNvbC1sZy17e0VudGl0eVV0aWxpdGllcy5nZXRXaWR0aChkaWFsb2dEYXRhLmVudGl0eSwga2V5LCAnbGcnKX19IGNvbC1tZC17e0VudGl0eVV0aWxpdGllcy5nZXRXaWR0aChkaWFsb2dEYXRhLmVudGl0eSwga2V5LCAnbWQnKX19IGNvbC1zbS17e0VudGl0eVV0aWxpdGllcy5nZXRXaWR0aChkaWFsb2dEYXRhLmVudGl0eSwga2V5LCAnc20nKX19XCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9uZ3gtbWF0LWVudGl0eS1pbnB1dD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Zvcm0+XG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG5cbiAgICA8bWF0LWRpYWxvZy1hY3Rpb25zPlxuICAgICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJhZGRBcnJheUl0ZW0oKVwiIFtkaXNhYmxlZF09XCIhRW50aXR5VXRpbGl0aWVzLmlzRW50aXR5VmFsaWQoZGlhbG9nRGF0YS5lbnRpdHksICdjcmVhdGUnKVwiPlxuICAgICAgICAgICAge3tkaWFsb2dEYXRhLmNyZWF0ZURpYWxvZ0RhdGEuY3JlYXRlQnV0dG9uTGFiZWx9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtcmFpc2VkLWJ1dHRvbiAoY2xpY2spPVwiY2FuY2VsQWRkQXJyYXlJdGVtKClcIiBjbGFzcz1cImNhbmNlbC1idXR0b25cIj5cbiAgICAgICAgICAgIHt7ZGlhbG9nRGF0YS5jcmVhdGVEaWFsb2dEYXRhLmNhbmNlbEJ1dHRvbkxhYmVsfX1cbiAgICAgICAgPC9idXR0b24+XG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XG5cbjwvbmctdGVtcGxhdGU+Il19