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
@@ -1,828 +0,0 @@
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LnV0aWxpdGllcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1tYXRlcmlhbC1lbnRpdHkvc3JjL2NsYXNzZXMvZW50aXR5LnV0aWxpdGllcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQWlCLGNBQWMsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBV3hGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN0RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFakQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBb0JqRDs7R0FFRztBQUNILE1BQU0sT0FBZ0IsZUFBZTtJQStDakM7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsZ0JBQWdCLENBQWdELE1BQWtCO1FBQ3JGLE1BQU0sR0FBRyxHQUF5QixFQUFFLENBQUM7UUFDckMsS0FBSyxNQUFNLEdBQUcsSUFBSSxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQzlDLE1BQU0sUUFBUSxHQUFvQyxlQUFlLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQ25HLElBQUksUUFBUSxDQUFDLGFBQWEsRUFBRTtnQkFDeEIsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUNqQjtTQUNKO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDZixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsZ0JBQWdCLENBQWdELE1BQWtCO1FBQ3JGLE1BQU0sR0FBRyxHQUF5QixFQUFFLENBQUM7UUFDckMsS0FBSyxNQUFNLEdBQUcsSUFBSSxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQzlDLE1BQU0sUUFB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QUFFeEU7O0dBRUc7QUFDYSw2QkFBYSxHQUFXLFdBQVcsQ0FBQztBQUVwRDs7R0FFRztBQUNhLG9DQUFvQixHQUFXLGlCQUFpQixDQUFDO0FBRWpFOztHQUVHO0FBQ2Esd0JBQVEsR0FBVyxNQUFNLENBQUM7QUFFMUM7O0dBRUc7QUFDYSw4QkFBYyxHQUFXLFdBQVcsQ0FBQztBQUVyRDs7R0FFRztBQUNhLG9DQUFvQixHQUFXLGdCQUFnQixDQUFDO0FBRWhFOztHQUVHO0FBQ2Esa0NBQWtCLEdBQVcsY0FBYyxDQUFDO0FBMko1RCwrR0FBK0c7QUFDeEcseUJBQVMsR0FBRyxlQUFlLENBQUMsR0FBRyxDQUFDO0FBQ3ZDLCtHQUErRztBQUN4RyxxQkFBSyxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUaW1lIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IERhdGVGaWx0ZXJGbiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RhdGVwaWNrZXInO1xuaW1wb3J0IHsgRGF0ZVJhbmdlQXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCwgRW50aXR5QXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvYXJyYXkvYXJyYXktZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgRGVjb3JhdG9yVHlwZSwgRGVjb3JhdG9yVHlwZXMgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2Jhc2UvZGVjb3JhdG9yLXR5cGVzLmVudW0nO1xuaW1wb3J0IHsgUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvYmFzZS9wcm9wZXJ0eS1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBUb2dnbGVCb29sZWFuRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2Jvb2xlYW4vYm9vbGVhbi1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBDdXN0b21EZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvY3VzdG9tL2N1c3RvbS1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBEYXRlUmFuZ2VEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIERhdGVUaW1lRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsLCBEZWZhdWx0RGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9kYXRlL2RhdGUtZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgRGF0ZVJhbmdlIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9kYXRlL2RhdGUtZGVjb3JhdG9yLmRhdGEnO1xuaW1wb3J0IHsgRGVmYXVsdEZpbGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvZmlsZS9maWxlLWRlY29yYXRvci1pbnRlcm5hbC5kYXRhJztcbmltcG9ydCB7IEZpbGVEYXRhIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9maWxlL2ZpbGUtZGVjb3JhdG9yLmRhdGEnO1xuaW1wb3J0IHsgRGVmYXVsdE51bWJlckRlY29yYXRvckNvbmZpZ0ludGVybmFsIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9udW1iZXIvbnVtYmVyLWRlY29yYXRvci1pbnRlcm5hbC5kYXRhJztcbmltcG9ydCB7IERlZmF1bHRPYmplY3REZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvb2JqZWN0L29iamVjdC1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBEZWZhdWx0U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIFBhc3N3b3JkU3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIFRleHRib3hTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvc3RyaW5nL3N0cmluZy1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBMb2Rhc2hVdGlsaXRpZXMgfSBmcm9tICcuLi9lbmNhcHN1bGF0aW9uL2xvZGFzaC51dGlsaXRpZXMnO1xuaW1wb3J0IHsgUmVmbGVjdFV0aWxpdGllcyB9IGZyb20gJy4uL2VuY2Fwc3VsYXRpb24vcmVmbGVjdC51dGlsaXRpZXMnO1xuaW1wb3J0IHsgRGF0ZVV0aWxpdGllcyB9IGZyb20gJy4vZGF0ZS51dGlsaXRpZXMnO1xuaW1wb3J0IHsgQmFzZUVudGl0eVR5cGUgfSBmcm9tICcuL2VudGl0eS5tb2RlbCc7XG5pbXBvcnQgeyBGaWxlVXRpbGl0aWVzIH0gZnJvbSAnLi9maWxlLnV0aWxpdGllcyc7XG5cbi8qKlxuICogU2hvd3MgaW5mb3JtYXRpb24gYWJvdXQgZGlmZmVyZW5jZXMgYmV0d2VlbiB0d28gZW50aXRpZXMuXG4gKi9cbmludGVyZmFjZSBEaWZmZXJlbmNlPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4ge1xuICAgIC8qKlxuICAgICAqIFRoZSBrZXkgd2hlcmUgdGhlIHR3byBlbnRpdGllcyBoYXZlIGRpZmZlcmVudCB2YWx1ZXMuXG4gICAgICovXG4gICAga2V5OiBrZXlvZiBFbnRpdHlUeXBlLFxuICAgIC8qKlxuICAgICAqIFRoZSB2YWx1ZSBiZWZvcmUgYW55IGNoYW5nZXMuXG4gICAgICovXG4gICAgYmVmb3JlOiB1bmtub3duLFxuICAgIC8qKlxuICAgICAqIFRoZSBjdXJyZW50IHZhbHVlIGFmdGVyIGNoYW5nZXMuXG4gICAgICovXG4gICAgYWZ0ZXI6IHVua25vd25cbn1cblxuLyoqXG4gKiBDb250YWlucyBIZWxwZXJNZXRob2RzIGFyb3VuZCBoYW5kbGluZyBFbnRpdGllcyBhbmQgdGhlaXIgcHJvcGVydHktbWV0YWRhdGEuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBFbnRpdHlVdGlsaXRpZXMge1xuXG4gICAgLyoqXG4gICAgICogVGhlIGtleSBmb3IgYWxsIGtleXMgb2YgbWV0YWRhdGEgdGhhdCBzaG91bGQgYmUgc2V0IHRvIHVuZGVmaW5lZCB3aGVuIHRoZSBlbnRpdHkgZ2V0cyByZXNldC5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVhZG9ubHkgTUVUQURBVEFfS0VZU19UT19SRVNFVF9LRVk6IHN0cmluZyA9ICdtZXRhZGF0YUtleXNUb1Jlc2V0JztcblxuICAgIC8qKlxuICAgICAqIFRoZSBrZXkgZm9yIHRoZSBtZXRhZGF0YSB0aGF0IHNhdmVzIHRoZSBzaW5nbGUgcHJldmlldyBpbWFnZSB2YWx1ZSBvbiBpbWFnZSBwcm9wZXJ0aWVzLlxuICAgICAqL1xuICAgIHN0YXRpYyByZWFkb25seSBTSU5HTEVfUFJFVklFV19JTUFHRV9LRVk6IHN0cmluZyA9ICdzaW5nbGVQcmV2aWV3SW1hZ2UnO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGtleSBmb3IgdGhlIG1ldGFkYXRhIHRoYXQgc2F2ZXMgdGhlIG11bHRpIHByZXZpZXcgaW1hZ2VzIHZhbHVlIG9uIGltYWdlIHByb3BlcnRpZXMuXG4gICAgICovXG4gICAgc3RhdGljIHJlYWRvbmx5IE1VTFRJX1BSRVZJRVdfSU1BR0VTX0tFWTogc3RyaW5nID0gJ211bHRpUHJldmlld0ltYWdlcyc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUga2V5IGZvciB0aGUgbWV0YWRhdGEgdGhhdCBzYXZlcyB0aGUgZmlsZW5hbWVzIHZhbHVlIG9uIGZpbGUgcHJvcGVydGllcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVhZG9ubHkgRklMRU5BTUVTX0tFWTogc3RyaW5nID0gJ2ZpbGVOYW1lcyc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUga2V5IGZvciB0aGUgbWV0YWRhdGEgdGhhdCBzYXZlcyB0aGUgY29uZmlybSBwYXNzd29yZCB2YWx1ZSBvbiBwYXNzd29yZCBwcm9wZXJ0aWVzLlxuICAgICAqL1xuICAgIHN0YXRpYyByZWFkb25seSBDT05GSVJNX1BBU1NXT1JEX0tFWTogc3RyaW5nID0gJ2NvbmZpcm1QYXNzd29yZCc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUga2V5IGZvciB0aGUgbWV0YWRhdGEgdGhhdCBzYXZlcyB0aGUgdGltZSB2YWx1ZSBvbiBkYXRlIHRpbWUgcHJvcGVydGllcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVhZG9ubHkgVElNRV9LRVk6IHN0cmluZyA9ICd0aW1lJztcblxuICAgIC8qKlxuICAgICAqIFRoZSBrZXkgZm9yIHRoZSBtZXRhZGF0YSB0aGF0IHNhdmVzIHRoZSBkYXRlIHJhbmdlIHZhbHVlIG9uIGRhdGUgcmFuZ2UgcHJvcGVydGllcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVhZG9ubHkgREFURV9SQU5HRV9LRVk6IHN0cmluZyA9ICdkYXRlUmFuZ2UnO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGtleSBmb3IgdGhlIG1ldGFkYXRhIHRoYXQgc2F2ZXMgdGhlIGRhdGUgcmFuZ2Ugc3RhcnQgdmFsdWUgb24gZGF0ZSByYW5nZSBwcm9wZXJ0aWVzLlxuICAgICAqL1xuICAgIHN0YXRpYyByZWFkb25seSBEQVRFX1JBTkdFX1NUQVJUX0tFWTogc3RyaW5nID0gJ2RhdGVSYW5nZVN0YXJ0JztcblxuICAgIC8qKlxuICAgICAqIFRoZSBrZXkgZm9yIHRoZSBtZXRhZGF0YSB0aGF0IHNhdmVzIHRoZSBkYXRlIHJhbmdlIGVuZCB2YWx1ZSBvbiBkYXRlIHJhbmdlIHByb3BlcnRpZXMuXG4gICAgICovXG4gICAgc3RhdGljIHJlYWRvbmx5IERBVEVfUkFOR0VfRU5EX0tFWTogc3RyaW5nID0gJ2RhdGVSYW5nZUVuZCc7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwcm9wZXJ0aWVzIHRvIG9taXQgd2hlbiB1cGRhdGluZyB0aGUgZW50aXR5LlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gZ2V0IHRoZSBwcm9wZXJ0aWVzIHdoaWNoIHNob3VsZCBiZSBsZWZ0IG91dCBmb3IgdXBkYXRpbmcgZnJvbS5cbiAgICAgKiBAcmV0dXJucyBUaGUgcHJvcGVydGllcyB3aGljaCBzaG91bGQgYmUgbGVmdCBvdXQgZm9yIHVwZGF0aW5nIGFuIEVudGl0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0T21pdEZvclVwZGF0ZTxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KGVudGl0eTogRW50aXR5VHlwZSk6IChrZXlvZiBFbnRpdHlUeXBlKVtdIHtcbiAgICAgICAgY29uc3QgcmVzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBFbnRpdHlVdGlsaXRpZXMua2V5c09mKGVudGl0eSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG1ldGFkYXRhOiBQcm9wZXJ0eURlY29yYXRvckNvbmZpZ0ludGVybmFsID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrZXkpO1xuICAgICAgICAgICAgaWYgKG1ldGFkYXRhLm9taXRGb3JVcGRhdGUpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcHJvcGVydGllcyB0byBvbWl0IHdoZW4gY3JlYXRpbmcgbmV3IGVudGl0aWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gZ2V0IHRoZSBwcm9wZXJ0aWVzIHdoaWNoIHNob3VsZCBiZSBsZWZ0IG91dCBmb3IgY3JlYXRpbmcgZnJvbS5cbiAgICAgKiBAcmV0dXJucyBUaGUgcHJvcGVydGllcyB3aGljaCBzaG91bGQgYmUgbGVmdCBvdXQgZm9yIGNyZWF0aW5nIGEgbmV3IEVudGl0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0T21pdEZvckNyZWF0ZTxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KGVudGl0eTogRW50aXR5VHlwZSk6IChrZXlvZiBFbnRpdHlUeXBlKVtdIHtcbiAgICAgICAgY29uc3QgcmVzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBFbnRpdHlVdGlsaXRpZXMua2V5c09mKGVudGl0eSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG1ldGFkYXRhOiBQcm9wZXJ0eURlY29yYXRvckNvbmZpZ0ludGVybmFsID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrZXkpO1xuICAgICAgICAgICAgaWYgKG1ldGFkYXRhLm9taXRGb3JDcmVhdGUpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgcHJvcGVydGllcyBvbiB0aGUgZ2l2ZW4gZW50aXR5IHdoaWNoIGFyZSBmaWxlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIGNoZWNrIGZvciBmaWxlIHByb3BlcnRpZXMuXG4gICAgICogQHBhcmFtIG9taXQgLSBXaGV0aGVyIHRvIGxlYXZlIG91dCB2YWx1ZXMgdGhhdCBhcmUgb21pdHRlZCBmb3IgY3JlYXRlIG9yIGRlbGV0ZS5cbiAgICAgKiBAcmV0dXJucyBUaGUga2V5cyBvZiBhbGwgZmlsZSBwcm9wZXJ0aWVzIG9uIHRoZSBnaXZlbiBlbnRpdHkuXG4gICAgICovXG4gICAgc3RhdGljIGdldEZpbGVQcm9wZXJ0aWVzPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgb21pdD86ICdjcmVhdGUnIHwgJ3VwZGF0ZSdcbiAgICApOiAoa2V5b2YgRW50aXR5VHlwZSlbXSB7XG4gICAgICAgIGNvbnN0IHJlczogKGtleW9mIEVudGl0eVR5cGUpW10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgRW50aXR5VXRpbGl0aWVzLmtleXNPZihlbnRpdHkpKSB7XG4gICAgICAgICAgICBjb25zdCB0eXBlOiBEZWNvcmF0b3JUeXBlcyA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eVR5cGUoZW50aXR5LCBrZXkpO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09IERlY29yYXRvclR5cGVzLkZJTEVfREVGQVVMVCB8fCB0eXBlID09PSBEZWNvcmF0b3JUeXBlcy5GSUxFX0lNQUdFKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWV0YWRhdGE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGtleSk7XG4gICAgICAgICAgICAgICAgaWYgKCEobWV0YWRhdGEub21pdEZvckNyZWF0ZSAmJiBvbWl0ID09PSAnY3JlYXRlJykgJiYgIShtZXRhZGF0YS5vbWl0Rm9yVXBkYXRlICYmIG9taXQgPT09ICd1cGRhdGUnKSkge1xuICAgICAgICAgICAgICAgICAgICByZXMucHVzaChrZXkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG1ldGFkYXRhIGluY2x1ZGVkIGluIGFuIHByb3BlcnR5LlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgd2l0aCB0aGUgcHJvcGVydHkgdG8gZ2V0IHRoZSBtZXRhZGF0YSBmcm9tLlxuICAgICAqIEBwYXJhbSBwcm9wZXJ0eUtleSAtIFRoZSBwcm9wZXJ0eSBvbiB0aGUgZ2l2ZW4gRW50aXR5IHRvIGdldCB0aGUgbWV0YWRhdGEgZnJvbS5cbiAgICAgKiBAcGFyYW0gdHlwZSAtIEZvciBzZWN1cmUgVHlwaW5nLCBkZWZpbmVzIHRoZSByZXR1cm5lZCBQcm9wZXJ0eUNvbmZpZy5cbiAgICAgKiBAcmV0dXJucyBUaGUgbWV0YWRhdGEgb2YgdGhlIHByb3BlcnR5LlxuICAgICAqIEB0aHJvd3MgV2hlbiBubyBtZXRhZGF0YSBjYW4gYmUgZm91bmQgZm9yIHRoZSBnaXZlbiBwcm9wZXJ0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0UHJvcGVydHlNZXRhZGF0YTxcbiAgICAgICAgRW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+LFxuICAgICAgICBUIGV4dGVuZHMgRGVjb3JhdG9yVHlwZXMsXG4gICAgICAgIEN1c3RvbU1ldGFkYXRhVHlwZSBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gICAgPihcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLFxuICAgICAgICBwcm9wZXJ0eUtleToga2V5b2YgRW50aXR5VHlwZSxcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgICB0eXBlPzogVFxuICAgICk6IERlY29yYXRvclR5cGU8VCwgQ3VzdG9tTWV0YWRhdGFUeXBlPiB7XG4gICAgICAgIGNvbnN0IG1ldGFkYXRhOiB1bmtub3duID0gUmVmbGVjdFV0aWxpdGllcy5nZXRNZXRhZGF0YSgnbWV0YWRhdGEnLCBlbnRpdHksIHByb3BlcnR5S2V5KTtcbiAgICAgICAgaWYgKG1ldGFkYXRhID09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICBgQ291bGQgbm90IGZpbmQgbWV0YWRhdGEgZm9yIHByb3BlcnR5ICR7U3RyaW5nKHByb3BlcnR5S2V5KX0gb24gdGhlIGVudGl0eSAke0pTT04uc3RyaW5naWZ5KGVudGl0eSl9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWV0YWRhdGEgYXMgRGVjb3JhdG9yVHlwZTxULCBDdXN0b21NZXRhZGF0YVR5cGU+O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHR5cGUgb2YgdGhlIHByb3BlcnR5LW1ldGFkYXRhLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgd2l0aCB0aGUgcHJvcGVydHkgdG8gZ2V0IHRoZSB0eXBlIGZyb20uXG4gICAgICogQHBhcmFtIHByb3BlcnR5S2V5IC0gVGhlIHByb3BlcnR5IG9uIHRoZSBnaXZlbiBFbnRpdHkgdG8gZ2V0IHRoZSB0eXBlIGZyb20uXG4gICAgICogQHJldHVybnMgVGhlIHR5cGUgb2YgdGhlIG1ldGFkYXRhLlxuICAgICAqIEB0aHJvd3MgV2lsbCB0aHJvdyBhbiBlcnJvciBpZiBubyBtZXRhZGF0YSBjYW4gYmUgZm91bmQgZm9yIHRoZSBnaXZlbiBwcm9wZXJ0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0UHJvcGVydHlUeXBlPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSwgcHJvcGVydHlLZXk6IGtleW9mIEVudGl0eVR5cGVcbiAgICApOiBEZWNvcmF0b3JUeXBlcyB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBwcm9wZXJ0eVR5cGU6IHVua25vd24gPSBSZWZsZWN0VXRpbGl0aWVzLmdldE1ldGFkYXRhKCd0eXBlJywgZW50aXR5LCBwcm9wZXJ0eUtleSk7XG4gICAgICAgICAgICBpZiAocHJvcGVydHlUeXBlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGBDb3VsZCBub3QgZmluZCB0eXBlIG1ldGFkYXRhIGZvciBwcm9wZXJ0eSAke1N0cmluZyhwcm9wZXJ0eUtleSl9IG9uIHRoZSBlbnRpdHkgJHtKU09OLnN0cmluZ2lmeShlbnRpdHkpfWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHByb3BlcnR5VHlwZSBhcyBEZWNvcmF0b3JUeXBlcztcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICBgQ291bGQgbm90IGZpbmQgdHlwZSBtZXRhZGF0YSBmb3IgcHJvcGVydHkgJHtTdHJpbmcocHJvcGVydHlLZXkpfSBvbiB0aGUgZW50aXR5ICR7SlNPTi5zdHJpbmdpZnkoZW50aXR5KX1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhbGwgcHJvcGVydHkgdmFsdWVzIGJhc2VkIG9uIGEgZ2l2ZW4gZW50aXR5IGRhdGEtb2JqZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHRhcmdldCAtIFRoZSB0YXJnZXQgb2JqZWN0IHRoYXQgbmVlZHMgdG8gYmUgY29uc3RydWN0ZWQgKGlmIGNhbGxlZCBpbnNpZGUgYW4gRW50aXR5IGNvbnN0cnVjdG9yIGl0cyB1c3VhbGx5IHRoaXMpLlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZGF0YSBvYmplY3QgdG8gZ2V0IHRoZSBwcm9wZXJ0eSB2YWx1ZXMgZnJvbS5cbiAgICAgKiBAYWxpYXMgbmV3XG4gICAgICogQGFsaWFzIGJ1aWxkXG4gICAgICogQGFsaWFzIGNvbnN0cnVjdFxuICAgICAqL1xuICAgIHN0YXRpYyBuZXc8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+Pih0YXJnZXQ6IEVudGl0eVR5cGUsIGVudGl0eT86IEVudGl0eVR5cGUpOiB2b2lkIHtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gdGFyZ2V0KSB7XG4gICAgICAgICAgICBjb25zdCB0eXBlOiBEZWNvcmF0b3JUeXBlcyA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eVR5cGUodGFyZ2V0LCBrZXkpO1xuICAgICAgICAgICAgbGV0IHZhbHVlOiB1bmtub3duID0gZW50aXR5ID8gUmVmbGVjdFV0aWxpdGllcy5nZXQoZW50aXR5LCBrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5PQkpFQ1Q6XG4gICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9iamVjdE1ldGFkYXRhOiBEZWZhdWx0T2JqZWN0RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw8YW55PlxuICAgICAgICAgICAgICAgICAgICAgICAgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YSh0YXJnZXQsIGtleSwgRGVjb3JhdG9yVHlwZXMuT0JKRUNUKTtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBuZXcgb2JqZWN0TWV0YWRhdGEuRW50aXR5Q2xhc3ModmFsdWUgYXMgb2JqZWN0IHwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5BUlJBWTpcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5wdXRBcnJheTogRW50aXR5VHlwZVtdIHwgdW5kZWZpbmVkID0gdmFsdWUgYXMgRW50aXR5VHlwZVtdIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNBcnJheTogRW50aXR5VHlwZVtdID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dEFycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJyYXlNZXRhZGF0YTogRW50aXR5QXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbDxhbnk+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YSh0YXJnZXQsIGtleSwgRGVjb3JhdG9yVHlwZXMuQVJSQVkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGlucHV0QXJyYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpdGVtV2l0aE1ldGFkYXRhOiBFbnRpdHlUeXBlID0gbmV3IGFycmF5TWV0YWRhdGEuRW50aXR5Q2xhc3MoaXRlbSkgYXMgRW50aXR5VHlwZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNBcnJheS5wdXNoKGl0ZW1XaXRoTWV0YWRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gcmVzQXJyYXk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgUmVmbGVjdFV0aWxpdGllcy5zZXQodGFyZ2V0LCBrZXksIHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L21lbWJlci1vcmRlcmluZywganNkb2MvcmVxdWlyZS1qc2RvYywgQHR5cGVzY3JpcHQtZXNsaW50L3R5cGVkZWZcbiAgICBzdGF0aWMgY29uc3RydWN0ID0gRW50aXR5VXRpbGl0aWVzLm5ldztcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L21lbWJlci1vcmRlcmluZywganNkb2MvcmVxdWlyZS1qc2RvYywgQHR5cGVzY3JpcHQtZXNsaW50L3R5cGVkZWZcbiAgICBzdGF0aWMgYnVpbGQgPSBFbnRpdHlVdGlsaXRpZXMubmV3O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoZSB2YWx1ZXMgb24gYW4gZW50aXR5IGFyZSB2YWxpZC5cbiAgICAgKiBBbHNvIGNoZWNrcyBhbGwgdGhlIHZhbGlkYXRvcnMgZ2l2ZW4gYnkgdGhlIG1ldGFkYXRhIChcInJlcXVpcmVkXCIsIFwibWF4TGVuZ3RoXCIgZXRjLikuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byB2YWxpZGF0ZS5cbiAgICAgKiBAcGFyYW0gb21pdCAtIFdoZXRoZXIgdG8gY2hlY2sgZm9yIGNyZWF0aW5nIG9yIGVkaXRpbmcgdmFsaWRpdHkuXG4gICAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgdGhlIGVudGl0eSBpcyB2YWxpZC5cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNFbnRpdHlWYWxpZDxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KGVudGl0eTogRW50aXR5VHlwZSwgb21pdDogJ2NyZWF0ZScgfCAndXBkYXRlJyk6IGJvb2xlYW4ge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBlbnRpdHkpIHtcbiAgICAgICAgICAgIGlmICghRW50aXR5VXRpbGl0aWVzLmlzUHJvcGVydHlWYWxpZChlbnRpdHksIGtleSwgb21pdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIHNpbmdsZSBwcm9wZXJ0eSB2YWx1ZSBpcyB2YWxpZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHdoZXJlIHRoZSBwcm9wZXJ0eSBpcyBmcm9tLlxuICAgICAqIEBwYXJhbSBrZXkgLSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkuXG4gICAgICogQHBhcmFtIG9taXQgLSBXaGV0aGVyIHRvIGNoZWNrIGlmIHRoZSBnaXZlbiBlbnRpdHkgaXMgdmFsaWQgZm9yIGNyZWF0aW9uIG9yIHVwZGF0aW5nLlxuICAgICAqIEByZXR1cm5zIFdoZXRoZXIgb3Igbm90IHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyB2YWxpZC5cbiAgICAgKiBAdGhyb3dzIFRocm93cyB3aGVuIGl0IGV4dHJhY3RzIGFuIHVua25vd24gbWV0YWRhdGEgdHlwZS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHN0YXRpYyBpc1Byb3BlcnR5VmFsaWQ8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLFxuICAgICAgICBrZXk6IGtleW9mIEVudGl0eVR5cGUsXG4gICAgICAgIG9taXQ6ICdjcmVhdGUnIHwgJ3VwZGF0ZSdcbiAgICApOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgdHlwZTogRGVjb3JhdG9yVHlwZXMgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlUeXBlKGVudGl0eSwga2V5KTtcbiAgICAgICAgY29uc3QgbWV0YWRhdGE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGtleSwgdHlwZSk7XG5cbiAgICAgICAgaWYgKG1ldGFkYXRhLm9taXRGb3JDcmVhdGUgJiYgb21pdCA9PT0gJ2NyZWF0ZScpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5vbWl0Rm9yVXBkYXRlICYmIG9taXQgPT09ICd1cGRhdGUnKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEucmVxdWlyZWQpIHtcbiAgICAgICAgICAgIGlmIChlbnRpdHlba2V5XSA9PSBudWxsIHx8IGVudGl0eVtrZXldID09PSAnJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQk9PTEVBTl9EUk9QRE9XTjpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQk9PTEVBTl9DSEVDS0JPWDpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQk9PTEVBTl9UT0dHTEU6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5Qm9vbGVhbjogYm9vbGVhbiA9IGVudGl0eVtrZXldIGFzIGJvb2xlYW47XG4gICAgICAgICAgICAgICAgY29uc3QgYm9vbGVhbk1ldGFkYXRhOiBUb2dnbGVCb29sZWFuRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBtZXRhZGF0YSBhcyBUb2dnbGVCb29sZWFuRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNCb29sZWFuVmFsaWQoZW50aXR5Qm9vbGVhbiwgYm9vbGVhbk1ldGFkYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5TVFJJTkdfRFJPUERPV046XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLlNUUklORzpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuU1RSSU5HX0FVVE9DT01QTEVURTpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlTdHJpbmc6IHN0cmluZyA9IGVudGl0eVtrZXldIGFzIHN0cmluZztcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJpbmdNZXRhZGF0YTogRGVmYXVsdFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsID0gbWV0YWRhdGEgYXMgRGVmYXVsdFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICAgICAgICAgIGlmICghRW50aXR5VXRpbGl0aWVzLmlzU3RyaW5nVmFsaWQoZW50aXR5U3RyaW5nLCBzdHJpbmdNZXRhZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuU1RSSU5HX1RFWFRCT1g6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5VGV4dGJveDogc3RyaW5nID0gZW50aXR5W2tleV0gYXMgc3RyaW5nO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRleHRib3hNZXRhZGF0YTogVGV4dGJveFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsID0gbWV0YWRhdGEgYXMgVGV4dGJveFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICAgICAgICAgIGlmICghRW50aXR5VXRpbGl0aWVzLmlzVGV4dGJveFZhbGlkKGVudGl0eVRleHRib3gsIHRleHRib3hNZXRhZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuU1RSSU5HX1BBU1NXT1JEOlxuICAgICAgICAgICAgICAgIGNvbnN0IGVudGl0eVBhc3N3b3JkOiBzdHJpbmcgPSBlbnRpdHlba2V5XSBhcyBzdHJpbmc7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFzc3dvcmRNZXRhZGF0YTogUGFzc3dvcmRTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IG1ldGFkYXRhIGFzIFBhc3N3b3JkU3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgICAgICAgICAgY29uc3QgY29uZmlybVBhc3N3b3JkOiBzdHJpbmcgPSBSZWZsZWN0VXRpbGl0aWVzLmdldE1ldGFkYXRhKHRoaXMuQ09ORklSTV9QQVNTV09SRF9LRVksIGVudGl0eSwga2V5KSBhcyBzdHJpbmc7XG4gICAgICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNQYXNzd29yZFZhbGlkKGVudGl0eVBhc3N3b3JkLCBwYXNzd29yZE1ldGFkYXRhLCBjb25maXJtUGFzc3dvcmQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLk5VTUJFUl9EUk9QRE9XTjpcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuTlVNQkVSOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5OVU1CRVJfU0xJREVSOlxuICAgICAgICAgICAgICAgIGNvbnN0IGVudGl0eU51bWJlcjogbnVtYmVyID0gZW50aXR5W2tleV0gYXMgbnVtYmVyO1xuICAgICAgICAgICAgICAgIGNvbnN0IG51bWJlck1ldGFkYXRhOiBEZWZhdWx0TnVtYmVyRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBtZXRhZGF0YSBhcyBEZWZhdWx0TnVtYmVyRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNOdW1iZXJWYWxpZChlbnRpdHlOdW1iZXIsIG51bWJlck1ldGFkYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5PQkpFQ1Q6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5T2JqZWN0OiBFbnRpdHlUeXBlID0gZW50aXR5W2tleV0gYXMgRW50aXR5VHlwZTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHBhcmFtZXRlcktleSBpbiBlbnRpdHlPYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFFbnRpdHlVdGlsaXRpZXMuaXNQcm9wZXJ0eVZhbGlkKGVudGl0eU9iamVjdCwgcGFyYW1ldGVyS2V5LCBvbWl0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5BUlJBWV9TVFJJTkdfQ0hJUFM6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZX1NUUklOR19BVVRPQ09NUExFVEVfQ0hJUFM6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZX0RBVEU6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZX0RBVEVfVElNRTpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfREFURV9SQU5HRTpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVk6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5QXJyYXk6IHVua25vd25bXSA9IGVudGl0eVtrZXldIGFzIHVua25vd25bXTtcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5TWV0YWRhdGE6IEVudGl0eUFycmF5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw8RW50aXR5VHlwZT4gPSBtZXRhZGF0YSBhcyBFbnRpdHlBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsPEVudGl0eVR5cGU+O1xuICAgICAgICAgICAgICAgIGlmIChhcnJheU1ldGFkYXRhLnJlcXVpcmVkICYmICFlbnRpdHlBcnJheS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuREFURTpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlEYXRlOiBEYXRlID0gbmV3IERhdGUoZW50aXR5W2tleV0gYXMgRGF0ZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0ZU1ldGFkYXRhOiBEZWZhdWx0RGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsID0gbWV0YWRhdGEgYXMgRGVmYXVsdERhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgICAgICAgICBpZiAoIUVudGl0eVV0aWxpdGllcy5pc0RhdGVWYWxpZChlbnRpdHlEYXRlLCBkYXRlTWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkRBVEVfUkFOR0U6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5RGF0ZVJhbmdlOiBEYXRlUmFuZ2UgPSBMb2Rhc2hVdGlsaXRpZXMuY2xvbmVEZWVwKGVudGl0eVtrZXldIGFzIERhdGVSYW5nZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0ZVJhbmdlTWV0YWRhdGE6IERhdGVSYW5nZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IG1ldGFkYXRhIGFzIERhdGVSYW5nZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgICAgICAgICBpZiAoIUVudGl0eVV0aWxpdGllcy5pc0RhdGVSYW5nZVZhbGlkKGVudGl0eURhdGVSYW5nZSwgZGF0ZVJhbmdlTWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkRBVEVfVElNRTpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlEYXRlVGltZTogRGF0ZSA9IG5ldyBEYXRlKGVudGl0eVtrZXldIGFzIERhdGUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGVUaW1lTWV0YWRhdGE6IERhdGVUaW1lRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsID0gbWV0YWRhdGEgYXMgRGF0ZVRpbWVEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgICAgICAgICAgY29uc3QgaGFzVGltZTogYm9vbGVhbiA9IFJlZmxlY3RVdGlsaXRpZXMuaGFzTWV0YWRhdGEodGhpcy5USU1FX0tFWSwgZW50aXR5LCBrZXkpO1xuICAgICAgICAgICAgICAgIGlmICghRW50aXR5VXRpbGl0aWVzLmlzRGF0ZVRpbWVWYWxpZChlbnRpdHlEYXRlVGltZSwgZGF0ZVRpbWVNZXRhZGF0YSwgaGFzVGltZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuRklMRV9ERUZBVUxUOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5GSUxFX0lNQUdFOlxuICAgICAgICAgICAgICAgIGNvbnN0IGVudGl0eUZpbGU6IEZpbGVEYXRhIHwgRmlsZURhdGFbXSA9IGVudGl0eVtrZXldIGFzIEZpbGVEYXRhIHwgRmlsZURhdGFbXTtcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlGaWxlTWV0YWRhdGE6IERlZmF1bHRGaWxlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBtZXRhZGF0YSBhcyBEZWZhdWx0RmlsZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICAgICAgICAgIGlmICghRW50aXR5VXRpbGl0aWVzLmlzRmlsZURhdGFWYWxpZChlbnRpdHlGaWxlLCBlbnRpdHlGaWxlTWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLlJFRkVSRU5DRVNfTUFOWTpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQ1VTVE9NOlxuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55LCBtYXgtbGVuXG4gICAgICAgICAgICAgICAgY29uc3QgY3VzdG9tTWV0YWRhdGE6IEN1c3RvbURlY29yYXRvckNvbmZpZ0ludGVybmFsPEVudGl0eVR5cGUsIGFueSwgYW55LCBhbnk+ID0gbWV0YWRhdGEgYXMgQ3VzdG9tRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw8RW50aXR5VHlwZSwgYW55LCBhbnksIGFueT47XG4gICAgICAgICAgICAgICAgaWYgKCFjdXN0b21NZXRhZGF0YS5pc1ZhbGlkKGVudGl0eVtrZXldLCBvbWl0KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCB2YWxpZGF0ZSB0aGUgaW5wdXQgYmVjYXVzZSB0aGUgRGVjb3JhdG9yVHlwZSAke3R5cGV9IGlzIG5vdCBrbm93bmApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzQm9vbGVhblZhbGlkKHZhbHVlOiBib29sZWFuLCBtZXRhZGF0YTogVG9nZ2xlQm9vbGVhbkRlY29yYXRvckNvbmZpZ0ludGVybmFsKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChtZXRhZGF0YS5yZXF1aXJlZCAmJiAhdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc1N0cmluZ1ZhbGlkKHZhbHVlOiBzdHJpbmcsIG1ldGFkYXRhOiBEZWZhdWx0U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKG1ldGFkYXRhLm1heExlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPiBtZXRhZGF0YS5tYXhMZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEubWluTGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA8IG1ldGFkYXRhLm1pbkxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5yZWdleCAmJiAhdmFsdWUubWF0Y2gobWV0YWRhdGEucmVnZXgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNUZXh0Ym94VmFsaWQodmFsdWU6IHN0cmluZywgbWV0YWRhdGE6IFRleHRib3hTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAobWV0YWRhdGEubWF4TGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA+IG1ldGFkYXRhLm1heExlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW5MZW5ndGggJiYgdmFsdWUubGVuZ3RoIDwgbWV0YWRhdGEubWluTGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNQYXNzd29yZFZhbGlkKHZhbHVlOiBzdHJpbmcsIG1ldGFkYXRhOiBQYXNzd29yZFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsLCBjb25maXJtUGFzc3dvcmQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAodmFsdWUgIT09IGNvbmZpcm1QYXNzd29yZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhMZW5ndGggJiYgdmFsdWUubGVuZ3RoID4gbWV0YWRhdGEubWF4TGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pbkxlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPCBtZXRhZGF0YS5taW5MZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEucmVnZXggJiYgIXZhbHVlLm1hdGNoKG1ldGFkYXRhLnJlZ2V4KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzTnVtYmVyVmFsaWQodmFsdWU6IG51bWJlciwgbWV0YWRhdGE6IERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAobWV0YWRhdGEubWF4ICYmIHZhbHVlID4gbWV0YWRhdGEubWF4KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pbiAmJiB2YWx1ZSA8IG1ldGFkYXRhLm1pbikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRGF0ZVZhbGlkKHZhbHVlOiBEYXRlLCBtZXRhZGF0YTogRGVmYXVsdERhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAobWV0YWRhdGEubWluICYmIHZhbHVlLmdldFRpbWUoKSA8IG1ldGFkYXRhLm1pbih2YWx1ZSkuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1heCAmJiB2YWx1ZS5nZXRUaW1lKCkgPiBtZXRhZGF0YS5tYXgodmFsdWUpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5maWx0ZXIgJiYgIW1ldGFkYXRhLmZpbHRlcih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc0RhdGVSYW5nZVZhbGlkKHZhbHVlOiBEYXRlUmFuZ2UsIG1ldGFkYXRhOiBEYXRlUmFuZ2VEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKG1ldGFkYXRhLnJlcXVpcmVkKSB7XG4gICAgICAgICAgICBpZiAoISh2YWx1ZS5zdGFydCBhcyBEYXRlIHwgdW5kZWZpbmVkKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKHZhbHVlLmVuZCBhcyBEYXRlIHwgdW5kZWZpbmVkKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YWx1ZS5zdGFydCA9IG5ldyBEYXRlKHZhbHVlLnN0YXJ0KTtcbiAgICAgICAgdmFsdWUuZW5kID0gbmV3IERhdGUodmFsdWUuZW5kKTtcbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pblN0YXJ0ICYmIHZhbHVlLnN0YXJ0LmdldFRpbWUoKSA8IG1ldGFkYXRhLm1pblN0YXJ0KHZhbHVlLnN0YXJ0KS5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEubWF4U3RhcnQgJiYgdmFsdWUuc3RhcnQuZ2V0VGltZSgpID4gbWV0YWRhdGEubWF4U3RhcnQodmFsdWUuc3RhcnQpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW5FbmQgJiYgdmFsdWUuZW5kLmdldFRpbWUoKSA8IG1ldGFkYXRhLm1pbkVuZCh2YWx1ZS5lbmQpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhFbmQgJiYgdmFsdWUuZW5kLmdldFRpbWUoKSA+IG1ldGFkYXRhLm1heEVuZCh2YWx1ZS5lbmQpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5maWx0ZXIpIHtcbiAgICAgICAgICAgIGlmICghbWV0YWRhdGEuZmlsdGVyKHZhbHVlLnN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbWV0YWRhdGEuZmlsdGVyKHZhbHVlLmVuZCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUudmFsdWVzKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBkYXRlIG9mIHZhbHVlLnZhbHVlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIW1ldGFkYXRhLmZpbHRlcihkYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRGF0ZVRpbWVWYWxpZCh2YWx1ZTogRGF0ZSwgbWV0YWRhdGE6IERhdGVUaW1lRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsLCBoYXNUaW1lOiBib29sZWFuKTogYm9vbGVhbiB7XG4gICAgICAgIGlmICghaGFzVGltZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW5EYXRlICYmIHZhbHVlLmdldFRpbWUoKSA8IG1ldGFkYXRhLm1pbkRhdGUodmFsdWUpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhEYXRlICYmIHZhbHVlLmdldFRpbWUoKSA+IG1ldGFkYXRhLm1heERhdGUodmFsdWUpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5maWx0ZXJEYXRlICYmICFtZXRhZGF0YS5maWx0ZXJEYXRlKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRpbWU6IFRpbWUgPSB7XG4gICAgICAgICAgICBob3VyczogdmFsdWUuZ2V0SG91cnMoKSxcbiAgICAgICAgICAgIG1pbnV0ZXM6IHZhbHVlLmdldE1pbnV0ZXMoKVxuICAgICAgICB9O1xuICAgICAgICBpZiAobWV0YWRhdGEubWluVGltZSkge1xuICAgICAgICAgICAgY29uc3QgbWluVGltZTogVGltZSA9IG1ldGFkYXRhLm1pblRpbWUodmFsdWUpO1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICEoXG4gICAgICAgICAgICAgICAgICAgIHRpbWUuaG91cnMgPiBtaW5UaW1lLmhvdXJzXG4gICAgICAgICAgICAgICAgICAgIHx8IChcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWUuaG91cnMgPT09IG1pblRpbWUuaG91cnNcbiAgICAgICAgICAgICAgICAgICAgICAgICYmIHRpbWUubWludXRlcyA+PSBtaW5UaW1lLm1pbnV0ZXNcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEubWF4VGltZSkge1xuICAgICAgICAgICAgY29uc3QgbWF4VGltZTogVGltZSA9IG1ldGFkYXRhLm1heFRpbWUodmFsdWUpO1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICEoXG4gICAgICAgICAgICAgICAgICAgIHRpbWUuaG91cnMgPCBtYXhUaW1lLmhvdXJzXG4gICAgICAgICAgICAgICAgICAgIHx8IChcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWUuaG91cnMgPT09IG1heFRpbWUuaG91cnNcbiAgICAgICAgICAgICAgICAgICAgICAgICYmIHRpbWUubWludXRlcyA8PSBtYXhUaW1lLm1pbnV0ZXNcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEuZmlsdGVyVGltZSkge1xuICAgICAgICAgICAgaWYgKCFtZXRhZGF0YS5maWx0ZXJUaW1lKHRpbWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRmlsZURhdGFWYWxpZCh2YWx1ZTogRmlsZURhdGEgfCBGaWxlRGF0YVtdLCBtZXRhZGF0YTogRGVmYXVsdEZpbGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBmaWxlczogRmlsZURhdGFbXSA9IG1ldGFkYXRhLm11bHRpcGxlID8gdmFsdWUgYXMgRmlsZURhdGFbXSA6IFt2YWx1ZSBhcyBGaWxlRGF0YV07XG4gICAgICAgIGxldCBmaWxlU2l6ZVRvdGFsOiBudW1iZXIgPSAwO1xuICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgICAgIGlmICghZmlsZS5uYW1lIHx8ICFmaWxlLmZpbGUgJiYgIWZpbGUudXJsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFGaWxlVXRpbGl0aWVzLmlzTWltZVR5cGVWYWxpZChmaWxlLnR5cGUsIG1ldGFkYXRhLmFsbG93ZWRNaW1lVHlwZXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKEZpbGVVdGlsaXRpZXMudHJhbnNmb3JtVG9NZWdhQnl0ZXMoZmlsZS5zaXplLCAnQicpID4gbWV0YWRhdGEubWF4U2l6ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbGVTaXplVG90YWwgKz0gZmlsZS5zaXplO1xuICAgICAgICAgICAgaWYgKEZpbGVVdGlsaXRpZXMudHJhbnNmb3JtVG9NZWdhQnl0ZXMoZmlsZVNpemVUb3RhbCwgJ0InKSA+IG1ldGFkYXRhLm1heFNpemVUb3RhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYW4gZW50aXR5IGlzIFwiZGlydHlcIiAoaWYgaXRzIHZhbHVlcyBoYXZlIGNoYW5nZWQpLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgYWZ0ZXIgYWxsIGNoYW5nZXMuXG4gICAgICogQHBhcmFtIGVudGl0eVByaW9yQ2hhbmdlcyAtIFRoZSBlbnRpdHkgYmVmb3JlIHRoZSBjaGFuZ2VzLlxuICAgICAqIEByZXR1cm5zIFdoZXRoZXIgb3Igbm90IHRoZSBlbnRpdHkgaXMgZGlydHkuXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIGlzRGlydHk8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLFxuICAgICAgICBlbnRpdHlQcmlvckNoYW5nZXM6IEVudGl0eVR5cGVcbiAgICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgaWYgKCEoZW50aXR5UHJpb3JDaGFuZ2VzIGFzIEVudGl0eVR5cGUgfCB1bmRlZmluZWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBkaWZmZXJlbmNlczogRGlmZmVyZW5jZTxFbnRpdHlUeXBlPltdID0gYXdhaXQgRW50aXR5VXRpbGl0aWVzLmRpZmZlcmVuY2VzRm9yRGlydHkoZW50aXR5LCBlbnRpdHlQcmlvckNoYW5nZXMpO1xuICAgICAgICAgICAgcmV0dXJuIGRpZmZlcmVuY2VzLmxlbmd0aCA/IHRydWUgOiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGFzeW5jIGRpZmZlcmVuY2VzRm9yRGlydHk8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLFxuICAgICAgICBlbnRpdHlQcmlvckNoYW5nZXM6IEVudGl0eVR5cGVcbiAgICApOiBQcm9taXNlPERpZmZlcmVuY2U8RW50aXR5VHlwZT5bXT4ge1xuICAgICAgICBjb25zdCByZXM6IERpZmZlcmVuY2U8RW50aXR5VHlwZT5bXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBSZWZsZWN0VXRpbGl0aWVzLm93bktleXMoZW50aXR5KSkge1xuICAgICAgICAgICAgY29uc3QgbWV0YWRhdGE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGtleSk7XG4gICAgICAgICAgICBjb25zdCB0eXBlOiBEZWNvcmF0b3JUeXBlcyA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eVR5cGUoZW50aXR5LCBrZXkpO1xuICAgICAgICAgICAgaWYgKCEoYXdhaXQgRW50aXR5VXRpbGl0aWVzLmlzRXF1YWwoZW50aXR5W2tleV0sIGVudGl0eVByaW9yQ2hhbmdlc1trZXldLCBtZXRhZGF0YSwgdHlwZSkpKSB7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgICAgICAgICAgYmVmb3JlOiBlbnRpdHlQcmlvckNoYW5nZXNba2V5XSxcbiAgICAgICAgICAgICAgICAgICAgYWZ0ZXI6IGVudGl0eVtrZXldXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIG5lZWRlZCB0byBzZXQgYmxvYiBmaWxlIGRhdGEgc28gdGhhdCBpdCBpcyBvbmx5IHJlcXVlc3RlZCBvbmNlLlxuICAgICAgICAgICAgICAgIGVudGl0eVByaW9yQ2hhbmdlc1trZXldID0gTG9kYXNoVXRpbGl0aWVzLmNsb25lRGVlcChlbnRpdHlba2V5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb21wYXJlcyB0d28gRW50aXRpZXMgYW5kIHJldHVybnMgdGhlaXIgZGlmZmVyZW5jZSBpbiBhbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGZpcnN0IGVudGl0eSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSBlbnRpdHlQcmlvckNoYW5nZXMgLSBUaGUgc2Vjb25kIGVudGl0eSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIFRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBFbnRpdGllcyBpbiBmb3JtIG9mIGEgUGFydGlhbC5cbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgZGlmZmVyZW5jZTxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGVudGl0eVByaW9yQ2hhbmdlczogRW50aXR5VHlwZVxuICAgICk6IFByb21pc2U8UGFydGlhbDxFbnRpdHlUeXBlPj4ge1xuICAgICAgICBjb25zdCByZXM6IFBhcnRpYWw8RW50aXR5VHlwZT4gPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZW50aXR5KSB7XG4gICAgICAgICAgICBjb25zdCBtZXRhZGF0YTogUHJvcGVydHlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwga2V5KTtcbiAgICAgICAgICAgIGNvbnN0IHR5cGU6IERlY29yYXRvclR5cGVzID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5VHlwZShlbnRpdHksIGtleSk7XG4gICAgICAgICAgICBpZiAoIShhd2FpdCBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbChlbnRpdHlba2V5XSwgZW50aXR5UHJpb3JDaGFuZ2VzW2tleV0sIG1ldGFkYXRhLCB0eXBlKSkpIHtcbiAgICAgICAgICAgICAgICByZXNba2V5XSA9IGVudGl0eVtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHR3byBnaXZlbiB2YWx1ZXMgYXJlIGVxdWFsLlxuICAgICAqIEl0IHVzZXMgdGhlIGlzRXF1YWwgbWV0aG9kIGZyb20gTG9kYXNoVXRpbGl0aWVzIGFuZCBleHRlbmRzIGl0IHdpdGggZnVuY3Rpb25hbGl0eSByZWdhcmRpbmcgRGF0ZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdXBkYXRlZCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0gdmFsdWVQcmlvckNoYW5nZXMgLSBUaGUgdmFsdWUgYmVmb3JlIGFueSBjaGFuZ2VzLlxuICAgICAqIEBwYXJhbSBtZXRhZGF0YSAtIFRoZSBtZXRhZGF0YSBvZiB0aGUgcHJvcGVydHkuXG4gICAgICogQHBhcmFtIHR5cGUgLSBUaGUgdHlwZSBvZiB0aGUgcHJvcGVydHkuXG4gICAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgdGhlIGdpdmVuIHZhbHVlcyBhcmUgZXF1YWwuXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIGlzRXF1YWwoXG4gICAgICAgIHZhbHVlOiB1bmtub3duLFxuICAgICAgICB2YWx1ZVByaW9yQ2hhbmdlczogdW5rbm93bixcbiAgICAgICAgbWV0YWRhdGE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsXG4gICAgICAgIHR5cGU6IERlY29yYXRvclR5cGVzXG4gICAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5EQVRFX1JBTkdFOlxuICAgICAgICAgICAgICAgIHJldHVybiBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbERhdGVSYW5nZShcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlUHJpb3JDaGFuZ2VzLFxuICAgICAgICAgICAgICAgICAgICAobWV0YWRhdGEgYXMgRGF0ZVJhbmdlRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsKS5maWx0ZXJcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5EQVRFOlxuICAgICAgICAgICAgICAgIHJldHVybiBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbERhdGUodmFsdWUsIHZhbHVlUHJpb3JDaGFuZ2VzKTtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuREFURV9USU1FOlxuICAgICAgICAgICAgICAgIHJldHVybiBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbERhdGVUaW1lKHZhbHVlLCB2YWx1ZVByaW9yQ2hhbmdlcyk7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZX0RBVEU6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZX0RBVEVfVElNRTpcbiAgICAgICAgICAgICAgICByZXR1cm4gRW50aXR5VXRpbGl0aWVzLmlzRXF1YWxBcnJheURhdGUodmFsdWUsIHZhbHVlUHJpb3JDaGFuZ2VzKTtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfREFURV9SQU5HRTpcbiAgICAgICAgICAgICAgICByZXR1cm4gRW50aXR5VXRpbGl0aWVzLmlzRXF1YWxBcnJheURhdGVSYW5nZShcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlUHJpb3JDaGFuZ2VzLFxuICAgICAgICAgICAgICAgICAgICAobWV0YWRhdGEgYXMgRGF0ZVJhbmdlQXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCkuZmlsdGVyXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfU1RSSU5HX0NISVBTOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5BUlJBWV9TVFJJTkdfQVVUT0NPTVBMRVRFX0NISVBTOlxuICAgICAgICAgICAgICAgIHJldHVybiBFbnRpdHlVdGlsaXRpZXMuaXNFcXVhbEFycmF5U3RyaW5nKHZhbHVlLCB2YWx1ZVByaW9yQ2hhbmdlcyk7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkZJTEVfSU1BR0U6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkZJTEVfREVGQVVMVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gRW50aXR5VXRpbGl0aWVzLmlzRXF1YWxGaWxlKHZhbHVlLCB2YWx1ZVByaW9yQ2hhbmdlcywgKG1ldGFkYXRhIGFzIERlZmF1bHRGaWxlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwpLm11bHRpcGxlKTtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQ1VTVE9NOlxuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVudGl0eVV0aWxpdGllcy5pc0VxdWFsQ3VzdG9tKHZhbHVlLCB2YWx1ZVByaW9yQ2hhbmdlcywgbWV0YWRhdGEgYXMgQ3VzdG9tRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw8YW55LCBhbnksIGFueSwgYW55Pik7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiBMb2Rhc2hVdGlsaXRpZXMuaXNFcXVhbCh2YWx1ZSwgdmFsdWVQcmlvckNoYW5nZXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNFcXVhbEFycmF5U3RyaW5nKHZhbHVlOiB1bmtub3duLCB2YWx1ZVByaW9yQ2hhbmdlczogdW5rbm93bik6IGJvb2xlYW4gfCBQcm9taXNlTGlrZTxib29sZWFuPiB7XG4gICAgICAgIGNvbnN0IHN0cmluZ0FycmF5OiBzdHJpbmdbXSA9IExvZGFzaFV0aWxpdGllcy5jbG9uZURlZXAodmFsdWUgYXMgc3RyaW5nW10pLnNvcnQoKTtcbiAgICAgICAgY29uc3Qgc3RyaW5nQXJyYXlQcmlvckNoYW5nZXM6IHN0cmluZ1tdID0gTG9kYXNoVXRpbGl0aWVzLmNsb25lRGVlcCh2YWx1ZVByaW9yQ2hhbmdlcyBhcyBzdHJpbmdbXSkuc29ydCgpO1xuICAgICAgICByZXR1cm4gTG9kYXNoVXRpbGl0aWVzLmlzRXF1YWwoc3RyaW5nQXJyYXksIHN0cmluZ0FycmF5UHJpb3JDaGFuZ2VzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc0VxdWFsQXJyYXlEYXRlKHZhbHVlOiB1bmtub3duLCB2YWx1ZVByaW9yQ2hhbmdlczogdW5rbm93bik6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBuZXdWYWx1ZTogRGF0ZVtdID0gKHZhbHVlIGFzIERhdGVbXSkubWFwKHYgPT4gbmV3IERhdGUodikpLnNvcnQoKTtcbiAgICAgICAgY29uc3QgbmV3VmFsdWVQcmlvckNoYW5nZXM6IERhdGVbXSA9ICh2YWx1ZVByaW9yQ2hhbmdlcyBhcyBEYXRlW10pLm1hcCh2ID0+IG5ldyBEYXRlKHYpKS5zb3J0KCk7XG4gICAgICAgIHJldHVybiBMb2Rhc2hVdGlsaXRpZXMuaXNFcXVhbChuZXdWYWx1ZSwgbmV3VmFsdWVQcmlvckNoYW5nZXMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRXF1YWxBcnJheURhdGVSYW5nZSh2YWx1ZTogdW5rbm93biwgdmFsdWVQcmlvckNoYW5nZXM6IHVua25vd24sIGZpbHRlcj86IERhdGVGaWx0ZXJGbjxEYXRlPik6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBkYXRlUmFuZ2VzOiBEYXRlUmFuZ2VbXSA9ICh2YWx1ZSBhcyBEYXRlUmFuZ2VbXSkuc29ydCgpO1xuICAgICAgICBjb25zdCBkYXRlUmFuZ2VzUHJpb3JDaGFuZ2VzOiBEYXRlUmFuZ2VbXSA9ICh2YWx1ZVByaW9yQ2hhbmdlcyBhcyBEYXRlUmFuZ2VbXSkuc29ydCgpO1xuICAgICAgICBpZiAoZGF0ZVJhbmdlcy5sZW5ndGggIT09IGRhdGVSYW5nZXNQcmlvckNoYW5nZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgaTogbnVtYmVyID0gMDsgaSA8IGRhdGVSYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICghRW50aXR5VXRpbGl0aWVzLmlzRXF1YWxEYXRlUmFuZ2UoZGF0ZVJhbmdlc1tpXSwgZGF0ZVJhbmdlc1ByaW9yQ2hhbmdlc1tpXSwgZmlsdGVyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc0VxdWFsRGF0ZVRpbWUodmFsdWU6IHVua25vd24sIHZhbHVlUHJpb3JDaGFuZ2VzOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGRhdGU6IERhdGUgPSBuZXcgRGF0ZSh2YWx1ZSBhcyBEYXRlKTtcbiAgICAgICAgY29uc3QgZGF0ZVByaW9yQ2hhbmdlczogRGF0ZSA9IG5ldyBEYXRlKHZhbHVlUHJpb3JDaGFuZ2VzIGFzIERhdGUpO1xuICAgICAgICByZXR1cm4gTG9kYXNoVXRpbGl0aWVzLmlzRXF1YWwoZGF0ZSwgZGF0ZVByaW9yQ2hhbmdlcyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNFcXVhbERhdGUodmFsdWU6IHVua25vd24sIHZhbHVlUHJpb3JDaGFuZ2VzOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGRhdGU6IERhdGUgPSBuZXcgRGF0ZSh2YWx1ZSBhcyBEYXRlKTtcbiAgICAgICAgY29uc3QgZGF0ZVByaW9yQ2hhbmdlczogRGF0ZSA9IG5ldyBEYXRlKHZhbHVlUHJpb3JDaGFuZ2VzIGFzIERhdGUpO1xuICAgICAgICBkYXRlLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICAgICAgICBkYXRlUHJpb3JDaGFuZ2VzLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICAgICAgICByZXR1cm4gTG9kYXNoVXRpbGl0aWVzLmlzRXF1YWwoZGF0ZSwgZGF0ZVByaW9yQ2hhbmdlcyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNFcXVhbERhdGVSYW5nZSh2YWx1ZTogdW5rbm93biwgdmFsdWVQcmlvckNoYW5nZXM6IHVua25vd24sIGZpbHRlcj86IERhdGVGaWx0ZXJGbjxEYXRlPik6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBkYXRlUmFuZ2U6IERhdGVSYW5nZSA9IExvZGFzaFV0aWxpdGllcy5jbG9uZURlZXAodmFsdWUpIGFzIERhdGVSYW5nZTtcbiAgICAgICAgZGF0ZVJhbmdlLnN0YXJ0ID0gbmV3IERhdGUoKHZhbHVlIGFzIERhdGVSYW5nZSkuc3RhcnQpO1xuICAgICAgICBkYXRlUmFuZ2UuZW5kID0gbmV3IERhdGUoKHZhbHVlIGFzIERhdGVSYW5nZSkuZW5kKTtcbiAgICAgICAgZGF0ZVJhbmdlLnZhbHVlcyA9IERhdGVVdGlsaXRpZXMuZ2V0RGF0ZXNCZXR3ZWVuKFxuICAgICAgICAgICAgZGF0ZVJhbmdlLnN0YXJ0LFxuICAgICAgICAgICAgZGF0ZVJhbmdlLmVuZCxcbiAgICAgICAgICAgIGZpbHRlclxuICAgICAgICApO1xuICAgICAgICBjb25zdCBkYXRlUmFuZ2VQcmlvckNoYW5nZXM6IERhdGVSYW5nZSA9IExvZGFzaFV0aWxpdGllcy5jbG9uZURlZXAodmFsdWVQcmlvckNoYW5nZXMpIGFzIERhdGVSYW5nZTtcbiAgICAgICAgZGF0ZVJhbmdlUHJpb3JDaGFuZ2VzLnN0YXJ0ID0gbmV3IERhdGUoKHZhbHVlUHJpb3JDaGFuZ2VzIGFzIERhdGVSYW5nZSkuc3RhcnQpO1xuICAgICAgICBkYXRlUmFuZ2VQcmlvckNoYW5nZXMuZW5kID0gbmV3IERhdGUoKHZhbHVlUHJpb3JDaGFuZ2VzIGFzIERhdGVSYW5nZSkuZW5kKTtcbiAgICAgICAgZGF0ZVJhbmdlUHJpb3JDaGFuZ2VzLnZhbHVlcyA9IERhdGVVdGlsaXRpZXMuZ2V0RGF0ZXNCZXR3ZWVuKFxuICAgICAgICAgICAgZGF0ZVJhbmdlUHJpb3JDaGFuZ2VzLnN0YXJ0LFxuICAgICAgICAgICAgZGF0ZVJhbmdlUHJpb3JDaGFuZ2VzLmVuZCxcbiAgICAgICAgICAgIGZpbHRlclxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gTG9kYXNoVXRpbGl0aWVzLmlzRXF1YWwoZGF0ZVJhbmdlLCBkYXRlUmFuZ2VQcmlvckNoYW5nZXMpO1xuICAgIH1cblxuICAgIC8vIFRPRE86IEZpbmQgYSB3YXkgdG8gdXNlIGJsb2JzIHdpdGggamVzdFxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgcHJpdmF0ZSBzdGF0aWMgYXN5bmMgaXNFcXVhbEZpbGUodmFsdWU6IHVua25vd24sIHZhbHVlUHJpb3JDaGFuZ2VzOiB1bmtub3duLCBtdWx0aXBsZTogYm9vbGVhbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHZhbHVlUHJpb3JDaGFuZ2VzID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmaWxlczogRmlsZURhdGFbXSA9IG11bHRpcGxlID8gKHZhbHVlIGFzIEZpbGVEYXRhW10pLnNvcnQoKSA6IFt2YWx1ZSBhcyBGaWxlRGF0YV0uc29ydCgpO1xuICAgICAgICBjb25zdCBmaWxlc1ByaW9yQ2hhbmdlczogRmlsZURhdGFbXSA9IG11bHRpcGxlID8gKHZhbHVlUHJpb3JDaGFuZ2VzIGFzIEZpbGVEYXRhW10pLnNvcnQoKSA6IFt2YWx1ZVByaW9yQ2hhbmdlcyBhcyBGaWxlRGF0YV0uc29ydCgpO1xuICAgICAgICBpZiAoZmlsZXMubGVuZ3RoICE9PSBmaWxlc1ByaW9yQ2hhbmdlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIC8vIGNoZWNrcyB0aGlzIGJlZm9yZSBhY3R1YWxseSBnZXR0aW5nIGFueSBmaWxlcyBkdWUgdG8gcGVyZm9ybWFuY2UgcmVhc29ucy5cbiAgICAgICAgICAgIGlmICghTG9kYXNoVXRpbGl0aWVzLmlzRXF1YWwoTG9kYXNoVXRpbGl0aWVzLm9taXQoZmlsZXNbaV0sICdmaWxlJyksIExvZGFzaFV0aWxpdGllcy5vbWl0KGZpbGVzUHJpb3JDaGFuZ2VzW2ldLCAnZmlsZScpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaWxlc1ByaW9yQ2hhbmdlc1tpXS5maWxlICYmICFmaWxlc1tpXS5maWxlKSB7XG4gICAgICAgICAgICAgICAgZmlsZXNbaV0gPSBhd2FpdCBGaWxlVXRpbGl0aWVzLmdldEZpbGVEYXRhKGZpbGVzW2ldKTtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IGZpbGVzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpbGVzW2ldLmZpbGUgJiYgIWZpbGVzUHJpb3JDaGFuZ2VzW2ldLmZpbGUpIHtcbiAgICAgICAgICAgICAgICBmaWxlc1ByaW9yQ2hhbmdlc1tpXSA9IGF3YWl0IEZpbGVVdGlsaXRpZXMuZ2V0RmlsZURhdGEoZmlsZXNQcmlvckNoYW5nZXNbaV0pO1xuICAgICAgICAgICAgICAgIHZhbHVlUHJpb3JDaGFuZ2VzID0gZmlsZXNQcmlvckNoYW5nZXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIUxvZGFzaFV0aWxpdGllcy5pc0VxdWFsKGF3YWl0IGZpbGVzW2ldLmZpbGU/LnRleHQoKSwgYXdhaXQgZmlsZXNQcmlvckNoYW5nZXNbaV0uZmlsZT8udGV4dCgpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc0VxdWFsQ3VzdG9tKFxuICAgICAgICB2YWx1ZTogdW5rbm93bixcbiAgICAgICAgdmFsdWVQcmlvckNoYW5nZXM6IHVua25vd24sXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIG1ldGFkYXRhOiBDdXN0b21EZWNvcmF0b3JDb25maWdJbnRlcm5hbDxhbnksIGFueSwgYW55LCBhbnk+XG4gICAgKTogYm9vbGVhbiB7XG4gICAgICAgIGlmICghbWV0YWRhdGEuaXNFcXVhbCh2YWx1ZSwgdmFsdWVQcmlvckNoYW5nZXMsIG1ldGFkYXRhKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXBhcmUgZnVuY3Rpb24gZm9yIHNvcnRpbmcgZW50aXR5IGtleXMgYnkgdGhlaXIgb3JkZXIgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYSAtIEZpcnN0IGtleSBvZiBlbnRpdHkuXG4gICAgICogQHBhcmFtIGIgLSBTZWNvbmQga2V5IG9mIGVudGl0eS5cbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gQ3VycmVudCBlbnRpdHkgKHVzZWQgdG8gZ2V0IG1ldGFkYXRhIG9mIGVudGl0eSBrZXlzKS5cbiAgICAgKiBAcmV0dXJucyAwIGlmIGJvdGggdmFsdWVzIGhhdmUgdGhlIHNhbWUgb3JkZXIsIGEgbmVnYXRpdmUgdmFsdWUgaWYgJ2EnIGNvbWVzIGJlZm9yZSAnYicsIGEgcG9zaXRpdmUgdmFsdWUgaWYgJ2EnIGNvbWVzIGJlaGluZCAnYicuXG4gICAgICovXG4gICAgc3RhdGljIGNvbXBhcmVPcmRlcjxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBhOiBrZXlvZiBFbnRpdHlUeXBlLFxuICAgICAgICBiOiBrZXlvZiBFbnRpdHlUeXBlLFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGVcbiAgICApOiBudW1iZXIge1xuICAgICAgICBjb25zdCBtZXRhZGF0YUE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGEpO1xuICAgICAgICBjb25zdCBtZXRhZGF0YUI6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGIpO1xuXG4gICAgICAgIGlmIChtZXRhZGF0YUEucG9zaXRpb24ub3JkZXIgPT09IC0xKSB7XG4gICAgICAgICAgICBpZiAobWV0YWRhdGFCLnBvc2l0aW9uLm9yZGVyID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobWV0YWRhdGFCLnBvc2l0aW9uLm9yZGVyID09PSAtMSkge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXRhZGF0YUEucG9zaXRpb24ub3JkZXIgLSBtZXRhZGF0YUIucG9zaXRpb24ub3JkZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYm9vdHN0cmFwIGNvbHVtbiB2YWx1ZXMgZm9yIFwibGdcIiwgXCJtZFwiLCBcInNtXCIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gRW50aXR5IHRvIGdldCB0aGUgYm9vdHN0cmFwIGNvbHVtbiB2YWx1ZXMgb2YgdGhlIGtleS5cbiAgICAgKiBAcGFyYW0ga2V5IC0gS2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQgYm9vdHN0cmFwIGNvbHVtbiB2YWx1ZXMgZnJvbS5cbiAgICAgKiBAcGFyYW0gdHlwZSAtIERlZmluZXMgZm9yIHdoaWNoIHNjcmVlbiBzaXplIHRoZSBjb2x1bW4gdmFsdWVzIHNob3VsZCBiZSByZXR1cm5lZC5cbiAgICAgKiBAcmV0dXJucyBCb290c3RyYXAgY29sdW1uIHZhbHVlLlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRXaWR0aDxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGtleToga2V5b2YgRW50aXR5VHlwZSwgdHlwZTogJ2xnJyB8ICdtZCcgfCAnc20nXG4gICAgKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgbWV0YWRhdGE6IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGtleSk7XG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnbGcnOlxuICAgICAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YS5kZWZhdWx0V2lkdGhzWzBdO1xuICAgICAgICAgICAgY2FzZSAnbWQnOlxuICAgICAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YS5kZWZhdWx0V2lkdGhzWzFdO1xuICAgICAgICAgICAgY2FzZSAnc20nOlxuICAgICAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YS5kZWZhdWx0V2lkdGhzWzJdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzZXRzIGFsbCBjaGFuZ2VzIG9uIGFuIGVudGl0eS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIHJlc2V0LlxuICAgICAqIEBwYXJhbSBlbnRpdHlQcmlvckNoYW5nZXMgLSBUaGUgZW50aXR5IGJlZm9yZSBhbnkgY2hhbmdlcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzZXRDaGFuZ2VzT25FbnRpdHk8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihlbnRpdHk6IEVudGl0eVR5cGUsIGVudGl0eVByaW9yQ2hhbmdlczogRW50aXR5VHlwZSk6IHZvaWQge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBlbnRpdHlQcmlvckNoYW5nZXMpIHtcbiAgICAgICAgICAgIFJlZmxlY3RVdGlsaXRpZXMuc2V0KGVudGl0eSwga2V5LCBSZWZsZWN0VXRpbGl0aWVzLmdldChlbnRpdHlQcmlvckNoYW5nZXMsIGtleSkpO1xuICAgICAgICAgICAgaWYgKFJlZmxlY3RVdGlsaXRpZXMuaGFzTWV0YWRhdGEodGhpcy5NRVRBREFUQV9LRVlTX1RPX1JFU0VUX0tFWSwgZW50aXR5LCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBrIG9mIChSZWZsZWN0VXRpbGl0aWVzLmdldE1ldGFkYXRhKHRoaXMuTUVUQURBVEFfS0VZU19UT19SRVNFVF9LRVksIGVudGl0eSwga2V5KSBhcyBzdHJpbmdbXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFJlZmxlY3RVdGlsaXRpZXMuaGFzTWV0YWRhdGEoaywgZW50aXR5LCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBSZWZsZWN0VXRpbGl0aWVzLmRlZmluZU1ldGFkYXRhKGssIHVuZGVmaW5lZCwgZW50aXR5LCBrZXkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0RW50aXR5Um93czxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIHRhYjogbnVtYmVyLFxuICAgICAgICBoaWRlT21pdEZvckNyZWF0ZTogYm9vbGVhbixcbiAgICAgICAgaGlkZU9taXRGb3JFZGl0OiBib29sZWFuXG4gICAgKTogRW50aXR5Um93PEVudGl0eVR5cGU+W10ge1xuICAgICAgICBjb25zdCByZXM6IEVudGl0eVJvdzxFbnRpdHlUeXBlPltdID0gW107XG5cbiAgICAgICAgY29uc3Qga2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBFbnRpdHlVdGlsaXRpZXMua2V5c09mKGVudGl0eSwgaGlkZU9taXRGb3JDcmVhdGUsIGhpZGVPbWl0Rm9yRWRpdCk7XG4gICAgICAgIGNvbnN0IG51bWJlck9mUm93czogbnVtYmVyID0gRW50aXR5VXRpbGl0aWVzLmdldE51bWJlck9mUm93czxFbnRpdHlUeXBlPihrZXlzLCBlbnRpdHksIHRhYik7XG4gICAgICAgIGZvciAobGV0IGk6IG51bWJlciA9IDE7IGkgPD0gbnVtYmVyT2ZSb3dzOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHJvdzogRW50aXR5Um93PEVudGl0eVR5cGU+ID0ge1xuICAgICAgICAgICAgICAgIHJvdzogaSxcbiAgICAgICAgICAgICAgICBrZXlzOiBFbnRpdHlVdGlsaXRpZXMuZ2V0S2V5c0ZvclJvdzxFbnRpdHlUeXBlPihrZXlzLCBlbnRpdHksIGksIHRhYilcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXMucHVzaChyb3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEVudGl0eVV0aWxpdGllcy5nZXRLZXlzRm9yUm93PEVudGl0eVR5cGU+KGtleXMsIGVudGl0eSwgLTEsIHRhYikubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBsYXN0Um93OiBFbnRpdHlSb3c8RW50aXR5VHlwZT4gPSB7XG4gICAgICAgICAgICAgICAgcm93OiBudW1iZXJPZlJvd3MgKyAxLFxuICAgICAgICAgICAgICAgIGtleXM6IEVudGl0eVV0aWxpdGllcy5nZXRLZXlzRm9yUm93PEVudGl0eVR5cGU+KGtleXMsIGVudGl0eSwgLTEsIHRhYilcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXMucHVzaChsYXN0Um93KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdGFicyB0aGF0IGFyZSB1c2VkIHRvIGRpc3BsYXkgdGhlIGdpdmVuIGVudGl0eS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIGdldCB0aGUgcm93cyBmcm9tLlxuICAgICAqIEBwYXJhbSBoaWRlT21pdEZvckNyZWF0ZSAtIFdoZXRoZXIgb3Igbm90IGtleXMgd2l0aCB0aGUgbWV0YWRhdGEgb21pdEZvckNyZWF0ZSBzaG91bGQgYmUgZmlsdGVyZWQgb3V0LlxuICAgICAqIEBwYXJhbSBoaWRlT21pdEZvckVkaXQgLSBXaGV0aGVyIG9yIG5vdCBrZXlzIHdpdGggdGhlIG1ldGFkYXRhIG9taXRGb3JVcGRhdGUgc2hvdWxkIGJlIGZpbHRlcmVkIG91dC5cbiAgICAgKiBAcmV0dXJucyBUaGUgc29ydGVkIFRhYnMgY29udGFpbmluZyB0aGUgcm93cyBhbmQgdGhlIGtleXMgdG8gZGlzcGxheSBpbiB0aGF0IHJvdy5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RW50aXR5VGFiczxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGhpZGVPbWl0Rm9yQ3JlYXRlOiBib29sZWFuID0gZmFsc2UsXG4gICAgICAgIGhpZGVPbWl0Rm9yRWRpdDogYm9vbGVhbiA9IGZhbHNlXG4gICAgKTogRW50aXR5VGFiPEVudGl0eVR5cGU+W10ge1xuICAgICAgICBjb25zdCByZXM6IEVudGl0eVRhYjxFbnRpdHlUeXBlPltdID0gW107XG4gICAgICAgIGNvbnN0IGtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdID0gRW50aXR5VXRpbGl0aWVzLmtleXNPZihlbnRpdHksIGhpZGVPbWl0Rm9yQ3JlYXRlLCBoaWRlT21pdEZvckVkaXQpO1xuICAgICAgICBjb25zdCBudW1iZXJPZlRhYnM6IG51bWJlciA9IEVudGl0eVV0aWxpdGllcy5nZXROdW1iZXJPZlRhYnM8RW50aXR5VHlwZT4oa2V5cywgZW50aXR5KTtcblxuICAgICAgICBpZiAoRW50aXR5VXRpbGl0aWVzLmdldEVudGl0eVJvd3M8RW50aXR5VHlwZT4oZW50aXR5LCAtMSwgaGlkZU9taXRGb3JDcmVhdGUsIGhpZGVPbWl0Rm9yRWRpdCkubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBmaXJzdFRhYjogRW50aXR5VGFiPEVudGl0eVR5cGU+ID0ge1xuICAgICAgICAgICAgICAgIHRhYk5hbWU6IEVudGl0eVV0aWxpdGllcy5nZXRGaXJzdFRhYk5hbWUoZW50aXR5KSxcbiAgICAgICAgICAgICAgICB0YWI6IC0xLFxuICAgICAgICAgICAgICAgIHJvd3M6IEVudGl0eVV0aWxpdGllcy5nZXRFbnRpdHlSb3dzPEVudGl0eVR5cGU+KGVudGl0eSwgLTEsIGhpZGVPbWl0Rm9yQ3JlYXRlLCBoaWRlT21pdEZvckVkaXQpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVzLnB1c2goZmlyc3RUYWIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgaTogbnVtYmVyID0gMjsgaSA8PSBudW1iZXJPZlRhYnM7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgdGFiOiBFbnRpdHlUYWI8RW50aXR5VHlwZT4gPSB7XG4gICAgICAgICAgICAgICAgdGFiTmFtZTogRW50aXR5VXRpbGl0aWVzLmdldFRhYk5hbWUoZW50aXR5LCBpKSxcbiAgICAgICAgICAgICAgICB0YWI6IGksXG4gICAgICAgICAgICAgICAgcm93czogRW50aXR5VXRpbGl0aWVzLmdldEVudGl0eVJvd3M8RW50aXR5VHlwZT4oZW50aXR5LCBpLCBoaWRlT21pdEZvckNyZWF0ZSwgaGlkZU9taXRGb3JFZGl0KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcy5wdXNoKHRhYik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGdldEtleXNGb3JSb3c8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihcbiAgICAgICAga2V5czogKGtleW9mIEVudGl0eVR5cGUpW10sXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgcm93OiBudW1iZXIsXG4gICAgICAgIHRhYjogbnVtYmVyXG4gICAgKTogKGtleW9mIEVudGl0eVR5cGUpW10ge1xuICAgICAgICByZXR1cm4ga2V5c1xuICAgICAgICAgICAgLmZpbHRlcihrID0+IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgaykucG9zaXRpb24ucm93ID09PSByb3cpXG4gICAgICAgICAgICAuZmlsdGVyKGsgPT4gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrKS5wb3NpdGlvbi50YWIgPT09IHRhYilcbiAgICAgICAgICAgIC5zb3J0KChhLCBiKSA9PiBFbnRpdHlVdGlsaXRpZXMuY29tcGFyZU9yZGVyKGEsIGIsIGVudGl0eSkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGdldE51bWJlck9mUm93czxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+KFxuICAgICAgICBrZXlzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSxcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLFxuICAgICAgICB0YWI6IG51bWJlclxuICAgICk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBrZXlzXG4gICAgICAgICAgICAuZmlsdGVyKGsgPT4gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrKS5wb3NpdGlvbi50YWIgPT09IHRhYilcbiAgICAgICAgICAgIC5tYXAoayA9PiBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGspLnBvc2l0aW9uLnJvdylcbiAgICAgICAgICAgIC5zb3J0KChhLCBiKSA9PiAoYSA+IGIgPyAtMSA6IDEpKVswXTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBnZXROdW1iZXJPZlRhYnM8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihrZXlzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSwgZW50aXR5OiBFbnRpdHlUeXBlKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIGtleXNcbiAgICAgICAgICAgIC5tYXAoayA9PiBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGspLnBvc2l0aW9uLnRhYilcbiAgICAgICAgICAgIC5zb3J0KChhLCBiKSA9PiAoYSA+IGIgPyAtMSA6IDEpKVswXTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBnZXRUYWJOYW1lPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4oZW50aXR5OiBFbnRpdHlUeXBlLCB0YWI6IG51bWJlcik6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHByb3ZpZGVkVGFiTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkID0gRW50aXR5VXRpbGl0aWVzLmtleXNPZihlbnRpdHkpXG4gICAgICAgICAgICAubWFwKGsgPT4gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrKSlcbiAgICAgICAgICAgIC5maW5kKG0gPT4gbS5wb3NpdGlvbi50YWIgPT09IHRhYiAmJiBtLnBvc2l0aW9uLnRhYk5hbWUpPy5wb3NpdGlvbi50YWJOYW1lO1xuICAgICAgICByZXR1cm4gcHJvdmlkZWRUYWJOYW1lID8/IGBUYWIgJHt0YWJ9YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBnZXRGaXJzdFRhYk5hbWU8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihlbnRpdHk6IEVudGl0eVR5cGUpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBwcm92aWRlZFRhYk5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCA9IEVudGl0eVV0aWxpdGllcy5rZXlzT2YoZW50aXR5KVxuICAgICAgICAgICAgLm1hcChrID0+IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgaykpXG4gICAgICAgICAgICAuZmluZChtID0+IG0ucG9zaXRpb24udGFiTmFtZSAmJiBtLnBvc2l0aW9uLnRhYiA9PT0gLTEpPy5wb3NpdGlvbi50YWJOYW1lO1xuICAgICAgICByZXR1cm4gcHJvdmlkZWRUYWJOYW1lID8/ICdUYWIgMSc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUga2V5cyBvZiB0aGUgcHJvdmlkZWQgZW50aXR5IGNvcnJlY3RseSB0eXBlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIGdldCB0aGUga2V5cyBvZi5cbiAgICAgKiBAcGFyYW0gaGlkZU9taXRGb3JDcmVhdGUgLSBXaGV0aGVyIG9yIG5vdCBrZXlzIHdpdGggdGhlIG1ldGFkYXRhIG9taXRGb3JDcmVhdGUgc2hvdWxkIGJlIGZpbHRlcmVkIG91dC5cbiAgICAgKiBAcGFyYW0gaGlkZU9taXRGb3JFZGl0IC0gV2hldGhlciBvciBub3Qga2V5cyB3aXRoIHRoZSBtZXRhZGF0YSBvbWl0Rm9yVXBkYXRlIHNob3VsZCBiZSBmaWx0ZXJlZCBvdXQuXG4gICAgICogQHJldHVybnMgQW4gYXJyYXkgb2Yga2V5cyBvZiB0aGUgZW50aXR5LlxuICAgICAqL1xuICAgIHN0YXRpYyBrZXlzT2Y8RW50aXR5VHlwZSBleHRlbmRzIEJhc2VFbnRpdHlUeXBlPEVudGl0eVR5cGU+PihcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlLFxuICAgICAgICBoaWRlT21pdEZvckNyZWF0ZTogYm9vbGVhbiA9IGZhbHNlLFxuICAgICAgICBoaWRlT21pdEZvckVkaXQ6IGJvb2xlYW4gPSBmYWxzZVxuICAgICk6IChrZXlvZiBFbnRpdHlUeXBlKVtdIHtcbiAgICAgICAgbGV0IGtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdID0gUmVmbGVjdFV0aWxpdGllcy5vd25LZXlzKGVudGl0eSk7XG4gICAgICAgIGlmIChoaWRlT21pdEZvckNyZWF0ZSkge1xuICAgICAgICAgICAgY29uc3Qgb21pdEZvckNyZWF0ZUtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdID0gRW50aXR5VXRpbGl0aWVzLmdldE9taXRGb3JDcmVhdGUoZW50aXR5KTtcbiAgICAgICAgICAgIGtleXMgPSBrZXlzLmZpbHRlcihrID0+ICFvbWl0Rm9yQ3JlYXRlS2V5cy5pbmNsdWRlcyhrKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpZGVPbWl0Rm9yRWRpdCkge1xuICAgICAgICAgICAgY29uc3Qgb21pdEZvclVwZGF0ZUtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdID0gRW50aXR5VXRpbGl0aWVzLmdldE9taXRGb3JVcGRhdGUoZW50aXR5KTtcbiAgICAgICAgICAgIGtleXMgPSBrZXlzLmZpbHRlcihrID0+ICFvbWl0Rm9yVXBkYXRlS2V5cy5pbmNsdWRlcyhrKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtleXM7XG4gICAgfVxufVxuXG4vKipcbiAqIEEgcm93IHRoYXQgY29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgaG93IHRvIGRpc3BsYXkgYW4gZW50aXR5LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVudGl0eVJvdzxFbnRpdHlUeXBlIGV4dGVuZHMgQmFzZUVudGl0eVR5cGU8RW50aXR5VHlwZT4+IHtcbiAgICAvKipcbiAgICAgKiBUaGUgcm93IGluIHdoaWNoIHRoaXMgc2hvdWxkIGJlIGRpc3BsYXllZC5cbiAgICAgKi9cbiAgICByb3c6IG51bWJlcixcbiAgICAvKipcbiAgICAgKiBUaGUga2V5cyBvZiB0aGUgdmFsdWVzIHRoYXQgc2hvdWxkIGJlIGRpc3BsYXllZCBpbiB0aGF0IHJvdy5cbiAgICAgKi9cbiAgICBrZXlzOiAoa2V5b2YgRW50aXR5VHlwZSlbXVxufVxuXG4vKipcbiAqIEEgdGFiIHRoYXQgY29udGFpbnMgYWxsIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBob3cgdG8gZGlzcGxheSBhbiBlbnRpdHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5VGFiPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4ge1xuICAgIC8qKlxuICAgICAqIFRoZSB0YWIgaW4gd2hpY2ggdGhlIHJvd3Mgc2hvdWxkIGJlIGRpc3BsYXllZC5cbiAgICAgKi9cbiAgICB0YWI6IG51bWJlcixcbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0byBkaXNwbGF5IGluc2lkZSB0aGUgdGFiLlxuICAgICAqL1xuICAgIHRhYk5hbWU6IHN0cmluZyxcbiAgICAvKipcbiAgICAgKiBUaGUgcm93cyB0aGF0IHNob3VsZCBiZSBkaXNwbGF5ZWQgaW5zaWRlIHRoaXMgdGFiLC5cbiAgICAgKi9cbiAgICByb3dzOiBFbnRpdHlSb3c8RW50aXR5VHlwZT5bXVxufSJdfQ==