ngx-material-entity 15.1.3 → 15.1.5

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 (98) hide show
  1. package/README.md +100 -0
  2. package/components/confirm-dialog/confirm-dialog.component.d.ts +1 -1
  3. package/components/edit-page/edit-page.component.d.ts +112 -0
  4. package/components/edit-page/page-edit-data.builder.d.ts +17 -0
  5. package/components/input/array/array-date-input/array-date-input.component.d.ts +1 -1
  6. package/components/input/array/array-date-range-input/array-date-range-input.component.d.ts +1 -1
  7. package/components/input/array/array-date-time-input/array-date-time-input.component.d.ts +1 -1
  8. package/components/input/array/array-table.class.d.ts +1 -1
  9. package/components/input/date/date-input/date-input.component.d.ts +1 -1
  10. package/components/input/date/date-time-input/date-time-input.component.d.ts +1 -1
  11. package/components/input/file/file-default-input/file-default-input.component.d.ts +1 -1
  12. package/components/input/file/file-image-input/file-image-input.component.d.ts +1 -1
  13. package/components/input/file/file-input/file-input.component.d.ts +3 -3
  14. package/components/input/input.component.d.ts +3 -3
  15. package/components/input/relations/references-many-input/references-many-input.component.d.ts +1 -1
  16. package/components/input/string/string-password-input/string-password-input.component.d.ts +1 -1
  17. package/components/table/create-dialog/create-entity-dialog-data.builder.d.ts +3 -3
  18. package/components/table/create-dialog/create-entity-dialog-data.d.ts +1 -1
  19. package/components/table/create-dialog/create-entity-dialog.component.d.ts +4 -4
  20. package/components/table/default.actions.d.ts +21 -0
  21. package/components/table/edit-dialog/{edit-dialog-data.builder.d.ts → edit-data.builder.d.ts} +7 -7
  22. package/components/table/edit-dialog/{edit-entity-dialog-data.d.ts → edit-entity-data.d.ts} +5 -5
  23. package/components/table/edit-dialog/edit-entity-dialog.component.d.ts +6 -6
  24. package/components/table/edit-dialog/edit-entity.builder.d.ts +24 -0
  25. package/components/table/table-data.builder.d.ts +11 -7
  26. package/components/table/table-data.d.ts +29 -8
  27. package/components/table/table.component.d.ts +14 -7
  28. package/components/table/table.module.d.ts +4 -3
  29. package/encapsulation/js-2-xml.utilities.d.ts +15 -0
  30. package/encapsulation/jszip.utilities.d.ts +3 -2
  31. package/encapsulation/lodash.utilities.d.ts +7 -0
  32. package/esm2020/classes/entity.model.mjs +2 -2
  33. package/esm2020/components/confirm-dialog/confirm-dialog.component.mjs +4 -4
  34. package/esm2020/components/edit-page/edit-page.component.mjs +203 -0
  35. package/esm2020/components/edit-page/page-edit-data.builder.mjs +32 -0
  36. package/esm2020/components/input/array/array-date-input/array-date-input.component.mjs +4 -4
  37. package/esm2020/components/input/array/array-date-range-input/array-date-range-input.component.mjs +4 -4
  38. package/esm2020/components/input/array/array-date-time-input/array-date-time-input.component.mjs +4 -4
  39. package/esm2020/components/input/array/array-table.class.mjs +3 -3
  40. package/esm2020/components/input/base-input.component.mjs +2 -2
  41. package/esm2020/components/input/date/date-input/date-input.component.mjs +2 -2
  42. package/esm2020/components/input/date/date-range-input/date-range-input.component.mjs +5 -5
  43. package/esm2020/components/input/date/date-time-input/date-time-input.component.mjs +3 -3
  44. package/esm2020/components/input/file/file-default-input/file-default-input.component.mjs +2 -2
  45. package/esm2020/components/input/file/file-image-input/file-image-input.component.mjs +3 -3
  46. package/esm2020/components/input/file/file-input/file-input.component.mjs +5 -5
  47. package/esm2020/components/input/input.component.mjs +6 -6
  48. package/esm2020/components/input/relations/references-many-input/references-many-input.component.mjs +4 -4
  49. package/esm2020/components/input/string/string-password-input/string-password-input.component.mjs +4 -4
  50. package/esm2020/components/table/create-dialog/create-entity-dialog-data.builder.mjs +2 -2
  51. package/esm2020/components/table/create-dialog/create-entity-dialog-data.mjs +1 -1
  52. package/esm2020/components/table/create-dialog/create-entity-dialog.component.mjs +5 -5
  53. package/esm2020/components/table/default.actions.mjs +65 -0
  54. package/esm2020/components/table/edit-dialog/edit-data.builder.mjs +41 -0
  55. package/esm2020/components/table/edit-dialog/edit-entity-data.mjs +2 -0
  56. package/esm2020/components/table/edit-dialog/edit-entity-dialog.component.mjs +16 -16
  57. package/esm2020/components/table/edit-dialog/edit-entity.builder.mjs +28 -0
  58. package/esm2020/components/table/table-data.builder.mjs +19 -8
  59. package/esm2020/components/table/table-data.mjs +1 -1
  60. package/esm2020/components/table/table.component.mjs +73 -29
  61. package/esm2020/components/table/table.module.mjs +5 -1
  62. package/esm2020/decorators/array/array-decorator-internal.data.mjs +2 -2
  63. package/esm2020/decorators/base/base-property.decorator.mjs +2 -2
  64. package/esm2020/decorators/date/date-decorator-internal.data.mjs +2 -2
  65. package/esm2020/decorators/date/date.decorator.mjs +2 -2
  66. package/esm2020/decorators/file/file.decorator.mjs +2 -2
  67. package/esm2020/decorators/string/string.decorator.mjs +2 -2
  68. package/esm2020/encapsulation/js-2-xml.utilities.mjs +18 -0
  69. package/esm2020/encapsulation/jszip.utilities.mjs +1 -1
  70. package/esm2020/encapsulation/lodash.utilities.mjs +13 -1
  71. package/esm2020/public-api.mjs +31 -26
  72. package/esm2020/services/entity.service.mjs +252 -0
  73. package/esm2020/services/unsaved-changes.guard.mjs +14 -0
  74. package/esm2020/utilities/date.utilities.mjs +158 -0
  75. package/esm2020/utilities/entity.utilities.mjs +828 -0
  76. package/esm2020/utilities/file.utilities.mjs +176 -0
  77. package/esm2020/utilities/selection.utilities.mjs +50 -0
  78. package/fesm2015/ngx-material-entity.mjs +1071 -644
  79. package/fesm2015/ngx-material-entity.mjs.map +1 -1
  80. package/fesm2020/ngx-material-entity.mjs +992 -571
  81. package/fesm2020/ngx-material-entity.mjs.map +1 -1
  82. package/package.json +3 -2
  83. package/public-api.d.ts +28 -25
  84. package/{classes → services}/entity.service.d.ts +25 -1
  85. package/services/unsaved-changes.guard.d.ts +4 -0
  86. package/{classes → utilities}/entity.utilities.d.ts +1 -1
  87. package/{classes → utilities}/file.utilities.d.ts +7 -0
  88. package/components/table/edit-dialog/edit-entity-dialog.builder.d.ts +0 -24
  89. package/esm2020/classes/date.utilities.mjs +0 -158
  90. package/esm2020/classes/entity.service.mjs +0 -213
  91. package/esm2020/classes/entity.utilities.mjs +0 -828
  92. package/esm2020/classes/file.utilities.mjs +0 -163
  93. package/esm2020/classes/selection.utilities.mjs +0 -50
  94. package/esm2020/components/table/edit-dialog/edit-dialog-data.builder.mjs +0 -41
  95. package/esm2020/components/table/edit-dialog/edit-entity-dialog-data.mjs +0 -2
  96. package/esm2020/components/table/edit-dialog/edit-entity-dialog.builder.mjs +0 -28
  97. /package/{classes → utilities}/date.utilities.d.ts +0 -0
  98. /package/{classes → utilities}/selection.utilities.d.ts +0 -0
@@ -0,0 +1,828 @@
1
+ import { DecoratorTypes } from '../decorators/base/decorator-types.enum';
2
+ import { LodashUtilities } from '../encapsulation/lodash.utilities';
3
+ import { ReflectUtilities } from '../encapsulation/reflect.utilities';
4
+ import { DateUtilities } from './date.utilities';
5
+ import { FileUtilities } from './file.utilities';
6
+ /**
7
+ * Contains HelperMethods around handling Entities and their property-metadata.
8
+ */
9
+ export class EntityUtilities {
10
+ /**
11
+ * Gets the properties to omit when updating the entity.
12
+ *
13
+ * @param entity - The entity to get the properties which should be left out for updating from.
14
+ * @returns The properties which should be left out for updating an Entity.
15
+ */
16
+ static getOmitForUpdate(entity) {
17
+ const res = [];
18
+ for (const key of EntityUtilities.keysOf(entity)) {
19
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
20
+ if (metadata.omitForUpdate) {
21
+ res.push(key);
22
+ }
23
+ }
24
+ return res;
25
+ }
26
+ /**
27
+ * Gets the properties to omit when creating new entities.
28
+ *
29
+ * @param entity - The entity to get the properties which should be left out for creating from.
30
+ * @returns The properties which should be left out for creating a new Entity.
31
+ */
32
+ static getOmitForCreate(entity) {
33
+ const res = [];
34
+ for (const key of EntityUtilities.keysOf(entity)) {
35
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
36
+ if (metadata.omitForCreate) {
37
+ res.push(key);
38
+ }
39
+ }
40
+ return res;
41
+ }
42
+ /**
43
+ * Gets all properties on the given entity which are files.
44
+ *
45
+ * @param entity - The entity to check for file properties.
46
+ * @param omit - Whether to leave out values that are omitted for create or delete.
47
+ * @returns The keys of all file properties on the given entity.
48
+ */
49
+ static getFileProperties(entity, omit) {
50
+ const res = [];
51
+ for (const key of EntityUtilities.keysOf(entity)) {
52
+ const type = EntityUtilities.getPropertyType(entity, key);
53
+ if (type === DecoratorTypes.FILE_DEFAULT || type === DecoratorTypes.FILE_IMAGE) {
54
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
55
+ if (!(metadata.omitForCreate && omit === 'create') && !(metadata.omitForUpdate && omit === 'update')) {
56
+ res.push(key);
57
+ }
58
+ }
59
+ }
60
+ return res;
61
+ }
62
+ /**
63
+ * Gets the metadata included in an property.
64
+ *
65
+ * @param entity - The entity with the property to get the metadata from.
66
+ * @param propertyKey - The property on the given Entity to get the metadata from.
67
+ * @param type - For secure Typing, defines the returned PropertyConfig.
68
+ * @returns The metadata of the property.
69
+ * @throws When no metadata can be found for the given property.
70
+ */
71
+ static getPropertyMetadata(entity, propertyKey,
72
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
73
+ type) {
74
+ const metadata = ReflectUtilities.getMetadata('metadata', entity, propertyKey);
75
+ if (metadata == null) {
76
+ throw new Error(`Could not find metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
77
+ }
78
+ return metadata;
79
+ }
80
+ /**
81
+ * Gets the type of the property-metadata.
82
+ *
83
+ * @param entity - The entity with the property to get the type from.
84
+ * @param propertyKey - The property on the given Entity to get the type from.
85
+ * @returns The type of the metadata.
86
+ * @throws Will throw an error if no metadata can be found for the given property.
87
+ */
88
+ static getPropertyType(entity, propertyKey) {
89
+ try {
90
+ const propertyType = ReflectUtilities.getMetadata('type', entity, propertyKey);
91
+ if (propertyType == null) {
92
+ throw new Error(`Could not find type metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
93
+ }
94
+ return propertyType;
95
+ }
96
+ catch (error) {
97
+ throw new Error(`Could not find type metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
98
+ }
99
+ }
100
+ /**
101
+ * Sets all property values based on a given entity data-object.
102
+ *
103
+ * @param target - The target object that needs to be constructed (if called inside an Entity constructor its usually this).
104
+ * @param entity - The data object to get the property values from.
105
+ * @alias new
106
+ * @alias build
107
+ * @alias construct
108
+ */
109
+ static new(target, entity) {
110
+ for (const key in target) {
111
+ const type = EntityUtilities.getPropertyType(target, key);
112
+ let value = entity ? ReflectUtilities.get(entity, key) : undefined;
113
+ switch (type) {
114
+ case DecoratorTypes.OBJECT:
115
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
116
+ const objectMetadata = EntityUtilities.getPropertyMetadata(target, key, DecoratorTypes.OBJECT);
117
+ value = new objectMetadata.EntityClass(value);
118
+ break;
119
+ case DecoratorTypes.ARRAY:
120
+ const inputArray = value;
121
+ const resArray = [];
122
+ if (inputArray) {
123
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
124
+ const arrayMetadata = EntityUtilities.getPropertyMetadata(target, key, DecoratorTypes.ARRAY);
125
+ for (const item of inputArray) {
126
+ const itemWithMetadata = new arrayMetadata.EntityClass(item);
127
+ resArray.push(itemWithMetadata);
128
+ }
129
+ }
130
+ value = resArray;
131
+ break;
132
+ default:
133
+ break;
134
+ }
135
+ ReflectUtilities.set(target, key, value);
136
+ }
137
+ }
138
+ /**
139
+ * Checks if the values on an entity are valid.
140
+ * Also checks all the validators given by the metadata ("required", "maxLength" etc.).
141
+ *
142
+ * @param entity - The entity to validate.
143
+ * @param omit - Whether to check for creating or editing validity.
144
+ * @returns Whether or not the entity is valid.
145
+ */
146
+ static isEntityValid(entity, omit) {
147
+ for (const key in entity) {
148
+ if (!EntityUtilities.isPropertyValid(entity, key, omit)) {
149
+ return false;
150
+ }
151
+ }
152
+ return true;
153
+ }
154
+ /**
155
+ * Checks if a single property value is valid.
156
+ *
157
+ * @param entity - The entity where the property is from.
158
+ * @param key - The name of the property.
159
+ * @param omit - Whether to check if the given entity is valid for creation or updating.
160
+ * @returns Whether or not the property value is valid.
161
+ * @throws Throws when it extracts an unknown metadata type.
162
+ */
163
+ static isPropertyValid(entity, key, omit) {
164
+ const type = EntityUtilities.getPropertyType(entity, key);
165
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key, type);
166
+ if (metadata.omitForCreate && omit === 'create') {
167
+ return true;
168
+ }
169
+ if (metadata.omitForUpdate && omit === 'update') {
170
+ return true;
171
+ }
172
+ if (metadata.required) {
173
+ if (entity[key] == null || entity[key] === '') {
174
+ return false;
175
+ }
176
+ }
177
+ switch (type) {
178
+ case DecoratorTypes.BOOLEAN_DROPDOWN:
179
+ break;
180
+ case DecoratorTypes.BOOLEAN_CHECKBOX:
181
+ case DecoratorTypes.BOOLEAN_TOGGLE:
182
+ const entityBoolean = entity[key];
183
+ const booleanMetadata = metadata;
184
+ if (!EntityUtilities.isBooleanValid(entityBoolean, booleanMetadata)) {
185
+ return false;
186
+ }
187
+ break;
188
+ case DecoratorTypes.STRING_DROPDOWN:
189
+ break;
190
+ case DecoratorTypes.STRING:
191
+ case DecoratorTypes.STRING_AUTOCOMPLETE:
192
+ const entityString = entity[key];
193
+ const stringMetadata = metadata;
194
+ if (!EntityUtilities.isStringValid(entityString, stringMetadata)) {
195
+ return false;
196
+ }
197
+ break;
198
+ case DecoratorTypes.STRING_TEXTBOX:
199
+ const entityTextbox = entity[key];
200
+ const textboxMetadata = metadata;
201
+ if (!EntityUtilities.isTextboxValid(entityTextbox, textboxMetadata)) {
202
+ return false;
203
+ }
204
+ break;
205
+ case DecoratorTypes.STRING_PASSWORD:
206
+ const entityPassword = entity[key];
207
+ const passwordMetadata = metadata;
208
+ const confirmPassword = ReflectUtilities.getMetadata(this.CONFIRM_PASSWORD_KEY, entity, key);
209
+ if (!EntityUtilities.isPasswordValid(entityPassword, passwordMetadata, confirmPassword)) {
210
+ return false;
211
+ }
212
+ break;
213
+ case DecoratorTypes.NUMBER_DROPDOWN:
214
+ return true;
215
+ case DecoratorTypes.NUMBER:
216
+ case DecoratorTypes.NUMBER_SLIDER:
217
+ const entityNumber = entity[key];
218
+ const numberMetadata = metadata;
219
+ if (!EntityUtilities.isNumberValid(entityNumber, numberMetadata)) {
220
+ return false;
221
+ }
222
+ break;
223
+ case DecoratorTypes.OBJECT:
224
+ const entityObject = entity[key];
225
+ for (const parameterKey in entityObject) {
226
+ if (!EntityUtilities.isPropertyValid(entityObject, parameterKey, omit)) {
227
+ return false;
228
+ }
229
+ }
230
+ break;
231
+ case DecoratorTypes.ARRAY_STRING_CHIPS:
232
+ case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
233
+ case DecoratorTypes.ARRAY_DATE:
234
+ case DecoratorTypes.ARRAY_DATE_TIME:
235
+ case DecoratorTypes.ARRAY_DATE_RANGE:
236
+ case DecoratorTypes.ARRAY:
237
+ const entityArray = entity[key];
238
+ // eslint-disable-next-line max-len
239
+ const arrayMetadata = metadata;
240
+ if (arrayMetadata.required && !entityArray.length) {
241
+ return false;
242
+ }
243
+ break;
244
+ case DecoratorTypes.DATE:
245
+ const entityDate = new Date(entity[key]);
246
+ const dateMetadata = metadata;
247
+ if (!EntityUtilities.isDateValid(entityDate, dateMetadata)) {
248
+ return false;
249
+ }
250
+ break;
251
+ case DecoratorTypes.DATE_RANGE:
252
+ const entityDateRange = LodashUtilities.cloneDeep(entity[key]);
253
+ const dateRangeMetadata = metadata;
254
+ if (!EntityUtilities.isDateRangeValid(entityDateRange, dateRangeMetadata)) {
255
+ return false;
256
+ }
257
+ break;
258
+ case DecoratorTypes.DATE_TIME:
259
+ const entityDateTime = new Date(entity[key]);
260
+ const dateTimeMetadata = metadata;
261
+ const hasTime = ReflectUtilities.hasMetadata(this.TIME_KEY, entity, key);
262
+ if (!EntityUtilities.isDateTimeValid(entityDateTime, dateTimeMetadata, hasTime)) {
263
+ return false;
264
+ }
265
+ break;
266
+ case DecoratorTypes.FILE_DEFAULT:
267
+ case DecoratorTypes.FILE_IMAGE:
268
+ const entityFile = entity[key];
269
+ const entityFileMetadata = metadata;
270
+ if (!EntityUtilities.isFileDataValid(entityFile, entityFileMetadata)) {
271
+ return false;
272
+ }
273
+ break;
274
+ case DecoratorTypes.REFERENCES_MANY:
275
+ break;
276
+ case DecoratorTypes.CUSTOM:
277
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, max-len
278
+ const customMetadata = metadata;
279
+ if (!customMetadata.isValid(entity[key], omit)) {
280
+ return false;
281
+ }
282
+ break;
283
+ default:
284
+ throw new Error(`Could not validate the input because the DecoratorType ${type} is not known`);
285
+ }
286
+ return true;
287
+ }
288
+ static isBooleanValid(value, metadata) {
289
+ if (metadata.required && !value) {
290
+ return false;
291
+ }
292
+ return true;
293
+ }
294
+ static isStringValid(value, metadata) {
295
+ if (metadata.maxLength && value.length > metadata.maxLength) {
296
+ return false;
297
+ }
298
+ if (metadata.minLength && value.length < metadata.minLength) {
299
+ return false;
300
+ }
301
+ if (metadata.regex && !value.match(metadata.regex)) {
302
+ return false;
303
+ }
304
+ return true;
305
+ }
306
+ static isTextboxValid(value, metadata) {
307
+ if (metadata.maxLength && value.length > metadata.maxLength) {
308
+ return false;
309
+ }
310
+ if (metadata.minLength && value.length < metadata.minLength) {
311
+ return false;
312
+ }
313
+ return true;
314
+ }
315
+ static isPasswordValid(value, metadata, confirmPassword) {
316
+ if (value !== confirmPassword) {
317
+ return false;
318
+ }
319
+ if (metadata.maxLength && value.length > metadata.maxLength) {
320
+ return false;
321
+ }
322
+ if (metadata.minLength && value.length < metadata.minLength) {
323
+ return false;
324
+ }
325
+ if (metadata.regex && !value.match(metadata.regex)) {
326
+ return false;
327
+ }
328
+ return true;
329
+ }
330
+ static isNumberValid(value, metadata) {
331
+ if (metadata.max && value > metadata.max) {
332
+ return false;
333
+ }
334
+ if (metadata.min && value < metadata.min) {
335
+ return false;
336
+ }
337
+ return true;
338
+ }
339
+ static isDateValid(value, metadata) {
340
+ if (metadata.min && value.getTime() < metadata.min(value).getTime()) {
341
+ return false;
342
+ }
343
+ if (metadata.max && value.getTime() > metadata.max(value).getTime()) {
344
+ return false;
345
+ }
346
+ if (metadata.filter && !metadata.filter(value)) {
347
+ return false;
348
+ }
349
+ return true;
350
+ }
351
+ static isDateRangeValid(value, metadata) {
352
+ if (metadata.required) {
353
+ if (!value.start) {
354
+ return false;
355
+ }
356
+ if (!value.end) {
357
+ return false;
358
+ }
359
+ }
360
+ value.start = new Date(value.start);
361
+ value.end = new Date(value.end);
362
+ if (metadata.minStart && value.start.getTime() < metadata.minStart(value.start).getTime()) {
363
+ return false;
364
+ }
365
+ if (metadata.maxStart && value.start.getTime() > metadata.maxStart(value.start).getTime()) {
366
+ return false;
367
+ }
368
+ if (metadata.minEnd && value.end.getTime() < metadata.minEnd(value.end).getTime()) {
369
+ return false;
370
+ }
371
+ if (metadata.maxEnd && value.end.getTime() > metadata.maxEnd(value.end).getTime()) {
372
+ return false;
373
+ }
374
+ if (metadata.filter) {
375
+ if (!metadata.filter(value.start)) {
376
+ return false;
377
+ }
378
+ if (!metadata.filter(value.end)) {
379
+ return false;
380
+ }
381
+ if (value.values) {
382
+ for (const date of value.values) {
383
+ if (!metadata.filter(date)) {
384
+ return false;
385
+ }
386
+ }
387
+ }
388
+ }
389
+ return true;
390
+ }
391
+ static isDateTimeValid(value, metadata, hasTime) {
392
+ if (!hasTime) {
393
+ return false;
394
+ }
395
+ if (metadata.minDate && value.getTime() < metadata.minDate(value).getTime()) {
396
+ return false;
397
+ }
398
+ if (metadata.maxDate && value.getTime() > metadata.maxDate(value).getTime()) {
399
+ return false;
400
+ }
401
+ if (metadata.filterDate && !metadata.filterDate(value)) {
402
+ return false;
403
+ }
404
+ const time = {
405
+ hours: value.getHours(),
406
+ minutes: value.getMinutes()
407
+ };
408
+ if (metadata.minTime) {
409
+ const minTime = metadata.minTime(value);
410
+ if (!(time.hours > minTime.hours
411
+ || (time.hours === minTime.hours
412
+ && time.minutes >= minTime.minutes))) {
413
+ return false;
414
+ }
415
+ }
416
+ if (metadata.maxTime) {
417
+ const maxTime = metadata.maxTime(value);
418
+ if (!(time.hours < maxTime.hours
419
+ || (time.hours === maxTime.hours
420
+ && time.minutes <= maxTime.minutes))) {
421
+ return false;
422
+ }
423
+ }
424
+ if (metadata.filterTime) {
425
+ if (!metadata.filterTime(time)) {
426
+ return false;
427
+ }
428
+ }
429
+ return true;
430
+ }
431
+ static isFileDataValid(value, metadata) {
432
+ const files = metadata.multiple ? value : [value];
433
+ let fileSizeTotal = 0;
434
+ for (const file of files) {
435
+ if (!file.name || !file.file && !file.url) {
436
+ return false;
437
+ }
438
+ if (!FileUtilities.isMimeTypeValid(file.type, metadata.allowedMimeTypes)) {
439
+ return false;
440
+ }
441
+ if (FileUtilities.transformToMegaBytes(file.size, 'B') > metadata.maxSize) {
442
+ return false;
443
+ }
444
+ fileSizeTotal += file.size;
445
+ if (FileUtilities.transformToMegaBytes(fileSizeTotal, 'B') > metadata.maxSizeTotal) {
446
+ return false;
447
+ }
448
+ }
449
+ return true;
450
+ }
451
+ /**
452
+ * Checks if an entity is "dirty" (if its values have changed).
453
+ *
454
+ * @param entity - The entity after all changes.
455
+ * @param entityPriorChanges - The entity before the changes.
456
+ * @returns Whether or not the entity is dirty.
457
+ */
458
+ static async isDirty(entity, entityPriorChanges) {
459
+ if (!entityPriorChanges) {
460
+ return false;
461
+ }
462
+ else {
463
+ const differences = await EntityUtilities.differencesForDirty(entity, entityPriorChanges);
464
+ return differences.length ? true : false;
465
+ }
466
+ }
467
+ static async differencesForDirty(entity, entityPriorChanges) {
468
+ const res = [];
469
+ for (const key of ReflectUtilities.ownKeys(entity)) {
470
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
471
+ const type = EntityUtilities.getPropertyType(entity, key);
472
+ if (!(await EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
473
+ res.push({
474
+ key: key,
475
+ before: entityPriorChanges[key],
476
+ after: entity[key]
477
+ });
478
+ }
479
+ else {
480
+ // This is needed to set blob file data so that it is only requested once.
481
+ entityPriorChanges[key] = LodashUtilities.cloneDeep(entity[key]);
482
+ }
483
+ }
484
+ return res;
485
+ }
486
+ /**
487
+ * Compares two Entities and returns their difference in an object.
488
+ *
489
+ * @param entity - The first entity to compare.
490
+ * @param entityPriorChanges - The second entity to compare.
491
+ * @returns The difference between the two Entities in form of a Partial.
492
+ */
493
+ static async difference(entity, entityPriorChanges) {
494
+ const res = {};
495
+ for (const key in entity) {
496
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
497
+ const type = EntityUtilities.getPropertyType(entity, key);
498
+ if (!(await EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
499
+ res[key] = entity[key];
500
+ }
501
+ }
502
+ return res;
503
+ }
504
+ /**
505
+ * Checks if two given values are equal.
506
+ * It uses the isEqual method from LodashUtilities and extends it with functionality regarding Dates.
507
+ *
508
+ * @param value - The updated value.
509
+ * @param valuePriorChanges - The value before any changes.
510
+ * @param metadata - The metadata of the property.
511
+ * @param type - The type of the property.
512
+ * @returns Whether or not the given values are equal.
513
+ */
514
+ static async isEqual(value, valuePriorChanges, metadata, type) {
515
+ switch (type) {
516
+ case DecoratorTypes.DATE_RANGE:
517
+ return EntityUtilities.isEqualDateRange(value, valuePriorChanges, metadata.filter);
518
+ case DecoratorTypes.DATE:
519
+ return EntityUtilities.isEqualDate(value, valuePriorChanges);
520
+ case DecoratorTypes.DATE_TIME:
521
+ return EntityUtilities.isEqualDateTime(value, valuePriorChanges);
522
+ case DecoratorTypes.ARRAY_DATE:
523
+ case DecoratorTypes.ARRAY_DATE_TIME:
524
+ return EntityUtilities.isEqualArrayDate(value, valuePriorChanges);
525
+ case DecoratorTypes.ARRAY_DATE_RANGE:
526
+ return EntityUtilities.isEqualArrayDateRange(value, valuePriorChanges, metadata.filter);
527
+ case DecoratorTypes.ARRAY_STRING_CHIPS:
528
+ case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
529
+ return EntityUtilities.isEqualArrayString(value, valuePriorChanges);
530
+ case DecoratorTypes.FILE_IMAGE:
531
+ case DecoratorTypes.FILE_DEFAULT:
532
+ return EntityUtilities.isEqualFile(value, valuePriorChanges, metadata.multiple);
533
+ case DecoratorTypes.CUSTOM:
534
+ // eslint-disable-next-line max-len, @typescript-eslint/no-explicit-any
535
+ return EntityUtilities.isEqualCustom(value, valuePriorChanges, metadata);
536
+ default:
537
+ return LodashUtilities.isEqual(value, valuePriorChanges);
538
+ }
539
+ }
540
+ static isEqualArrayString(value, valuePriorChanges) {
541
+ const stringArray = LodashUtilities.cloneDeep(value).sort();
542
+ const stringArrayPriorChanges = LodashUtilities.cloneDeep(valuePriorChanges).sort();
543
+ return LodashUtilities.isEqual(stringArray, stringArrayPriorChanges);
544
+ }
545
+ static isEqualArrayDate(value, valuePriorChanges) {
546
+ const newValue = value.map(v => new Date(v)).sort();
547
+ const newValuePriorChanges = valuePriorChanges.map(v => new Date(v)).sort();
548
+ return LodashUtilities.isEqual(newValue, newValuePriorChanges);
549
+ }
550
+ static isEqualArrayDateRange(value, valuePriorChanges, filter) {
551
+ const dateRanges = value.sort();
552
+ const dateRangesPriorChanges = valuePriorChanges.sort();
553
+ if (dateRanges.length !== dateRangesPriorChanges.length) {
554
+ return false;
555
+ }
556
+ for (let i = 0; i < dateRanges.length; i++) {
557
+ if (!EntityUtilities.isEqualDateRange(dateRanges[i], dateRangesPriorChanges[i], filter)) {
558
+ return false;
559
+ }
560
+ }
561
+ return true;
562
+ }
563
+ static isEqualDateTime(value, valuePriorChanges) {
564
+ const date = new Date(value);
565
+ const datePriorChanges = new Date(valuePriorChanges);
566
+ return LodashUtilities.isEqual(date, datePriorChanges);
567
+ }
568
+ static isEqualDate(value, valuePriorChanges) {
569
+ const date = new Date(value);
570
+ const datePriorChanges = new Date(valuePriorChanges);
571
+ date.setHours(0, 0, 0, 0);
572
+ datePriorChanges.setHours(0, 0, 0, 0);
573
+ return LodashUtilities.isEqual(date, datePriorChanges);
574
+ }
575
+ static isEqualDateRange(value, valuePriorChanges, filter) {
576
+ const dateRange = LodashUtilities.cloneDeep(value);
577
+ dateRange.start = new Date(value.start);
578
+ dateRange.end = new Date(value.end);
579
+ dateRange.values = DateUtilities.getDatesBetween(dateRange.start, dateRange.end, filter);
580
+ const dateRangePriorChanges = LodashUtilities.cloneDeep(valuePriorChanges);
581
+ dateRangePriorChanges.start = new Date(valuePriorChanges.start);
582
+ dateRangePriorChanges.end = new Date(valuePriorChanges.end);
583
+ dateRangePriorChanges.values = DateUtilities.getDatesBetween(dateRangePriorChanges.start, dateRangePriorChanges.end, filter);
584
+ return LodashUtilities.isEqual(dateRange, dateRangePriorChanges);
585
+ }
586
+ // TODO: Find a way to use blobs with jest
587
+ /* istanbul ignore next */
588
+ static async isEqualFile(value, valuePriorChanges, multiple) {
589
+ if (value == null) {
590
+ if (valuePriorChanges == null) {
591
+ return true;
592
+ }
593
+ else {
594
+ return false;
595
+ }
596
+ }
597
+ const files = multiple ? value.sort() : [value].sort();
598
+ const filesPriorChanges = multiple ? valuePriorChanges.sort() : [valuePriorChanges].sort();
599
+ if (files.length !== filesPriorChanges.length) {
600
+ return false;
601
+ }
602
+ for (let i = 0; i < files.length; i++) {
603
+ // checks this before actually getting any files due to performance reasons.
604
+ if (!LodashUtilities.isEqual(LodashUtilities.omit(files[i], 'file'), LodashUtilities.omit(filesPriorChanges[i], 'file'))) {
605
+ return false;
606
+ }
607
+ if (filesPriorChanges[i].file && !files[i].file) {
608
+ files[i] = await FileUtilities.getFileData(files[i]);
609
+ value = files[i];
610
+ }
611
+ if (files[i].file && !filesPriorChanges[i].file) {
612
+ filesPriorChanges[i] = await FileUtilities.getFileData(filesPriorChanges[i]);
613
+ valuePriorChanges = filesPriorChanges[i];
614
+ }
615
+ if (!LodashUtilities.isEqual(await files[i].file?.text(), await filesPriorChanges[i].file?.text())) {
616
+ return false;
617
+ }
618
+ }
619
+ return true;
620
+ }
621
+ static isEqualCustom(value, valuePriorChanges,
622
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
623
+ metadata) {
624
+ if (!metadata.isEqual(value, valuePriorChanges, metadata)) {
625
+ return false;
626
+ }
627
+ return true;
628
+ }
629
+ /**
630
+ * Compare function for sorting entity keys by their order value.
631
+ *
632
+ * @param a - First key of entity.
633
+ * @param b - Second key of entity.
634
+ * @param entity - Current entity (used to get metadata of entity keys).
635
+ * @returns 0 if both values have the same order, a negative value if 'a' comes before 'b', a positive value if 'a' comes behind 'b'.
636
+ */
637
+ static compareOrder(a, b, entity) {
638
+ const metadataA = EntityUtilities.getPropertyMetadata(entity, a);
639
+ const metadataB = EntityUtilities.getPropertyMetadata(entity, b);
640
+ if (metadataA.position.order === -1) {
641
+ if (metadataB.position.order === -1) {
642
+ return 0;
643
+ }
644
+ return 1;
645
+ }
646
+ else if (metadataB.position.order === -1) {
647
+ return -1;
648
+ }
649
+ return metadataA.position.order - metadataB.position.order;
650
+ }
651
+ /**
652
+ * Gets the bootstrap column values for "lg", "md", "sm".
653
+ *
654
+ * @param entity - Entity to get the bootstrap column values of the key.
655
+ * @param key - Key of the property to get bootstrap column values from.
656
+ * @param type - Defines for which screen size the column values should be returned.
657
+ * @returns Bootstrap column value.
658
+ */
659
+ static getWidth(entity, key, type) {
660
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
661
+ switch (type) {
662
+ case 'lg':
663
+ return metadata.defaultWidths[0];
664
+ case 'md':
665
+ return metadata.defaultWidths[1];
666
+ case 'sm':
667
+ return metadata.defaultWidths[2];
668
+ }
669
+ }
670
+ /**
671
+ * Resets all changes on an entity.
672
+ *
673
+ * @param entity - The entity to reset.
674
+ * @param entityPriorChanges - The entity before any changes.
675
+ */
676
+ static resetChangesOnEntity(entity, entityPriorChanges) {
677
+ for (const key in entityPriorChanges) {
678
+ ReflectUtilities.set(entity, key, ReflectUtilities.get(entityPriorChanges, key));
679
+ if (ReflectUtilities.hasMetadata(this.METADATA_KEYS_TO_RESET_KEY, entity, key)) {
680
+ for (const k of ReflectUtilities.getMetadata(this.METADATA_KEYS_TO_RESET_KEY, entity, key)) {
681
+ if (ReflectUtilities.hasMetadata(k, entity, key)) {
682
+ ReflectUtilities.defineMetadata(k, undefined, entity, key);
683
+ }
684
+ }
685
+ }
686
+ }
687
+ }
688
+ static getEntityRows(entity, tab, hideOmitForCreate, hideOmitForEdit) {
689
+ const res = [];
690
+ const keys = EntityUtilities.keysOf(entity, hideOmitForCreate, hideOmitForEdit);
691
+ const numberOfRows = EntityUtilities.getNumberOfRows(keys, entity, tab);
692
+ for (let i = 1; i <= numberOfRows; i++) {
693
+ const row = {
694
+ row: i,
695
+ keys: EntityUtilities.getKeysForRow(keys, entity, i, tab)
696
+ };
697
+ res.push(row);
698
+ }
699
+ if (EntityUtilities.getKeysForRow(keys, entity, -1, tab).length) {
700
+ const lastRow = {
701
+ row: numberOfRows + 1,
702
+ keys: EntityUtilities.getKeysForRow(keys, entity, -1, tab)
703
+ };
704
+ res.push(lastRow);
705
+ }
706
+ return res;
707
+ }
708
+ /**
709
+ * Gets the tabs that are used to display the given entity.
710
+ *
711
+ * @param entity - The entity to get the rows from.
712
+ * @param hideOmitForCreate - Whether or not keys with the metadata omitForCreate should be filtered out.
713
+ * @param hideOmitForEdit - Whether or not keys with the metadata omitForUpdate should be filtered out.
714
+ * @returns The sorted Tabs containing the rows and the keys to display in that row.
715
+ */
716
+ static getEntityTabs(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
717
+ const res = [];
718
+ const keys = EntityUtilities.keysOf(entity, hideOmitForCreate, hideOmitForEdit);
719
+ const numberOfTabs = EntityUtilities.getNumberOfTabs(keys, entity);
720
+ if (EntityUtilities.getEntityRows(entity, -1, hideOmitForCreate, hideOmitForEdit).length) {
721
+ const firstTab = {
722
+ tabName: EntityUtilities.getFirstTabName(entity),
723
+ tab: -1,
724
+ rows: EntityUtilities.getEntityRows(entity, -1, hideOmitForCreate, hideOmitForEdit)
725
+ };
726
+ res.push(firstTab);
727
+ }
728
+ for (let i = 2; i <= numberOfTabs; i++) {
729
+ const tab = {
730
+ tabName: EntityUtilities.getTabName(entity, i),
731
+ tab: i,
732
+ rows: EntityUtilities.getEntityRows(entity, i, hideOmitForCreate, hideOmitForEdit)
733
+ };
734
+ res.push(tab);
735
+ }
736
+ return res;
737
+ }
738
+ static getKeysForRow(keys, entity, row, tab) {
739
+ return keys
740
+ .filter(k => EntityUtilities.getPropertyMetadata(entity, k).position.row === row)
741
+ .filter(k => EntityUtilities.getPropertyMetadata(entity, k).position.tab === tab)
742
+ .sort((a, b) => EntityUtilities.compareOrder(a, b, entity));
743
+ }
744
+ static getNumberOfRows(keys, entity, tab) {
745
+ return keys
746
+ .filter(k => EntityUtilities.getPropertyMetadata(entity, k).position.tab === tab)
747
+ .map(k => EntityUtilities.getPropertyMetadata(entity, k).position.row)
748
+ .sort((a, b) => (a > b ? -1 : 1))[0];
749
+ }
750
+ static getNumberOfTabs(keys, entity) {
751
+ return keys
752
+ .map(k => EntityUtilities.getPropertyMetadata(entity, k).position.tab)
753
+ .sort((a, b) => (a > b ? -1 : 1))[0];
754
+ }
755
+ static getTabName(entity, tab) {
756
+ const providedTabName = EntityUtilities.keysOf(entity)
757
+ .map(k => EntityUtilities.getPropertyMetadata(entity, k))
758
+ .find(m => m.position.tab === tab && m.position.tabName)?.position.tabName;
759
+ return providedTabName ?? `Tab ${tab}`;
760
+ }
761
+ static getFirstTabName(entity) {
762
+ const providedTabName = EntityUtilities.keysOf(entity)
763
+ .map(k => EntityUtilities.getPropertyMetadata(entity, k))
764
+ .find(m => m.position.tabName && m.position.tab === -1)?.position.tabName;
765
+ return providedTabName ?? 'Tab 1';
766
+ }
767
+ /**
768
+ * Gets the keys of the provided entity correctly typed.
769
+ *
770
+ * @param entity - The entity to get the keys of.
771
+ * @param hideOmitForCreate - Whether or not keys with the metadata omitForCreate should be filtered out.
772
+ * @param hideOmitForEdit - Whether or not keys with the metadata omitForUpdate should be filtered out.
773
+ * @returns An array of keys of the entity.
774
+ */
775
+ static keysOf(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
776
+ let keys = ReflectUtilities.ownKeys(entity);
777
+ if (hideOmitForCreate) {
778
+ const omitForCreateKeys = EntityUtilities.getOmitForCreate(entity);
779
+ keys = keys.filter(k => !omitForCreateKeys.includes(k));
780
+ }
781
+ if (hideOmitForEdit) {
782
+ const omitForUpdateKeys = EntityUtilities.getOmitForUpdate(entity);
783
+ keys = keys.filter(k => !omitForUpdateKeys.includes(k));
784
+ }
785
+ return keys;
786
+ }
787
+ }
788
+ /**
789
+ * The key for all keys of metadata that should be set to undefined when the entity gets reset.
790
+ */
791
+ EntityUtilities.METADATA_KEYS_TO_RESET_KEY = 'metadataKeysToReset';
792
+ /**
793
+ * The key for the metadata that saves the single preview image value on image properties.
794
+ */
795
+ EntityUtilities.SINGLE_PREVIEW_IMAGE_KEY = 'singlePreviewImage';
796
+ /**
797
+ * The key for the metadata that saves the multi preview images value on image properties.
798
+ */
799
+ EntityUtilities.MULTI_PREVIEW_IMAGES_KEY = 'multiPreviewImages';
800
+ /**
801
+ * The key for the metadata that saves the filenames value on file properties.
802
+ */
803
+ EntityUtilities.FILENAMES_KEY = 'fileNames';
804
+ /**
805
+ * The key for the metadata that saves the confirm password value on password properties.
806
+ */
807
+ EntityUtilities.CONFIRM_PASSWORD_KEY = 'confirmPassword';
808
+ /**
809
+ * The key for the metadata that saves the time value on date time properties.
810
+ */
811
+ EntityUtilities.TIME_KEY = 'time';
812
+ /**
813
+ * The key for the metadata that saves the date range value on date range properties.
814
+ */
815
+ EntityUtilities.DATE_RANGE_KEY = 'dateRange';
816
+ /**
817
+ * The key for the metadata that saves the date range start value on date range properties.
818
+ */
819
+ EntityUtilities.DATE_RANGE_START_KEY = 'dateRangeStart';
820
+ /**
821
+ * The key for the metadata that saves the date range end value on date range properties.
822
+ */
823
+ EntityUtilities.DATE_RANGE_END_KEY = 'dateRangeEnd';
824
+ // eslint-disable-next-line @typescript-eslint/member-ordering, jsdoc/require-jsdoc, @typescript-eslint/typedef
825
+ EntityUtilities.construct = EntityUtilities.new;
826
+ // eslint-disable-next-line @typescript-eslint/member-ordering, jsdoc/require-jsdoc, @typescript-eslint/typedef
827
+ EntityUtilities.build = EntityUtilities.new;
828
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LnV0aWxpdGllcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1tYXRlcmlhbC1lbnRpdHkvc3JjL3V0aWxpdGllcy9lbnRpdHkudXRpbGl0aWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE9BQU8sRUFBaUIsY0FBYyxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFXeEYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFvQmpEOztHQUVHO0FBQ0gsTUFBTSxPQUFnQixlQUFlO0lBK0NqQzs7Ozs7T0FLRztJQUNILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBZ0QsTUFBa0I7UUFDckYsTUFBTSxHQUFHLEdBQXlCLEVBQUUsQ0FBQztRQUNyQyxLQUFLLE1BQU0sR0FBRyxJQUFJLGVBQWUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDOUMsTUFBTSxRQUFRLEdBQW9DLGVBQWUsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDbkcsSUFBSSxRQUFRLENBQUMsYUFBYSxFQUFFO2dCQUN4QixHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ2pCO1NBQ0o7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNmLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBZ0QsTUFBa0I7UUFDckYsTUFBTSxHQUFHLEdBQXlCLEVBQUUsQ0FBQztRQUNyQyxLQUFLLE1BQU0sR0FBRyxJQUFJLGVBQWUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDOUMsTUFBTSxR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QztBQUV4RTs7R0FFRztBQUNhLDZCQUFhLEdBQVcsV0FBVyxDQUFDO0FBRXBEOztHQUVHO0FBQ2Esb0NBQW9CLEdBQVcsaUJBQWlCLENBQUM7QUFFakU7O0dBRUc7QUFDYSx3QkFBUSxHQUFXLE1BQU0sQ0FBQztBQUUxQzs7R0FFRztBQUNhLDhCQUFjLEdBQVcsV0FBVyxDQUFDO0FBRXJEOztHQUVHO0FBQ2Esb0NBQW9CLEdBQVcsZ0JBQWdCLENBQUM7QUFFaEU7O0dBRUc7QUFDYSxrQ0FBa0IsR0FBVyxjQUFjLENBQUM7QUEySjVELCtHQUErRztBQUN4Ryx5QkFBUyxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUM7QUFDdkMsK0dBQStHO0FBQ3hHLHFCQUFLLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRpbWUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRGF0ZUZpbHRlckZuIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGF0ZXBpY2tlcic7XG5pbXBvcnQgeyBCYXNlRW50aXR5VHlwZSB9IGZyb20gJy4uL2NsYXNzZXMvZW50aXR5Lm1vZGVsJztcbmltcG9ydCB7IERhdGVSYW5nZUFycmF5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIEVudGl0eUFycmF5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2FycmF5L2FycmF5LWRlY29yYXRvci1pbnRlcm5hbC5kYXRhJztcbmltcG9ydCB7IERlY29yYXRvclR5cGUsIERlY29yYXRvclR5cGVzIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9iYXNlL2RlY29yYXRvci10eXBlcy5lbnVtJztcbmltcG9ydCB7IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2Jhc2UvcHJvcGVydHktZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgVG9nZ2xlQm9vbGVhbkRlY29yYXRvckNvbmZpZ0ludGVybmFsIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9ib29sZWFuL2Jvb2xlYW4tZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgQ3VzdG9tRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2N1c3RvbS9jdXN0b20tZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgRGF0ZVJhbmdlRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsLCBEYXRlVGltZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCwgRGVmYXVsdERhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvZGF0ZS9kYXRlLWRlY29yYXRvci1pbnRlcm5hbC5kYXRhJztcbmltcG9ydCB7IERhdGVSYW5nZSB9IGZyb20gJy4uL2RlY29yYXRvcnMvZGF0ZS9kYXRlLWRlY29yYXRvci5kYXRhJztcbmltcG9ydCB7IERlZmF1bHRGaWxlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2ZpbGUvZmlsZS1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBGaWxlRGF0YSB9IGZyb20gJy4uL2RlY29yYXRvcnMvZmlsZS9maWxlLWRlY29yYXRvci5kYXRhJztcbmltcG9ydCB7IERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvbnVtYmVyL251bWJlci1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBEZWZhdWx0T2JqZWN0RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL29iamVjdC9vYmplY3QtZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgRGVmYXVsdFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsLCBQYXNzd29yZFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsLCBUZXh0Ym94U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL3N0cmluZy9zdHJpbmctZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgTG9kYXNoVXRpbGl0aWVzIH0gZnJvbSAnLi4vZW5jYXBzdWxhdGlvbi9sb2Rhc2gudXRpbGl0aWVzJztcbmltcG9ydCB7IFJlZmxlY3RVdGlsaXRpZXMgfSBmcm9tICcuLi9lbmNhcHN1bGF0aW9uL3JlZmxlY3QudXRpbGl0aWVzJztcbmltcG9ydCB7IERhdGVVdGlsaXRpZXMgfSBmcm9tICcuL2RhdGUudXRpbGl0aWVzJztcbmltcG9ydCB7IEZpbGVVdGlsaXRpZXMgfSBmcm9tICcuL2ZpbGUudXRpbGl0aWVzJztcblxuLyoqXG4gKiBTaG93cyBpbmZvcm1hdGlvbiBhYm91dCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHR3byBlbnRpdGllcy5cbiAqL1xuaW50ZXJmYWNlIERpZmZlcmVuY2U8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PiB7XG4gICAgLyoqXG4gICAgICogVGhlIGtleSB3aGVyZSB0aGUgdHdvIGVudGl0aWVzIGhhdmUgZGlmZmVyZW50IHZhbHVlcy5cbiAgICAgKi9cbiAgICBrZXk6IGtleW9mIEVudGl0eVR5cGUsXG4gICAgLyoqXG4gICAgICogVGhlIHZhbHVlIGJlZm9yZSBhbnkgY2hhbmdlcy5cbiAgICAgKi9cbiAgICBiZWZvcmU6IHVua25vd24sXG4gICAgLyoqXG4gICAgICogVGhlIGN1cnJlbnQgdmFsdWUgYWZ0ZXIgY2hhbmdlcy5cbiAgICAgKi9cbiAgICBhZnRlcjogdW5rbm93blxufVxuXG4vKipcbiAqIENvbnRhaW5zIEhlbHBlck1ldGhvZHMgYXJvdW5kIGhhbmRsaW5nIEVudGl0aWVzIGFuZCB0aGVpciBwcm9wZXJ0eS1tZXRhZGF0YS5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEVudGl0eVV0aWxpdGllcyB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUga2V5IGZvciBhbGwga2V5cyBvZiBtZXRhZGF0YSB0aGF0IHNob3VsZCBiZSBzZXQgdG8gdW5kZWZpbmVkIHdoZW4gdGhlIGVudGl0eSBnZXRzIHJlc2V0LlxuICAgICAqL1xuICAgIHN0YXRpYyByZWFkb25seSBNRVRBREFUQV9LRVlTX1RPX1JFU0VUX0tFWTogc3RyaW5nID0gJ21ldGFkYXRhS2V5c1RvUmVzZXQnO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGtleSBmb3IgdGhlIG1ldGFkYXRhIHRoYXQgc2F2ZXMgdGhlIHNpbmdsZSBwcmV2aWV3IGltYWdlIHZhbHVlIG9uIGltYWdlIHByb3BlcnRpZXMuXG4gICAgICovXG4gICAgc3RhdGljIHJlYWRvbmx5IFNJTkdMRV9QUkVWSUVXX0lNQUdFX0tFWTogc3RyaW5nID0gJ3NpbmdsZVByZXZpZXdJbWFnZSc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUga2V5IGZvciB0aGUgbWV0YWRhdGEgdGhhdCBzYXZlcyB0aGUgbXVsdGkgcHJldmlldyBpbWFnZXMgdmFsdWUgb24gaW1hZ2UgcHJvcGVydGllcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVhZG9ubHkgTVVMVElfUFJFVklFV19JTUFHRVNfS0VZOiBzdHJpbmcgPSAnbXVsdGlQcmV2aWV3SW1hZ2VzJztcblxuICAgIC8qKlxuICAgICAqIFRoZSBrZXkgZm9yIHRoZSBtZXRhZGF0YSB0aGF0IHNhdmVzIHRoZSBmaWxlbmFtZXMgdmFsdWUgb24gZmlsZSBwcm9wZXJ0aWVzLlxuICAgICAqL1xuICAgIHN0YXRpYyByZWFkb25seSBGSUxFTkFNRVNfS0VZOiBzdHJpbmcgPSAnZmlsZU5hbWVzJztcblxuICAgIC8qKlxuICAgICAqIFRoZSBrZXkgZm9yIHRoZSBtZXRhZGF0YSB0aGF0IHNhdmVzIHRoZSBjb25maXJtIHBhc3N3b3JkIHZhbHVlIG9uIHBhc3N3b3JkIHByb3BlcnRpZXMuXG4gICAgICovXG4gICAgc3RhdGljIHJlYWRvbmx5IENPTkZJUk1fUEFTU1dPUkRfS0VZOiBzdHJpbmcgPSAnY29uZmlybVBhc3N3b3JkJztcblxuICAgIC8qKlxuICAgICAqIFRoZSBrZXkgZm9yIHRoZSBtZXRhZGF0YSB0aGF0IHNhdmVzIHRoZSB0aW1lIHZhbHVlIG9uIGRhdGUgdGltZSBwcm9wZXJ0aWVzLlxuICAgICAqL1xuICAgIHN0YXRpYyByZWFkb25seSBUSU1FX0tFWTogc3RyaW5nID0gJ3RpbWUnO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGtleSBmb3IgdGhlIG1ldGFkYXRhIHRoYXQgc2F2ZXMgdGhlIGRhdGUgcmFuZ2UgdmFsdWUgb24gZGF0ZSByYW5nZSBwcm9wZXJ0aWVzLlxuICAgICAqL1xuICAgIHN0YXRpYyByZWFkb25seSBEQVRFX1JBTkdFX0tFWTogc3RyaW5nID0gJ2RhdGVSYW5nZSc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUga2V5IGZvciB0aGUgbWV0YWRhdGEgdGhhdCBzYXZlcyB0aGUgZGF0ZSByYW5nZSBzdGFydCB2YWx1ZSBvbiBkYXRlIHJhbmdlIHByb3BlcnRpZXMuXG4gICAgICovXG4gICAgc3RhdGljIHJlYWRvbmx5IERBVEVfUkFOR0VfU1RBUlRfS0VZOiBzdHJpbmcgPSAnZGF0ZVJhbmdlU3RhcnQnO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGtleSBmb3IgdGhlIG1ldGFkYXRhIHRoYXQgc2F2ZXMgdGhlIGRhdGUgcmFuZ2UgZW5kIHZhbHVlIG9uIGRhdGUgcmFuZ2UgcHJvcGVydGllcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVhZG9ubHkgREFURV9SQU5HRV9FTkRfS0VZOiBzdHJpbmcgPSAnZGF0ZVJhbmdlRW5kJztcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHByb3BlcnRpZXMgdG8gb21pdCB3aGVuIHVwZGF0aW5nIHRoZSBlbnRpdHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBnZXQgdGhlIHByb3BlcnRpZXMgd2hpY2ggc2hvdWxkIGJlIGxlZnQgb3V0IGZvciB1cGRhdGluZyBmcm9tLlxuICAgICAqIEByZXR1cm5zIFRoZSBwcm9wZXJ0aWVzIHdoaWNoIHNob3VsZCBiZSBsZWZ0IG91dCBmb3IgdXBkYXRpbmcgYW4gRW50aXR5LlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRPbWl0Rm9yVXBkYXRlPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oZW50aXR5OiBFbnRpdHlUeXBlKTogKGtleW9mIEVudGl0eVR5cGUpW10ge1xuICAgICAgICBjb25zdCByZXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdID0gW107XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIEVudGl0eVV0aWxpdGllcy5rZXlzT2YoZW50aXR5KSkge1xuICAgICAgICAgICAgY29uc3QgbWV0YWRhdGE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGtleSk7XG4gICAgICAgICAgICBpZiAobWV0YWRhdGEub21pdEZvclVwZGF0ZSkge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwcm9wZXJ0aWVzIHRvIG9taXQgd2hlbiBjcmVhdGluZyBuZXcgZW50aXRpZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBnZXQgdGhlIHByb3BlcnRpZXMgd2hpY2ggc2hvdWxkIGJlIGxlZnQgb3V0IGZvciBjcmVhdGluZyBmcm9tLlxuICAgICAqIEByZXR1cm5zIFRoZSBwcm9wZXJ0aWVzIHdoaWNoIHNob3VsZCBiZSBsZWZ0IG91dCBmb3IgY3JlYXRpbmcgYSBuZXcgRW50aXR5LlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRPbWl0Rm9yQ3JlYXRlPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oZW50aXR5OiBFbnRpdHlUeXBlKTogKGtleW9mIEVudGl0eVR5cGUpW10ge1xuICAgICAgICBjb25zdCByZXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdID0gW107XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIEVudGl0eVV0aWxpdGllcy5rZXlzT2YoZW50aXR5KSkge1xuICAgICAgICAgICAgY29uc3QgbWV0YWRhdGE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGtleSk7XG4gICAgICAgICAgICBpZiAobWV0YWRhdGEub21pdEZvckNyZWF0ZSkge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCBwcm9wZXJ0aWVzIG9uIHRoZSBnaXZlbiBlbnRpdHkgd2hpY2ggYXJlIGZpbGVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gY2hlY2sgZm9yIGZpbGUgcHJvcGVydGllcy5cbiAgICAgKiBAcGFyYW0gb21pdCAtIFdoZXRoZXIgdG8gbGVhdmUgb3V0IHZhbHVlcyB0aGF0IGFyZSBvbWl0dGVkIGZvciBjcmVhdGUgb3IgZGVsZXRlLlxuICAgICAqIEByZXR1cm5zIFRoZSBrZXlzIG9mIGFsbCBmaWxlIHByb3BlcnRpZXMgb24gdGhlIGdpdmVuIGVudGl0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RmlsZVByb3BlcnRpZXM8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLFxuICAgICAgICBvbWl0PzogJ2NyZWF0ZScgfCAndXBkYXRlJ1xuICAgICk6IChrZXlvZiBFbnRpdHlUeXBlKVtdIHtcbiAgICAgICAgY29uc3QgcmVzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBFbnRpdHlVdGlsaXRpZXMua2V5c09mKGVudGl0eSkpIHtcbiAgICAgICAgICAgIGNvbnN0IHR5cGU6IERlY29yYXRvclR5cGVzID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5VHlwZShlbnRpdHksIGtleSk7XG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gRGVjb3JhdG9yVHlwZXMuRklMRV9ERUZBVUxUIHx8IHR5cGUgPT09IERlY29yYXRvclR5cGVzLkZJTEVfSU1BR0UpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtZXRhZGF0YTogUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwga2V5KTtcbiAgICAgICAgICAgICAgICBpZiAoIShtZXRhZGF0YS5vbWl0Rm9yQ3JlYXRlICYmIG9taXQgPT09ICdjcmVhdGUnKSAmJiAhKG1ldGFkYXRhLm9taXRGb3JVcGRhdGUgJiYgb21pdCA9PT0gJ3VwZGF0ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKGtleSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbWV0YWRhdGEgaW5jbHVkZWQgaW4gYW4gcHJvcGVydHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB3aXRoIHRoZSBwcm9wZXJ0eSB0byBnZXQgdGhlIG1ldGFkYXRhIGZyb20uXG4gICAgICogQHBhcmFtIHByb3BlcnR5S2V5IC0gVGhlIHByb3BlcnR5IG9uIHRoZSBnaXZlbiBFbnRpdHkgdG8gZ2V0IHRoZSBtZXRhZGF0YSBmcm9tLlxuICAgICAqIEBwYXJhbSB0eXBlIC0gRm9yIHNlY3VyZSBUeXBpbmcsIGRlZmluZXMgdGhlIHJldHVybmVkIFByb3BlcnR5Q29uZmlnLlxuICAgICAqIEByZXR1cm5zIFRoZSBtZXRhZGF0YSBvZiB0aGUgcHJvcGVydHkuXG4gICAgICogQHRocm93cyBXaGVuIG5vIG1ldGFkYXRhIGNhbiBiZSBmb3VuZCBmb3IgdGhlIGdpdmVuIHByb3BlcnR5LlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRQcm9wZXJ0eU1ldGFkYXRhPFxuICAgICAgICBFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4sXG4gICAgICAgIFQgZXh0ZW5kcyBEZWNvcmF0b3JUeXBlcyxcbiAgICAgICAgQ3VzdG9tTWV0YWRhdGFUeXBlIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgICA+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIHByb3BlcnR5S2V5OiBrZXlvZiBFbnRpdHlUeXBlLFxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICAgIHR5cGU/OiBUXG4gICAgKTogRGVjb3JhdG9yVHlwZTxULCBDdXN0b21NZXRhZGF0YVR5cGU+IHtcbiAgICAgICAgY29uc3QgbWV0YWRhdGE6IHVua25vd24gPSBSZWZsZWN0VXRpbGl0aWVzLmdldE1ldGFkYXRhKCdtZXRhZGF0YScsIGVudGl0eSwgcHJvcGVydHlLZXkpO1xuICAgICAgICBpZiAobWV0YWRhdGEgPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIGBDb3VsZCBub3QgZmluZCBtZXRhZGF0YSBmb3IgcHJvcGVydHkgJHtTdHJpbmcocHJvcGVydHlLZXkpfSBvbiB0aGUgZW50aXR5ICR7SlNPTi5zdHJpbmdpZnkoZW50aXR5KX1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXRhZGF0YSBhcyBEZWNvcmF0b3JUeXBlPFQsIEN1c3RvbU1ldGFkYXRhVHlwZT47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdHlwZSBvZiB0aGUgcHJvcGVydHktbWV0YWRhdGEuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB3aXRoIHRoZSBwcm9wZXJ0eSB0byBnZXQgdGhlIHR5cGUgZnJvbS5cbiAgICAgKiBAcGFyYW0gcHJvcGVydHlLZXkgLSBUaGUgcHJvcGVydHkgb24gdGhlIGdpdmVuIEVudGl0eSB0byBnZXQgdGhlIHR5cGUgZnJvbS5cbiAgICAgKiBAcmV0dXJucyBUaGUgdHlwZSBvZiB0aGUgbWV0YWRhdGEuXG4gICAgICogQHRocm93cyBXaWxsIHRocm93IGFuIGVycm9yIGlmIG5vIG1ldGFkYXRhIGNhbiBiZSBmb3VuZCBmb3IgdGhlIGdpdmVuIHByb3BlcnR5LlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRQcm9wZXJ0eVR5cGU8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLCBwcm9wZXJ0eUtleToga2V5b2YgRW50aXR5VHlwZVxuICAgICk6IERlY29yYXRvclR5cGVzIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHByb3BlcnR5VHlwZTogdW5rbm93biA9IFJlZmxlY3RVdGlsaXRpZXMuZ2V0TWV0YWRhdGEoJ3R5cGUnLCBlbnRpdHksIHByb3BlcnR5S2V5KTtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0eVR5cGUgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgYENvdWxkIG5vdCBmaW5kIHR5cGUgbWV0YWRhdGEgZm9yIHByb3BlcnR5ICR7U3RyaW5nKHByb3BlcnR5S2V5KX0gb24gdGhlIGVudGl0eSAke0pTT04uc3RyaW5naWZ5KGVudGl0eSl9YFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcHJvcGVydHlUeXBlIGFzIERlY29yYXRvclR5cGVzO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIGBDb3VsZCBub3QgZmluZCB0eXBlIG1ldGFkYXRhIGZvciBwcm9wZXJ0eSAke1N0cmluZyhwcm9wZXJ0eUtleSl9IG9uIHRoZSBlbnRpdHkgJHtKU09OLnN0cmluZ2lmeShlbnRpdHkpfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGFsbCBwcm9wZXJ0eSB2YWx1ZXMgYmFzZWQgb24gYSBnaXZlbiBlbnRpdHkgZGF0YS1vYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gVGhlIHRhcmdldCBvYmplY3QgdGhhdCBuZWVkcyB0byBiZSBjb25zdHJ1Y3RlZCAoaWYgY2FsbGVkIGluc2lkZSBhbiBFbnRpdHkgY29uc3RydWN0b3IgaXRzIHVzdWFsbHkgdGhpcykuXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBkYXRhIG9iamVjdCB0byBnZXQgdGhlIHByb3BlcnR5IHZhbHVlcyBmcm9tLlxuICAgICAqIEBhbGlhcyBuZXdcbiAgICAgKiBAYWxpYXMgYnVpbGRcbiAgICAgKiBAYWxpYXMgY29uc3RydWN0XG4gICAgICovXG4gICAgc3RhdGljIG5ldzxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KHRhcmdldDogRW50aXR5VHlwZSwgZW50aXR5PzogRW50aXR5VHlwZSk6IHZvaWQge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiB0YXJnZXQpIHtcbiAgICAgICAgICAgIGNvbnN0IHR5cGU6IERlY29yYXRvclR5cGVzID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5VHlwZSh0YXJnZXQsIGtleSk7XG4gICAgICAgICAgICBsZXQgdmFsdWU6IHVua25vd24gPSBlbnRpdHkgPyBSZWZsZWN0VXRpbGl0aWVzLmdldChlbnRpdHksIGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLk9CSkVDVDpcbiAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2JqZWN0TWV0YWRhdGE6IERlZmF1bHRPYmplY3REZWNvcmF0b3JDb25maWdJbnRlcm5hbDxhbnk+XG4gICAgICAgICAgICAgICAgICAgICAgICA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKHRhcmdldCwga2V5LCBEZWNvcmF0b3JUeXBlcy5PQkpFQ1QpO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IG5ldyBvYmplY3RNZXRhZGF0YS5FbnRpdHlDbGFzcyh2YWx1ZSBhcyBvYmplY3QgfCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZOlxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbnB1dEFycmF5OiBFbnRpdHlUeXBlW10gfCB1bmRlZmluZWQgPSB2YWx1ZSBhcyBFbnRpdHlUeXBlW10gfCB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc0FycmF5OiBFbnRpdHlUeXBlW10gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0QXJyYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhcnJheU1ldGFkYXRhOiBFbnRpdHlBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsPGFueT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKHRhcmdldCwga2V5LCBEZWNvcmF0b3JUeXBlcy5BUlJBWSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaW5wdXRBcnJheSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1XaXRoTWV0YWRhdGE6IEVudGl0eVR5cGUgPSBuZXcgYXJyYXlNZXRhZGF0YS5FbnRpdHlDbGFzcyhpdGVtKSBhcyBFbnRpdHlUeXBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc0FycmF5LnB1c2goaXRlbVdpdGhNZXRhZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSByZXNBcnJheTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBSZWZsZWN0VXRpbGl0aWVzLnNldCh0YXJnZXQsIGtleSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbWVtYmVyLW9yZGVyaW5nLCBqc2RvYy9yZXF1aXJlLWpzZG9jLCBAdHlwZXNjcmlwdC1lc2xpbnQvdHlwZWRlZlxuICAgIHN0YXRpYyBjb25zdHJ1Y3QgPSBFbnRpdHlVdGlsaXRpZXMubmV3O1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbWVtYmVyLW9yZGVyaW5nLCBqc2RvYy9yZXF1aXJlLWpzZG9jLCBAdHlwZXNjcmlwdC1lc2xpbnQvdHlwZWRlZlxuICAgIHN0YXRpYyBidWlsZCA9IEVudGl0eVV0aWxpdGllcy5uZXc7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgdGhlIHZhbHVlcyBvbiBhbiBlbnRpdHkgYXJlIHZhbGlkLlxuICAgICAqIEFsc28gY2hlY2tzIGFsbCB0aGUgdmFsaWRhdG9ycyBnaXZlbiBieSB0aGUgbWV0YWRhdGEgKFwicmVxdWlyZWRcIiwgXCJtYXhMZW5ndGhcIiBldGMuKS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIHZhbGlkYXRlLlxuICAgICAqIEBwYXJhbSBvbWl0IC0gV2hldGhlciB0byBjaGVjayBmb3IgY3JlYXRpbmcgb3IgZWRpdGluZyB2YWxpZGl0eS5cbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIG9yIG5vdCB0aGUgZW50aXR5IGlzIHZhbGlkLlxuICAgICAqL1xuICAgIHN0YXRpYyBpc0VudGl0eVZhbGlkPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oZW50aXR5OiBFbnRpdHlUeXBlLCBvbWl0OiAnY3JlYXRlJyB8ICd1cGRhdGUnKTogYm9vbGVhbiB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIGVudGl0eSkge1xuICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNQcm9wZXJ0eVZhbGlkKGVudGl0eSwga2V5LCBvbWl0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgc2luZ2xlIHByb3BlcnR5IHZhbHVlIGlzIHZhbGlkLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgd2hlcmUgdGhlIHByb3BlcnR5IGlzIGZyb20uXG4gICAgICogQHBhcmFtIGtleSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICAgKiBAcGFyYW0gb21pdCAtIFdoZXRoZXIgdG8gY2hlY2sgaWYgdGhlIGdpdmVuIGVudGl0eSBpcyB2YWxpZCBmb3IgY3JlYXRpb24gb3IgdXBkYXRpbmcuXG4gICAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgdGhlIHByb3BlcnR5IHZhbHVlIGlzIHZhbGlkLlxuICAgICAqIEB0aHJvd3MgVGhyb3dzIHdoZW4gaXQgZXh0cmFjdHMgYW4gdW5rbm93biBtZXRhZGF0YSB0eXBlLlxuICAgICAqL1xuICAgIHByaXZhdGUgc3RhdGljIGlzUHJvcGVydHlWYWxpZDxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGtleToga2V5b2YgRW50aXR5VHlwZSxcbiAgICAgICAgb21pdDogJ2NyZWF0ZScgfCAndXBkYXRlJ1xuICAgICk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCB0eXBlOiBEZWNvcmF0b3JUeXBlcyA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eVR5cGUoZW50aXR5LCBrZXkpO1xuICAgICAgICBjb25zdCBtZXRhZGF0YTogUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwga2V5LCB0eXBlKTtcblxuICAgICAgICBpZiAobWV0YWRhdGEub21pdEZvckNyZWF0ZSAmJiBvbWl0ID09PSAnY3JlYXRlJykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm9taXRGb3JVcGRhdGUgJiYgb21pdCA9PT0gJ3VwZGF0ZScpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5yZXF1aXJlZCkge1xuICAgICAgICAgICAgaWYgKGVudGl0eVtrZXldID09IG51bGwgfHwgZW50aXR5W2tleV0gPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5CT09MRUFOX0RST1BET1dOOlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5CT09MRUFOX0NIRUNLQk9YOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5CT09MRUFOX1RPR0dMRTpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlCb29sZWFuOiBib29sZWFuID0gZW50aXR5W2tleV0gYXMgYm9vbGVhbjtcbiAgICAgICAgICAgICAgICBjb25zdCBib29sZWFuTWV0YWRhdGE6IFRvZ2dsZUJvb2xlYW5EZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IG1ldGFkYXRhIGFzIFRvZ2dsZUJvb2xlYW5EZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgICAgICAgICBpZiAoIUVudGl0eVV0aWxpdGllcy5pc0Jvb2xlYW5WYWxpZChlbnRpdHlCb29sZWFuLCBib29sZWFuTWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLlNUUklOR19EUk9QRE9XTjpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuU1RSSU5HOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5TVFJJTkdfQVVUT0NPTVBMRVRFOlxuICAgICAgICAgICAgICAgIGNvbnN0IGVudGl0eVN0cmluZzogc3RyaW5nID0gZW50aXR5W2tleV0gYXMgc3RyaW5nO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmluZ01ldGFkYXRhOiBEZWZhdWx0U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBtZXRhZGF0YSBhcyBEZWZhdWx0U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNTdHJpbmdWYWxpZChlbnRpdHlTdHJpbmcsIHN0cmluZ01ldGFkYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5TVFJJTkdfVEVYVEJPWDpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlUZXh0Ym94OiBzdHJpbmcgPSBlbnRpdHlba2V5XSBhcyBzdHJpbmc7XG4gICAgICAgICAgICAgICAgY29uc3QgdGV4dGJveE1ldGFkYXRhOiBUZXh0Ym94U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBtZXRhZGF0YSBhcyBUZXh0Ym94U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNUZXh0Ym94VmFsaWQoZW50aXR5VGV4dGJveCwgdGV4dGJveE1ldGFkYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5TVFJJTkdfUEFTU1dPUkQ6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5UGFzc3dvcmQ6IHN0cmluZyA9IGVudGl0eVtrZXldIGFzIHN0cmluZztcbiAgICAgICAgICAgICAgICBjb25zdCBwYXNzd29yZE1ldGFkYXRhOiBQYXNzd29yZFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsID0gbWV0YWRhdGEgYXMgUGFzc3dvcmRTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25maXJtUGFzc3dvcmQ6IHN0cmluZyA9IFJlZmxlY3RVdGlsaXRpZXMuZ2V0TWV0YWRhdGEodGhpcy5DT05GSVJNX1BBU1NXT1JEX0tFWSwgZW50aXR5LCBrZXkpIGFzIHN0cmluZztcbiAgICAgICAgICAgICAgICBpZiAoIUVudGl0eVV0aWxpdGllcy5pc1Bhc3N3b3JkVmFsaWQoZW50aXR5UGFzc3dvcmQsIHBhc3N3b3JkTWV0YWRhdGEsIGNvbmZpcm1QYXNzd29yZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuTlVNQkVSX0RST1BET1dOOlxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5OVU1CRVI6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLk5VTUJFUl9TTElERVI6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5TnVtYmVyOiBudW1iZXIgPSBlbnRpdHlba2V5XSBhcyBudW1iZXI7XG4gICAgICAgICAgICAgICAgY29uc3QgbnVtYmVyTWV0YWRhdGE6IERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IG1ldGFkYXRhIGFzIERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgICAgICAgICBpZiAoIUVudGl0eVV0aWxpdGllcy5pc051bWJlclZhbGlkKGVudGl0eU51bWJlciwgbnVtYmVyTWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLk9CSkVDVDpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlPYmplY3Q6IEVudGl0eVR5cGUgPSBlbnRpdHlba2V5XSBhcyBFbnRpdHlUeXBlO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcGFyYW1ldGVyS2V5IGluIGVudGl0eU9iamVjdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIUVudGl0eVV0aWxpdGllcy5pc1Byb3BlcnR5VmFsaWQoZW50aXR5T2JqZWN0LCBwYXJhbWV0ZXJLZXksIG9taXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZX1NUUklOR19DSElQUzpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfU1RSSU5HX0FVVE9DT01QTEVURV9DSElQUzpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfREFURTpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfREFURV9USU1FOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5BUlJBWV9EQVRFX1JBTkdFOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5BUlJBWTpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlBcnJheTogdW5rbm93bltdID0gZW50aXR5W2tleV0gYXMgdW5rbm93bltdO1xuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gICAgICAgICAgICAgICAgY29uc3QgYXJyYXlNZXRhZGF0YTogRW50aXR5QXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbDxFbnRpdHlUeXBlPiA9IG1ldGFkYXRhIGFzIEVudGl0eUFycmF5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw8RW50aXR5VHlwZT47XG4gICAgICAgICAgICAgICAgaWYgKGFycmF5TWV0YWRhdGEucmVxdWlyZWQgJiYgIWVudGl0eUFycmF5Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5EQVRFOlxuICAgICAgICAgICAgICAgIGNvbnN0IGVudGl0eURhdGU6IERhdGUgPSBuZXcgRGF0ZShlbnRpdHlba2V5XSBhcyBEYXRlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRlTWV0YWRhdGE6IERlZmF1bHREYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBtZXRhZGF0YSBhcyBEZWZhdWx0RGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICAgICAgICAgIGlmICghRW50aXR5VXRpbGl0aWVzLmlzRGF0ZVZhbGlkKGVudGl0eURhdGUsIGRhdGVNZXRhZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuREFURV9SQU5HRTpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlEYXRlUmFuZ2U6IERhdGVSYW5nZSA9IExvZGFzaFV0aWxpdGllcy5jbG9uZURlZXAoZW50aXR5W2tleV0gYXMgRGF0ZVJhbmdlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRlUmFuZ2VNZXRhZGF0YTogRGF0ZVJhbmdlRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsID0gbWV0YWRhdGEgYXMgRGF0ZVJhbmdlRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICAgICAgICAgIGlmICghRW50aXR5VXRpbGl0aWVzLmlzRGF0ZVJhbmdlVmFsaWQoZW50aXR5RGF0ZVJhbmdlLCBkYXRlUmFuZ2VNZXRhZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuREFURV9USU1FOlxuICAgICAgICAgICAgICAgIGNvbnN0IGVudGl0eURhdGVUaW1lOiBEYXRlID0gbmV3IERhdGUoZW50aXR5W2tleV0gYXMgRGF0ZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0ZVRpbWVNZXRhZGF0YTogRGF0ZVRpbWVEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBtZXRhZGF0YSBhcyBEYXRlVGltZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgICAgICAgICBjb25zdCBoYXNUaW1lOiBib29sZWFuID0gUmVmbGVjdFV0aWxpdGllcy5oYXNNZXRhZGF0YSh0aGlzLlRJTUVfS0VZLCBlbnRpdHksIGtleSk7XG4gICAgICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNEYXRlVGltZVZhbGlkKGVudGl0eURhdGVUaW1lLCBkYXRlVGltZU1ldGFkYXRhLCBoYXNUaW1lKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5GSUxFX0RFRkFVTFQ6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkZJTEVfSU1BR0U6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5RmlsZTogRmlsZURhdGEgfCBGaWxlRGF0YVtdID0gZW50aXR5W2tleV0gYXMgRmlsZURhdGEgfCBGaWxlRGF0YVtdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVudGl0eUZpbGVNZXRhZGF0YTogRGVmYXVsdEZpbGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IG1ldGFkYXRhIGFzIERlZmF1bHRGaWxlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNGaWxlRGF0YVZhbGlkKGVudGl0eUZpbGUsIGVudGl0eUZpbGVNZXRhZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuUkVGRVJFTkNFU19NQU5ZOlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5DVVNUT006XG4gICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnksIG1heC1sZW5cbiAgICAgICAgICAgICAgICBjb25zdCBjdXN0b21NZXRhZGF0YTogQ3VzdG9tRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw8RW50aXR5VHlwZSwgYW55LCBhbnksIGFueT4gPSBtZXRhZGF0YSBhcyBDdXN0b21EZWNvcmF0b3JDb25maWdJbnRlcm5hbDxFbnRpdHlUeXBlLCBhbnksIGFueSwgYW55PjtcbiAgICAgICAgICAgICAgICBpZiAoIWN1c3RvbU1ldGFkYXRhLmlzVmFsaWQoZW50aXR5W2tleV0sIG9taXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IHZhbGlkYXRlIHRoZSBpbnB1dCBiZWNhdXNlIHRoZSBEZWNvcmF0b3JUeXBlICR7dHlwZX0gaXMgbm90IGtub3duYCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNCb29sZWFuVmFsaWQodmFsdWU6IGJvb2xlYW4sIG1ldGFkYXRhOiBUb2dnbGVCb29sZWFuRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKG1ldGFkYXRhLnJlcXVpcmVkICYmICF2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzU3RyaW5nVmFsaWQodmFsdWU6IHN0cmluZywgbWV0YWRhdGE6IERlZmF1bHRTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAobWV0YWRhdGEubWF4TGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA+IG1ldGFkYXRhLm1heExlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW5MZW5ndGggJiYgdmFsdWUubGVuZ3RoIDwgbWV0YWRhdGEubWluTGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLnJlZ2V4ICYmICF2YWx1ZS5tYXRjaChtZXRhZGF0YS5yZWdleCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc1RleHRib3hWYWxpZCh2YWx1ZTogc3RyaW5nLCBtZXRhZGF0YTogVGV4dGJveFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhMZW5ndGggJiYgdmFsdWUubGVuZ3RoID4gbWV0YWRhdGEubWF4TGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pbkxlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPCBtZXRhZGF0YS5taW5MZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc1Bhc3N3b3JkVmFsaWQodmFsdWU6IHN0cmluZywgbWV0YWRhdGE6IFBhc3N3b3JkU3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIGNvbmZpcm1QYXNzd29yZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIGlmICh2YWx1ZSAhPT0gY29uZmlybVBhc3N3b3JkKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1heExlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPiBtZXRhZGF0YS5tYXhMZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEubWluTGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA8IG1ldGFkYXRhLm1pbkxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5yZWdleCAmJiAhdmFsdWUubWF0Y2gobWV0YWRhdGEucmVnZXgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNOdW1iZXJWYWxpZCh2YWx1ZTogbnVtYmVyLCBtZXRhZGF0YTogRGVmYXVsdE51bWJlckRlY29yYXRvckNvbmZpZ0ludGVybmFsKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXggJiYgdmFsdWUgPiBtZXRhZGF0YS5tYXgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEubWluICYmIHZhbHVlIDwgbWV0YWRhdGEubWluKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNEYXRlVmFsaWQodmFsdWU6IERhdGUsIG1ldGFkYXRhOiBEZWZhdWx0RGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW4gJiYgdmFsdWUuZ2V0VGltZSgpIDwgbWV0YWRhdGEubWluKHZhbHVlKS5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEubWF4ICYmIHZhbHVlLmdldFRpbWUoKSA+IG1ldGFkYXRhLm1heCh2YWx1ZSkuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLmZpbHRlciAmJiAhbWV0YWRhdGEuZmlsdGVyKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRGF0ZVJhbmdlVmFsaWQodmFsdWU6IERhdGVSYW5nZSwgbWV0YWRhdGE6IERhdGVSYW5nZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAobWV0YWRhdGEucmVxdWlyZWQpIHtcbiAgICAgICAgICAgIGlmICghKHZhbHVlLnN0YXJ0IGFzIERhdGUgfCB1bmRlZmluZWQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEodmFsdWUuZW5kIGFzIERhdGUgfCB1bmRlZmluZWQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhbHVlLnN0YXJ0ID0gbmV3IERhdGUodmFsdWUuc3RhcnQpO1xuICAgICAgICB2YWx1ZS5lbmQgPSBuZXcgRGF0ZSh2YWx1ZS5lbmQpO1xuICAgICAgICBpZiAobWV0YWRhdGEubWluU3RhcnQgJiYgdmFsdWUuc3RhcnQuZ2V0VGltZSgpIDwgbWV0YWRhdGEubWluU3RhcnQodmFsdWUuc3RhcnQpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhTdGFydCAmJiB2YWx1ZS5zdGFydC5nZXRUaW1lKCkgPiBtZXRhZGF0YS5tYXhTdGFydCh2YWx1ZS5zdGFydCkuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pbkVuZCAmJiB2YWx1ZS5lbmQuZ2V0VGltZSgpIDwgbWV0YWRhdGEubWluRW5kKHZhbHVlLmVuZCkuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1heEVuZCAmJiB2YWx1ZS5lbmQuZ2V0VGltZSgpID4gbWV0YWRhdGEubWF4RW5kKHZhbHVlLmVuZCkuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLmZpbHRlcikge1xuICAgICAgICAgICAgaWYgKCFtZXRhZGF0YS5maWx0ZXIodmFsdWUuc3RhcnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtZXRhZGF0YS5maWx0ZXIodmFsdWUuZW5kKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh2YWx1ZS52YWx1ZXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGRhdGUgb2YgdmFsdWUudmFsdWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghbWV0YWRhdGEuZmlsdGVyKGRhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNEYXRlVGltZVZhbGlkKHZhbHVlOiBEYXRlLCBtZXRhZGF0YTogRGF0ZVRpbWVEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIGhhc1RpbWU6IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCFoYXNUaW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pbkRhdGUgJiYgdmFsdWUuZ2V0VGltZSgpIDwgbWV0YWRhdGEubWluRGF0ZSh2YWx1ZSkuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1heERhdGUgJiYgdmFsdWUuZ2V0VGltZSgpID4gbWV0YWRhdGEubWF4RGF0ZSh2YWx1ZSkuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLmZpbHRlckRhdGUgJiYgIW1ldGFkYXRhLmZpbHRlckRhdGUodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGltZTogVGltZSA9IHtcbiAgICAgICAgICAgIGhvdXJzOiB2YWx1ZS5nZXRIb3VycygpLFxuICAgICAgICAgICAgbWludXRlczogdmFsdWUuZ2V0TWludXRlcygpXG4gICAgICAgIH07XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW5UaW1lKSB7XG4gICAgICAgICAgICBjb25zdCBtaW5UaW1lOiBUaW1lID0gbWV0YWRhdGEubWluVGltZSh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgICAgICAgdGltZS5ob3VycyA+IG1pblRpbWUuaG91cnNcbiAgICAgICAgICAgICAgICAgICAgfHwgKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGltZS5ob3VycyA9PT0gbWluVGltZS5ob3Vyc1xuICAgICAgICAgICAgICAgICAgICAgICAgJiYgdGltZS5taW51dGVzID49IG1pblRpbWUubWludXRlc1xuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhUaW1lKSB7XG4gICAgICAgICAgICBjb25zdCBtYXhUaW1lOiBUaW1lID0gbWV0YWRhdGEubWF4VGltZSh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgICAgICAgdGltZS5ob3VycyA8IG1heFRpbWUuaG91cnNcbiAgICAgICAgICAgICAgICAgICAgfHwgKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGltZS5ob3VycyA9PT0gbWF4VGltZS5ob3Vyc1xuICAgICAgICAgICAgICAgICAgICAgICAgJiYgdGltZS5taW51dGVzIDw9IG1heFRpbWUubWludXRlc1xuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5maWx0ZXJUaW1lKSB7XG4gICAgICAgICAgICBpZiAoIW1ldGFkYXRhLmZpbHRlclRpbWUodGltZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNGaWxlRGF0YVZhbGlkKHZhbHVlOiBGaWxlRGF0YSB8IEZpbGVEYXRhW10sIG1ldGFkYXRhOiBEZWZhdWx0RmlsZURlY29yYXRvckNvbmZpZ0ludGVybmFsKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGZpbGVzOiBGaWxlRGF0YVtdID0gbWV0YWRhdGEubXVsdGlwbGUgPyB2YWx1ZSBhcyBGaWxlRGF0YVtdIDogW3ZhbHVlIGFzIEZpbGVEYXRhXTtcbiAgICAgICAgbGV0IGZpbGVTaXplVG90YWw6IG51bWJlciA9IDA7XG4gICAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICAgICAgaWYgKCFmaWxlLm5hbWUgfHwgIWZpbGUuZmlsZSAmJiAhZmlsZS51cmwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIUZpbGVVdGlsaXRpZXMuaXNNaW1lVHlwZVZhbGlkKGZpbGUudHlwZSwgbWV0YWRhdGEuYWxsb3dlZE1pbWVUeXBlcykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoRmlsZVV0aWxpdGllcy50cmFuc2Zvcm1Ub01lZ2FCeXRlcyhmaWxlLnNpemUsICdCJykgPiBtZXRhZGF0YS5tYXhTaXplKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmlsZVNpemVUb3RhbCArPSBmaWxlLnNpemU7XG4gICAgICAgICAgICBpZiAoRmlsZVV0aWxpdGllcy50cmFuc2Zvcm1Ub01lZ2FCeXRlcyhmaWxlU2l6ZVRvdGFsLCAnQicpID4gbWV0YWRhdGEubWF4U2l6ZVRvdGFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhbiBlbnRpdHkgaXMgXCJkaXJ0eVwiIChpZiBpdHMgdmFsdWVzIGhhdmUgY2hhbmdlZCkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSBhZnRlciBhbGwgY2hhbmdlcy5cbiAgICAgKiBAcGFyYW0gZW50aXR5UHJpb3JDaGFuZ2VzIC0gVGhlIGVudGl0eSBiZWZvcmUgdGhlIGNoYW5nZXMuXG4gICAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgdGhlIGVudGl0eSBpcyBkaXJ0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgaXNEaXJ0eTxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGVudGl0eVByaW9yQ2hhbmdlczogRW50aXR5VHlwZVxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBpZiAoIShlbnRpdHlQcmlvckNoYW5nZXMgYXMgRW50aXR5VHlwZSB8IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGRpZmZlcmVuY2VzOiBEaWZmZXJlbmNlPEVudGl0eVR5cGU+W10gPSBhd2FpdCBFbnRpdHlVdGlsaXRpZXMuZGlmZmVyZW5jZXNGb3JEaXJ0eShlbnRpdHksIGVudGl0eVByaW9yQ2hhbmdlcyk7XG4gICAgICAgICAgICByZXR1cm4gZGlmZmVyZW5jZXMubGVuZ3RoID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgYXN5bmMgZGlmZmVyZW5jZXNGb3JEaXJ0eTxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGVudGl0eVByaW9yQ2hhbmdlczogRW50aXR5VHlwZVxuICAgICk6IFByb21pc2U8RGlmZmVyZW5jZTxFbnRpdHlUeXBlPltdPiB7XG4gICAgICAgIGNvbnN0IHJlczogRGlmZmVyZW5jZTxFbnRpdHlUeXBlPltdID0gW107XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIFJlZmxlY3RVdGlsaXRpZXMub3duS2V5cyhlbnRpdHkpKSB7XG4gICAgICAgICAgICBjb25zdCBtZXRhZGF0YTogUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwga2V5KTtcbiAgICAgICAgICAgIGNvbnN0IHR5cGU6IERlY29yYXRvclR5cGVzID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5VHlwZShlbnRpdHksIGtleSk7XG4gICAgICAgICAgICBpZiAoIShhd2FpdCBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbChlbnRpdHlba2V5XSwgZW50aXR5UHJpb3JDaGFuZ2VzW2tleV0sIG1ldGFkYXRhLCB0eXBlKSkpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5LFxuICAgICAgICAgICAgICAgICAgICBiZWZvcmU6IGVudGl0eVByaW9yQ2hhbmdlc1trZXldLFxuICAgICAgICAgICAgICAgICAgICBhZnRlcjogZW50aXR5W2tleV1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgbmVlZGVkIHRvIHNldCBibG9iIGZpbGUgZGF0YSBzbyB0aGF0IGl0IGlzIG9ubHkgcmVxdWVzdGVkIG9uY2UuXG4gICAgICAgICAgICAgICAgZW50aXR5UHJpb3JDaGFuZ2VzW2tleV0gPSBMb2Rhc2hVdGlsaXRpZXMuY2xvbmVEZWVwKGVudGl0eVtrZXldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXBhcmVzIHR3byBFbnRpdGllcyBhbmQgcmV0dXJucyB0aGVpciBkaWZmZXJlbmNlIGluIGFuIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZmlyc3QgZW50aXR5IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIGVudGl0eVByaW9yQ2hhbmdlcyAtIFRoZSBzZWNvbmQgZW50aXR5IHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMgVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIEVudGl0aWVzIGluIGZvcm0gb2YgYSBQYXJ0aWFsLlxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBkaWZmZXJlbmNlPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgZW50aXR5UHJpb3JDaGFuZ2VzOiBFbnRpdHlUeXBlXG4gICAgKTogUHJvbWlzZTxQYXJ0aWFsPEVudGl0eVR5cGU+PiB7XG4gICAgICAgIGNvbnN0IHJlczogUGFydGlhbDxFbnRpdHlUeXBlPiA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBlbnRpdHkpIHtcbiAgICAgICAgICAgIGNvbnN0IG1ldGFkYXRhOiBQcm9wZXJ0eURlY29yYXRvckNvbmZpZ0ludGVybmFsID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrZXkpO1xuICAgICAgICAgICAgY29uc3QgdHlwZTogRGVjb3JhdG9yVHlwZXMgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlUeXBlKGVudGl0eSwga2V5KTtcbiAgICAgICAgICAgIGlmICghKGF3YWl0IEVudGl0eVV0aWxpdGllcy5pc0VxdWFsKGVudGl0eVtrZXldLCBlbnRpdHlQcmlvckNoYW5nZXNba2V5XSwgbWV0YWRhdGEsIHR5cGUpKSkge1xuICAgICAgICAgICAgICAgIHJlc1trZXldID0gZW50aXR5W2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgdHdvIGdpdmVuIHZhbHVlcyBhcmUgZXF1YWwuXG4gICAgICogSXQgdXNlcyB0aGUgaXNFcXVhbCBtZXRob2QgZnJvbSBMb2Rhc2hVdGlsaXRpZXMgYW5kIGV4dGVuZHMgaXQgd2l0aCBmdW5jdGlvbmFsaXR5IHJlZ2FyZGluZyBEYXRlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB1cGRhdGVkIHZhbHVlLlxuICAgICAqIEBwYXJhbSB2YWx1ZVByaW9yQ2hhbmdlcyAtIFRoZSB2YWx1ZSBiZWZvcmUgYW55IGNoYW5nZXMuXG4gICAgICogQHBhcmFtIG1ldGFkYXRhIC0gVGhlIG1ldGFkYXRhIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICAgKiBAcGFyYW0gdHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIG9yIG5vdCB0aGUgZ2l2ZW4gdmFsdWVzIGFyZSBlcXVhbC5cbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgaXNFcXVhbChcbiAgICAgICAgdmFsdWU6IHVua25vd24sXG4gICAgICAgIHZhbHVlUHJpb3JDaGFuZ2VzOiB1bmtub3duLFxuICAgICAgICBtZXRhZGF0YTogUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCxcbiAgICAgICAgdHlwZTogRGVjb3JhdG9yVHlwZXNcbiAgICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkRBVEVfUkFOR0U6XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVudGl0eVV0aWxpdGllcy5pc0VxdWFsRGF0ZVJhbmdlKFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVQcmlvckNoYW5nZXMsXG4gICAgICAgICAgICAgICAgICAgIChtZXRhZGF0YSBhcyBEYXRlUmFuZ2VEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwpLmZpbHRlclxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkRBVEU6XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVudGl0eVV0aWxpdGllcy5pc0VxdWFsRGF0ZSh2YWx1ZSwgdmFsdWVQcmlvckNoYW5nZXMpO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5EQVRFX1RJTUU6XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVudGl0eVV0aWxpdGllcy5pc0VxdWFsRGF0ZVRpbWUodmFsdWUsIHZhbHVlUHJpb3JDaGFuZ2VzKTtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfREFURTpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfREFURV9USU1FOlxuICAgICAgICAgICAgICAgIHJldHVybiBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbEFycmF5RGF0ZSh2YWx1ZSwgdmFsdWVQcmlvckNoYW5nZXMpO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5BUlJBWV9EQVRFX1JBTkdFOlxuICAgICAgICAgICAgICAgIHJldHVybiBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbEFycmF5RGF0ZVJhbmdlKFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVQcmlvckNoYW5nZXMsXG4gICAgICAgICAgICAgICAgICAgIChtZXRhZGF0YSBhcyBEYXRlUmFuZ2VBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsKS5maWx0ZXJcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5BUlJBWV9TVFJJTkdfQ0hJUFM6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZX1NUUklOR19BVVRPQ09NUExFVEVfQ0hJUFM6XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVudGl0eVV0aWxpdGllcy5pc0VxdWFsQXJyYXlTdHJpbmcodmFsdWUsIHZhbHVlUHJpb3JDaGFuZ2VzKTtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuRklMRV9JTUFHRTpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuRklMRV9ERUZBVUxUOlxuICAgICAgICAgICAgICAgIHJldHVybiBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbEZpbGUodmFsdWUsIHZhbHVlUHJpb3JDaGFuZ2VzLCAobWV0YWRhdGEgYXMgRGVmYXVsdEZpbGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCkubXVsdGlwbGUpO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5DVVNUT006XG4gICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW4sIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgICAgICByZXR1cm4gRW50aXR5VXRpbGl0aWVzLmlzRXF1YWxDdXN0b20odmFsdWUsIHZhbHVlUHJpb3JDaGFuZ2VzLCBtZXRhZGF0YSBhcyBDdXN0b21EZWNvcmF0b3JDb25maWdJbnRlcm5hbDxhbnksIGFueSwgYW55LCBhbnk+KTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIExvZGFzaFV0aWxpdGllcy5pc0VxdWFsKHZhbHVlLCB2YWx1ZVByaW9yQ2hhbmdlcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc0VxdWFsQXJyYXlTdHJpbmcodmFsdWU6IHVua25vd24sIHZhbHVlUHJpb3JDaGFuZ2VzOiB1bmtub3duKTogYm9vbGVhbiB8IFByb21pc2VMaWtlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3Qgc3RyaW5nQXJyYXk6IHN0cmluZ1tdID0gTG9kYXNoVXRpbGl0aWVzLmNsb25lRGVlcCh2YWx1ZSBhcyBzdHJpbmdbXSkuc29ydCgpO1xuICAgICAgICBjb25zdCBzdHJpbmdBcnJheVByaW9yQ2hhbmdlczogc3RyaW5nW10gPSBMb2Rhc2hVdGlsaXRpZXMuY2xvbmVEZWVwKHZhbHVlUHJpb3JDaGFuZ2VzIGFzIHN0cmluZ1tdKS5zb3J0KCk7XG4gICAgICAgIHJldHVybiBMb2Rhc2hVdGlsaXRpZXMuaXNFcXVhbChzdHJpbmdBcnJheSwgc3RyaW5nQXJyYXlQcmlvckNoYW5nZXMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRXF1YWxBcnJheURhdGUodmFsdWU6IHVua25vd24sIHZhbHVlUHJpb3JDaGFuZ2VzOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IG5ld1ZhbHVlOiBEYXRlW10gPSAodmFsdWUgYXMgRGF0ZVtdKS5tYXAodiA9PiBuZXcgRGF0ZSh2KSkuc29ydCgpO1xuICAgICAgICBjb25zdCBuZXdWYWx1ZVByaW9yQ2hhbmdlczogRGF0ZVtdID0gKHZhbHVlUHJpb3JDaGFuZ2VzIGFzIERhdGVbXSkubWFwKHYgPT4gbmV3IERhdGUodikpLnNvcnQoKTtcbiAgICAgICAgcmV0dXJuIExvZGFzaFV0aWxpdGllcy5pc0VxdWFsKG5ld1ZhbHVlLCBuZXdWYWx1ZVByaW9yQ2hhbmdlcyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNFcXVhbEFycmF5RGF0ZVJhbmdlKHZhbHVlOiB1bmtub3duLCB2YWx1ZVByaW9yQ2hhbmdlczogdW5rbm93biwgZmlsdGVyPzogRGF0ZUZpbHRlckZuPERhdGU+KTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGRhdGVSYW5nZXM6IERhdGVSYW5nZVtdID0gKHZhbHVlIGFzIERhdGVSYW5nZVtdKS5zb3J0KCk7XG4gICAgICAgIGNvbnN0IGRhdGVSYW5nZXNQcmlvckNoYW5nZXM6IERhdGVSYW5nZVtdID0gKHZhbHVlUHJpb3JDaGFuZ2VzIGFzIERhdGVSYW5nZVtdKS5zb3J0KCk7XG4gICAgICAgIGlmIChkYXRlUmFuZ2VzLmxlbmd0aCAhPT0gZGF0ZVJhbmdlc1ByaW9yQ2hhbmdlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgZGF0ZVJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbERhdGVSYW5nZShkYXRlUmFuZ2VzW2ldLCBkYXRlUmFuZ2VzUHJpb3JDaGFuZ2VzW2ldLCBmaWx0ZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRXF1YWxEYXRlVGltZSh2YWx1ZTogdW5rbm93biwgdmFsdWVQcmlvckNoYW5nZXM6IHVua25vd24pOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgZGF0ZTogRGF0ZSA9IG5ldyBEYXRlKHZhbHVlIGFzIERhdGUpO1xuICAgICAgICBjb25zdCBkYXRlUHJpb3JDaGFuZ2VzOiBEYXRlID0gbmV3IERhdGUodmFsdWVQcmlvckNoYW5nZXMgYXMgRGF0ZSk7XG4gICAgICAgIHJldHVybiBMb2Rhc2hVdGlsaXRpZXMuaXNFcXVhbChkYXRlLCBkYXRlUHJpb3JDaGFuZ2VzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc0VxdWFsRGF0ZSh2YWx1ZTogdW5rbm93biwgdmFsdWVQcmlvckNoYW5nZXM6IHVua25vd24pOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgZGF0ZTogRGF0ZSA9IG5ldyBEYXRlKHZhbHVlIGFzIERhdGUpO1xuICAgICAgICBjb25zdCBkYXRlUHJpb3JDaGFuZ2VzOiBEYXRlID0gbmV3IERhdGUodmFsdWVQcmlvckNoYW5nZXMgYXMgRGF0ZSk7XG4gICAgICAgIGRhdGUuc2V0SG91cnMoMCwgMCwgMCwgMCk7XG4gICAgICAgIGRhdGVQcmlvckNoYW5nZXMuc2V0SG91cnMoMCwgMCwgMCwgMCk7XG4gICAgICAgIHJldHVybiBMb2Rhc2hVdGlsaXRpZXMuaXNFcXVhbChkYXRlLCBkYXRlUHJpb3JDaGFuZ2VzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc0VxdWFsRGF0ZVJhbmdlKHZhbHVlOiB1bmtub3duLCB2YWx1ZVByaW9yQ2hhbmdlczogdW5rbm93biwgZmlsdGVyPzogRGF0ZUZpbHRlckZuPERhdGU+KTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGRhdGVSYW5nZTogRGF0ZVJhbmdlID0gTG9kYXNoVXRpbGl0aWVzLmNsb25lRGVlcCh2YWx1ZSkgYXMgRGF0ZVJhbmdlO1xuICAgICAgICBkYXRlUmFuZ2Uuc3RhcnQgPSBuZXcgRGF0ZSgodmFsdWUgYXMgRGF0ZVJhbmdlKS5zdGFydCk7XG4gICAgICAgIGRhdGVSYW5nZS5lbmQgPSBuZXcgRGF0ZSgodmFsdWUgYXMgRGF0ZVJhbmdlKS5lbmQpO1xuICAgICAgICBkYXRlUmFuZ2UudmFsdWVzID0gRGF0ZVV0aWxpdGllcy5nZXREYXRlc0JldHdlZW4oXG4gICAgICAgICAgICBkYXRlUmFuZ2Uuc3RhcnQsXG4gICAgICAgICAgICBkYXRlUmFuZ2UuZW5kLFxuICAgICAgICAgICAgZmlsdGVyXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGRhdGVSYW5nZVByaW9yQ2hhbmdlczogRGF0ZVJhbmdlID0gTG9kYXNoVXRpbGl0aWVzLmNsb25lRGVlcCh2YWx1ZVByaW9yQ2hhbmdlcykgYXMgRGF0ZVJhbmdlO1xuICAgICAgICBkYXRlUmFuZ2VQcmlvckNoYW5nZXMuc3RhcnQgPSBuZXcgRGF0ZSgodmFsdWVQcmlvckNoYW5nZXMgYXMgRGF0ZVJhbmdlKS5zdGFydCk7XG4gICAgICAgIGRhdGVSYW5nZVByaW9yQ2hhbmdlcy5lbmQgPSBuZXcgRGF0ZSgodmFsdWVQcmlvckNoYW5nZXMgYXMgRGF0ZVJhbmdlKS5lbmQpO1xuICAgICAgICBkYXRlUmFuZ2VQcmlvckNoYW5nZXMudmFsdWVzID0gRGF0ZVV0aWxpdGllcy5nZXREYXRlc0JldHdlZW4oXG4gICAgICAgICAgICBkYXRlUmFuZ2VQcmlvckNoYW5nZXMuc3RhcnQsXG4gICAgICAgICAgICBkYXRlUmFuZ2VQcmlvckNoYW5nZXMuZW5kLFxuICAgICAgICAgICAgZmlsdGVyXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBMb2Rhc2hVdGlsaXRpZXMuaXNFcXVhbChkYXRlUmFuZ2UsIGRhdGVSYW5nZVByaW9yQ2hhbmdlcyk7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogRmluZCBhIHdheSB0byB1c2UgYmxvYnMgd2l0aCBqZXN0XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBwcml2YXRlIHN0YXRpYyBhc3luYyBpc0VxdWFsRmlsZSh2YWx1ZTogdW5rbm93biwgdmFsdWVQcmlvckNoYW5nZXM6IHVua25vd24sIG11bHRpcGxlOiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICBpZiAodmFsdWVQcmlvckNoYW5nZXMgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZpbGVzOiBGaWxlRGF0YVtdID0gbXVsdGlwbGUgPyAodmFsdWUgYXMgRmlsZURhdGFbXSkuc29ydCgpIDogW3ZhbHVlIGFzIEZpbGVEYXRhXS5zb3J0KCk7XG4gICAgICAgIGNvbnN0IGZpbGVzUHJpb3JDaGFuZ2VzOiBGaWxlRGF0YVtdID0gbXVsdGlwbGUgPyAodmFsdWVQcmlvckNoYW5nZXMgYXMgRmlsZURhdGFbXSkuc29ydCgpIDogW3ZhbHVlUHJpb3JDaGFuZ2VzIGFzIEZpbGVEYXRhXS5zb3J0KCk7XG4gICAgICAgIGlmIChmaWxlcy5sZW5ndGggIT09IGZpbGVzUHJpb3JDaGFuZ2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGk6IG51bWJlciA9IDA7IGkgPCBmaWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgLy8gY2hlY2tzIHRoaXMgYmVmb3JlIGFjdHVhbGx5IGdldHRpbmcgYW55IGZpbGVzIGR1ZSB0byBwZXJmb3JtYW5jZSByZWFzb25zLlxuICAgICAgICAgICAgaWYgKCFMb2Rhc2hVdGlsaXRpZXMuaXNFcXVhbChMb2Rhc2hVdGlsaXRpZXMub21pdChmaWxlc1tpXSwgJ2ZpbGUnKSwgTG9kYXNoVXRpbGl0aWVzLm9taXQoZmlsZXNQcmlvckNoYW5nZXNbaV0sICdmaWxlJykpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpbGVzUHJpb3JDaGFuZ2VzW2ldLmZpbGUgJiYgIWZpbGVzW2ldLmZpbGUpIHtcbiAgICAgICAgICAgICAgICBmaWxlc1tpXSA9IGF3YWl0IEZpbGVVdGlsaXRpZXMuZ2V0RmlsZURhdGEoZmlsZXNbaV0pO1xuICAgICAgICAgICAgICAgIHZhbHVlID0gZmlsZXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlsZXNbaV0uZmlsZSAmJiAhZmlsZXNQcmlvckNoYW5nZXNbaV0uZmlsZSkge1xuICAgICAgICAgICAgICAgIGZpbGVzUHJpb3JDaGFuZ2VzW2ldID0gYXdhaXQgRmlsZVV0aWxpdGllcy5nZXRGaWxlRGF0YShmaWxlc1ByaW9yQ2hhbmdlc1tpXSk7XG4gICAgICAgICAgICAgICAgdmFsdWVQcmlvckNoYW5nZXMgPSBmaWxlc1ByaW9yQ2hhbmdlc1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghTG9kYXNoVXRpbGl0aWVzLmlzRXF1YWwoYXdhaXQgZmlsZXNbaV0uZmlsZT8udGV4dCgpLCBhd2FpdCBmaWxlc1ByaW9yQ2hhbmdlc1tpXS5maWxlPy50ZXh0KCkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRXF1YWxDdXN0b20oXG4gICAgICAgIHZhbHVlOiB1bmtub3duLFxuICAgICAgICB2YWx1ZVByaW9yQ2hhbmdlczogdW5rbm93bixcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgbWV0YWRhdGE6IEN1c3RvbURlY29yYXRvckNvbmZpZ0ludGVybmFsPGFueSwgYW55LCBhbnksIGFueT5cbiAgICApOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCFtZXRhZGF0YS5pc0VxdWFsKHZhbHVlLCB2YWx1ZVByaW9yQ2hhbmdlcywgbWV0YWRhdGEpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcGFyZSBmdW5jdGlvbiBmb3Igc29ydGluZyBlbnRpdHkga2V5cyBieSB0aGVpciBvcmRlciB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhIC0gRmlyc3Qga2V5IG9mIGVudGl0eS5cbiAgICAgKiBAcGFyYW0gYiAtIFNlY29uZCBrZXkgb2YgZW50aXR5LlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBDdXJyZW50IGVudGl0eSAodXNlZCB0byBnZXQgbWV0YWRhdGEgb2YgZW50aXR5IGtleXMpLlxuICAgICAqIEByZXR1cm5zIDAgaWYgYm90aCB2YWx1ZXMgaGF2ZSB0aGUgc2FtZSBvcmRlciwgYSBuZWdhdGl2ZSB2YWx1ZSBpZiAnYScgY29tZXMgYmVmb3JlICdiJywgYSBwb3NpdGl2ZSB2YWx1ZSBpZiAnYScgY29tZXMgYmVoaW5kICdiJy5cbiAgICAgKi9cbiAgICBzdGF0aWMgY29tcGFyZU9yZGVyPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oXG4gICAgICAgIGE6IGtleW9mIEVudGl0eVR5cGUsXG4gICAgICAgIGI6IGtleW9mIEVudGl0eVR5cGUsXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZVxuICAgICk6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IG1ldGFkYXRhQTogUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgYSk7XG4gICAgICAgIGNvbnN0IG1ldGFkYXRhQjogUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgYik7XG5cbiAgICAgICAgaWYgKG1ldGFkYXRhQS5wb3NpdGlvbi5vcmRlciA9PT0gLTEpIHtcbiAgICAgICAgICAgIGlmIChtZXRhZGF0YUIucG9zaXRpb24ub3JkZXIgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChtZXRhZGF0YUIucG9zaXRpb24ub3JkZXIgPT09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1ldGFkYXRhQS5wb3NpdGlvbi5vcmRlciAtIG1ldGFkYXRhQi5wb3NpdGlvbi5vcmRlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBib290c3RyYXAgY29sdW1uIHZhbHVlcyBmb3IgXCJsZ1wiLCBcIm1kXCIsIFwic21cIi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBFbnRpdHkgdG8gZ2V0IHRoZSBib290c3RyYXAgY29sdW1uIHZhbHVlcyBvZiB0aGUga2V5LlxuICAgICAqIEBwYXJhbSBrZXkgLSBLZXkgb2YgdGhlIHByb3BlcnR5IHRvIGdldCBib290c3RyYXAgY29sdW1uIHZhbHVlcyBmcm9tLlxuICAgICAqIEBwYXJhbSB0eXBlIC0gRGVmaW5lcyBmb3Igd2hpY2ggc2NyZWVuIHNpemUgdGhlIGNvbHVtbiB2YWx1ZXMgc2hvdWxkIGJlIHJldHVybmVkLlxuICAgICAqIEByZXR1cm5zIEJvb3RzdHJhcCBjb2x1bW4gdmFsdWUuXG4gICAgICovXG4gICAgc3RhdGljIGdldFdpZHRoPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAga2V5OiBrZXlvZiBFbnRpdHlUeXBlLCB0eXBlOiAnbGcnIHwgJ21kJyB8ICdzbSdcbiAgICApOiBudW1iZXIge1xuICAgICAgICBjb25zdCBtZXRhZGF0YTogUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwga2V5KTtcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdsZyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhLmRlZmF1bHRXaWR0aHNbMF07XG4gICAgICAgICAgICBjYXNlICdtZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhLmRlZmF1bHRXaWR0aHNbMV07XG4gICAgICAgICAgICBjYXNlICdzbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhLmRlZmF1bHRXaWR0aHNbMl07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNldHMgYWxsIGNoYW5nZXMgb24gYW4gZW50aXR5LlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gcmVzZXQuXG4gICAgICogQHBhcmFtIGVudGl0eVByaW9yQ2hhbmdlcyAtIFRoZSBlbnRpdHkgYmVmb3JlIGFueSBjaGFuZ2VzLlxuICAgICAqL1xuICAgIHN0YXRpYyByZXNldENoYW5nZXNPbkVudGl0eTxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KGVudGl0eTogRW50aXR5VHlwZSwgZW50aXR5UHJpb3JDaGFuZ2VzOiBFbnRpdHlUeXBlKTogdm9pZCB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIGVudGl0eVByaW9yQ2hhbmdlcykge1xuICAgICAgICAgICAgUmVmbGVjdFV0aWxpdGllcy5zZXQoZW50aXR5LCBrZXksIFJlZmxlY3RVdGlsaXRpZXMuZ2V0KGVudGl0eVByaW9yQ2hhbmdlcywga2V5KSk7XG4gICAgICAgICAgICBpZiAoUmVmbGVjdFV0aWxpdGllcy5oYXNNZXRhZGF0YSh0aGlzLk1FVEFEQVRBX0tFWVNfVE9fUkVTRVRfS0VZLCBlbnRpdHksIGtleSkpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGsgb2YgKFJlZmxlY3RVdGlsaXRpZXMuZ2V0TWV0YWRhdGEodGhpcy5NRVRBREFUQV9LRVlTX1RPX1JFU0VUX0tFWSwgZW50aXR5LCBrZXkpIGFzIHN0cmluZ1tdKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoUmVmbGVjdFV0aWxpdGllcy5oYXNNZXRhZGF0YShrLCBlbnRpdHksIGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlZmxlY3RVdGlsaXRpZXMuZGVmaW5lTWV0YWRhdGEoaywgdW5kZWZpbmVkLCBlbnRpdHksIGtleSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBnZXRFbnRpdHlSb3dzPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgdGFiOiBudW1iZXIsXG4gICAgICAgIGhpZGVPbWl0Rm9yQ3JlYXRlOiBib29sZWFuLFxuICAgICAgICBoaWRlT21pdEZvckVkaXQ6IGJvb2xlYW5cbiAgICApOiBFbnRpdHlSb3c8RW50aXR5VHlwZT5bXSB7XG4gICAgICAgIGNvbnN0IHJlczogRW50aXR5Um93PEVudGl0eVR5cGU+W10gPSBbXTtcblxuICAgICAgICBjb25zdCBrZXlzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSA9IEVudGl0eVV0aWxpdGllcy5rZXlzT2YoZW50aXR5LCBoaWRlT21pdEZvckNyZWF0ZSwgaGlkZU9taXRGb3JFZGl0KTtcbiAgICAgICAgY29uc3QgbnVtYmVyT2ZSb3dzOiBudW1iZXIgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0TnVtYmVyT2ZSb3dzPEVudGl0eVR5cGU+KGtleXMsIGVudGl0eSwgdGFiKTtcbiAgICAgICAgZm9yIChsZXQgaTogbnVtYmVyID0gMTsgaSA8PSBudW1iZXJPZlJvd3M7IGkrKykge1xuICAgICAgICAgICAgY29uc3Qgcm93OiBFbnRpdHlSb3c8RW50aXR5VHlwZT4gPSB7XG4gICAgICAgICAgICAgICAgcm93OiBpLFxuICAgICAgICAgICAgICAgIGtleXM6IEVudGl0eVV0aWxpdGllcy5nZXRLZXlzRm9yUm93PEVudGl0eVR5cGU+KGtleXMsIGVudGl0eSwgaSwgdGFiKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcy5wdXNoKHJvdyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoRW50aXR5VXRpbGl0aWVzLmdldEtleXNGb3JSb3c8RW50aXR5VHlwZT4oa2V5cywgZW50aXR5LCAtMSwgdGFiKS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RSb3c6IEVudGl0eVJvdzxFbnRpdHlUeXBlPiA9IHtcbiAgICAgICAgICAgICAgICByb3c6IG51bWJlck9mUm93cyArIDEsXG4gICAgICAgICAgICAgICAga2V5czogRW50aXR5VXRpbGl0aWVzLmdldEtleXNGb3JSb3c8RW50aXR5VHlwZT4oa2V5cywgZW50aXR5LCAtMSwgdGFiKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcy5wdXNoKGxhc3RSb3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB0YWJzIHRoYXQgYXJlIHVzZWQgdG8gZGlzcGxheSB0aGUgZ2l2ZW4gZW50aXR5LlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gZ2V0IHRoZSByb3dzIGZyb20uXG4gICAgICogQHBhcmFtIGhpZGVPbWl0Rm9yQ3JlYXRlIC0gV2hldGhlciBvciBub3Qga2V5cyB3aXRoIHRoZSBtZXRhZGF0YSBvbWl0Rm9yQ3JlYXRlIHNob3VsZCBiZSBmaWx0ZXJlZCBvdXQuXG4gICAgICogQHBhcmFtIGhpZGVPbWl0Rm9yRWRpdCAtIFdoZXRoZXIgb3Igbm90IGtleXMgd2l0aCB0aGUgbWV0YWRhdGEgb21pdEZvclVwZGF0ZSBzaG91bGQgYmUgZmlsdGVyZWQgb3V0LlxuICAgICAqIEByZXR1cm5zIFRoZSBzb3J0ZWQgVGFicyBjb250YWluaW5nIHRoZSByb3dzIGFuZCB0aGUga2V5cyB0byBkaXNwbGF5IGluIHRoYXQgcm93LlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRFbnRpdHlUYWJzPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgaGlkZU9taXRGb3JDcmVhdGU6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICAgICAgaGlkZU9taXRGb3JFZGl0OiBib29sZWFuID0gZmFsc2VcbiAgICApOiBFbnRpdHlUYWI8RW50aXR5VHlwZT5bXSB7XG4gICAgICAgIGNvbnN0IHJlczogRW50aXR5VGFiPEVudGl0eVR5cGU+W10gPSBbXTtcbiAgICAgICAgY29uc3Qga2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBFbnRpdHlVdGlsaXRpZXMua2V5c09mKGVudGl0eSwgaGlkZU9taXRGb3JDcmVhdGUsIGhpZGVPbWl0Rm9yRWRpdCk7XG4gICAgICAgIGNvbnN0IG51bWJlck9mVGFiczogbnVtYmVyID0gRW50aXR5VXRpbGl0aWVzLmdldE51bWJlck9mVGFiczxFbnRpdHlUeXBlPihrZXlzLCBlbnRpdHkpO1xuXG4gICAgICAgIGlmIChFbnRpdHlVdGlsaXRpZXMuZ2V0RW50aXR5Um93czxFbnRpdHlUeXBlPihlbnRpdHksIC0xLCBoaWRlT21pdEZvckNyZWF0ZSwgaGlkZU9taXRGb3JFZGl0KS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0VGFiOiBFbnRpdHlUYWI8RW50aXR5VHlwZT4gPSB7XG4gICAgICAgICAgICAgICAgdGFiTmFtZTogRW50aXR5VXRpbGl0aWVzLmdldEZpcnN0VGFiTmFtZShlbnRpdHkpLFxuICAgICAgICAgICAgICAgIHRhYjogLTEsXG4gICAgICAgICAgICAgICAgcm93czogRW50aXR5VXRpbGl0aWVzLmdldEVudGl0eVJvd3M8RW50aXR5VHlwZT4oZW50aXR5LCAtMSwgaGlkZU9taXRGb3JDcmVhdGUsIGhpZGVPbWl0Rm9yRWRpdClcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXMucHVzaChmaXJzdFRhYik7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAyOyBpIDw9IG51bWJlck9mVGFiczsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCB0YWI6IEVudGl0eVRhYjxFbnRpdHlUeXBlPiA9IHtcbiAgICAgICAgICAgICAgICB0YWJOYW1lOiBFbnRpdHlVdGlsaXRpZXMuZ2V0VGFiTmFtZShlbnRpdHksIGkpLFxuICAgICAgICAgICAgICAgIHRhYjogaSxcbiAgICAgICAgICAgICAgICByb3dzOiBFbnRpdHlVdGlsaXRpZXMuZ2V0RW50aXR5Um93czxFbnRpdHlUeXBlPihlbnRpdHksIGksIGhpZGVPbWl0Rm9yQ3JlYXRlLCBoaWRlT21pdEZvckVkaXQpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVzLnB1c2godGFiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0S2V5c0ZvclJvdzxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBrZXlzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSxcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLFxuICAgICAgICByb3c6IG51bWJlcixcbiAgICAgICAgdGFiOiBudW1iZXJcbiAgICApOiAoa2V5b2YgRW50aXR5VHlwZSlbXSB7XG4gICAgICAgIHJldHVybiBrZXlzXG4gICAgICAgICAgICAuZmlsdGVyKGsgPT4gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrKS5wb3NpdGlvbi5yb3cgPT09IHJvdylcbiAgICAgICAgICAgIC5maWx0ZXIoayA9PiBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGspLnBvc2l0aW9uLnRhYiA9PT0gdGFiKVxuICAgICAgICAgICAgLnNvcnQoKGEsIGIpID0+IEVudGl0eVV0aWxpdGllcy5jb21wYXJlT3JkZXIoYSwgYiwgZW50aXR5KSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0TnVtYmVyT2ZSb3dzPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oXG4gICAgICAgIGtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdLFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIHRhYjogbnVtYmVyXG4gICAgKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIGtleXNcbiAgICAgICAgICAgIC5maWx0ZXIoayA9PiBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGspLnBvc2l0aW9uLnRhYiA9PT0gdGFiKVxuICAgICAgICAgICAgLm1hcChrID0+IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgaykucG9zaXRpb24ucm93KVxuICAgICAgICAgICAgLnNvcnQoKGEsIGIpID0+IChhID4gYiA/IC0xIDogMSkpWzBdO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGdldE51bWJlck9mVGFiczxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KGtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdLCBlbnRpdHk6IEVudGl0eVR5cGUpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4ga2V5c1xuICAgICAgICAgICAgLm1hcChrID0+IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgaykucG9zaXRpb24udGFiKVxuICAgICAgICAgICAgLnNvcnQoKGEsIGIpID0+IChhID4gYiA/IC0xIDogMSkpWzBdO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGdldFRhYk5hbWU8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihlbnRpdHk6IEVudGl0eVR5cGUsIHRhYjogbnVtYmVyKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcHJvdmlkZWRUYWJOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQgPSBFbnRpdHlVdGlsaXRpZXMua2V5c09mKGVudGl0eSlcbiAgICAgICAgICAgIC5tYXAoayA9PiBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGspKVxuICAgICAgICAgICAgLmZpbmQobSA9PiBtLnBvc2l0aW9uLnRhYiA9PT0gdGFiICYmIG0ucG9zaXRpb24udGFiTmFtZSk/LnBvc2l0aW9uLnRhYk5hbWU7XG4gICAgICAgIHJldHVybiBwcm92aWRlZFRhYk5hbWUgPz8gYFRhYiAke3RhYn1gO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGdldEZpcnN0VGFiTmFtZTxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KGVudGl0eTogRW50aXR5VHlwZSk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHByb3ZpZGVkVGFiTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkID0gRW50aXR5VXRpbGl0aWVzLmtleXNPZihlbnRpdHkpXG4gICAgICAgICAgICAubWFwKGsgPT4gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrKSlcbiAgICAgICAgICAgIC5maW5kKG0gPT4gbS5wb3NpdGlvbi50YWJOYW1lICYmIG0ucG9zaXRpb24udGFiID09PSAtMSk/LnBvc2l0aW9uLnRhYk5hbWU7XG4gICAgICAgIHJldHVybiBwcm92aWRlZFRhYk5hbWUgPz8gJ1RhYiAxJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBrZXlzIG9mIHRoZSBwcm92aWRlZCBlbnRpdHkgY29ycmVjdGx5IHR5cGVkLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gZ2V0IHRoZSBrZXlzIG9mLlxuICAgICAqIEBwYXJhbSBoaWRlT21pdEZvckNyZWF0ZSAtIFdoZXRoZXIgb3Igbm90IGtleXMgd2l0aCB0aGUgbWV0YWRhdGEgb21pdEZvckNyZWF0ZSBzaG91bGQgYmUgZmlsdGVyZWQgb3V0LlxuICAgICAqIEBwYXJhbSBoaWRlT21pdEZvckVkaXQgLSBXaGV0aGVyIG9yIG5vdCBrZXlzIHdpdGggdGhlIG1ldGFkYXRhIG9taXRGb3JVcGRhdGUgc2hvdWxkIGJlIGZpbHRlcmVkIG91dC5cbiAgICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiBrZXlzIG9mIHRoZSBlbnRpdHkuXG4gICAgICovXG4gICAgc3RhdGljIGtleXNPZjxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGhpZGVPbWl0Rm9yQ3JlYXRlOiBib29sZWFuID0gZmFsc2UsXG4gICAgICAgIGhpZGVPbWl0Rm9yRWRpdDogYm9vbGVhbiA9IGZhbHNlXG4gICAgKTogKGtleW9mIEVudGl0eVR5cGUpW10ge1xuICAgICAgICBsZXQga2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBSZWZsZWN0VXRpbGl0aWVzLm93bktleXMoZW50aXR5KTtcbiAgICAgICAgaWYgKGhpZGVPbWl0Rm9yQ3JlYXRlKSB7XG4gICAgICAgICAgICBjb25zdCBvbWl0Rm9yQ3JlYXRlS2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBFbnRpdHlVdGlsaXRpZXMuZ2V0T21pdEZvckNyZWF0ZShlbnRpdHkpO1xuICAgICAgICAgICAga2V5cyA9IGtleXMuZmlsdGVyKGsgPT4gIW9taXRGb3JDcmVhdGVLZXlzLmluY2x1ZGVzKGspKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlkZU9taXRGb3JFZGl0KSB7XG4gICAgICAgICAgICBjb25zdCBvbWl0Rm9yVXBkYXRlS2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBFbnRpdHlVdGlsaXRpZXMuZ2V0T21pdEZvclVwZGF0ZShlbnRpdHkpO1xuICAgICAgICAgICAga2V5cyA9IGtleXMuZmlsdGVyKGsgPT4gIW9taXRGb3JVcGRhdGVLZXlzLmluY2x1ZGVzKGspKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ga2V5cztcbiAgICB9XG59XG5cbi8qKlxuICogQSByb3cgdGhhdCBjb250YWlucyBpbmZvcm1hdGlvbiBhYm91dCBob3cgdG8gZGlzcGxheSBhbiBlbnRpdHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5Um93PEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4ge1xuICAgIC8qKlxuICAgICAqIFRoZSByb3cgaW4gd2hpY2ggdGhpcyBzaG91bGQgYmUgZGlzcGxheWVkLlxuICAgICAqL1xuICAgIHJvdzogbnVtYmVyLFxuICAgIC8qKlxuICAgICAqIFRoZSBrZXlzIG9mIHRoZSB2YWx1ZXMgdGhhdCBzaG91bGQgYmUgZGlzcGxheWVkIGluIHRoYXQgcm93LlxuICAgICAqL1xuICAgIGtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdXG59XG5cbi8qKlxuICogQSB0YWIgdGhhdCBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uIGFib3V0IGhvdyB0byBkaXNwbGF5IGFuIGVudGl0eS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlUYWI8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PiB7XG4gICAgLyoqXG4gICAgICogVGhlIHRhYiBpbiB3aGljaCB0aGUgcm93cyBzaG91bGQgYmUgZGlzcGxheWVkLlxuICAgICAqL1xuICAgIHRhYjogbnVtYmVyLFxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRvIGRpc3BsYXkgaW5zaWRlIHRoZSB0YWIuXG4gICAgICovXG4gICAgdGFiTmFtZTogc3RyaW5nLFxuICAgIC8qKlxuICAgICAqIFRoZSByb3dzIHRoYXQgc2hvdWxkIGJlIGRpc3BsYXllZCBpbnNpZGUgdGhpcyB0YWIsLlxuICAgICAqL1xuICAgIHJvd3M6IEVudGl0eVJvdzxFbnRpdHlUeXBlPltdXG59Il19