@decaf-ts/ui-decorators 0.5.25 → 0.5.27

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 (72) hide show
  1. package/LICENSE.md +173 -17
  2. package/README.md +20 -2
  3. package/dist/ui-decorators.cjs +2 -1550
  4. package/dist/ui-decorators.cjs.map +1 -0
  5. package/dist/ui-decorators.js +2 -0
  6. package/dist/ui-decorators.js.map +1 -0
  7. package/lib/esm/index.d.ts +1 -1
  8. package/lib/esm/index.js +2 -2
  9. package/lib/esm/index.js.map +1 -0
  10. package/lib/esm/model/Renderable.js +1 -1
  11. package/lib/esm/model/Renderable.js.map +1 -0
  12. package/lib/esm/model/decorators.js +1 -1
  13. package/lib/esm/model/decorators.js.map +1 -0
  14. package/lib/esm/model/index.js +1 -1
  15. package/lib/esm/model/index.js.map +1 -0
  16. package/lib/esm/model/model.js +1 -1
  17. package/lib/esm/model/model.js.map +1 -0
  18. package/lib/esm/model/overrides.js +1 -1
  19. package/lib/esm/model/overrides.js.map +1 -0
  20. package/lib/esm/ui/Rendering.js +1 -1
  21. package/lib/esm/ui/Rendering.js.map +1 -0
  22. package/lib/esm/ui/constants.js +1 -1
  23. package/lib/esm/ui/constants.js.map +1 -0
  24. package/lib/esm/ui/decorators.js +1 -1
  25. package/lib/esm/ui/decorators.js.map +1 -0
  26. package/lib/esm/ui/errors.js +1 -1
  27. package/lib/esm/ui/errors.js.map +1 -0
  28. package/lib/esm/ui/handlers.js +1 -1
  29. package/lib/esm/ui/handlers.js.map +1 -0
  30. package/lib/esm/ui/index.js +1 -1
  31. package/lib/esm/ui/index.js.map +1 -0
  32. package/lib/esm/ui/interfaces.js +1 -1
  33. package/lib/esm/ui/interfaces.js.map +1 -0
  34. package/lib/esm/ui/types.d.ts +0 -1
  35. package/lib/esm/ui/types.js +1 -1
  36. package/lib/esm/ui/types.js.map +1 -0
  37. package/lib/esm/ui/utils.js +1 -1
  38. package/lib/esm/ui/utils.js.map +1 -0
  39. package/lib/index.cjs +2 -2
  40. package/lib/index.d.ts +1 -1
  41. package/lib/index.js.map +1 -0
  42. package/lib/model/Renderable.cjs +1 -1
  43. package/lib/model/Renderable.js.map +1 -0
  44. package/lib/model/decorators.cjs +1 -1
  45. package/lib/model/decorators.js.map +1 -0
  46. package/lib/model/index.cjs +1 -1
  47. package/lib/model/index.js.map +1 -0
  48. package/lib/model/model.cjs +1 -1
  49. package/lib/model/model.js.map +1 -0
  50. package/lib/model/overrides.cjs +1 -1
  51. package/lib/model/overrides.js.map +1 -0
  52. package/lib/ui/Rendering.cjs +1 -1
  53. package/lib/ui/Rendering.js.map +1 -0
  54. package/lib/ui/constants.cjs +1 -1
  55. package/lib/ui/constants.js.map +1 -0
  56. package/lib/ui/decorators.cjs +1 -1
  57. package/lib/ui/decorators.js.map +1 -0
  58. package/lib/ui/errors.cjs +1 -1
  59. package/lib/ui/errors.js.map +1 -0
  60. package/lib/ui/handlers.cjs +1 -1
  61. package/lib/ui/handlers.js.map +1 -0
  62. package/lib/ui/index.cjs +1 -1
  63. package/lib/ui/index.js.map +1 -0
  64. package/lib/ui/interfaces.cjs +1 -1
  65. package/lib/ui/interfaces.js.map +1 -0
  66. package/lib/ui/types.cjs +1 -1
  67. package/lib/ui/types.d.ts +0 -1
  68. package/lib/ui/types.js.map +1 -0
  69. package/lib/ui/utils.cjs +1 -1
  70. package/lib/ui/utils.js.map +1 -0
  71. package/package.json +14 -22
  72. package/dist/ui-decorators.esm.cjs +0 -1519
@@ -1,1519 +0,0 @@
1
- import { ValidationKeys, ModelKeys, PasswordValidator, DateValidator, URLValidator, EmailValidator, GreaterThanOrEqualValidator, GreaterThanValidator, LessThanOrEqualValidator, LessThanValidator, DiffValidator, EqualsValidator, PatternValidator, MaxLengthValidator, MinLengthValidator, StepValidator, MaxValidator, MinValidator, RequiredValidator, formatDate, ReservedModels, parseDate, Model, propMetadata } from '@decaf-ts/decorator-validation';
2
- import { Reflection, metadata, apply } from '@decaf-ts/reflection';
3
- import { InternalError, findModelId, OperationKeys } from '@decaf-ts/db-decorators';
4
- import 'reflect-metadata';
5
-
6
- /**
7
- * @description Constants and enums for UI rendering and validation
8
- * @summary Defines keys, mappings, and HTML5 input types for UI components
9
- * This module provides constants used throughout the UI decorators library for
10
- * rendering, validation, and HTML element generation.
11
- * @module ui/constants
12
- * @memberOf module:ui-decorators
13
- */
14
- var UIMediaBreakPoints;
15
- (function (UIMediaBreakPoints) {
16
- UIMediaBreakPoints["SMALL"] = "s";
17
- UIMediaBreakPoints["MEDIUM"] = "m";
18
- UIMediaBreakPoints["LARGE"] = "l";
19
- UIMediaBreakPoints["XLARGE"] = "xl";
20
- })(UIMediaBreakPoints || (UIMediaBreakPoints = {}));
21
- /**
22
- * @description Key constants used for UI metadata and rendering
23
- * @summary Collection of string constants used as keys for UI-related metadata
24
- * These keys are used throughout the library to store and retrieve metadata related to
25
- * UI models, elements, properties, and validation rules.
26
- *
27
- * @typedef {Object} UIKeysType
28
- * @property {string} REFLECT - Base reflection key for UI metadata
29
- * @property {string} UIMODEL - Key for UI model metadata
30
- * @property {string} RENDERED_BY - Key for specifying rendering engine
31
- * @property {string} ELEMENT - Key for element metadata
32
- * @property {string} PROP - Key for property metadata
33
- * @property {string} NAME - Key for name attribute
34
- * @property {string} NAME_PREFIX - Prefix for input names
35
- * @property {string} CUSTOM_PROPS - Key for custom validation properties
36
- * @property {string} UILISTITEM - Key for list item metadata
37
- * @property {string} UILISTPROP - Key for list property metadata
38
- * @property {string} TYPE - Key for type metadata
39
- * @property {string} SUB_TYPE - Key for subtype metadata
40
- * @property {string} HIDDEN - Key for hidden attribute
41
- * @property {string} FORMAT - Key for format metadata
42
- * @property {string} READ_ONLY - Key for readonly attribute
43
- * @property {string} REQUIRED - Key for required validation
44
- * @property {string} MIN - Key for minimum value validation
45
- * @property {string} MIN_LENGTH - Key for minimum length validation
46
- * @property {string} MAX - Key for maximum value validation
47
- * @property {string} MAX_LENGTH - Key for maximum length validation
48
- * @property {string} PATTERN - Key for pattern validation
49
- * @property {string} URL - Key for URL validation
50
- * @property {string} STEP - Key for step validation
51
- * @property {string} DATE - Key for date validation
52
- * @property {string} EMAIL - Key for email validation
53
- * @property {string} PASSWORD - Key for password validation
54
- * @property {string} EQUALS - Key for equality validation
55
- * @property {string} DIFF - Key for difference validation
56
- * @property {string} LESS_THAN - Key for less than validation
57
- * @property {string} LESS_THAN_OR_EQUAL - Key for less than or equal validation
58
- * @property {string} GREATER_THAN - Key for greater than validation
59
- * @property {string} GREATER_THAN_OR_EQUAL - Key for greater than or equal validation
60
- *
61
- * @const UIKeys
62
- * @type {UIKeysType}
63
- * @readonly
64
- * @memberOf module:ui-decorators
65
- */
66
- const UIKeys = {
67
- REFLECT: `${ModelKeys.REFLECT}.ui.`,
68
- UIMODEL: "uimodel",
69
- RENDERED_BY: "rendered-by",
70
- ELEMENT: "element",
71
- PROP: "prop",
72
- CHILD: "child",
73
- NAME: "name",
74
- NAME_PREFIX: "input-",
75
- CUSTOM_PROPS: "customValidationProps",
76
- UILISTITEM: "uilistitem",
77
- UILISTPROP: "listprop",
78
- UILAYOUT: "uilayout",
79
- UILAYOUTITEM: "uilayoutitem",
80
- HANDLERS: "handlers",
81
- TYPE: "type",
82
- SUB_TYPE: "subtype",
83
- HIDDEN: "hidden",
84
- FORMAT: "format",
85
- ORDER: "order",
86
- READ_ONLY: "readonly",
87
- REQUIRED: ValidationKeys.REQUIRED,
88
- MIN: ValidationKeys.MIN,
89
- MIN_LENGTH: ValidationKeys.MIN_LENGTH,
90
- MAX: ValidationKeys.MAX,
91
- MAX_LENGTH: ValidationKeys.MAX_LENGTH,
92
- PATTERN: ValidationKeys.PATTERN,
93
- URL: ValidationKeys.URL,
94
- STEP: ValidationKeys.STEP,
95
- DATE: ValidationKeys.DATE,
96
- EMAIL: ValidationKeys.EMAIL,
97
- PASSWORD: ValidationKeys.PASSWORD,
98
- EQUALS: ValidationKeys.EQUALS,
99
- DIFF: ValidationKeys.DIFF,
100
- LESS_THAN: ValidationKeys.LESS_THAN,
101
- LESS_THAN_OR_EQUAL: ValidationKeys.LESS_THAN_OR_EQUAL,
102
- GREATER_THAN: ValidationKeys.GREATER_THAN,
103
- GREATER_THAN_OR_EQUAL: ValidationKeys.GREATER_THAN_OR_EQUAL,
104
- };
105
- /**
106
- * @description Mapping of input types to their corresponding validators
107
- * @summary Maps special input types to their validator classes
108
- * This constant maps input types like email, URL, date, and password to their
109
- * corresponding validator classes from the decorator-validation library.
110
- *
111
- * @typedef {Object.<string, Constructor<Validator>>} ValidatableByTypeMap
112
- * @property {Constructor<EmailValidator>} email - Validator for email inputs
113
- * @property {Constructor<URLValidator>} url - Validator for URL inputs
114
- * @property {Constructor<DateValidator>} date - Validator for date inputs
115
- * @property {Constructor<PasswordValidator>} password - Validator for password inputs
116
- *
117
- * @const ValidatableByType
118
- * @type {ValidatableByTypeMap}
119
- * @readonly
120
- * @memberOf module:ui-decorators
121
- */
122
- const ValidatableByType = {
123
- [UIKeys.EMAIL]: EmailValidator,
124
- [UIKeys.URL]: URLValidator,
125
- [UIKeys.DATE]: DateValidator,
126
- [UIKeys.PASSWORD]: PasswordValidator,
127
- };
128
- /**
129
- * @description Mapping of validation attributes to their corresponding validators
130
- * @summary Maps HTML validation attributes to their validator classes
131
- * This constant maps HTML validation attributes like required, min, max, pattern, etc.
132
- * to their corresponding validator classes from the decorator-validation library.
133
- *
134
- * @typedef {Object.<string, Constructor<Validator>>} ValidatableByAttributeMap
135
- * @property {Constructor<RequiredValidator>} required - Validator for required fields
136
- * @property {Constructor<MinValidator>} min - Validator for minimum value
137
- * @property {Constructor<MaxValidator>} max - Validator for maximum value
138
- * @property {Constructor<StepValidator>} step - Validator for step value
139
- * @property {Constructor<MinLengthValidator>} minlength - Validator for minimum length
140
- * @property {Constructor<MaxLengthValidator>} maxlength - Validator for maximum length
141
- * @property {Constructor<PatternValidator>} pattern - Validator for regex pattern
142
- * @property {Constructor<EqualsValidator>} equals - Validator for equality
143
- * @property {Constructor<DiffValidator>} diff - Validator for difference
144
- * @property {Constructor<LessThanValidator>} lessthan - Validator for less than comparison
145
- * @property {Constructor<LessThanOrEqualValidator>} lessthanorequal - Validator for less than or equal comparison
146
- * @property {Constructor<GreaterThanValidator>} greaterthan - Validator for greater than comparison
147
- * @property {Constructor<GreaterThanOrEqualValidator>} greaterthanorequal - Validator for greater than or equal comparison
148
- *
149
- * @const ValidatableByAttribute
150
- * @type {ValidatableByAttributeMap}
151
- * @readonly
152
- * @memberOf module:ui-decorators
153
- */
154
- const ValidatableByAttribute = {
155
- [UIKeys.REQUIRED]: RequiredValidator,
156
- [UIKeys.MIN]: MinValidator,
157
- [UIKeys.MAX]: MaxValidator,
158
- [UIKeys.STEP]: StepValidator,
159
- [UIKeys.MIN_LENGTH]: MinLengthValidator,
160
- [UIKeys.MAX_LENGTH]: MaxLengthValidator,
161
- [UIKeys.PATTERN]: PatternValidator,
162
- [UIKeys.EQUALS]: EqualsValidator,
163
- [UIKeys.DIFF]: DiffValidator,
164
- [UIKeys.LESS_THAN]: LessThanValidator,
165
- [UIKeys.LESS_THAN_OR_EQUAL]: LessThanOrEqualValidator,
166
- [UIKeys.GREATER_THAN]: GreaterThanValidator,
167
- [UIKeys.GREATER_THAN_OR_EQUAL]: GreaterThanOrEqualValidator,
168
- };
169
- /**
170
- * @description Standard date format string for HTML5 date inputs
171
- * @summary Format string for HTML5 date inputs (yyyy-MM-dd)
172
- * This constant defines the standard date format string used for HTML5 date inputs.
173
- *
174
- * @const HTML5DateFormat
175
- * @type {string}
176
- * @readonly
177
- * @memberOf module:ui-decorators
178
- */
179
- const HTML5DateFormat = "yyyy-MM-dd";
180
- /**
181
- * @description Collection of HTML5 input type values
182
- * @summary Maps input type constants to their HTML attribute values
183
- * This constant provides a mapping of input type constants to their corresponding
184
- * HTML attribute values for use in form elements.
185
- *
186
- * @typedef {Object} HTML5InputTypesMap
187
- * @property {string} BUTTON - Button input type
188
- * @property {string} CHECKBOX - Checkbox input type
189
- * @property {string} COLOR - Color picker input type
190
- * @property {string} DATE - Date picker input type
191
- * @property {string} DATETIME_LOCAL - Local datetime picker input type
192
- * @property {string} EMAIL - Email input type with validation
193
- * @property {string} FILE - File upload input type
194
- * @property {string} HIDDEN - Hidden input type
195
- * @property {string} IMAGE - Image input type
196
- * @property {string} MONTH - Month picker input type
197
- * @property {string} NUMBER - Numeric input type
198
- * @property {string} PASSWORD - Password input type with masked text
199
- * @property {string} RADIO - Radio button input type
200
- * @property {string} RANGE - Range slider input type
201
- * @property {string} RESET - Form reset button input type
202
- * @property {string} SEARCH - Search input type
203
- * @property {string} SUBMIT - Form submit button input type
204
- * @property {string} TEL - Telephone number input type
205
- * @property {string} TEXT - Basic text input type
206
- * @property {string} TIME - Time picker input type
207
- * @property {string} URL - URL input type with validation
208
- * @property {string} WEEK - Week picker input type
209
- *
210
- * @const HTML5InputTypes
211
- * @type {HTML5InputTypesMap}
212
- * @readonly
213
- * @memberOf module:ui-decorators
214
- */
215
- const HTML5InputTypes = {
216
- BUTTON: "button",
217
- CHECKBOX: "checkbox",
218
- COLOR: "color",
219
- DATE: UIKeys.DATE,
220
- DATETIME_LOCAL: "datetime-local",
221
- EMAIL: UIKeys.EMAIL,
222
- FILE: "file",
223
- HIDDEN: "hidden",
224
- IMAGE: "image",
225
- MONTH: "month",
226
- NUMBER: "number",
227
- PASSWORD: UIKeys.PASSWORD,
228
- RADIO: "radio",
229
- RANGE: "range",
230
- RESET: "reset",
231
- SEARCH: "search",
232
- SUBMIT: "submit",
233
- TEL: "tel",
234
- TEXT: "text",
235
- TEXTAREA: 'textarea',
236
- SELECT: 'select',
237
- TIME: "time",
238
- URL: UIKeys.URL,
239
- WEEK: "week",
240
- };
241
- /**
242
- * @description Array of HTML5 input types that use checkboxes
243
- * @summary List of input types that represent checkable controls
244
- * This constant defines an array of HTML5 input types that represent
245
- * checkable controls (checkbox and radio).
246
- *
247
- * @const HTML5CheckTypes
248
- * @type {string[]}
249
- * @readonly
250
- * @memberOf module:ui-decorators
251
- */
252
- const HTML5CheckTypes = [
253
- HTML5InputTypes.CHECKBOX,
254
- HTML5InputTypes.RADIO,
255
- ];
256
-
257
- /**
258
- * @description Error thrown when a rendering operation fails
259
- * @summary Specialized error for rendering failures in UI components
260
- * This error is thrown when the rendering engine encounters an error while
261
- * attempting to render a UI component or model.
262
- *
263
- * @param {string|Error} msg The error message or original error
264
- *
265
- * @class RenderingError
266
- * @extends BaseError
267
- * @category Errors
268
- *
269
- * @example
270
- * // Throwing a rendering error
271
- * try {
272
- * // Rendering code that might fail
273
- * if (!component.canRender()) {
274
- * throw new RenderingError('Component cannot be rendered');
275
- * }
276
- * } catch (error) {
277
- * console.error('Rendering failed:', error.message);
278
- * }
279
- */
280
- class RenderingError extends InternalError {
281
- /**
282
- * @description Creates a new RenderingError instance
283
- * @summary Initializes the error with a message or original error
284
- * @param {string|Error} msg The error message or original error
285
- */
286
- constructor(msg) {
287
- super(msg, RenderingError.name);
288
- }
289
- }
290
-
291
- /**
292
- * @function formatByType
293
- *
294
- * @memberOf module:ui-decorators
295
- */
296
- function formatByType(type, value, ...args) {
297
- if (type === UIKeys.DATE) {
298
- if (!value)
299
- return "";
300
- const format = args.shift() || HTML5DateFormat;
301
- return formatDate(new Date(value), format);
302
- }
303
- return value;
304
- }
305
- function parseValueByType(type, value, fieldProps) {
306
- let result = undefined;
307
- switch (type) {
308
- case Array.name: {
309
- const parsed = Array.isArray(value) ? value.map(v => parseValueByType(ReservedModels.STRING, v, fieldProps)) : [value];
310
- result = parsed.join(",");
311
- break;
312
- }
313
- case HTML5InputTypes.NUMBER:
314
- result = parseToNumber(value);
315
- break;
316
- case HTML5InputTypes.DATE: {
317
- const format = fieldProps.format;
318
- if (value && `${value}`.trim().length) {
319
- result =
320
- typeof value === ReservedModels.NUMBER
321
- ? new Date(value)
322
- : value
323
- ? format
324
- ? parseDate(format, value)
325
- : new Date(value)
326
- : undefined;
327
- }
328
- break;
329
- }
330
- default:
331
- result =
332
- typeof value === ReservedModels.OBJECT ?
333
- (Array.isArray(value) ? value.join(",") : JSON.stringify(value)) :
334
- typeof value === ReservedModels.BOOLEAN ?
335
- value : typeof value === ReservedModels.STRING ?
336
- escapeHtml(value) : result;
337
- }
338
- if (typeof result === "undefined") {
339
- throw new InternalError(`Failed to parse value of type ${type} from ${typeof value} - ${value}`);
340
- }
341
- return result;
342
- }
343
- function parseToNumber(value) {
344
- if (typeof value === "number" && !isNaN(value))
345
- return value;
346
- const parsed = Number(value);
347
- if (!isNaN(parsed))
348
- return parsed;
349
- return undefined;
350
- }
351
- function escapeHtml(value) {
352
- if (!value)
353
- return value;
354
- const tagsToReplace = {
355
- "&": "&amp;",
356
- "<": "&lt;",
357
- ">": "&gt;",
358
- };
359
- return `${value}`.replace(/[&<>]/g, (tag) => {
360
- return tagsToReplace[tag] || tag;
361
- });
362
- }
363
- function revertHtml(value) {
364
- const tagsToReplace = {
365
- "&amp;": "&",
366
- "&lt;": "<",
367
- "&gt;": ">",
368
- };
369
- return `${value}`.replace(/&lt;|&gt;|&amp;/g, (tag) => {
370
- return tagsToReplace[tag] || tag;
371
- });
372
- }
373
- function generateUIModelID(model) {
374
- let id;
375
- try {
376
- id = findModelId(model);
377
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
378
- }
379
- catch (e) {
380
- id = Date.now();
381
- }
382
- const name = model.constructor.name;
383
- return `${name}-${id}`;
384
- }
385
-
386
- /**
387
- * @description Abstract class for rendering UI components based on model metadata.
388
- * @summary The RenderingEngine class provides a framework for converting model metadata into UI field definitions.
389
- * It handles the translation of model properties to UI elements, applies validation rules, and manages different rendering flavors.
390
- * This class is designed to be extended by specific rendering implementations.
391
- *
392
- * @template T The type of the rendering result, defaults to void
393
- * @template R The type of the field definition, defaults to FieldDefinition<T>
394
- *
395
- * @param {string} flavour - The flavor of the rendering engine.
396
- *
397
- * @class RenderingEngine
398
- */
399
- class RenderingEngine {
400
- /**
401
- * @description Cache for storing rendering engine instances or constructors.
402
- * @private
403
- * @static
404
- */
405
- static { this.cache = {}; }
406
- constructor(flavour) {
407
- this.flavour = flavour;
408
- /**
409
- * Flag indicating whether the rendering engine has been initialized.
410
- */
411
- this.initialized = false;
412
- RenderingEngine.register(this);
413
- console.log(`decaf's ${flavour} rendering engine loaded`);
414
- }
415
- /**
416
- * @description Translates between model types and HTML input types.
417
- * @summary Converts model data types to appropriate HTML input types and vice versa.
418
- *
419
- * @param {string} key - The key to translate.
420
- * @param {boolean} [toView=true] - Direction of translation (true for model to view, false for view to model).
421
- * @returns {string} The translated type.
422
- */
423
- translate(key, toView = true) {
424
- if (toView) {
425
- switch (key) {
426
- case ReservedModels.STRING:
427
- return HTML5InputTypes.TEXT;
428
- case ReservedModels.NUMBER:
429
- case ReservedModels.BIGINT:
430
- return HTML5InputTypes.NUMBER;
431
- case ReservedModels.BOOLEAN:
432
- return HTML5InputTypes.CHECKBOX;
433
- case ReservedModels.DATE:
434
- return HTML5InputTypes.DATE;
435
- }
436
- }
437
- else {
438
- switch (key) {
439
- case HTML5InputTypes.SELECT:
440
- case HTML5InputTypes.TEXT:
441
- case HTML5InputTypes.EMAIL:
442
- case HTML5InputTypes.COLOR:
443
- case HTML5InputTypes.PASSWORD:
444
- case HTML5InputTypes.TEL:
445
- case HTML5InputTypes.URL:
446
- case HTML5InputTypes.SEARCH:
447
- case HTML5InputTypes.HIDDEN:
448
- case HTML5InputTypes.TEXTAREA:
449
- case HTML5InputTypes.RADIO:
450
- return ReservedModels.STRING;
451
- case HTML5InputTypes.NUMBER:
452
- return ReservedModels.NUMBER;
453
- case HTML5InputTypes.CHECKBOX:
454
- return ReservedModels.BOOLEAN;
455
- case HTML5InputTypes.DATE:
456
- case HTML5InputTypes.DATETIME_LOCAL:
457
- case HTML5InputTypes.TIME:
458
- return ReservedModels.DATE;
459
- }
460
- }
461
- return key;
462
- }
463
- /**
464
- * @description Retrieves class decorator metadata for a model instance
465
- * @summary Extracts UI-related class decorators from a model and returns them as an array
466
- * This method collects metadata from various UI class decorators including @uimodel,
467
- * @uilistitem, @uihandlers, and @uilayout applied to the model class.
468
- *
469
- * @template M Type extending Model
470
- * @param {M} model - The model instance to extract metadata from
471
- * @returns {UIClassMetadata[]} Array of UI class metadata objects
472
- *
473
- * @private
474
- */
475
- getClassDecoratorsMetadata(model) {
476
- return [
477
- Reflect.getMetadata(RenderingEngine.key(UIKeys.UIMODEL), model.constructor) ||
478
- Reflect.getMetadata(RenderingEngine.key(UIKeys.UIMODEL), Model.get(model.constructor.name)),
479
- Reflect.getMetadata(RenderingEngine.key(UIKeys.UILISTITEM), model.constructor) ||
480
- Reflect.getMetadata(RenderingEngine.key(UIKeys.UILISTITEM), Model.get(model.constructor.name)),
481
- Reflect.getMetadata(RenderingEngine.key(UIKeys.HANDLERS), model.constructor) ||
482
- Reflect.getMetadata(RenderingEngine.key(UIKeys.HANDLERS), Model.get(model.constructor.name)),
483
- Reflect.getMetadata(RenderingEngine.key(UIKeys.UILAYOUT), model.constructor) ||
484
- Reflect.getMetadata(RenderingEngine.key(UIKeys.UILAYOUT), Model.get(model.constructor.name)),
485
- ].filter(Boolean);
486
- }
487
- /**
488
- * @description Checks if a type is validatable by its nature.
489
- * @summary Determines if a given UI key represents a type that is inherently validatable.
490
- *
491
- * @param {string} key - The UI key to check.
492
- * @returns {boolean} True if the type is validatable, false otherwise.
493
- */
494
- isValidatableByType(key) {
495
- return Object.keys(ValidatableByType).includes(key);
496
- }
497
- /**
498
- * @description Checks if a type is validatable by attribute.
499
- * @summary Determines if a given UI key represents a validation that can be applied as an attribute.
500
- *
501
- * @param {string} key - The UI key to check.
502
- * @returns {boolean} True if the type is validatable by attribute, false otherwise.
503
- */
504
- isValidatableByAttribute(key) {
505
- return Object.keys(ValidatableByAttribute).includes(key);
506
- }
507
- /**
508
- * @description Converts validation metadata to an attribute value.
509
- * @summary Transforms validation metadata into a value suitable for use as an HTML attribute.
510
- *
511
- * @param {string} key - The validation key.
512
- * @param {ValidationMetadata} value - The validation metadata.
513
- * @returns {string | number | boolean} The converted attribute value.
514
- * @throws {Error} If the given key is not validatable by attribute.
515
- */
516
- toAttributeValue(key, value) {
517
- if (!Object.keys(ValidatableByAttribute).includes(key))
518
- throw new Error(`Invalid attribute key "${key}". Expected one of: ${Object.keys(ValidatableByAttribute).join(", ")}.`);
519
- return key === UIKeys.REQUIRED ? true : value[key];
520
- }
521
- /**
522
- * @description Converts a model to a field definition.
523
- * @summary Processes a model instance, extracting UI-related metadata and validation rules to create a field definition.
524
- *
525
- * @template M Type extending Model
526
- * @template T Type referencing the specific Rendering engine field properties/inputs
527
- * @param {M} model - The model instance to convert.
528
- * @param {Record<string, unknown>} [globalProps={}] - Global properties to apply to all child elements.
529
- * @param {boolean} [generateId=true] - Flag indicating whether to populate the rendererId property.
530
- * @returns {FieldDefinition<T>} A field definition object representing the UI structure of the model.
531
- * @throws {RenderingError} If no UI definitions are set for the model or if there are invalid decorators.
532
- *
533
- * @mermaid
534
- * sequenceDiagram
535
- * participant C as Client
536
- * participant RE as RenderingEngine
537
- * participant R as Reflection
538
- * participant M as Model
539
- * C->>RE: toFieldDefinition(model, globalProps)
540
- * RE->>R: getMetadata(UIKeys.UIMODEL, model.constructor)
541
- * R-->>RE: UIModelMetadata
542
- * RE->>R: getAllPropertyDecorators(model, UIKeys.REFLECT)
543
- * R-->>RE: Record<string, DecoratorMetadata[]>
544
- * RE->>R: getAllPropertyDecorators(model, ValidationKeys.REFLECT)
545
- * R-->>RE: Record<string, DecoratorMetadata<ValidationMetadata>[]>
546
- * loop For each property
547
- * RE->>RE: Process UI decorators
548
- * RE->>RE: Apply validation rules
549
- * end
550
- * RE-->>C: FieldDefinition<T>
551
- */
552
- toFieldDefinition(model, globalProps = {}, generateId = true) {
553
- const { inheritProps, ...globalPropsWithoutInherits } = globalProps;
554
- globalProps = globalPropsWithoutInherits;
555
- const classDecorators = this.getClassDecoratorsMetadata(model);
556
- if (!classDecorators.length)
557
- throw new RenderingError(`No ui definitions set for model ${model.constructor.name}. Did you use @uimodel?`);
558
- const classDecorator = Object.assign({}, ...classDecorators, inheritProps ? inheritProps : {} // override tag and properties when it is a component that should inherit properties from its parent.
559
- );
560
- const { tag, props, item, handlers } = classDecorator;
561
- const uiDecorators = Reflection.getAllPropertyDecorators(model, UIKeys.REFLECT);
562
- let children;
563
- let childProps = item?.props || {};
564
- let mapper = {};
565
- const getPath = (parent, prop) => {
566
- return parent ? [parent, prop].join(".") : prop;
567
- };
568
- if (uiDecorators) {
569
- const validationDecorators = Reflection.getAllPropertyDecorators(model, ValidationKeys.REFLECT);
570
- for (const key in uiDecorators) {
571
- const decs = uiDecorators[key];
572
- const types = Object.values(decs).filter(({ key }) => [UIKeys.PROP, UIKeys.ELEMENT, UIKeys.CHILD].includes(key));
573
- if (types?.length > 1)
574
- throw new RenderingError(`Only one type of decoration is allowed. Please choose between @uiprop, @uichild or @uielement`);
575
- const hasHideOnDecorator = decs.find(({ key }) => key === UIKeys.HIDDEN);
576
- if (hasHideOnDecorator) {
577
- const hasUiElementDecorator = decs.find(({ key }) => key === UIKeys.ELEMENT);
578
- if (!hasUiElementDecorator)
579
- throw new RenderingError(`@uielement no found in "${key}". It is required to use hiddenOn decorator.`);
580
- }
581
- decs.shift();
582
- const sorted = decs.sort((a) => {
583
- return a.key === UIKeys.ELEMENT ? -1 : 1;
584
- });
585
- sorted.forEach((dec) => {
586
- if (!dec)
587
- throw new RenderingError(`No decorator found`);
588
- switch (dec.key) {
589
- case UIKeys.PROP: {
590
- childProps[key] = dec.props;
591
- break;
592
- }
593
- case UIKeys.CHILD: {
594
- if (!Model.isPropertyModel(model, key))
595
- throw new RenderingError(`Child "${key}" must be a model.`);
596
- let Clazz;
597
- const submodel = model[key];
598
- const constructable = typeof submodel === "object" &&
599
- submodel !== null &&
600
- !Array.isArray(submodel);
601
- // create instance if undefined
602
- if (!constructable) {
603
- const clazzName = dec.props.props
604
- ?.name;
605
- Clazz = new (Model.get(clazzName))();
606
- }
607
- children = children || [];
608
- const childrenGlobalProps = Object.assign({}, globalProps || {}, { "model": Clazz }, {
609
- inheritProps: dec.props,
610
- childOf: getPath(globalProps?.childOf, key),
611
- });
612
- const childDefinition = this.toFieldDefinition(submodel || Clazz, // Must avoid undefined values — an instance is required to retrieve properties.
613
- childrenGlobalProps, false);
614
- children.push(childDefinition);
615
- break;
616
- }
617
- case UIKeys.UILISTPROP: {
618
- mapper = mapper || {};
619
- if (dec.props?.name)
620
- mapper[dec.props?.name] = key;
621
- const props = Object.assign({}, classDecorator.props?.item || {}, item?.props || {}, dec.props?.props || {}, globalProps);
622
- childProps = {
623
- tag: item?.tag || props.render || "",
624
- props: Object.assign({}, childProps?.props, { mapper }, props),
625
- };
626
- break;
627
- }
628
- case UIKeys.HIDDEN:
629
- case UIKeys.ORDER:
630
- case UIKeys.UILAYOUTITEM:
631
- case UIKeys.ELEMENT: {
632
- children = children || [];
633
- const uiProps = dec.props;
634
- const props = Object.assign({}, childProps?.props, uiProps.props || {}, (uiProps?.props?.name ? {
635
- path: getPath(globalProps?.childOf, uiProps.props.name),
636
- childOf: undefined, // The childOf prop is passed by globalProps when it is a nested prop
637
- } : {}), globalProps);
638
- const childDefinition = {
639
- tag: uiProps.tag || childProps?.tag || tag || "",
640
- props,
641
- };
642
- if (dec.key === UIKeys.ELEMENT) {
643
- const validationDecs = validationDecorators[key];
644
- const typeDec = validationDecs.shift();
645
- for (const dec of validationDecs) {
646
- if (this.isValidatableByAttribute(dec.key)) {
647
- childDefinition.props[this.translate(dec.key)] = this.toAttributeValue(dec.key, dec.props);
648
- continue;
649
- }
650
- if (this.isValidatableByType(dec.key)) {
651
- if (dec.key === HTML5InputTypes.DATE) {
652
- childDefinition.props[UIKeys.FORMAT] = dec.props.format || HTML5DateFormat;
653
- }
654
- childDefinition.props[UIKeys.TYPE] = dec.key;
655
- continue;
656
- }
657
- }
658
- if (!childDefinition.props[UIKeys.TYPE]) {
659
- const basicType = typeDec.props.name;
660
- childDefinition.props[UIKeys.TYPE] = this.translate(basicType.toLowerCase(), true);
661
- }
662
- childDefinition.props.value = formatByType(childDefinition.props[UIKeys.TYPE], model[key], childDefinition.props[UIKeys.FORMAT]);
663
- children.push(childDefinition);
664
- }
665
- else {
666
- const child = children.find(c => c.props?.name === key || dec.key === UIKeys.UILAYOUTITEM && c?.props?.childOf === key);
667
- if (child) {
668
- if (dec.key !== UIKeys.UILAYOUTITEM) {
669
- child.props = Object.assign({}, child.props, { [dec.key]: uiProps });
670
- }
671
- else {
672
- const { row, col, props } = dec.props;
673
- child.props = Object.assign({}, props || {}, child.props, row, col);
674
- }
675
- }
676
- else {
677
- children.push(childDefinition);
678
- }
679
- }
680
- break;
681
- }
682
- default:
683
- throw new RenderingError(`Invalid key: ${dec.key}`);
684
- }
685
- });
686
- }
687
- }
688
- globalProps = Object.assign({}, props, globalProps, {
689
- handlers: handlers || {},
690
- });
691
- const operation = globalProps?.operation;
692
- children = children?.sort((a, b) => ((a?.props?.order ?? 0) - (b?.props?.order ?? 0)))
693
- .filter((item) => {
694
- const hiddenOn = (item?.props?.hidden || []);
695
- if (!hiddenOn?.length)
696
- return item;
697
- if (!hiddenOn.includes(operation))
698
- return item;
699
- });
700
- const result = {
701
- tag: tag,
702
- item: childProps,
703
- props: globalProps,
704
- children: children,
705
- };
706
- if (generateId)
707
- result.rendererId = generateUIModelID(model);
708
- return result;
709
- }
710
- /**
711
- * @description Registers a rendering engine instance.
712
- * @summary Adds a rendering engine to the static cache and sets it as the current engine.
713
- *
714
- * @param {RenderingEngine<unknown, unknown>} engine - The rendering engine to register.
715
- * @throws {InternalError} If an engine with the same flavor already exists.
716
- *
717
- * @static
718
- */
719
- static register(engine) {
720
- if (engine.flavour in this.cache)
721
- throw new InternalError(`Rendering engine under ${engine.flavour} already exists`);
722
- this.cache[engine.flavour] = engine;
723
- this.current = engine;
724
- }
725
- /**
726
- * @description Retrieves or initializes a rendering engine.
727
- * @summary Gets an existing engine instance or creates and initializes a new one if given a constructor.
728
- *
729
- * @template O The type of the rendering engine output
730
- * @param {Constructor<RenderingEngine<O>> | RenderingEngine<O>} obj - The engine instance or constructor.
731
- * @returns {RenderingEngine<O>} The initialized rendering engine.
732
- *
733
- * @private
734
- * @static
735
- */
736
- static getOrBoot(obj) {
737
- if (obj instanceof RenderingEngine)
738
- return obj;
739
- const engine = new obj();
740
- engine.initialize(); // make the booting async. use the initialized flag to control it
741
- return engine;
742
- }
743
- /**
744
- * @description Retrieves a rendering engine by flavor.
745
- * @summary Gets the current rendering engine or a specific one by flavor.
746
- *
747
- * @template O The type of the rendering engine output
748
- * @param {string} [flavour] - The flavor of the rendering engine to retrieve.
749
- * @returns {RenderingEngine<O>} The requested rendering engine.
750
- * @throws {InternalError} If the requested flavor does not exist.
751
- *
752
- * @static
753
- */
754
- static get(flavour) {
755
- if (!flavour)
756
- return this.getOrBoot(this.current);
757
- if (!(flavour in this.cache))
758
- throw new InternalError(`Rendering engine under ${flavour} does not exist`);
759
- return this.getOrBoot(this.cache[flavour]);
760
- }
761
- /**
762
- * @description Renders a model using the appropriate rendering engine.
763
- * @summary Determines the correct rendering engine for a model and invokes its render method.
764
- *
765
- * @template M Type extending Model
766
- * @param {M} model - The model to render.
767
- * @param {...any[]} args - Additional arguments to pass to the render method.
768
- * @returns {any} The result of the rendering process.
769
- * @throws {InternalError} If no registered model is found.
770
- *
771
- * @static
772
- */
773
- static render(model, ...args) {
774
- const constructor = Model.get(model.constructor.name) || Model.fromObject(model);
775
- if (!constructor)
776
- throw new InternalError("No model registered found");
777
- const flavour = Reflect.getMetadata(RenderingEngine.key(UIKeys.RENDERED_BY), constructor);
778
- // @ts-expect-error for the var args type check
779
- return RenderingEngine.get(flavour).render(model, ...args);
780
- }
781
- /**
782
- * @description Generates a metadata key for UI-related properties.
783
- * @summary Prefixes a given key with the UI reflection prefix.
784
- *
785
- * @param {string} key - The key to prefix.
786
- * @returns {string} The prefixed key.
787
- *
788
- * @static
789
- */
790
- static key(key) {
791
- return `${UIKeys.REFLECT}${key}`;
792
- }
793
- }
794
-
795
- /**
796
- * @description Decorator that tags a class as a UI model
797
- * @summary Adds rendering capabilities to a model class by providing a render method
798
- * This decorator applies metadata to the class that enables it to be rendered by the UI rendering engine.
799
- * The model will be rendered with the specified tag and properties.
800
- *
801
- * @param {string} [tag] The HTML tag to use when rendering this model (defaults to class name)
802
- * @param {Record<string, any>} [props] Additional properties to pass to the rendered element
803
- * @return {Function} A class decorator function
804
- *
805
- * @function uimodel
806
- * @category Class Decorators
807
- *
808
- * @example
809
- * // Basic usage with default tag (class name)
810
- * @uimodel()
811
- * class UserProfile extends Model {
812
- * @attribute()
813
- * name: string;
814
- *
815
- * @attribute()
816
- * email: string;
817
- * }
818
- *
819
- * // Usage with custom tag and properties
820
- * @uimodel('div', { class: 'user-card' })
821
- * class UserCard extends Model {
822
- * @attribute()
823
- * username: string;
824
- * }
825
- *
826
- * @mermaid
827
- * sequenceDiagram
828
- * participant System
829
- * participant uimodel
830
- * participant constructor
831
- * participant instance
832
- * System->>uimodel:do(constructor)
833
- * uimodel->>constructor: Executes the constructor
834
- * constructor->>uimodel: returns instance
835
- * uimodel->>instance: adds the render method
836
- * uimodel->>System: returns UIModel instance
837
- */
838
- function uimodel(tag, props) {
839
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
840
- return (original, propertyKey) => {
841
- const meta = {
842
- tag: tag || original.name,
843
- props: props,
844
- };
845
- return metadata(RenderingEngine.key(UIKeys.UIMODEL), meta)(original);
846
- };
847
- }
848
- /**
849
- * @description Decorator that specifies which rendering engine to use for a model
850
- * @summary Associates a model with a specific rendering engine implementation
851
- * This decorator allows you to override the default rendering engine for a specific model class,
852
- * enabling different rendering strategies for different models.
853
- *
854
- * @param {string} engine The name of the rendering engine to use
855
- * @return {Function} A class decorator function
856
- *
857
- * @function renderedBy
858
- * @category Class Decorators
859
- *
860
- * @example
861
- * // Specify a custom rendering engine for a model
862
- * @uimodel()
863
- * @renderedBy('react')
864
- * class ReactComponent extends Model {
865
- * @attribute()
866
- * title: string;
867
- * }
868
- *
869
- * @mermaid
870
- * sequenceDiagram
871
- * participant System
872
- * participant renderedBy
873
- * participant Model
874
- * participant RenderingEngine
875
- * System->>renderedBy: apply to Model
876
- * renderedBy->>Model: adds engine metadata
877
- * Model->>RenderingEngine: uses specified engine
878
- * RenderingEngine->>System: renders with custom engine
879
- */
880
- function renderedBy(engine) {
881
- return apply(metadata(RenderingEngine.key(UIKeys.RENDERED_BY), engine));
882
- }
883
- /**
884
- * @description Decorator that tags a model as a list item for UI rendering
885
- * @summary Specifies how a model should be rendered when displayed in a list context
886
- * This decorator applies metadata to the class that enables it to be rendered as a list item
887
- * by the UI rendering engine. The model will be rendered with the specified tag and properties
888
- * when it appears in a list.
889
- *
890
- * @param {string} [tag] The HTML tag to use when rendering this model as a list item (defaults to class name)
891
- * @param {Record<string, any>} [props] Additional properties to pass to the rendered list item element
892
- * @return {Function} A class decorator function
893
- *
894
- * @function uilistitem
895
- * @category Class Decorators
896
- *
897
- * @example
898
- * // Basic usage with default tag (class name)
899
- * @uimodel()
900
- * @uilistitem()
901
- * class TodoItem extends Model {
902
- * @attribute()
903
- * title: string;
904
- *
905
- * @attribute()
906
- * completed: boolean;
907
- * }
908
- *
909
- * // Usage with custom tag and properties
910
- * @uimodel()
911
- * @uilistitem('li', { class: 'list-group-item' })
912
- * class ListItem extends Model {
913
- * @attribute()
914
- * text: string;
915
- * }
916
- *
917
- * @mermaid
918
- * sequenceDiagram
919
- * participant System
920
- * participant uilistitem
921
- * participant Model
922
- * participant RenderingEngine
923
- * System->>uilistitem: apply to Model
924
- * uilistitem->>Model: adds list item metadata
925
- * Model->>RenderingEngine: uses list item metadata when in list context
926
- * RenderingEngine->>System: renders with list item styling
927
- */
928
- function uilistitem(tag, props) {
929
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
930
- return (original, propertyKey) => {
931
- const meta = {
932
- item: {
933
- tag: tag || original.name,
934
- props: props,
935
- },
936
- };
937
- return metadata(RenderingEngine.key(UIKeys.UILISTITEM), meta)(original);
938
- };
939
- }
940
- /**
941
- * @description Decorator that adds event handlers to a UI model
942
- * @summary Specifies event handlers that should be attached to the rendered model
943
- * This decorator allows you to define event handlers that will be automatically
944
- * attached to the rendered UI element. The handlers are passed as properties
945
- * to the rendering engine.
946
- *
947
- * @param {Record<string, any>} [props] Object containing event handler functions and other properties
948
- * @return {Function} A class decorator function
949
- *
950
- * @function uihandlers
951
- * @category Class Decorators
952
- *
953
- * @example
954
- * // Add event handlers to a model
955
- * @uimodel('button')
956
- * @uihandlers({
957
- * onClick: (event) => console.log('Button clicked'),
958
- * onMouseOver: (event) => console.log('Mouse over button'),
959
- * disabled: false
960
- * })
961
- * class ClickableButton extends Model {
962
- * @attribute()
963
- * label: string;
964
- * }
965
- *
966
- * // Add form submission handlers
967
- * @uimodel('form')
968
- * @uihandlers({
969
- * onSubmit: (event) => {
970
- * event.preventDefault();
971
- * console.log('Form submitted');
972
- * },
973
- * onReset: (event) => console.log('Form reset')
974
- * })
975
- * class ContactForm extends Model {
976
- * @attribute()
977
- * email: string;
978
- * }
979
- *
980
- * @mermaid
981
- * sequenceDiagram
982
- * participant System
983
- * participant uihandlers
984
- * participant Model
985
- * participant RenderingEngine
986
- * participant UI
987
- * System->>uihandlers: apply to Model
988
- * uihandlers->>Model: adds handler metadata
989
- * Model->>RenderingEngine: requests rendering with handlers
990
- * RenderingEngine->>UI: renders element with event handlers attached
991
- * UI->>Model: triggers handlers on events
992
- */
993
- function uihandlers(props) {
994
- return (original) => {
995
- const meta = {
996
- handlers: props
997
- };
998
- return metadata(RenderingEngine.key(UIKeys.HANDLERS), meta)(original);
999
- };
1000
- }
1001
- /**
1002
- * @description Decorator that creates a layout container with grid specifications
1003
- * @summary Combines UI model functionality with layout grid configuration
1004
- * This decorator creates a UI model that acts as a layout container with specified
1005
- * column and row configurations. It's a convenience decorator that combines
1006
- * @uimodel with layout-specific properties for responsive grid layouts.
1007
- *
1008
- * @param {string} tag The HTML tag to use for the layout container
1009
- * @param {number} [cols=1] Number of columns in the grid layout
1010
- * @param {number|string[]} [rows=1] Number of rows or array of row definitions
1011
- * @param {UIMediaBreakPoints} [breakpoint='m'] Media breakpoint for responsive behavior
1012
- * @return {Function} A class decorator function
1013
- *
1014
- * @function uilayout
1015
- * @category Class Decorators
1016
- *
1017
- * @example
1018
- * // Create a simple 2-column layout
1019
- * @uilayout('div', 2, 3)
1020
- * class TwoColumnLayout extends Model {
1021
- * @attribute()
1022
- * @uilayoutitem(1, 1)
1023
- * header: string;
1024
- *
1025
- * @attribute()
1026
- * @uilayoutitem(1, 2)
1027
- * leftContent: string;
1028
- *
1029
- * @attribute()
1030
- * @uilayoutitem(2, 2)
1031
- * rightContent: string;
1032
- * }
1033
- *
1034
- * // Create a responsive layout with custom breakpoint
1035
- * @uilayout('section', 3, 2, 'l')
1036
- * class ResponsiveLayout extends Model {
1037
- * @attribute()
1038
- * @uilayoutitem(1, 1)
1039
- * title: string;
1040
- *
1041
- * @attribute()
1042
- * @uilayoutitem(2, 1)
1043
- * subtitle: string;
1044
- * }
1045
- *
1046
- * @mermaid
1047
- * sequenceDiagram
1048
- * participant System
1049
- * participant uilayout
1050
- * participant uimodel
1051
- * participant Model
1052
- * participant RenderingEngine
1053
- * System->>uilayout: apply to Model
1054
- * uilayout->>uimodel: call with layout props
1055
- * uimodel->>Model: adds model metadata with layout config
1056
- * Model->>RenderingEngine: requests rendering as layout container
1057
- * RenderingEngine->>System: renders grid layout with specified dimensions
1058
- */
1059
- function uilayout(tag, cols = 1, rows = 1, breakpoint = UIMediaBreakPoints.MEDIUM) {
1060
- return (original, propertyKey) => {
1061
- return uimodel(tag, { cols, rows, breakpoint })(original, propertyKey);
1062
- };
1063
- }
1064
-
1065
- /**
1066
- * @description Module that extends the Model prototype with rendering capabilities
1067
- * @summary Adds the render method to all Model instances from decorator-validation
1068
- * This module implements the Renderable interface for the Model class by adding a render method
1069
- * to its prototype. This allows any Model instance to be rendered using the RenderingEngine.
1070
- * @module model/overrides
1071
- * @memberOf module:ui-decorators/model
1072
- */
1073
- /**
1074
- * @description Renders the model using the appropriate rendering engine
1075
- * @summary Delegates rendering to the RenderingEngine based on model metadata
1076
- * This method implements the render method from the Renderable interface for all Model instances.
1077
- * It uses the RenderingEngine to determine how to render the model based on its metadata.
1078
- *
1079
- * @template M Type of the model being rendered
1080
- * @param {any[]} args Additional arguments to pass to the rendering engine
1081
- * @return {any} The rendered output in the format determined by the rendering engine
1082
- */
1083
- Model.prototype.render = function (...args) {
1084
- return RenderingEngine.render(this, ...args);
1085
- };
1086
-
1087
- /**
1088
- * @description Decorator that hides a property during specific CRUD operations
1089
- * @summary Controls property visibility based on operation type
1090
- * This decorator allows you to specify which CRUD operations should hide a property
1091
- * in the UI. The property will only be visible during operations not specified.
1092
- *
1093
- * @param operations - The CRUD operations during which the property should be hidden
1094
- * @return {Function} A property decorator function
1095
- *
1096
- * @function hideOn
1097
- * @category Property Decorators
1098
- *
1099
- * @example
1100
- * // Hide the password field during READ operations
1101
- * class User {
1102
- * @attribute()
1103
- * username: string;
1104
- *
1105
- * @attribute()
1106
- * @hideOn(OperationKeys.READ)
1107
- * password: string;
1108
- * }
1109
- *
1110
- * @mermaid
1111
- * sequenceDiagram
1112
- * participant Model
1113
- * participant hideOn
1114
- * participant RenderingEngine
1115
- * participant UI
1116
- * Model->>hideOn: Apply to property
1117
- * hideOn->>Model: Add hidden metadata
1118
- * RenderingEngine->>Model: Check if property should be hidden
1119
- * Model->>RenderingEngine: Return hidden operations
1120
- * RenderingEngine->>UI: Render or hide based on current operation
1121
- */
1122
- function hideOn(...operations) {
1123
- return propMetadata(RenderingEngine.key(UIKeys.HIDDEN), operations);
1124
- }
1125
- /**
1126
- * @description Decorator that sets the order of a UI element
1127
- * @summary Specifies the rendering order for UI components
1128
- * This decorator applies metadata to the property or class, indicating its order in the UI rendering sequence.
1129
- *
1130
- * @param {number} [order=1] The order value for the UI element (default is 1)
1131
- * @return {Function} A property or class decorator function
1132
- *
1133
- * @function uiorder
1134
- * @category Property Decorators
1135
- *
1136
- * @example
1137
- * // Set order for a field
1138
- * @uiorder(2)
1139
- * fieldName: string;
1140
- *
1141
- * // Set order for a class
1142
- * @uiorder(1)
1143
- * class UserProfile { ... }
1144
- *
1145
- * @mermaid
1146
- * sequenceDiagram
1147
- * participant System
1148
- * participant uiorder
1149
- * participant property
1150
- * System->>uiorder:do(property)
1151
- * uiorder->>property: sets order metadata
1152
- * uiorder->>System: returns decorated property
1153
- */
1154
- function uiorder(order = 1) {
1155
- return propMetadata(RenderingEngine.key(UIKeys.ORDER), order);
1156
- }
1157
- /**
1158
- * @description Decorator that completely hides a property in all UI operations
1159
- * @summary Makes a property invisible in all CRUD operations
1160
- * This decorator is a convenience wrapper around hideOn that hides a property
1161
- * during all CRUD operations (CREATE, READ, UPDATE, DELETE).
1162
- *
1163
- * @return {Function} A property decorator function
1164
- *
1165
- * @function hidden
1166
- * @category Property Decorators
1167
- *
1168
- * @example
1169
- * // Completely hide the internalId field in the UI
1170
- * class Product {
1171
- * @attribute()
1172
- * name: string;
1173
- *
1174
- * @attribute()
1175
- * @hidden()
1176
- * internalId: string;
1177
- * }
1178
- *
1179
- * @mermaid
1180
- * sequenceDiagram
1181
- * participant Model
1182
- * participant hidden
1183
- * participant hideOn
1184
- * participant RenderingEngine
1185
- * Model->>hidden: Apply to property
1186
- * hidden->>hideOn: Call with all operations
1187
- * hideOn->>Model: Add hidden metadata
1188
- * RenderingEngine->>Model: Check if property should be hidden
1189
- * Model->>RenderingEngine: Return all operations
1190
- * RenderingEngine->>UI: Always hide property
1191
- */
1192
- function hidden() {
1193
- return hideOn(OperationKeys.CREATE, OperationKeys.READ, OperationKeys.UPDATE, OperationKeys.DELETE);
1194
- }
1195
- /**
1196
- * @description Decorator that specifies how a property should be rendered as a UI element
1197
- * @summary Maps a model property to a specific UI element with custom properties
1198
- * This decorator allows you to define which HTML element or component should be used
1199
- * to render a specific property, along with any additional properties to pass to that element.
1200
- *
1201
- * @param {string} tag The HTML element or component tag name to use for rendering
1202
- * @param {Record<string, any>} [props] Additional properties to pass to the element
1203
- * @param {boolean} [serialize=false] Whether the property should be serialized
1204
- * @return {Function} A property decorator function
1205
- *
1206
- * @function uielement
1207
- * @category Property Decorators
1208
- *
1209
- * @example
1210
- * // Render a property as a text input
1211
- * class LoginForm {
1212
- * @attribute()
1213
- * @uielement('input', { type: 'text', placeholder: 'Enter username' })
1214
- * username: string;
1215
- *
1216
- * @attribute()
1217
- * @uielement('input', { type: 'password', placeholder: 'Enter password' })
1218
- * password: string;
1219
- *
1220
- * @attribute()
1221
- * @uielement('button', { class: 'btn-primary' })
1222
- * submit: string = 'Login';
1223
- * }
1224
- *
1225
- * @mermaid
1226
- * sequenceDiagram
1227
- * participant Model
1228
- * participant uielement
1229
- * participant RenderingEngine
1230
- * participant UI
1231
- * Model->>uielement: Apply to property
1232
- * uielement->>Model: Add element metadata
1233
- * RenderingEngine->>Model: Get element metadata
1234
- * Model->>RenderingEngine: Return tag and props
1235
- * RenderingEngine->>UI: Render with specified element
1236
- */
1237
- function uielement(tag, props, serialize = false) {
1238
- return (original, propertyKey) => {
1239
- const metadata = {
1240
- tag: tag,
1241
- serialize: serialize,
1242
- props: Object.assign({}, props || {}, {
1243
- name: propertyKey,
1244
- }),
1245
- };
1246
- return propMetadata(RenderingEngine.key(UIKeys.ELEMENT), metadata)(original, propertyKey);
1247
- };
1248
- }
1249
- /**
1250
- * @description Decorator that maps a model property to a UI component property
1251
- * @summary Specifies how a property should be passed to a UI component
1252
- * This decorator allows you to define how a model property should be mapped to
1253
- * a property of the UI component when rendering. It requires the class to be
1254
- * decorated with @uimodel.
1255
- *
1256
- * @param {string} [propName] The name of the property to pass to the component (defaults to the property key)
1257
- * @param {boolean} [stringify=false] Whether to stringify the property value
1258
- * @return {Function} A property decorator function
1259
- *
1260
- * @function uiprop
1261
- * @category Property Decorators
1262
- *
1263
- * @example
1264
- * // Map model properties to component properties
1265
- * @uimodel('user-profile')
1266
- * class UserProfile {
1267
- * @attribute()
1268
- * @uiprop() // Will be passed as 'fullName' to the component
1269
- * fullName: string;
1270
- *
1271
- * @attribute()
1272
- * @uiprop('userEmail') // Will be passed as 'userEmail' to the component
1273
- * email: string;
1274
- *
1275
- * @attribute()
1276
- * @uiprop('userData', true) // Will be passed as stringified JSON
1277
- * userData: Record<string, any>;
1278
- * }
1279
- *
1280
- * @mermaid
1281
- * sequenceDiagram
1282
- * participant Model
1283
- * participant uiprop
1284
- * participant RenderingEngine
1285
- * participant Component
1286
- * Model->>uiprop: Apply to property
1287
- * uiprop->>Model: Add prop metadata
1288
- * RenderingEngine->>Model: Get prop metadata
1289
- * Model->>RenderingEngine: Return prop name and stringify flag
1290
- * RenderingEngine->>Component: Pass property with specified name
1291
- */
1292
- function uiprop(propName = undefined, stringify = false) {
1293
- return (target, propertyKey) => {
1294
- const metadata = {
1295
- name: propName || propertyKey,
1296
- stringify: stringify,
1297
- };
1298
- propMetadata(RenderingEngine.key(UIKeys.PROP), metadata)(target, propertyKey);
1299
- };
1300
- }
1301
- /**
1302
- * @description Decorator that maps a nested model property to a UI component property.
1303
- * @summary Defines how a parent component should render the child model when nested.
1304
- *
1305
- * This decorator is used to decorate properties that are nested models.
1306
- * When applied, it allows overriding the default tag of the child model with the provided one,
1307
- * enabling different rendering behavior when the model acts as a child (nested)
1308
- * compared to when it is rendered as the parent model.
1309
- *
1310
- * It requires the class to be decorated with `@uimodel`.
1311
- *
1312
- * @param {string} clazz The model class name to pass to the component (defaults to the property key).
1313
- * @param {string} tag The HTML element or component tag name to override the UI tag of the nested model
1314
- * @param {Record<string, any>} [props] Additional properties to pass to the element
1315
- * @param {boolean} [serialize=false] Whether the property should be serialized
1316
- * @return {Function} A property decorator function.
1317
- *
1318
- * @function uichild
1319
- * @category Property Decorators
1320
- *
1321
- * @example
1322
- * // Map a nested model to a component property with a different tag when nested
1323
- * @uimodel('address-component')
1324
- * class Address {
1325
- * @attribute()
1326
- * street: string;
1327
- *
1328
- * @attribute()
1329
- * city: string;
1330
- * }
1331
- *
1332
- * @uimodel('user-profile')
1333
- * class UserProfile {
1334
- * @attribute()
1335
- * @uichild(Address.name, 'address-child-component')
1336
- * address: Address;
1337
- * }
1338
- *
1339
- * // In this example, the Address model has the default tag 'address-component' when rendered as a root component,
1340
- * // but when used inside UserProfile, it is rendered with the overridden tag 'address-child-component'
1341
- *
1342
- * @mermaid
1343
- * sequenceDiagram
1344
- * participant Model
1345
- * participant uichild
1346
- * participant RenderingEngine
1347
- * participant Component
1348
- * Model->>uichild: Apply to property
1349
- * uichild->>Model: Add child metadata
1350
- * RenderingEngine->>Model: Get child metadata
1351
- * Model->>RenderingEngine: Return prop name, stringify flag, and child tag override
1352
- * RenderingEngine->>Component: Pass property with specified name and render with overridden tag if nested
1353
- */
1354
- function uichild(clazz, tag, props = {}, isArray = false, serialize = false) {
1355
- return (target, propertyKey) => {
1356
- const metadata = {
1357
- tag: tag,
1358
- serialize: serialize,
1359
- props: Object.assign({}, props || {}, {
1360
- name: clazz || propertyKey,
1361
- }, isArray ? { customTypes: [Array.name], multiple: true } : { multiple: props?.multiple || false }),
1362
- };
1363
- propMetadata(RenderingEngine.key(UIKeys.CHILD), metadata)(target, propertyKey);
1364
- };
1365
- }
1366
- /**
1367
- * @description Decorator that maps a model property to a list item component
1368
- * @summary Specifies how a property should be rendered in a list context
1369
- * This decorator allows you to define how a model property containing a list
1370
- * should be rendered. It requires the class to be decorated with @uilistitem.
1371
- *
1372
- * @param {string} [propName] The name of the property to pass to the list component (defaults to the property key)
1373
- * @param {Record<string, any>} [props] Additional properties to pass to the list container
1374
- * @return {Function} A property decorator function
1375
- *
1376
- * @function uilistprop
1377
- * @category Property Decorators
1378
- *
1379
- * @example
1380
- * // Define a list property with custom rendering
1381
- * @uimodel('todo-list')
1382
- * class TodoList {
1383
- * @attribute()
1384
- * title: string;
1385
- *
1386
- * @attribute()
1387
- * @uilistprop('items', { class: 'todo-items-container' })
1388
- * items: TodoItem[];
1389
- * }
1390
- *
1391
- * @uilistitem('li', { class: 'todo-item' })
1392
- * class TodoItem extends Model {
1393
- * @attribute()
1394
- * text: string;
1395
- *
1396
- * @attribute()
1397
- * completed: boolean;
1398
- * }
1399
- *
1400
- * @mermaid
1401
- * sequenceDiagram
1402
- * participant Model
1403
- * participant uilistprop
1404
- * participant RenderingEngine
1405
- * participant ListContainer
1406
- * participant ListItems
1407
- * Model->>uilistprop: Apply to property
1408
- * uilistprop->>Model: Add list prop metadata
1409
- * RenderingEngine->>Model: Get list prop metadata
1410
- * Model->>RenderingEngine: Return prop name and container props
1411
- * RenderingEngine->>ListContainer: Create container with props
1412
- * RenderingEngine->>ListItems: Render each item using @uilistitem
1413
- * ListContainer->>RenderingEngine: Return rendered list
1414
- */
1415
- function uilistprop(propName = undefined, props) {
1416
- return (target, propertyKey) => {
1417
- const metadata = {
1418
- name: propName || propertyKey,
1419
- props: props || {},
1420
- };
1421
- propMetadata(RenderingEngine.key(UIKeys.UILISTPROP), metadata)(target, propertyKey);
1422
- };
1423
- }
1424
- /**
1425
- * @description Decorator that positions a property in a specific grid layout position
1426
- * @summary Specifies the column and row position for a property in a UI layout grid
1427
- * This decorator allows you to define the specific position of a property within
1428
- * a grid-based layout system. It specifies which column and row the property
1429
- * should occupy when rendered in the UI.
1430
- *
1431
- * @param {number} col The column position in the grid layout
1432
- * @param {number} [row=1] The row position in the grid layout (defaults to 1)
1433
- * @param {Record<string, any>} [props={}] Additional properties to pass to the layout item
1434
- * @return {Function} A property decorator function
1435
- *
1436
- * @function uilayoutitem
1437
- * @category Property Decorators
1438
- *
1439
- * @example
1440
- * // Position properties in a grid layout
1441
- * @uimodel('user-form')
1442
- * class UserForm {
1443
- * @attribute()
1444
- * @uilayoutitem(1, 1) // First column, first row
1445
- * firstName: string;
1446
- *
1447
- * @attribute()
1448
- * @uilayoutitem(2, 1) // Second column, first row
1449
- * lastName: string;
1450
- *
1451
- * @attribute()
1452
- * @uilayoutitem(1, 2, { colspan: 2 }) // First column, second row, spans 2 columns
1453
- * email: string;
1454
- *
1455
- * @attribute()
1456
- * @uilayoutitem(1, 3, { class: 'full-width' }) // First column, third row with custom class
1457
- * bio: string;
1458
- * }
1459
- *
1460
- * @mermaid
1461
- * sequenceDiagram
1462
- * participant Model
1463
- * participant uilayoutitem
1464
- * participant RenderingEngine
1465
- * participant LayoutContainer
1466
- * Model->>uilayoutitem: Apply to property
1467
- * uilayoutitem->>Model: Add layout item metadata
1468
- * RenderingEngine->>Model: Get layout item metadata
1469
- * Model->>RenderingEngine: Return column, row, and props
1470
- * RenderingEngine->>LayoutContainer: Position element at grid coordinates
1471
- * LayoutContainer->>RenderingEngine: Return positioned element
1472
- */
1473
- function uilayoutitem(col, row = 1, props = {}) {
1474
- return (target, propertyKey) => {
1475
- const metadata = {
1476
- name: propertyKey,
1477
- col,
1478
- row,
1479
- props: Object.assign({}, props, { row: row ?? 1, col: col ?? 1 }),
1480
- };
1481
- propMetadata(RenderingEngine.key(UIKeys.UILAYOUTITEM), metadata)(target, propertyKey);
1482
- };
1483
- }
1484
-
1485
- /**
1486
- * @description Class representing an event handler
1487
- * @summary Defines the structure for handling events in the UI decorators system
1488
- * This class provides a foundation for managing and processing events that occur
1489
- * within the UI components generated by the decorators.
1490
- * @class EventHandler
1491
- * @memberOf module:ui-decorators/ui
1492
- */
1493
- class EventHandler {
1494
- /**
1495
- * @description Creates an instance of EventHandler
1496
- * @summary Initializes a new EventHandler object
1497
- * This constructor currently doesn't take any parameters, but it can be
1498
- * extended in the future to accept configuration options if needed.
1499
- */
1500
- constructor() { }
1501
- }
1502
-
1503
- /**
1504
- * @description UI decorators module for TypeScript applications
1505
- * @summary A collection of decorators and utilities for building UI components in TypeScript applications.
1506
- * This module exports functionality from both the model and UI submodules, providing decorators for
1507
- * rendering, component definition, and UI state management.
1508
- * @module ui-decorators
1509
- */
1510
- /**
1511
- * @description Current package version string
1512
- * @summary Stores the current package version for reference
1513
- * @const VERSION
1514
- * @memberOf module:ui-decorators
1515
- */
1516
- const VERSION = "0.5.25";
1517
-
1518
- export { EventHandler, HTML5CheckTypes, HTML5DateFormat, HTML5InputTypes, RenderingEngine, RenderingError, UIKeys, UIMediaBreakPoints, VERSION, ValidatableByAttribute, ValidatableByType, escapeHtml, formatByType, generateUIModelID, hidden, hideOn, parseToNumber, parseValueByType, renderedBy, revertHtml, uichild, uielement, uihandlers, uilayout, uilayoutitem, uilistitem, uilistprop, uimodel, uiorder, uiprop };
1519
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidWktZGVjb3JhdG9ycy5lc20uY2pzIiwic291cmNlcyI6WyIuLi9zcmMvdWkvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3VpL2Vycm9ycy50cyIsIi4uL3NyYy91aS91dGlscy50cyIsIi4uL3NyYy91aS9SZW5kZXJpbmcudHMiLCIuLi9zcmMvbW9kZWwvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9tb2RlbC9vdmVycmlkZXMudHMiLCIuLi9zcmMvdWkvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy91aS9oYW5kbGVycy50cyIsIi4uL3NyYy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBkZXNjcmlwdGlvbiBDb25zdGFudHMgYW5kIGVudW1zIGZvciBVSSByZW5kZXJpbmcgYW5kIHZhbGlkYXRpb25cbiAqIEBzdW1tYXJ5IERlZmluZXMga2V5cywgbWFwcGluZ3MsIGFuZCBIVE1MNSBpbnB1dCB0eXBlcyBmb3IgVUkgY29tcG9uZW50c1xuICogVGhpcyBtb2R1bGUgcHJvdmlkZXMgY29uc3RhbnRzIHVzZWQgdGhyb3VnaG91dCB0aGUgVUkgZGVjb3JhdG9ycyBsaWJyYXJ5IGZvclxuICogcmVuZGVyaW5nLCB2YWxpZGF0aW9uLCBhbmQgSFRNTCBlbGVtZW50IGdlbmVyYXRpb24uXG4gKiBAbW9kdWxlIHVpL2NvbnN0YW50c1xuICogQG1lbWJlck9mIG1vZHVsZTp1aS1kZWNvcmF0b3JzXG4gKi9cblxuaW1wb3J0IHtcbiAgQ29uc3RydWN0b3IsXG4gIERhdGVWYWxpZGF0b3IsXG4gIERpZmZWYWxpZGF0b3IsXG4gIEVtYWlsVmFsaWRhdG9yLFxuICBFcXVhbHNWYWxpZGF0b3IsXG4gIEdyZWF0ZXJUaGFuT3JFcXVhbFZhbGlkYXRvcixcbiAgR3JlYXRlclRoYW5WYWxpZGF0b3IsXG4gIExlc3NUaGFuT3JFcXVhbFZhbGlkYXRvcixcbiAgTGVzc1RoYW5WYWxpZGF0b3IsXG4gIE1heExlbmd0aFZhbGlkYXRvcixcbiAgTWF4VmFsaWRhdG9yLFxuICBNaW5MZW5ndGhWYWxpZGF0b3IsXG4gIE1pblZhbGlkYXRvcixcbiAgTW9kZWxLZXlzLFxuICBQYXNzd29yZFZhbGlkYXRvcixcbiAgUGF0dGVyblZhbGlkYXRvcixcbiAgUmVxdWlyZWRWYWxpZGF0b3IsXG4gIFN0ZXBWYWxpZGF0b3IsXG4gIFVSTFZhbGlkYXRvcixcbiAgVmFsaWRhdGlvbktleXMsXG4gIFZhbGlkYXRvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG5cblxuZXhwb3J0IGVudW0gVUlNZWRpYUJyZWFrUG9pbnRzICB7XG4gIFNNQUxMID0gJ3MnLFxuICBNRURJVU0gPSAnbScsXG4gIExBUkdFID0gJ2wnLFxuICBYTEFSR0UgPSAneGwnLFxufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gS2V5IGNvbnN0YW50cyB1c2VkIGZvciBVSSBtZXRhZGF0YSBhbmQgcmVuZGVyaW5nXG4gKiBAc3VtbWFyeSBDb2xsZWN0aW9uIG9mIHN0cmluZyBjb25zdGFudHMgdXNlZCBhcyBrZXlzIGZvciBVSS1yZWxhdGVkIG1ldGFkYXRhXG4gKiBUaGVzZSBrZXlzIGFyZSB1c2VkIHRocm91Z2hvdXQgdGhlIGxpYnJhcnkgdG8gc3RvcmUgYW5kIHJldHJpZXZlIG1ldGFkYXRhIHJlbGF0ZWQgdG9cbiAqIFVJIG1vZGVscywgZWxlbWVudHMsIHByb3BlcnRpZXMsIGFuZCB2YWxpZGF0aW9uIHJ1bGVzLlxuICpcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFVJS2V5c1R5cGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBSRUZMRUNUIC0gQmFzZSByZWZsZWN0aW9uIGtleSBmb3IgVUkgbWV0YWRhdGFcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBVSU1PREVMIC0gS2V5IGZvciBVSSBtb2RlbCBtZXRhZGF0YVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFJFTkRFUkVEX0JZIC0gS2V5IGZvciBzcGVjaWZ5aW5nIHJlbmRlcmluZyBlbmdpbmVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBFTEVNRU5UIC0gS2V5IGZvciBlbGVtZW50IG1ldGFkYXRhXG4gKiBAcHJvcGVydHkge3N0cmluZ30gUFJPUCAtIEtleSBmb3IgcHJvcGVydHkgbWV0YWRhdGFcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBOQU1FIC0gS2V5IGZvciBuYW1lIGF0dHJpYnV0ZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IE5BTUVfUFJFRklYIC0gUHJlZml4IGZvciBpbnB1dCBuYW1lc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IENVU1RPTV9QUk9QUyAtIEtleSBmb3IgY3VzdG9tIHZhbGlkYXRpb24gcHJvcGVydGllc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFVJTElTVElURU0gLSBLZXkgZm9yIGxpc3QgaXRlbSBtZXRhZGF0YVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFVJTElTVFBST1AgLSBLZXkgZm9yIGxpc3QgcHJvcGVydHkgbWV0YWRhdGFcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUWVBFIC0gS2V5IGZvciB0eXBlIG1ldGFkYXRhXG4gKiBAcHJvcGVydHkge3N0cmluZ30gU1VCX1RZUEUgLSBLZXkgZm9yIHN1YnR5cGUgbWV0YWRhdGFcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBISURERU4gLSBLZXkgZm9yIGhpZGRlbiBhdHRyaWJ1dGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBGT1JNQVQgLSBLZXkgZm9yIGZvcm1hdCBtZXRhZGF0YVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFJFQURfT05MWSAtIEtleSBmb3IgcmVhZG9ubHkgYXR0cmlidXRlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gUkVRVUlSRUQgLSBLZXkgZm9yIHJlcXVpcmVkIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBNSU4gLSBLZXkgZm9yIG1pbmltdW0gdmFsdWUgdmFsaWRhdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IE1JTl9MRU5HVEggLSBLZXkgZm9yIG1pbmltdW0gbGVuZ3RoIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBNQVggLSBLZXkgZm9yIG1heGltdW0gdmFsdWUgdmFsaWRhdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IE1BWF9MRU5HVEggLSBLZXkgZm9yIG1heGltdW0gbGVuZ3RoIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBQQVRURVJOIC0gS2V5IGZvciBwYXR0ZXJuIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBVUkwgLSBLZXkgZm9yIFVSTCB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gU1RFUCAtIEtleSBmb3Igc3RlcCB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gREFURSAtIEtleSBmb3IgZGF0ZSB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gRU1BSUwgLSBLZXkgZm9yIGVtYWlsIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBQQVNTV09SRCAtIEtleSBmb3IgcGFzc3dvcmQgdmFsaWRhdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IEVRVUFMUyAtIEtleSBmb3IgZXF1YWxpdHkgdmFsaWRhdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IERJRkYgLSBLZXkgZm9yIGRpZmZlcmVuY2UgdmFsaWRhdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IExFU1NfVEhBTiAtIEtleSBmb3IgbGVzcyB0aGFuIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBMRVNTX1RIQU5fT1JfRVFVQUwgLSBLZXkgZm9yIGxlc3MgdGhhbiBvciBlcXVhbCB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gR1JFQVRFUl9USEFOIC0gS2V5IGZvciBncmVhdGVyIHRoYW4gdmFsaWRhdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IEdSRUFURVJfVEhBTl9PUl9FUVVBTCAtIEtleSBmb3IgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHZhbGlkYXRpb25cbiAqXG4gKiBAY29uc3QgVUlLZXlzXG4gKiBAdHlwZSB7VUlLZXlzVHlwZX1cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTp1aS1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBVSUtleXMgPSB7XG4gIFJFRkxFQ1Q6IGAke01vZGVsS2V5cy5SRUZMRUNUfS51aS5gLFxuICBVSU1PREVMOiBcInVpbW9kZWxcIixcbiAgUkVOREVSRURfQlk6IFwicmVuZGVyZWQtYnlcIixcbiAgRUxFTUVOVDogXCJlbGVtZW50XCIsXG4gIFBST1A6IFwicHJvcFwiLFxuICBDSElMRDogXCJjaGlsZFwiLFxuICBOQU1FOiBcIm5hbWVcIixcbiAgTkFNRV9QUkVGSVg6IFwiaW5wdXQtXCIsXG4gIENVU1RPTV9QUk9QUzogXCJjdXN0b21WYWxpZGF0aW9uUHJvcHNcIixcblxuICBVSUxJU1RJVEVNOiBcInVpbGlzdGl0ZW1cIixcbiAgVUlMSVNUUFJPUDogXCJsaXN0cHJvcFwiLFxuICBVSUxBWU9VVDogXCJ1aWxheW91dFwiLFxuICBVSUxBWU9VVElURU06IFwidWlsYXlvdXRpdGVtXCIsXG4gIEhBTkRMRVJTOiBcImhhbmRsZXJzXCIsXG5cbiAgVFlQRTogXCJ0eXBlXCIsXG4gIFNVQl9UWVBFOiBcInN1YnR5cGVcIixcblxuICBISURERU46IFwiaGlkZGVuXCIsXG4gIEZPUk1BVDogXCJmb3JtYXRcIixcbiAgT1JERVI6IFwib3JkZXJcIixcblxuICBSRUFEX09OTFk6IFwicmVhZG9ubHlcIixcbiAgUkVRVUlSRUQ6IFZhbGlkYXRpb25LZXlzLlJFUVVJUkVELFxuICBNSU46IFZhbGlkYXRpb25LZXlzLk1JTixcbiAgTUlOX0xFTkdUSDogVmFsaWRhdGlvbktleXMuTUlOX0xFTkdUSCxcbiAgTUFYOiBWYWxpZGF0aW9uS2V5cy5NQVgsXG4gIE1BWF9MRU5HVEg6IFZhbGlkYXRpb25LZXlzLk1BWF9MRU5HVEgsXG4gIFBBVFRFUk46IFZhbGlkYXRpb25LZXlzLlBBVFRFUk4sXG4gIFVSTDogVmFsaWRhdGlvbktleXMuVVJMLFxuICBTVEVQOiBWYWxpZGF0aW9uS2V5cy5TVEVQLFxuICBEQVRFOiBWYWxpZGF0aW9uS2V5cy5EQVRFLFxuICBFTUFJTDogVmFsaWRhdGlvbktleXMuRU1BSUwsXG4gIFBBU1NXT1JEOiBWYWxpZGF0aW9uS2V5cy5QQVNTV09SRCxcbiAgRVFVQUxTOiBWYWxpZGF0aW9uS2V5cy5FUVVBTFMsXG4gIERJRkY6IFZhbGlkYXRpb25LZXlzLkRJRkYsXG4gIExFU1NfVEhBTjogVmFsaWRhdGlvbktleXMuTEVTU19USEFOLFxuICBMRVNTX1RIQU5fT1JfRVFVQUw6IFZhbGlkYXRpb25LZXlzLkxFU1NfVEhBTl9PUl9FUVVBTCxcbiAgR1JFQVRFUl9USEFOOiBWYWxpZGF0aW9uS2V5cy5HUkVBVEVSX1RIQU4sXG4gIEdSRUFURVJfVEhBTl9PUl9FUVVBTDogVmFsaWRhdGlvbktleXMuR1JFQVRFUl9USEFOX09SX0VRVUFMLFxufTtcblxuXG5cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFwcGluZyBvZiBpbnB1dCB0eXBlcyB0byB0aGVpciBjb3JyZXNwb25kaW5nIHZhbGlkYXRvcnNcbiAqIEBzdW1tYXJ5IE1hcHMgc3BlY2lhbCBpbnB1dCB0eXBlcyB0byB0aGVpciB2YWxpZGF0b3IgY2xhc3Nlc1xuICogVGhpcyBjb25zdGFudCBtYXBzIGlucHV0IHR5cGVzIGxpa2UgZW1haWwsIFVSTCwgZGF0ZSwgYW5kIHBhc3N3b3JkIHRvIHRoZWlyXG4gKiBjb3JyZXNwb25kaW5nIHZhbGlkYXRvciBjbGFzc2VzIGZyb20gdGhlIGRlY29yYXRvci12YWxpZGF0aW9uIGxpYnJhcnkuXG4gKlxuICogQHR5cGVkZWYge09iamVjdC48c3RyaW5nLCBDb25zdHJ1Y3RvcjxWYWxpZGF0b3I+Pn0gVmFsaWRhdGFibGVCeVR5cGVNYXBcbiAqIEBwcm9wZXJ0eSB7Q29uc3RydWN0b3I8RW1haWxWYWxpZGF0b3I+fSBlbWFpbCAtIFZhbGlkYXRvciBmb3IgZW1haWwgaW5wdXRzXG4gKiBAcHJvcGVydHkge0NvbnN0cnVjdG9yPFVSTFZhbGlkYXRvcj59IHVybCAtIFZhbGlkYXRvciBmb3IgVVJMIGlucHV0c1xuICogQHByb3BlcnR5IHtDb25zdHJ1Y3RvcjxEYXRlVmFsaWRhdG9yPn0gZGF0ZSAtIFZhbGlkYXRvciBmb3IgZGF0ZSBpbnB1dHNcbiAqIEBwcm9wZXJ0eSB7Q29uc3RydWN0b3I8UGFzc3dvcmRWYWxpZGF0b3I+fSBwYXNzd29yZCAtIFZhbGlkYXRvciBmb3IgcGFzc3dvcmQgaW5wdXRzXG4gKlxuICogQGNvbnN0IFZhbGlkYXRhYmxlQnlUeXBlXG4gKiBAdHlwZSB7VmFsaWRhdGFibGVCeVR5cGVNYXB9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dWktZGVjb3JhdG9yc1xuICovXG5leHBvcnQgY29uc3QgVmFsaWRhdGFibGVCeVR5cGU6IFJlY29yZDxzdHJpbmcsIENvbnN0cnVjdG9yPFZhbGlkYXRvcj4+ID0ge1xuICBbVUlLZXlzLkVNQUlMXTogRW1haWxWYWxpZGF0b3IsXG4gIFtVSUtleXMuVVJMXTogVVJMVmFsaWRhdG9yLFxuICBbVUlLZXlzLkRBVEVdOiBEYXRlVmFsaWRhdG9yLFxuICBbVUlLZXlzLlBBU1NXT1JEXTogUGFzc3dvcmRWYWxpZGF0b3IsXG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYXBwaW5nIG9mIHZhbGlkYXRpb24gYXR0cmlidXRlcyB0byB0aGVpciBjb3JyZXNwb25kaW5nIHZhbGlkYXRvcnNcbiAqIEBzdW1tYXJ5IE1hcHMgSFRNTCB2YWxpZGF0aW9uIGF0dHJpYnV0ZXMgdG8gdGhlaXIgdmFsaWRhdG9yIGNsYXNzZXNcbiAqIFRoaXMgY29uc3RhbnQgbWFwcyBIVE1MIHZhbGlkYXRpb24gYXR0cmlidXRlcyBsaWtlIHJlcXVpcmVkLCBtaW4sIG1heCwgcGF0dGVybiwgZXRjLlxuICogdG8gdGhlaXIgY29ycmVzcG9uZGluZyB2YWxpZGF0b3IgY2xhc3NlcyBmcm9tIHRoZSBkZWNvcmF0b3ItdmFsaWRhdGlvbiBsaWJyYXJ5LlxuICpcbiAqIEB0eXBlZGVmIHtPYmplY3QuPHN0cmluZywgQ29uc3RydWN0b3I8VmFsaWRhdG9yPj59IFZhbGlkYXRhYmxlQnlBdHRyaWJ1dGVNYXBcbiAqIEBwcm9wZXJ0eSB7Q29uc3RydWN0b3I8UmVxdWlyZWRWYWxpZGF0b3I+fSByZXF1aXJlZCAtIFZhbGlkYXRvciBmb3IgcmVxdWlyZWQgZmllbGRzXG4gKiBAcHJvcGVydHkge0NvbnN0cnVjdG9yPE1pblZhbGlkYXRvcj59IG1pbiAtIFZhbGlkYXRvciBmb3IgbWluaW11bSB2YWx1ZVxuICogQHByb3BlcnR5IHtDb25zdHJ1Y3RvcjxNYXhWYWxpZGF0b3I+fSBtYXggLSBWYWxpZGF0b3IgZm9yIG1heGltdW0gdmFsdWVcbiAqIEBwcm9wZXJ0eSB7Q29uc3RydWN0b3I8U3RlcFZhbGlkYXRvcj59IHN0ZXAgLSBWYWxpZGF0b3IgZm9yIHN0ZXAgdmFsdWVcbiAqIEBwcm9wZXJ0eSB7Q29uc3RydWN0b3I8TWluTGVuZ3RoVmFsaWRhdG9yPn0gbWlubGVuZ3RoIC0gVmFsaWRhdG9yIGZvciBtaW5pbXVtIGxlbmd0aFxuICogQHByb3BlcnR5IHtDb25zdHJ1Y3RvcjxNYXhMZW5ndGhWYWxpZGF0b3I+fSBtYXhsZW5ndGggLSBWYWxpZGF0b3IgZm9yIG1heGltdW0gbGVuZ3RoXG4gKiBAcHJvcGVydHkge0NvbnN0cnVjdG9yPFBhdHRlcm5WYWxpZGF0b3I+fSBwYXR0ZXJuIC0gVmFsaWRhdG9yIGZvciByZWdleCBwYXR0ZXJuXG4gKiBAcHJvcGVydHkge0NvbnN0cnVjdG9yPEVxdWFsc1ZhbGlkYXRvcj59IGVxdWFscyAtIFZhbGlkYXRvciBmb3IgZXF1YWxpdHlcbiAqIEBwcm9wZXJ0eSB7Q29uc3RydWN0b3I8RGlmZlZhbGlkYXRvcj59IGRpZmYgLSBWYWxpZGF0b3IgZm9yIGRpZmZlcmVuY2VcbiAqIEBwcm9wZXJ0eSB7Q29uc3RydWN0b3I8TGVzc1RoYW5WYWxpZGF0b3I+fSBsZXNzdGhhbiAtIFZhbGlkYXRvciBmb3IgbGVzcyB0aGFuIGNvbXBhcmlzb25cbiAqIEBwcm9wZXJ0eSB7Q29uc3RydWN0b3I8TGVzc1RoYW5PckVxdWFsVmFsaWRhdG9yPn0gbGVzc3RoYW5vcmVxdWFsIC0gVmFsaWRhdG9yIGZvciBsZXNzIHRoYW4gb3IgZXF1YWwgY29tcGFyaXNvblxuICogQHByb3BlcnR5IHtDb25zdHJ1Y3RvcjxHcmVhdGVyVGhhblZhbGlkYXRvcj59IGdyZWF0ZXJ0aGFuIC0gVmFsaWRhdG9yIGZvciBncmVhdGVyIHRoYW4gY29tcGFyaXNvblxuICogQHByb3BlcnR5IHtDb25zdHJ1Y3RvcjxHcmVhdGVyVGhhbk9yRXF1YWxWYWxpZGF0b3I+fSBncmVhdGVydGhhbm9yZXF1YWwgLSBWYWxpZGF0b3IgZm9yIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCBjb21wYXJpc29uXG4gKlxuICogQGNvbnN0IFZhbGlkYXRhYmxlQnlBdHRyaWJ1dGVcbiAqIEB0eXBlIHtWYWxpZGF0YWJsZUJ5QXR0cmlidXRlTWFwfVxuICogQHJlYWRvbmx5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnVpLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IFZhbGlkYXRhYmxlQnlBdHRyaWJ1dGU6IFJlY29yZDxzdHJpbmcsIENvbnN0cnVjdG9yPFZhbGlkYXRvcj4+ID0ge1xuICBbVUlLZXlzLlJFUVVJUkVEXTogUmVxdWlyZWRWYWxpZGF0b3IsXG4gIFtVSUtleXMuTUlOXTogTWluVmFsaWRhdG9yLFxuICBbVUlLZXlzLk1BWF06IE1heFZhbGlkYXRvcixcbiAgW1VJS2V5cy5TVEVQXTogU3RlcFZhbGlkYXRvcixcbiAgW1VJS2V5cy5NSU5fTEVOR1RIXTogTWluTGVuZ3RoVmFsaWRhdG9yLFxuICBbVUlLZXlzLk1BWF9MRU5HVEhdOiBNYXhMZW5ndGhWYWxpZGF0b3IsXG4gIFtVSUtleXMuUEFUVEVSTl06IFBhdHRlcm5WYWxpZGF0b3IsXG4gIFtVSUtleXMuRVFVQUxTXTogRXF1YWxzVmFsaWRhdG9yLFxuICBbVUlLZXlzLkRJRkZdOiBEaWZmVmFsaWRhdG9yLFxuICBbVUlLZXlzLkxFU1NfVEhBTl06IExlc3NUaGFuVmFsaWRhdG9yLFxuICBbVUlLZXlzLkxFU1NfVEhBTl9PUl9FUVVBTF06IExlc3NUaGFuT3JFcXVhbFZhbGlkYXRvcixcbiAgW1VJS2V5cy5HUkVBVEVSX1RIQU5dOiBHcmVhdGVyVGhhblZhbGlkYXRvcixcbiAgW1VJS2V5cy5HUkVBVEVSX1RIQU5fT1JfRVFVQUxdOiBHcmVhdGVyVGhhbk9yRXF1YWxWYWxpZGF0b3IsXG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdGFuZGFyZCBkYXRlIGZvcm1hdCBzdHJpbmcgZm9yIEhUTUw1IGRhdGUgaW5wdXRzXG4gKiBAc3VtbWFyeSBGb3JtYXQgc3RyaW5nIGZvciBIVE1MNSBkYXRlIGlucHV0cyAoeXl5eS1NTS1kZClcbiAqIFRoaXMgY29uc3RhbnQgZGVmaW5lcyB0aGUgc3RhbmRhcmQgZGF0ZSBmb3JtYXQgc3RyaW5nIHVzZWQgZm9yIEhUTUw1IGRhdGUgaW5wdXRzLlxuICpcbiAqIEBjb25zdCBIVE1MNURhdGVGb3JtYXRcbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dWktZGVjb3JhdG9yc1xuICovXG5leHBvcnQgY29uc3QgSFRNTDVEYXRlRm9ybWF0ID0gXCJ5eXl5LU1NLWRkXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbGxlY3Rpb24gb2YgSFRNTDUgaW5wdXQgdHlwZSB2YWx1ZXNcbiAqIEBzdW1tYXJ5IE1hcHMgaW5wdXQgdHlwZSBjb25zdGFudHMgdG8gdGhlaXIgSFRNTCBhdHRyaWJ1dGUgdmFsdWVzXG4gKiBUaGlzIGNvbnN0YW50IHByb3ZpZGVzIGEgbWFwcGluZyBvZiBpbnB1dCB0eXBlIGNvbnN0YW50cyB0byB0aGVpciBjb3JyZXNwb25kaW5nXG4gKiBIVE1MIGF0dHJpYnV0ZSB2YWx1ZXMgZm9yIHVzZSBpbiBmb3JtIGVsZW1lbnRzLlxuICpcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEhUTUw1SW5wdXRUeXBlc01hcFxuICogQHByb3BlcnR5IHtzdHJpbmd9IEJVVFRPTiAtIEJ1dHRvbiBpbnB1dCB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQ0hFQ0tCT1ggLSBDaGVja2JveCBpbnB1dCB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQ09MT1IgLSBDb2xvciBwaWNrZXIgaW5wdXQgdHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IERBVEUgLSBEYXRlIHBpY2tlciBpbnB1dCB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gREFURVRJTUVfTE9DQUwgLSBMb2NhbCBkYXRldGltZSBwaWNrZXIgaW5wdXQgdHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IEVNQUlMIC0gRW1haWwgaW5wdXQgdHlwZSB3aXRoIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBGSUxFIC0gRmlsZSB1cGxvYWQgaW5wdXQgdHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IEhJRERFTiAtIEhpZGRlbiBpbnB1dCB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSU1BR0UgLSBJbWFnZSBpbnB1dCB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTU9OVEggLSBNb250aCBwaWNrZXIgaW5wdXQgdHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IE5VTUJFUiAtIE51bWVyaWMgaW5wdXQgdHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFBBU1NXT1JEIC0gUGFzc3dvcmQgaW5wdXQgdHlwZSB3aXRoIG1hc2tlZCB0ZXh0XG4gKiBAcHJvcGVydHkge3N0cmluZ30gUkFESU8gLSBSYWRpbyBidXR0b24gaW5wdXQgdHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFJBTkdFIC0gUmFuZ2Ugc2xpZGVyIGlucHV0IHR5cGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBSRVNFVCAtIEZvcm0gcmVzZXQgYnV0dG9uIGlucHV0IHR5cGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTRUFSQ0ggLSBTZWFyY2ggaW5wdXQgdHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFNVQk1JVCAtIEZvcm0gc3VibWl0IGJ1dHRvbiBpbnB1dCB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gVEVMIC0gVGVsZXBob25lIG51bWJlciBpbnB1dCB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gVEVYVCAtIEJhc2ljIHRleHQgaW5wdXQgdHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFRJTUUgLSBUaW1lIHBpY2tlciBpbnB1dCB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gVVJMIC0gVVJMIGlucHV0IHR5cGUgd2l0aCB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gV0VFSyAtIFdlZWsgcGlja2VyIGlucHV0IHR5cGVcbiAqXG4gKiBAY29uc3QgSFRNTDVJbnB1dFR5cGVzXG4gKiBAdHlwZSB7SFRNTDVJbnB1dFR5cGVzTWFwfVxuICogQHJlYWRvbmx5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnVpLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IEhUTUw1SW5wdXRUeXBlcyA9IHtcbiAgQlVUVE9OOiBcImJ1dHRvblwiLFxuICBDSEVDS0JPWDogXCJjaGVja2JveFwiLFxuICBDT0xPUjogXCJjb2xvclwiLFxuICBEQVRFOiBVSUtleXMuREFURSxcbiAgREFURVRJTUVfTE9DQUw6IFwiZGF0ZXRpbWUtbG9jYWxcIixcbiAgRU1BSUw6IFVJS2V5cy5FTUFJTCxcbiAgRklMRTogXCJmaWxlXCIsXG4gIEhJRERFTjogXCJoaWRkZW5cIixcbiAgSU1BR0U6IFwiaW1hZ2VcIixcbiAgTU9OVEg6IFwibW9udGhcIixcbiAgTlVNQkVSOiBcIm51bWJlclwiLFxuICBQQVNTV09SRDogVUlLZXlzLlBBU1NXT1JELFxuICBSQURJTzogXCJyYWRpb1wiLFxuICBSQU5HRTogXCJyYW5nZVwiLFxuICBSRVNFVDogXCJyZXNldFwiLFxuICBTRUFSQ0g6IFwic2VhcmNoXCIsXG4gIFNVQk1JVDogXCJzdWJtaXRcIixcbiAgVEVMOiBcInRlbFwiLFxuICBURVhUOiBcInRleHRcIixcbiAgVEVYVEFSRUE6ICd0ZXh0YXJlYScsXG4gIFNFTEVDVDogJ3NlbGVjdCcsXG4gIFRJTUU6IFwidGltZVwiLFxuICBVUkw6IFVJS2V5cy5VUkwsXG4gIFdFRUs6IFwid2Vla1wiLFxufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXJyYXkgb2YgSFRNTDUgaW5wdXQgdHlwZXMgdGhhdCB1c2UgY2hlY2tib3hlc1xuICogQHN1bW1hcnkgTGlzdCBvZiBpbnB1dCB0eXBlcyB0aGF0IHJlcHJlc2VudCBjaGVja2FibGUgY29udHJvbHNcbiAqIFRoaXMgY29uc3RhbnQgZGVmaW5lcyBhbiBhcnJheSBvZiBIVE1MNSBpbnB1dCB0eXBlcyB0aGF0IHJlcHJlc2VudFxuICogY2hlY2thYmxlIGNvbnRyb2xzIChjaGVja2JveCBhbmQgcmFkaW8pLlxuICpcbiAqIEBjb25zdCBIVE1MNUNoZWNrVHlwZXNcbiAqIEB0eXBlIHtzdHJpbmdbXX1cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTp1aS1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBIVE1MNUNoZWNrVHlwZXMgPSBbXG4gIEhUTUw1SW5wdXRUeXBlcy5DSEVDS0JPWCxcbiAgSFRNTDVJbnB1dFR5cGVzLlJBRElPLFxuXTtcbiIsImltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXJyb3IgdGhyb3duIHdoZW4gYSByZW5kZXJpbmcgb3BlcmF0aW9uIGZhaWxzXG4gKiBAc3VtbWFyeSBTcGVjaWFsaXplZCBlcnJvciBmb3IgcmVuZGVyaW5nIGZhaWx1cmVzIGluIFVJIGNvbXBvbmVudHNcbiAqIFRoaXMgZXJyb3IgaXMgdGhyb3duIHdoZW4gdGhlIHJlbmRlcmluZyBlbmdpbmUgZW5jb3VudGVycyBhbiBlcnJvciB3aGlsZVxuICogYXR0ZW1wdGluZyB0byByZW5kZXIgYSBVSSBjb21wb25lbnQgb3IgbW9kZWwuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyBUaGUgZXJyb3IgbWVzc2FnZSBvciBvcmlnaW5hbCBlcnJvclxuICpcbiAqIEBjbGFzcyBSZW5kZXJpbmdFcnJvclxuICogQGV4dGVuZHMgQmFzZUVycm9yXG4gKiBAY2F0ZWdvcnkgRXJyb3JzXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFRocm93aW5nIGEgcmVuZGVyaW5nIGVycm9yXG4gKiB0cnkge1xuICogICAvLyBSZW5kZXJpbmcgY29kZSB0aGF0IG1pZ2h0IGZhaWxcbiAqICAgaWYgKCFjb21wb25lbnQuY2FuUmVuZGVyKCkpIHtcbiAqICAgICB0aHJvdyBuZXcgUmVuZGVyaW5nRXJyb3IoJ0NvbXBvbmVudCBjYW5ub3QgYmUgcmVuZGVyZWQnKTtcbiAqICAgfVxuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgY29uc29sZS5lcnJvcignUmVuZGVyaW5nIGZhaWxlZDonLCBlcnJvci5tZXNzYWdlKTtcbiAqIH1cbiAqL1xuZXhwb3J0IGNsYXNzIFJlbmRlcmluZ0Vycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBSZW5kZXJpbmdFcnJvciBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyB0aGUgZXJyb3Igd2l0aCBhIG1lc3NhZ2Ugb3Igb3JpZ2luYWwgZXJyb3JcbiAgICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyBUaGUgZXJyb3IgbWVzc2FnZSBvciBvcmlnaW5hbCBlcnJvclxuICAgKi9cbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgUmVuZGVyaW5nRXJyb3IubmFtZSk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIGZvcm1hdERhdGUsXG4gIE1vZGVsLFxuICBwYXJzZURhdGUsXG4gIFJlc2VydmVkTW9kZWxzLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBIVE1MNURhdGVGb3JtYXQsIEhUTUw1SW5wdXRUeXBlcywgVUlLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBmaW5kTW9kZWxJZCwgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgRmllbGRQcm9wZXJ0aWVzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZnVuY3Rpb24gZm9ybWF0QnlUeXBlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1aS1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRCeVR5cGUoXG4gIHR5cGU6IGFueSxcbiAgdmFsdWU6IGFueSxcbiAgLi4uYXJnczogdW5rbm93bltdXG4pOiBzdHJpbmcgfCBudW1iZXIge1xuICBpZiAodHlwZSA9PT0gVUlLZXlzLkRBVEUpIHtcbiAgICBpZighdmFsdWUpXG4gICAgICAgIHJldHVybiBcIlwiO1xuICAgIGNvbnN0IGZvcm1hdDogc3RyaW5nID0gKGFyZ3Muc2hpZnQoKSBhcyBzdHJpbmcpIHx8IEhUTUw1RGF0ZUZvcm1hdDtcbiAgICByZXR1cm4gZm9ybWF0RGF0ZShuZXcgRGF0ZSh2YWx1ZSksIGZvcm1hdCk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VWYWx1ZUJ5VHlwZShcbiAgdHlwZTogc3RyaW5nLFxuICB2YWx1ZTogc3RyaW5nIHwgbnVtYmVyLFxuICBmaWVsZFByb3BzOiBGaWVsZFByb3BlcnRpZXNcbik6IHN0cmluZyB8IG51bWJlciB8IERhdGUge1xuICBsZXQgcmVzdWx0OiBzdHJpbmcgfCBudW1iZXIgfCBEYXRlIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlIEFycmF5Lm5hbWU6IHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IEFycmF5LmlzQXJyYXkodmFsdWUpID8gIHZhbHVlLm1hcCh2ID0+IHBhcnNlVmFsdWVCeVR5cGUoXG4gICAgICAgIFJlc2VydmVkTW9kZWxzLlNUUklORywgdiwgZmllbGRQcm9wc1xuICAgICAgKSkgOiBbdmFsdWVdO1xuICAgICAgcmVzdWx0ID0gcGFyc2VkLmpvaW4oXCIsXCIpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLk5VTUJFUjpcbiAgICAgIHJlc3VsdCA9IHBhcnNlVG9OdW1iZXIodmFsdWUpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuREFURToge1xuICAgICAgY29uc3QgZm9ybWF0OiBzdHJpbmcgfCB1bmRlZmluZWQgPSBmaWVsZFByb3BzLmZvcm1hdDtcbiAgICAgIGlmKHZhbHVlICYmIGAke3ZhbHVlfWAudHJpbSgpLmxlbmd0aCkge1xuICAgICAgICByZXN1bHQgPVxuICAgICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gUmVzZXJ2ZWRNb2RlbHMuTlVNQkVSXG4gICAgICAgICAgICA/IG5ldyBEYXRlKHZhbHVlKVxuICAgICAgICAgICAgOiB2YWx1ZVxuICAgICAgICAgICAgICA/IGZvcm1hdFxuICAgICAgICAgICAgICAgID8gcGFyc2VEYXRlKGZvcm1hdCwgdmFsdWUpXG4gICAgICAgICAgICAgICAgOiBuZXcgRGF0ZSh2YWx1ZSlcbiAgICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgZGVmYXVsdDpcbiAgICAgIHJlc3VsdCA9IFxuICAgICAgICB0eXBlb2YgdmFsdWUgPT09IFJlc2VydmVkTW9kZWxzLk9CSkVDVCA/IFxuICAgICAgICAgIChBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlLmpvaW4oXCIsXCIpIDogSlNPTi5zdHJpbmdpZnkodmFsdWUpKSA6XG4gICAgICAgICAgICB0eXBlb2YgdmFsdWUgPT09IFJlc2VydmVkTW9kZWxzLkJPT0xFQU4gP1xuICAgICAgICAgICAgICB2YWx1ZSA6IHR5cGVvZiB2YWx1ZSA9PT0gUmVzZXJ2ZWRNb2RlbHMuU1RSSU5HID8gXG4gICAgICAgICAgICAgICAgZXNjYXBlSHRtbCh2YWx1ZSBhcyBzdHJpbmcpIDogcmVzdWx0O1xuICB9XG4gIGlmICh0eXBlb2YgcmVzdWx0ID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIHBhcnNlIHZhbHVlIG9mIHR5cGUgJHt0eXBlfSBmcm9tICR7dHlwZW9mIHZhbHVlfSAtICR7dmFsdWV9YFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVG9OdW1iZXIodmFsdWU6IHN0cmluZyB8IG51bWJlcikge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiICYmICFpc05hTih2YWx1ZSkpIHJldHVybiB2YWx1ZTtcblxuICBjb25zdCBwYXJzZWQgPSBOdW1iZXIodmFsdWUpO1xuICBpZiAoIWlzTmFOKHBhcnNlZCkpIHJldHVybiBwYXJzZWQ7XG5cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZUh0bWwodmFsdWU6IHN0cmluZykge1xuICBpZiAoIXZhbHVlKSByZXR1cm4gdmFsdWU7XG5cbiAgY29uc3QgdGFnc1RvUmVwbGFjZTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICBcIiZcIjogXCImYW1wO1wiLFxuICAgIFwiPFwiOiBcIiZsdDtcIixcbiAgICBcIj5cIjogXCImZ3Q7XCIsXG4gIH07XG4gIHJldHVybiBgJHt2YWx1ZX1gLnJlcGxhY2UoL1smPD5dL2csICh0YWcpID0+IHtcbiAgICByZXR1cm4gdGFnc1RvUmVwbGFjZVt0YWddIHx8IHRhZztcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXZlcnRIdG1sKHZhbHVlOiBzdHJpbmcpIHtcbiAgY29uc3QgdGFnc1RvUmVwbGFjZTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICBcIiZhbXA7XCI6IFwiJlwiLFxuICAgIFwiJmx0O1wiOiBcIjxcIixcbiAgICBcIiZndDtcIjogXCI+XCIsXG4gIH07XG5cbiAgcmV0dXJuIGAke3ZhbHVlfWAucmVwbGFjZSgvJmx0O3wmZ3Q7fCZhbXA7L2csICh0YWcpID0+IHtcbiAgICByZXR1cm4gdGFnc1RvUmVwbGFjZVt0YWddIHx8IHRhZztcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVVJTW9kZWxJRDxNIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBNKSB7XG4gIGxldCBpZDogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50O1xuICB0cnkge1xuICAgIGlkID0gZmluZE1vZGVsSWQobW9kZWwpIGFzIHN0cmluZyB8IG51bWJlcjtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICBpZCA9IERhdGUubm93KCk7XG4gIH1cbiAgY29uc3QgbmFtZSA9IG1vZGVsLmNvbnN0cnVjdG9yLm5hbWU7XG4gIHJldHVybiBgJHtuYW1lfS0ke2lkfWA7XG59XG4iLCJpbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICBDb25zdHJ1Y3RvcixcbiAgTW9kZWwsXG4gIE1vZGVsQ29uc3RydWN0b3IsXG4gIFJlc2VydmVkTW9kZWxzLFxuICBWYWxpZGF0aW9uS2V5cyxcbiAgVmFsaWRhdGlvbk1ldGFkYXRhLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQge1xuICBIVE1MNURhdGVGb3JtYXQsXG4gIEhUTUw1SW5wdXRUeXBlcyxcbiAgVUlLZXlzLFxuICBWYWxpZGF0YWJsZUJ5QXR0cmlidXRlLFxuICBWYWxpZGF0YWJsZUJ5VHlwZSxcbn0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQge1xuICBDcnVkT3BlcmF0aW9uS2V5cyxcbiAgRmllbGREZWZpbml0aW9uLFxuICBGaWVsZFByb3BlcnRpZXMsXG4gIFVJQ2xhc3NNZXRhZGF0YSxcbiAgVUlFbGVtZW50TWV0YWRhdGEsXG4gIFVJTGlzdEl0ZW1FbGVtZW50TWV0YWRhdGEsXG4gIFVJTW9kZWxNZXRhZGF0YSxcbiAgVUlQcm9wTWV0YWRhdGEsXG59IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBSZW5kZXJpbmdFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgRGVjb3JhdG9yTWV0YWRhdGEsIFJlZmxlY3Rpb24gfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IGZvcm1hdEJ5VHlwZSwgZ2VuZXJhdGVVSU1vZGVsSUQgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBYnN0cmFjdCBjbGFzcyBmb3IgcmVuZGVyaW5nIFVJIGNvbXBvbmVudHMgYmFzZWQgb24gbW9kZWwgbWV0YWRhdGEuXG4gKiBAc3VtbWFyeSBUaGUgUmVuZGVyaW5nRW5naW5lIGNsYXNzIHByb3ZpZGVzIGEgZnJhbWV3b3JrIGZvciBjb252ZXJ0aW5nIG1vZGVsIG1ldGFkYXRhIGludG8gVUkgZmllbGQgZGVmaW5pdGlvbnMuXG4gKiBJdCBoYW5kbGVzIHRoZSB0cmFuc2xhdGlvbiBvZiBtb2RlbCBwcm9wZXJ0aWVzIHRvIFVJIGVsZW1lbnRzLCBhcHBsaWVzIHZhbGlkYXRpb24gcnVsZXMsIGFuZCBtYW5hZ2VzIGRpZmZlcmVudCByZW5kZXJpbmcgZmxhdm9ycy5cbiAqIFRoaXMgY2xhc3MgaXMgZGVzaWduZWQgdG8gYmUgZXh0ZW5kZWQgYnkgc3BlY2lmaWMgcmVuZGVyaW5nIGltcGxlbWVudGF0aW9ucy5cbiAqXG4gKiBAdGVtcGxhdGUgVCBUaGUgdHlwZSBvZiB0aGUgcmVuZGVyaW5nIHJlc3VsdCwgZGVmYXVsdHMgdG8gdm9pZFxuICogQHRlbXBsYXRlIFIgVGhlIHR5cGUgb2YgdGhlIGZpZWxkIGRlZmluaXRpb24sIGRlZmF1bHRzIHRvIEZpZWxkRGVmaW5pdGlvbjxUPlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIC0gVGhlIGZsYXZvciBvZiB0aGUgcmVuZGVyaW5nIGVuZ2luZS5cbiAqXG4gKiBAY2xhc3MgUmVuZGVyaW5nRW5naW5lXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZW5kZXJpbmdFbmdpbmU8VCA9IHZvaWQsIFIgPSBGaWVsZERlZmluaXRpb248VD4+IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDYWNoZSBmb3Igc3RvcmluZyByZW5kZXJpbmcgZW5naW5lIGluc3RhbmNlcyBvciBjb25zdHJ1Y3RvcnMuXG4gICAqIEBwcml2YXRlXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGNhY2hlOiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIHwgQ29uc3RydWN0b3I8UmVuZGVyaW5nRW5naW5lPHVua25vd24sIHVua25vd24+PlxuICAgIHwgUmVuZGVyaW5nRW5naW5lPHVua25vd24sIHVua25vd24+XG4gID4gPSB7fTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBjdXJyZW50bHkgYWN0aXZlIHJlbmRlcmluZyBlbmdpbmUuXG4gICAqIEBwcml2YXRlXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGN1cnJlbnQ6XG4gICAgfCBDb25zdHJ1Y3RvcjxSZW5kZXJpbmdFbmdpbmU8dW5rbm93biwgdW5rbm93bj4+XG4gICAgfCBSZW5kZXJpbmdFbmdpbmU8dW5rbm93biwgdW5rbm93bj47XG5cbiAgLyoqXG4gICAqIEZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSByZW5kZXJpbmcgZW5naW5lIGhhcyBiZWVuIGluaXRpYWxpemVkLlxuICAgKi9cbiAgcHJvdGVjdGVkIGluaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGZsYXZvdXI6IHN0cmluZykge1xuICAgIFJlbmRlcmluZ0VuZ2luZS5yZWdpc3Rlcih0aGlzKTtcbiAgICBjb25zb2xlLmxvZyhgZGVjYWYncyAke2ZsYXZvdXJ9IHJlbmRlcmluZyBlbmdpbmUgbG9hZGVkYCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSByZW5kZXJpbmcgZW5naW5lLlxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdG8gYmUgaW1wbGVtZW50ZWQgYnkgc3ViY2xhc3NlcyBmb3Igc3BlY2lmaWMgaW5pdGlhbGl6YXRpb24gbG9naWMuXG4gICAqXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgbmVlZGVkIGZvciBpbml0aWFsaXphdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gaW5pdGlhbGl6YXRpb24gaXMgY29tcGxldGUuXG4gICAqXG4gICAqIEBhYnN0cmFjdFxuICAgKi9cbiAgYWJzdHJhY3QgaW5pdGlhbGl6ZSguLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUcmFuc2xhdGVzIGJldHdlZW4gbW9kZWwgdHlwZXMgYW5kIEhUTUwgaW5wdXQgdHlwZXMuXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIG1vZGVsIGRhdGEgdHlwZXMgdG8gYXBwcm9wcmlhdGUgSFRNTCBpbnB1dCB0eXBlcyBhbmQgdmljZSB2ZXJzYS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBrZXkgdG8gdHJhbnNsYXRlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFt0b1ZpZXc9dHJ1ZV0gLSBEaXJlY3Rpb24gb2YgdHJhbnNsYXRpb24gKHRydWUgZm9yIG1vZGVsIHRvIHZpZXcsIGZhbHNlIGZvciB2aWV3IHRvIG1vZGVsKS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyYW5zbGF0ZWQgdHlwZS5cbiAgICovXG4gIHRyYW5zbGF0ZShrZXk6IHN0cmluZywgdG9WaWV3OiBib29sZWFuID0gdHJ1ZSk6IHN0cmluZyB7XG4gICAgaWYgKHRvVmlldykge1xuICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSBSZXNlcnZlZE1vZGVscy5TVFJJTkc6XG4gICAgICAgICAgcmV0dXJuIEhUTUw1SW5wdXRUeXBlcy5URVhUO1xuICAgICAgICBjYXNlIFJlc2VydmVkTW9kZWxzLk5VTUJFUjpcbiAgICAgICAgY2FzZSBSZXNlcnZlZE1vZGVscy5CSUdJTlQ6XG4gICAgICAgICAgcmV0dXJuIEhUTUw1SW5wdXRUeXBlcy5OVU1CRVI7XG4gICAgICAgIGNhc2UgUmVzZXJ2ZWRNb2RlbHMuQk9PTEVBTjpcbiAgICAgICAgICByZXR1cm4gSFRNTDVJbnB1dFR5cGVzLkNIRUNLQk9YO1xuICAgICAgICBjYXNlIFJlc2VydmVkTW9kZWxzLkRBVEU6XG4gICAgICAgICAgcmV0dXJuIEhUTUw1SW5wdXRUeXBlcy5EQVRFO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlIEhUTUw1SW5wdXRUeXBlcy5TRUxFQ1Q6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLlRFWFQ6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLkVNQUlMOlxuICAgICAgICBjYXNlIEhUTUw1SW5wdXRUeXBlcy5DT0xPUjpcbiAgICAgICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuUEFTU1dPUkQ6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLlRFTDpcbiAgICAgICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuVVJMOlxuICAgICAgICBjYXNlIEhUTUw1SW5wdXRUeXBlcy5TRUFSQ0g6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLkhJRERFTjpcbiAgICAgICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuVEVYVEFSRUE6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLlJBRElPOlxuICAgICAgICAgIHJldHVybiBSZXNlcnZlZE1vZGVscy5TVFJJTkc7XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLk5VTUJFUjpcbiAgICAgICAgICByZXR1cm4gUmVzZXJ2ZWRNb2RlbHMuTlVNQkVSO1xuICAgICAgICBjYXNlIEhUTUw1SW5wdXRUeXBlcy5DSEVDS0JPWDogXG4gICAgICAgICAgcmV0dXJuIFJlc2VydmVkTW9kZWxzLkJPT0xFQU47XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLkRBVEU6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLkRBVEVUSU1FX0xPQ0FMOlxuICAgICAgICBjYXNlIEhUTUw1SW5wdXRUeXBlcy5USU1FOlxuICAgICAgICAgIHJldHVybiBSZXNlcnZlZE1vZGVscy5EQVRFO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ga2V5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgY2xhc3MgZGVjb3JhdG9yIG1ldGFkYXRhIGZvciBhIG1vZGVsIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IEV4dHJhY3RzIFVJLXJlbGF0ZWQgY2xhc3MgZGVjb3JhdG9ycyBmcm9tIGEgbW9kZWwgYW5kIHJldHVybnMgdGhlbSBhcyBhbiBhcnJheVxuICAgKiBUaGlzIG1ldGhvZCBjb2xsZWN0cyBtZXRhZGF0YSBmcm9tIHZhcmlvdXMgVUkgY2xhc3MgZGVjb3JhdG9ycyBpbmNsdWRpbmcgQHVpbW9kZWwsXG4gICAqIEB1aWxpc3RpdGVtLCBAdWloYW5kbGVycywgYW5kIEB1aWxheW91dCBhcHBsaWVkIHRvIHRoZSBtb2RlbCBjbGFzcy5cbiAgICpcbiAgICogQHRlbXBsYXRlIE0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBleHRyYWN0IG1ldGFkYXRhIGZyb21cbiAgICogQHJldHVybnMge1VJQ2xhc3NNZXRhZGF0YVtdfSBBcnJheSBvZiBVSSBjbGFzcyBtZXRhZGF0YSBvYmplY3RzXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGdldENsYXNzRGVjb3JhdG9yc01ldGFkYXRhPE0gZXh0ZW5kcyBNb2RlbD4obW9kZWw6IE0pOiBVSUNsYXNzTWV0YWRhdGFbXSAge1xuICAgIHJldHVybiBbXG4gICAgICBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgICBSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5VSU1PREVMKSxcbiAgICAgICAgbW9kZWwuY29uc3RydWN0b3JcbiAgICAgICkgfHxcbiAgICAgIFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICAgIFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLlVJTU9ERUwpLFxuICAgICAgICBNb2RlbC5nZXQobW9kZWwuY29uc3RydWN0b3IubmFtZSkgYXMgYW55XG4gICAgICApLFxuICAgICAgUmVmbGVjdC5nZXRNZXRhZGF0YShcbiAgICAgICAgUmVuZGVyaW5nRW5naW5lLmtleShVSUtleXMuVUlMSVNUSVRFTSksXG4gICAgICAgIG1vZGVsLmNvbnN0cnVjdG9yXG4gICAgICApIHx8XG4gICAgICBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgICBSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5VSUxJU1RJVEVNKSxcbiAgICAgICAgTW9kZWwuZ2V0KG1vZGVsLmNvbnN0cnVjdG9yLm5hbWUpIGFzIGFueVxuICAgICAgKSxcbiAgICAgIFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICAgIFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLkhBTkRMRVJTKSxcbiAgICAgICAgbW9kZWwuY29uc3RydWN0b3JcbiAgICAgICkgfHxcbiAgICAgIFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICAgIFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLkhBTkRMRVJTKSxcbiAgICAgICAgTW9kZWwuZ2V0KG1vZGVsLmNvbnN0cnVjdG9yLm5hbWUpIGFzIGFueVxuICAgICAgKSxcbiAgICAgIFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICAgIFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLlVJTEFZT1VUKSxcbiAgICAgICAgbW9kZWwuY29uc3RydWN0b3JcbiAgICAgICkgfHxcbiAgICAgIFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICAgIFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLlVJTEFZT1VUKSxcbiAgICAgICAgTW9kZWwuZ2V0KG1vZGVsLmNvbnN0cnVjdG9yLm5hbWUpIGFzIGFueVxuICAgICAgKSxcbiAgICBdLmZpbHRlcihCb29sZWFuKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2hlY2tzIGlmIGEgdHlwZSBpcyB2YWxpZGF0YWJsZSBieSBpdHMgbmF0dXJlLlxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIGlmIGEgZ2l2ZW4gVUkga2V5IHJlcHJlc2VudHMgYSB0eXBlIHRoYXQgaXMgaW5oZXJlbnRseSB2YWxpZGF0YWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBVSSBrZXkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB0eXBlIGlzIHZhbGlkYXRhYmxlLCBmYWxzZSBvdGhlcndpc2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgaXNWYWxpZGF0YWJsZUJ5VHlwZShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhWYWxpZGF0YWJsZUJ5VHlwZSkuaW5jbHVkZXMoa2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2hlY2tzIGlmIGEgdHlwZSBpcyB2YWxpZGF0YWJsZSBieSBhdHRyaWJ1dGUuXG4gICAqIEBzdW1tYXJ5IERldGVybWluZXMgaWYgYSBnaXZlbiBVSSBrZXkgcmVwcmVzZW50cyBhIHZhbGlkYXRpb24gdGhhdCBjYW4gYmUgYXBwbGllZCBhcyBhbiBhdHRyaWJ1dGUuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgVUkga2V5IHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdHlwZSBpcyB2YWxpZGF0YWJsZSBieSBhdHRyaWJ1dGUsIGZhbHNlIG90aGVyd2lzZS5cbiAgICovXG4gIHByb3RlY3RlZCBpc1ZhbGlkYXRhYmxlQnlBdHRyaWJ1dGUoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMoVmFsaWRhdGFibGVCeUF0dHJpYnV0ZSkuaW5jbHVkZXMoa2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udmVydHMgdmFsaWRhdGlvbiBtZXRhZGF0YSB0byBhbiBhdHRyaWJ1dGUgdmFsdWUuXG4gICAqIEBzdW1tYXJ5IFRyYW5zZm9ybXMgdmFsaWRhdGlvbiBtZXRhZGF0YSBpbnRvIGEgdmFsdWUgc3VpdGFibGUgZm9yIHVzZSBhcyBhbiBIVE1MIGF0dHJpYnV0ZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSB2YWxpZGF0aW9uIGtleS5cbiAgICogQHBhcmFtIHtWYWxpZGF0aW9uTWV0YWRhdGF9IHZhbHVlIC0gVGhlIHZhbGlkYXRpb24gbWV0YWRhdGEuXG4gICAqIEByZXR1cm5zIHtzdHJpbmcgfCBudW1iZXIgfCBib29sZWFufSBUaGUgY29udmVydGVkIGF0dHJpYnV0ZSB2YWx1ZS5cbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBnaXZlbiBrZXkgaXMgbm90IHZhbGlkYXRhYmxlIGJ5IGF0dHJpYnV0ZS5cbiAgICovXG4gIHByb3RlY3RlZCB0b0F0dHJpYnV0ZVZhbHVlKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWxpZGF0aW9uTWV0YWRhdGFcbiAgKTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB7XG4gICAgaWYgKCFPYmplY3Qua2V5cyhWYWxpZGF0YWJsZUJ5QXR0cmlidXRlKS5pbmNsdWRlcyhrZXkpKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSW52YWxpZCBhdHRyaWJ1dGUga2V5IFwiJHtrZXl9XCIuIEV4cGVjdGVkIG9uZSBvZjogJHtPYmplY3Qua2V5cyhWYWxpZGF0YWJsZUJ5QXR0cmlidXRlKS5qb2luKFwiLCBcIil9LmBcbiAgICAgICk7XG5cbiAgICByZXR1cm4ga2V5ID09PSBVSUtleXMuUkVRVUlSRUQgPyB0cnVlIDogdmFsdWVba2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udmVydHMgYSBtb2RlbCB0byBhIGZpZWxkIGRlZmluaXRpb24uXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBhIG1vZGVsIGluc3RhbmNlLCBleHRyYWN0aW5nIFVJLXJlbGF0ZWQgbWV0YWRhdGEgYW5kIHZhbGlkYXRpb24gcnVsZXMgdG8gY3JlYXRlIGEgZmllbGQgZGVmaW5pdGlvbi5cbiAgICpcbiAgICogQHRlbXBsYXRlIE0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHRlbXBsYXRlIFQgVHlwZSByZWZlcmVuY2luZyB0aGUgc3BlY2lmaWMgUmVuZGVyaW5nIGVuZ2luZSBmaWVsZCBwcm9wZXJ0aWVzL2lucHV0c1xuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIGNvbnZlcnQuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IFtnbG9iYWxQcm9wcz17fV0gLSBHbG9iYWwgcHJvcGVydGllcyB0byBhcHBseSB0byBhbGwgY2hpbGQgZWxlbWVudHMuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2dlbmVyYXRlSWQ9dHJ1ZV0gLSBGbGFnIGluZGljYXRpbmcgd2hldGhlciB0byBwb3B1bGF0ZSB0aGUgcmVuZGVyZXJJZCBwcm9wZXJ0eS5cbiAgICogQHJldHVybnMge0ZpZWxkRGVmaW5pdGlvbjxUPn0gQSBmaWVsZCBkZWZpbml0aW9uIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIFVJIHN0cnVjdHVyZSBvZiB0aGUgbW9kZWwuXG4gICAqIEB0aHJvd3Mge1JlbmRlcmluZ0Vycm9yfSBJZiBubyBVSSBkZWZpbml0aW9ucyBhcmUgc2V0IGZvciB0aGUgbW9kZWwgb3IgaWYgdGhlcmUgYXJlIGludmFsaWQgZGVjb3JhdG9ycy5cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudFxuICAgKiAgcGFydGljaXBhbnQgUkUgYXMgUmVuZGVyaW5nRW5naW5lXG4gICAqICBwYXJ0aWNpcGFudCBSIGFzIFJlZmxlY3Rpb25cbiAgICogIHBhcnRpY2lwYW50IE0gYXMgTW9kZWxcbiAgICogIEMtPj5SRTogdG9GaWVsZERlZmluaXRpb24obW9kZWwsIGdsb2JhbFByb3BzKVxuICAgKiAgUkUtPj5SOiBnZXRNZXRhZGF0YShVSUtleXMuVUlNT0RFTCwgbW9kZWwuY29uc3RydWN0b3IpXG4gICAqICBSLS0+PlJFOiBVSU1vZGVsTWV0YWRhdGFcbiAgICogIFJFLT4+UjogZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzKG1vZGVsLCBVSUtleXMuUkVGTEVDVClcbiAgICogIFItLT4+UkU6IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhW10+XG4gICAqICBSRS0+PlI6IGdldEFsbFByb3BlcnR5RGVjb3JhdG9ycyhtb2RlbCwgVmFsaWRhdGlvbktleXMuUkVGTEVDVClcbiAgICogIFItLT4+UkU6IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT5bXT5cbiAgICogIGxvb3AgRm9yIGVhY2ggcHJvcGVydHlcbiAgICogICAgUkUtPj5SRTogUHJvY2VzcyBVSSBkZWNvcmF0b3JzXG4gICAqICAgIFJFLT4+UkU6IEFwcGx5IHZhbGlkYXRpb24gcnVsZXNcbiAgICogIGVuZFxuICAgKiAgUkUtLT4+QzogRmllbGREZWZpbml0aW9uPFQ+XG4gICAqL1xuICBwcm90ZWN0ZWQgdG9GaWVsZERlZmluaXRpb248TSBleHRlbmRzIE1vZGVsPihcbiAgICBtb2RlbDogTSxcbiAgICBnbG9iYWxQcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fSxcbiAgICBnZW5lcmF0ZUlkOiBib29sZWFuID0gdHJ1ZVxuICApOiBGaWVsZERlZmluaXRpb248VD4ge1xuICAgIFxuICAgIGNvbnN0IHsgaW5oZXJpdFByb3BzLCAuLi5nbG9iYWxQcm9wc1dpdGhvdXRJbmhlcml0cyB9ID0gZ2xvYmFsUHJvcHM7XG4gICAgZ2xvYmFsUHJvcHMgPSBnbG9iYWxQcm9wc1dpdGhvdXRJbmhlcml0cztcblxuICAgIGNvbnN0IGNsYXNzRGVjb3JhdG9ycyA9IHRoaXMuZ2V0Q2xhc3NEZWNvcmF0b3JzTWV0YWRhdGE8TT4obW9kZWwpO1xuXG4gICAgaWYgKCFjbGFzc0RlY29yYXRvcnMubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IFJlbmRlcmluZ0Vycm9yKFxuICAgICAgICBgTm8gdWkgZGVmaW5pdGlvbnMgc2V0IGZvciBtb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9LiBEaWQgeW91IHVzZSBAdWltb2RlbD9gXG4gICAgICApO1xuXG4gICAgY29uc3QgY2xhc3NEZWNvcmF0b3IgPSBPYmplY3QuYXNzaWduKFxuICAgICAge30sXG4gICAgICAuLi5jbGFzc0RlY29yYXRvcnMsXG4gICAgICBpbmhlcml0UHJvcHMgPyBpbmhlcml0UHJvcHMgOiB7fSAvLyBvdmVycmlkZSB0YWcgYW5kIHByb3BlcnRpZXMgd2hlbiBpdCBpcyBhIGNvbXBvbmVudCB0aGF0IHNob3VsZCBpbmhlcml0IHByb3BlcnRpZXMgZnJvbSBpdHMgcGFyZW50LlxuICAgICk7XG4gICAgY29uc3QgeyB0YWcsIHByb3BzLCBpdGVtLCBoYW5kbGVycyB9ID0gY2xhc3NEZWNvcmF0b3I7XG5cbiAgICBjb25zdCB1aURlY29yYXRvcnM6IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhW10+ID1cbiAgICAgIFJlZmxlY3Rpb24uZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzKG1vZGVsLCBVSUtleXMuUkVGTEVDVCkgYXMgUmVjb3JkPFxuICAgICAgICBzdHJpbmcsXG4gICAgICAgIERlY29yYXRvck1ldGFkYXRhW11cbiAgICAgID47XG4gICAgbGV0IGNoaWxkcmVuOiBGaWVsZERlZmluaXRpb248UmVjb3JkPHN0cmluZywgYW55Pj5bXSB8IHVuZGVmaW5lZDtcbiAgICBsZXQgY2hpbGRQcm9wczogUmVjb3JkPHN0cmluZywgYW55PiA9IGl0ZW0/LnByb3BzIHx8IHt9O1xuICAgIGxldCBtYXBwZXI6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBjb25zdCBnZXRQYXRoID0gKHBhcmVudDogc3RyaW5nIHwgdW5kZWZpbmVkLCBwcm9wOiBzdHJpbmcpID0+IHtcbiAgICAgIHJldHVybiBwYXJlbnQgPyBbcGFyZW50LCBwcm9wXS5qb2luKFwiLlwiKSA6IHByb3A7XG4gICAgfTtcblxuICAgIGlmICh1aURlY29yYXRvcnMpIHtcbiAgICAgIGNvbnN0IHZhbGlkYXRpb25EZWNvcmF0b3JzOiBSZWNvcmQ8XG4gICAgICAgIHN0cmluZyxcbiAgICAgICAgRGVjb3JhdG9yTWV0YWRhdGE8VmFsaWRhdGlvbk1ldGFkYXRhPltdXG4gICAgICA+ID0gUmVmbGVjdGlvbi5nZXRBbGxQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgIG1vZGVsLFxuICAgICAgICBWYWxpZGF0aW9uS2V5cy5SRUZMRUNUXG4gICAgICApIGFzIFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT5bXT47XG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiB1aURlY29yYXRvcnMpIHtcbiAgICAgICAgY29uc3QgZGVjcyA9IHVpRGVjb3JhdG9yc1trZXldO1xuICAgICAgICBjb25zdCB0eXBlcyA9IE9iamVjdC52YWx1ZXMoZGVjcykuZmlsdGVyKCh7a2V5fSkgPT4gW1VJS2V5cy5QUk9QLCBVSUtleXMuRUxFTUVOVCwgVUlLZXlzLkNISUxEXS5pbmNsdWRlcyhrZXkpKTtcbiAgICAgICAgaWYgKHR5cGVzPy5sZW5ndGggPiAxKVxuICAgICAgICAgIHRocm93IG5ldyBSZW5kZXJpbmdFcnJvcihcbiAgICAgICAgICAgIGBPbmx5IG9uZSB0eXBlIG9mIGRlY29yYXRpb24gaXMgYWxsb3dlZC4gUGxlYXNlIGNob29zZSBiZXR3ZWVuIEB1aXByb3AsIEB1aWNoaWxkIG9yIEB1aWVsZW1lbnRgXG4gICAgICAgICAgKTtcbiAgICAgICAgY29uc3QgaGFzSGlkZU9uRGVjb3JhdG9yID0gZGVjcy5maW5kKCh7IGtleSB9KSA9PiBrZXkgPT09IFVJS2V5cy5ISURERU4pO1xuICAgICAgICBpZihoYXNIaWRlT25EZWNvcmF0b3IpIHtcbiAgICAgICAgICBjb25zdCBoYXNVaUVsZW1lbnREZWNvcmF0b3IgPSBkZWNzLmZpbmQoKHsga2V5IH0pID0+IGtleSA9PT0gVUlLZXlzLkVMRU1FTlQpO1xuICAgICAgICAgIGlmKCFoYXNVaUVsZW1lbnREZWNvcmF0b3IpXG4gICAgICAgICAgICB0aHJvdyBuZXcgUmVuZGVyaW5nRXJyb3IoYEB1aWVsZW1lbnQgbm8gZm91bmQgaW4gXCIke2tleX1cIi4gSXQgaXMgcmVxdWlyZWQgdG8gdXNlIGhpZGRlbk9uIGRlY29yYXRvci5gKTtcblxuICAgICAgICB9XG4gICAgICAgIGRlY3Muc2hpZnQoKTtcbiAgICAgICAgY29uc3Qgc29ydGVkID0gZGVjcy5zb3J0KChhKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGEua2V5ID09PSBVSUtleXMuRUxFTUVOVCA/IC0xIDogMTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNvcnRlZC5mb3JFYWNoKChkZWMpID0+IHtcbiAgICAgICAgICBpZiAoIWRlYykgdGhyb3cgbmV3IFJlbmRlcmluZ0Vycm9yKGBObyBkZWNvcmF0b3IgZm91bmRgKTtcblxuICAgICAgICAgIHN3aXRjaCAoZGVjLmtleSkge1xuICAgICAgICAgICAgY2FzZSBVSUtleXMuUFJPUDoge1xuICAgICAgICAgICAgICBjaGlsZFByb3BzW2tleV0gPSBkZWMucHJvcHMgYXMgVUlQcm9wTWV0YWRhdGE7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBVSUtleXMuQ0hJTEQ6IHtcbiAgICAgICAgICAgICAgaWYgKCFNb2RlbC5pc1Byb3BlcnR5TW9kZWwobW9kZWwsIGtleSkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJlbmRlcmluZ0Vycm9yKGBDaGlsZCBcIiR7a2V5fVwiIG11c3QgYmUgYSBtb2RlbC5gKTtcblxuICAgICAgICAgICAgICBsZXQgQ2xheno7XG4gICAgICAgICAgICAgIGNvbnN0IHN1Ym1vZGVsID0gKG1vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2tleV0gYXMgTW9kZWw7XG4gICAgICAgICAgICAgIGNvbnN0IGNvbnN0cnVjdGFibGUgPVxuICAgICAgICAgICAgICAgIHR5cGVvZiBzdWJtb2RlbCA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgICAgICAgICAgIHN1Ym1vZGVsICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgIUFycmF5LmlzQXJyYXkoc3VibW9kZWwpO1xuICAgICAgICAgICAgICAvLyBjcmVhdGUgaW5zdGFuY2UgaWYgdW5kZWZpbmVkXG4gICAgICAgICAgICAgIGlmICghY29uc3RydWN0YWJsZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNsYXp6TmFtZSA9IChkZWMucHJvcHMucHJvcHMgYXMgUmVjb3JkPHN0cmluZywgYW55PilcbiAgICAgICAgICAgICAgICAgID8ubmFtZSBhcyBzdHJpbmc7XG4gICAgICAgICAgICAgICAgQ2xhenogPSBuZXcgKE1vZGVsLmdldChjbGF6ek5hbWUpIGFzIE1vZGVsQ29uc3RydWN0b3I8TW9kZWw+KSgpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBbXTtcbiAgICAgICAgICAgICAgY29uc3QgY2hpbGRyZW5HbG9iYWxQcm9wcyA9IE9iamVjdC5hc3NpZ24oe30sIGdsb2JhbFByb3BzIHx8IHt9LCB7XCJtb2RlbFwiOiBDbGF6en0gLHtcbiAgICAgICAgICAgICAgICBpbmhlcml0UHJvcHM6IGRlYy5wcm9wcyBhcyBVSU1vZGVsTWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgY2hpbGRPZjogZ2V0UGF0aChnbG9iYWxQcm9wcz8uY2hpbGRPZiBhcyBzdHJpbmcsIGtleSksXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBjb25zdCBjaGlsZERlZmluaXRpb24gPSB0aGlzLnRvRmllbGREZWZpbml0aW9uKFxuICAgICAgICAgICAgICAgIHN1Ym1vZGVsIHx8IENsYXp6LCAvLyBNdXN0IGF2b2lkIHVuZGVmaW5lZCB2YWx1ZXMg4oCUIGFuIGluc3RhbmNlIGlzIHJlcXVpcmVkIHRvIHJldHJpZXZlIHByb3BlcnRpZXMuXG4gICAgICAgICAgICAgICAgY2hpbGRyZW5HbG9iYWxQcm9wcyxcbiAgICAgICAgICAgICAgICBmYWxzZVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBjaGlsZHJlbi5wdXNoKFxuICAgICAgICAgICAgICAgIGNoaWxkRGVmaW5pdGlvbiBhcyBGaWVsZERlZmluaXRpb248UmVjb3JkPHN0cmluZywgYW55Pj5cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlIFVJS2V5cy5VSUxJU1RQUk9QOiB7XG4gICAgICAgICAgICAgIG1hcHBlciA9IG1hcHBlciB8fCB7fTtcbiAgICAgICAgICAgICAgaWYoZGVjLnByb3BzPy5uYW1lKVxuICAgICAgICAgICAgICAgIG1hcHBlcltkZWMucHJvcHM/Lm5hbWUgYXMgc3RyaW5nXSA9IGtleTtcbiAgICAgICAgICAgICAgY29uc3QgcHJvcHMgPSBPYmplY3QuYXNzaWduKFxuICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgIGNsYXNzRGVjb3JhdG9yLnByb3BzPy5pdGVtIHx8IHt9LFxuICAgICAgICAgICAgICAgIGl0ZW0/LnByb3BzIHx8IHt9LFxuICAgICAgICAgICAgICAgIGRlYy5wcm9wcz8ucHJvcHMgfHwge30sXG4gICAgICAgICAgICAgICAgZ2xvYmFsUHJvcHNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY2hpbGRQcm9wcyA9IHtcbiAgICAgICAgICAgICAgICB0YWc6IGl0ZW0/LnRhZyB8fCBwcm9wcy5yZW5kZXIgfHwgXCJcIixcbiAgICAgICAgICAgICAgICBwcm9wczogT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgICAgICAgIHt9LCBcbiAgICAgICAgICAgICAgICAgIGNoaWxkUHJvcHM/LnByb3BzLCBcbiAgICAgICAgICAgICAgICAgIHsgbWFwcGVyIH0sIFxuICAgICAgICAgICAgICAgICAgcHJvcHMpLFxuICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBVSUtleXMuSElEREVOOiBcbiAgICAgICAgICAgIGNhc2UgVUlLZXlzLk9SREVSOiBcbiAgICAgICAgICAgIGNhc2UgVUlLZXlzLlVJTEFZT1VUSVRFTTogXG4gICAgICAgICAgICBjYXNlIFVJS2V5cy5FTEVNRU5UOiB7XG4gICAgICAgICAgICAgIGNoaWxkcmVuID0gY2hpbGRyZW4gfHwgW107XG4gICAgICAgICAgICAgIGNvbnN0IHVpUHJvcHM6IFVJRWxlbWVudE1ldGFkYXRhID0gZGVjLnByb3BzIGFzIFVJRWxlbWVudE1ldGFkYXRhO1xuICAgICAgICAgICAgICBjb25zdCBwcm9wcyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICAgIGNoaWxkUHJvcHM/LnByb3BzLFxuICAgICAgICAgICAgICAgICAgdWlQcm9wcy5wcm9wcyB8fCB7fSxcbiAgICAgICAgICAgICAgICAgICh1aVByb3BzPy5wcm9wcz8ubmFtZSA/IHtcbiAgICAgICAgICAgICAgICAgICAgcGF0aDogZ2V0UGF0aChcbiAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxQcm9wcz8uY2hpbGRPZiBhcyBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgdWlQcm9wcy5wcm9wcyEubmFtZVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBjaGlsZE9mOiB1bmRlZmluZWQsIC8vIFRoZSBjaGlsZE9mIHByb3AgaXMgcGFzc2VkIGJ5IGdsb2JhbFByb3BzIHdoZW4gaXQgaXMgYSBuZXN0ZWQgcHJvcFxuICAgICAgICAgICAgICAgICAgfSA6IHt9KSxcbiAgICAgICAgICAgICAgICAgIGdsb2JhbFByb3BzXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjaGlsZERlZmluaXRpb246IEZpZWxkRGVmaW5pdGlvbjxSZWNvcmQ8c3RyaW5nLCBhbnk+PiA9IHtcbiAgICAgICAgICAgICAgICAgIHRhZzogIHVpUHJvcHMudGFnIHx8IGNoaWxkUHJvcHM/LnRhZyB8fCB0YWcgfHwgXCJcIixcbiAgICAgICAgICAgICAgICAgIHByb3BzLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGlmKGRlYy5rZXkgPT09IFVJS2V5cy5FTEVNRU5UKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsaWRhdGlvbkRlY3MgPSB2YWxpZGF0aW9uRGVjb3JhdG9yc1trZXldIGFzIERlY29yYXRvck1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT5bXTtcbiAgICAgICAgICAgICAgICBjb25zdCB0eXBlRGVjID0gdmFsaWRhdGlvbkRlY3Muc2hpZnQoKSBhcyBEZWNvcmF0b3JNZXRhZGF0YTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGRlYyBvZiB2YWxpZGF0aW9uRGVjcykge1xuICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNWYWxpZGF0YWJsZUJ5QXR0cmlidXRlKGRlYy5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkRGVmaW5pdGlvbi5wcm9wc1t0aGlzLnRyYW5zbGF0ZShkZWMua2V5KV0gPSB0aGlzLnRvQXR0cmlidXRlVmFsdWUoZGVjLmtleSwgZGVjLnByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1ZhbGlkYXRhYmxlQnlUeXBlKGRlYy5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZWMua2V5ID09PSBIVE1MNUlucHV0VHlwZXMuREFURSkge1xuICAgICAgICAgICAgICAgICAgICAgIGNoaWxkRGVmaW5pdGlvbi5wcm9wc1tVSUtleXMuRk9STUFUXSA9IGRlYy5wcm9wcy5mb3JtYXQgfHwgSFRNTDVEYXRlRm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkRGVmaW5pdGlvbi5wcm9wc1tVSUtleXMuVFlQRV0gPSBkZWMua2V5O1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkRGVmaW5pdGlvbi5wcm9wc1tVSUtleXMuVFlQRV0pIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGJhc2ljVHlwZSA9ICh0eXBlRGVjLnByb3BzIGFzIHsgbmFtZTogc3RyaW5nIH0pLm5hbWU7XG4gICAgICAgICAgICAgICAgICBjaGlsZERlZmluaXRpb24ucHJvcHNbVUlLZXlzLlRZUEVdID0gdGhpcy50cmFuc2xhdGUoXG4gICAgICAgICAgICAgICAgICAgIGJhc2ljVHlwZS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgICAgICAgICAgICB0cnVlXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNoaWxkRGVmaW5pdGlvbi5wcm9wcy52YWx1ZSA9IGZvcm1hdEJ5VHlwZShcbiAgICAgICAgICAgICAgICAgIGNoaWxkRGVmaW5pdGlvbi5wcm9wc1tVSUtleXMuVFlQRV0sXG4gICAgICAgICAgICAgICAgICBtb2RlbFtrZXkgYXMga2V5b2YgTV0sXG4gICAgICAgICAgICAgICAgICBjaGlsZERlZmluaXRpb24ucHJvcHNbVUlLZXlzLkZPUk1BVF1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNoaWxkcmVuLnB1c2goY2hpbGREZWZpbml0aW9uKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjaGlsZCA9IGNoaWxkcmVuLmZpbmQoYyA9PiBjLnByb3BzPy5uYW1lID09PSBrZXkgfHwgZGVjLmtleSA9PT0gVUlLZXlzLlVJTEFZT1VUSVRFTSAmJiBjPy5wcm9wcz8uY2hpbGRPZiA9PT0ga2V5KTtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQpIHtcbiAgICAgICAgICAgICAgICAgIGlmKGRlYy5rZXkgIT09IFVJS2V5cy5VSUxBWU9VVElURU0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGQucHJvcHMgPSBPYmplY3QuYXNzaWduKHt9LCBjaGlsZC5wcm9wcywgeyBbZGVjLmtleV06IHVpUHJvcHMgfSk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7cm93LCBjb2wsIHByb3BzfSA9IGRlYy5wcm9wcztcbiAgICAgICAgICAgICAgICAgICAgICBjaGlsZC5wcm9wcyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAgICAgICAgICAgICAge30sIFxuICAgICAgICAgICAgICAgICAgICAgIHByb3BzIHx8IHt9LFxuICAgICAgICAgICAgICAgICAgICAgIGNoaWxkLnByb3BzLFxuICAgICAgICAgICAgICAgICAgICAgIHJvdyxcbiAgICAgICAgICAgICAgICAgICAgICBjb2xcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgY2hpbGRyZW4ucHVzaChjaGlsZERlZmluaXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHRocm93IG5ldyBSZW5kZXJpbmdFcnJvcihgSW52YWxpZCBrZXk6ICR7ZGVjLmtleX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGdsb2JhbFByb3BzID0gT2JqZWN0LmFzc2lnbih7fSwgcHJvcHMsIGdsb2JhbFByb3BzLCB7XG4gICAgICBoYW5kbGVyczogaGFuZGxlcnMgfHwge30sXG4gICAgfSk7XG5cbiAgICBjb25zdCBvcGVyYXRpb24gPSBnbG9iYWxQcm9wcz8ub3BlcmF0aW9uO1xuICAgIGNoaWxkcmVuID0gY2hpbGRyZW4/LnNvcnQoKGEsIGIpID0+ICgoYT8ucHJvcHM/Lm9yZGVyID8/IDApIC0gKGI/LnByb3BzPy5vcmRlciA/PyAwKSkpXG4gICAgICAuZmlsdGVyKChpdGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IGhpZGRlbk9uID0gKGl0ZW0/LnByb3BzPy5oaWRkZW4gYXMgQ3J1ZE9wZXJhdGlvbktleXNbXSB8fCBbXSk7XG4gICAgICAgIGlmKCFoaWRkZW5Pbj8ubGVuZ3RoKVxuICAgICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgICBpZighaGlkZGVuT24uaW5jbHVkZXMob3BlcmF0aW9uIGFzIENydWRPcGVyYXRpb25LZXlzKSlcbiAgICAgICAgICByZXR1cm4gaXRlbTtcbiAgICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdDogRmllbGREZWZpbml0aW9uPFQ+ID0ge1xuICAgICAgdGFnOiB0YWcsXG4gICAgICBpdGVtOiBjaGlsZFByb3BzIGFzIFVJTGlzdEl0ZW1FbGVtZW50TWV0YWRhdGEsXG4gICAgICBwcm9wczogZ2xvYmFsUHJvcHMgYXMgVCAmIEZpZWxkUHJvcGVydGllcyxcbiAgICAgIGNoaWxkcmVuOiBjaGlsZHJlbiBhcyBGaWVsZERlZmluaXRpb248YW55PltdLFxuICAgIFxuICAgIH07XG5cbiAgICBpZiAoZ2VuZXJhdGVJZCkgcmVzdWx0LnJlbmRlcmVySWQgPSBnZW5lcmF0ZVVJTW9kZWxJRChtb2RlbCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZW5kZXJzIGEgbW9kZWwgd2l0aCBnbG9iYWwgcHJvcGVydGllcyBhbmQgYWRkaXRpb25hbCBhcmd1bWVudHMuXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0byBiZSBpbXBsZW1lbnRlZCBieSBzdWJjbGFzc2VzIHRvIGRlZmluZSBzcGVjaWZpYyByZW5kZXJpbmcgYmVoYXZpb3IuXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBNIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEB0ZW1wbGF0ZSBSIFJlbmRlcmluZyBlbmdpbmUgaW1wbGVtZW50YXRpb24gc3BlY2lmaWMgb3V0cHV0IHR5cGVcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCB0byBiZSByZW5kZXJlZC5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gZ2xvYmFsUHJvcHMgLSBHbG9iYWwgcHJvcGVydGllcyB0byBiZSBhcHBsaWVkIHRvIGFsbCBlbGVtZW50cyBkdXJpbmcgcmVuZGVyaW5nLlxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdGhhdCBtYXkgYmUgcmVxdWlyZWQgZm9yIHNwZWNpZmljIHJlbmRlcmluZyBpbXBsZW1lbnRhdGlvbnMuXG4gICAqIEByZXR1cm5zIHtSfSBUaGUgcmVuZGVyZWQgcmVzdWx0LCB0eXBlIGRlcGVuZHMgb24gdGhlIHNwZWNpZmljIGltcGxlbWVudGF0aW9uLlxuICAgKlxuICAgKiBAYWJzdHJhY3RcbiAgICovXG4gIGFic3RyYWN0IHJlbmRlcjxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG1vZGVsOiBNLFxuICAgIGdsb2JhbFByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBSO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXJzIGEgcmVuZGVyaW5nIGVuZ2luZSBpbnN0YW5jZS5cbiAgICogQHN1bW1hcnkgQWRkcyBhIHJlbmRlcmluZyBlbmdpbmUgdG8gdGhlIHN0YXRpYyBjYWNoZSBhbmQgc2V0cyBpdCBhcyB0aGUgY3VycmVudCBlbmdpbmUuXG4gICAqXG4gICAqIEBwYXJhbSB7UmVuZGVyaW5nRW5naW5lPHVua25vd24sIHVua25vd24+fSBlbmdpbmUgLSBUaGUgcmVuZGVyaW5nIGVuZ2luZSB0byByZWdpc3Rlci5cbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgYW4gZW5naW5lIHdpdGggdGhlIHNhbWUgZmxhdm9yIGFscmVhZHkgZXhpc3RzLlxuICAgKlxuICAgKiBAc3RhdGljXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXIoZW5naW5lOiBSZW5kZXJpbmdFbmdpbmU8dW5rbm93biwgdW5rbm93bj4pIHtcbiAgICBpZiAoZW5naW5lLmZsYXZvdXIgaW4gdGhpcy5jYWNoZSlcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgUmVuZGVyaW5nIGVuZ2luZSB1bmRlciAke2VuZ2luZS5mbGF2b3VyfSBhbHJlYWR5IGV4aXN0c2BcbiAgICAgICk7XG4gICAgdGhpcy5jYWNoZVtlbmdpbmUuZmxhdm91cl0gPSBlbmdpbmU7XG4gICAgdGhpcy5jdXJyZW50ID0gZW5naW5lO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgb3IgaW5pdGlhbGl6ZXMgYSByZW5kZXJpbmcgZW5naW5lLlxuICAgKiBAc3VtbWFyeSBHZXRzIGFuIGV4aXN0aW5nIGVuZ2luZSBpbnN0YW5jZSBvciBjcmVhdGVzIGFuZCBpbml0aWFsaXplcyBhIG5ldyBvbmUgaWYgZ2l2ZW4gYSBjb25zdHJ1Y3Rvci5cbiAgICpcbiAgICogQHRlbXBsYXRlIE8gVGhlIHR5cGUgb2YgdGhlIHJlbmRlcmluZyBlbmdpbmUgb3V0cHV0XG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8UmVuZGVyaW5nRW5naW5lPE8+PiB8IFJlbmRlcmluZ0VuZ2luZTxPPn0gb2JqIC0gVGhlIGVuZ2luZSBpbnN0YW5jZSBvciBjb25zdHJ1Y3Rvci5cbiAgICogQHJldHVybnMge1JlbmRlcmluZ0VuZ2luZTxPPn0gVGhlIGluaXRpYWxpemVkIHJlbmRlcmluZyBlbmdpbmUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldE9yQm9vdDxPPihcbiAgICBvYmo6IENvbnN0cnVjdG9yPFJlbmRlcmluZ0VuZ2luZTxPPj4gfCBSZW5kZXJpbmdFbmdpbmU8Tz5cbiAgKTogUmVuZGVyaW5nRW5naW5lPE8+IHtcbiAgICBpZiAob2JqIGluc3RhbmNlb2YgUmVuZGVyaW5nRW5naW5lKSByZXR1cm4gb2JqIGFzIFJlbmRlcmluZ0VuZ2luZTxPPjtcbiAgICBjb25zdCBlbmdpbmU6IFJlbmRlcmluZ0VuZ2luZTxPPiA9IG5ldyBvYmooKTtcbiAgICBlbmdpbmUuaW5pdGlhbGl6ZSgpOyAvLyBtYWtlIHRoZSBib290aW5nIGFzeW5jLiB1c2UgdGhlIGluaXRpYWxpemVkIGZsYWcgdG8gY29udHJvbCBpdFxuICAgIHJldHVybiBlbmdpbmUgYXMgUmVuZGVyaW5nRW5naW5lPE8+O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSByZW5kZXJpbmcgZW5naW5lIGJ5IGZsYXZvci5cbiAgICogQHN1bW1hcnkgR2V0cyB0aGUgY3VycmVudCByZW5kZXJpbmcgZW5naW5lIG9yIGEgc3BlY2lmaWMgb25lIGJ5IGZsYXZvci5cbiAgICpcbiAgICogQHRlbXBsYXRlIE8gVGhlIHR5cGUgb2YgdGhlIHJlbmRlcmluZyBlbmdpbmUgb3V0cHV0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZmxhdm91cl0gLSBUaGUgZmxhdm9yIG9mIHRoZSByZW5kZXJpbmcgZW5naW5lIHRvIHJldHJpZXZlLlxuICAgKiBAcmV0dXJucyB7UmVuZGVyaW5nRW5naW5lPE8+fSBUaGUgcmVxdWVzdGVkIHJlbmRlcmluZyBlbmdpbmUuXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIHRoZSByZXF1ZXN0ZWQgZmxhdm9yIGRvZXMgbm90IGV4aXN0LlxuICAgKlxuICAgKiBAc3RhdGljXG4gICAqL1xuICBzdGF0aWMgZ2V0PE8+KGZsYXZvdXI/OiBzdHJpbmcpOiBSZW5kZXJpbmdFbmdpbmU8Tz4ge1xuICAgIGlmICghZmxhdm91cilcbiAgICAgIHJldHVybiB0aGlzLmdldE9yQm9vdDxPPihcbiAgICAgICAgdGhpcy5jdXJyZW50IGFzIENvbnN0cnVjdG9yPFJlbmRlcmluZ0VuZ2luZTxPPj4gfCBSZW5kZXJpbmdFbmdpbmU8Tz5cbiAgICAgICk7XG4gICAgaWYgKCEoZmxhdm91ciBpbiB0aGlzLmNhY2hlKSlcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgUmVuZGVyaW5nIGVuZ2luZSB1bmRlciAke2ZsYXZvdXJ9IGRvZXMgbm90IGV4aXN0YFxuICAgICAgKTtcbiAgICByZXR1cm4gdGhpcy5nZXRPckJvb3Q8Tz4oXG4gICAgICB0aGlzLmNhY2hlW2ZsYXZvdXJdIGFzXG4gICAgICAgIHwgQ29uc3RydWN0b3I8UmVuZGVyaW5nRW5naW5lPE8+PlxuICAgICAgICB8IFJlbmRlcmluZ0VuZ2luZTxPPlxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlbmRlcnMgYSBtb2RlbCB1c2luZyB0aGUgYXBwcm9wcmlhdGUgcmVuZGVyaW5nIGVuZ2luZS5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB0aGUgY29ycmVjdCByZW5kZXJpbmcgZW5naW5lIGZvciBhIG1vZGVsIGFuZCBpbnZva2VzIGl0cyByZW5kZXIgbWV0aG9kLlxuICAgKlxuICAgKiBAdGVtcGxhdGUgTSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIHRvIHJlbmRlci5cbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIHJlbmRlciBtZXRob2QuXG4gICAqIEByZXR1cm5zIHthbnl9IFRoZSByZXN1bHQgb2YgdGhlIHJlbmRlcmluZyBwcm9jZXNzLlxuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiBubyByZWdpc3RlcmVkIG1vZGVsIGlzIGZvdW5kLlxuICAgKlxuICAgKiBAc3RhdGljXG4gICAqL1xuICBzdGF0aWMgcmVuZGVyPE0gZXh0ZW5kcyBNb2RlbD4obW9kZWw6IE0sIC4uLmFyZ3M6IGFueVtdKTogYW55IHtcbiAgICBjb25zdCBjb25zdHJ1Y3RvciA9XG4gICAgICBNb2RlbC5nZXQobW9kZWwuY29uc3RydWN0b3IubmFtZSkgfHwgTW9kZWwuZnJvbU9iamVjdChtb2RlbCk7XG4gICAgaWYgKCFjb25zdHJ1Y3RvcikgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJObyBtb2RlbCByZWdpc3RlcmVkIGZvdW5kXCIpO1xuICAgIGNvbnN0IGZsYXZvdXIgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgUmVuZGVyaW5nRW5naW5lLmtleShVSUtleXMuUkVOREVSRURfQlkpLFxuICAgICAgY29uc3RydWN0b3IgYXMgTW9kZWxDb25zdHJ1Y3RvcjxNb2RlbD5cbiAgICApO1xuXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBmb3IgdGhlIHZhciBhcmdzIHR5cGUgY2hlY2tcbiAgICByZXR1cm4gUmVuZGVyaW5nRW5naW5lLmdldChmbGF2b3VyKS5yZW5kZXIobW9kZWwsIC4uLmFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSBtZXRhZGF0YSBrZXkgZm9yIFVJLXJlbGF0ZWQgcHJvcGVydGllcy5cbiAgICogQHN1bW1hcnkgUHJlZml4ZXMgYSBnaXZlbiBrZXkgd2l0aCB0aGUgVUkgcmVmbGVjdGlvbiBwcmVmaXguXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUga2V5IHRvIHByZWZpeC5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHByZWZpeGVkIGtleS5cbiAgICpcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgc3RhdGljIGtleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke1VJS2V5cy5SRUZMRUNUfSR7a2V5fWA7XG4gIH1cbn1cbiIsImltcG9ydCB7IFVJS2V5cyB9IGZyb20gXCIuLi91aS9jb25zdGFudHNcIjtcbmltcG9ydCB7IGFwcGx5LCBtZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgUmVuZGVyaW5nRW5naW5lIH0gZnJvbSBcIi4uL3VpL1JlbmRlcmluZ1wiO1xuaW1wb3J0IHsgVUlMaXN0SXRlbU1vZGVsTWV0YWRhdGEsIFVJTWVkaWFCcmVha1BvaW50c1R5cGUsIFVJTW9kZWxNZXRhZGF0YSB9IGZyb20gXCIuLi91aS90eXBlc1wiO1xuaW1wb3J0IHsgVUlNZWRpYUJyZWFrUG9pbnRzIH0gZnJvbSBcIi4uL3VpL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgdGhhdCB0YWdzIGEgY2xhc3MgYXMgYSBVSSBtb2RlbFxuICogQHN1bW1hcnkgQWRkcyByZW5kZXJpbmcgY2FwYWJpbGl0aWVzIHRvIGEgbW9kZWwgY2xhc3MgYnkgcHJvdmlkaW5nIGEgcmVuZGVyIG1ldGhvZFxuICogVGhpcyBkZWNvcmF0b3IgYXBwbGllcyBtZXRhZGF0YSB0byB0aGUgY2xhc3MgdGhhdCBlbmFibGVzIGl0IHRvIGJlIHJlbmRlcmVkIGJ5IHRoZSBVSSByZW5kZXJpbmcgZW5naW5lLlxuICogVGhlIG1vZGVsIHdpbGwgYmUgcmVuZGVyZWQgd2l0aCB0aGUgc3BlY2lmaWVkIHRhZyBhbmQgcHJvcGVydGllcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW3RhZ10gVGhlIEhUTUwgdGFnIHRvIHVzZSB3aGVuIHJlbmRlcmluZyB0aGlzIG1vZGVsIChkZWZhdWx0cyB0byBjbGFzcyBuYW1lKVxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbcHJvcHNdIEFkZGl0aW9uYWwgcHJvcGVydGllcyB0byBwYXNzIHRvIHRoZSByZW5kZXJlZCBlbGVtZW50XG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBjbGFzcyBkZWNvcmF0b3IgZnVuY3Rpb25cbiAqXG4gKiBAZnVuY3Rpb24gdWltb2RlbFxuICogQGNhdGVnb3J5IENsYXNzIERlY29yYXRvcnNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gQmFzaWMgdXNhZ2Ugd2l0aCBkZWZhdWx0IHRhZyAoY2xhc3MgbmFtZSlcbiAqIEB1aW1vZGVsKClcbiAqIGNsYXNzIFVzZXJQcm9maWxlIGV4dGVuZHMgTW9kZWwge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgbmFtZTogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIGVtYWlsOiBzdHJpbmc7XG4gKiB9XG4gKlxuICogLy8gVXNhZ2Ugd2l0aCBjdXN0b20gdGFnIGFuZCBwcm9wZXJ0aWVzXG4gKiBAdWltb2RlbCgnZGl2JywgeyBjbGFzczogJ3VzZXItY2FyZCcgfSlcbiAqIGNsYXNzIFVzZXJDYXJkIGV4dGVuZHMgTW9kZWwge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgdXNlcm5hbWU6IHN0cmluZztcbiAqIH1cbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFN5c3RlbVxuICogICBwYXJ0aWNpcGFudCB1aW1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IGNvbnN0cnVjdG9yXG4gKiAgIHBhcnRpY2lwYW50IGluc3RhbmNlXG4gKiAgIFN5c3RlbS0+PnVpbW9kZWw6ZG8oY29uc3RydWN0b3IpXG4gKiAgIHVpbW9kZWwtPj5jb25zdHJ1Y3RvcjogRXhlY3V0ZXMgdGhlIGNvbnN0cnVjdG9yXG4gKiAgIGNvbnN0cnVjdG9yLT4+dWltb2RlbDogcmV0dXJucyBpbnN0YW5jZVxuICogICB1aW1vZGVsLT4+aW5zdGFuY2U6IGFkZHMgdGhlIHJlbmRlciBtZXRob2RcbiAqICAgdWltb2RlbC0+PlN5c3RlbTogcmV0dXJucyBVSU1vZGVsIGluc3RhbmNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1aW1vZGVsKHRhZz86IHN0cmluZywgcHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgcmV0dXJuIChvcmlnaW5hbDogYW55LCBwcm9wZXJ0eUtleT86IGFueSkgPT4ge1xuICAgIGNvbnN0IG1ldGE6IFVJTW9kZWxNZXRhZGF0YSA9IHtcbiAgICAgIHRhZzogdGFnIHx8IG9yaWdpbmFsLm5hbWUsXG4gICAgICBwcm9wczogcHJvcHMsXG4gICAgfTtcbiAgICByZXR1cm4gbWV0YWRhdGEoUmVuZGVyaW5nRW5naW5lLmtleShVSUtleXMuVUlNT0RFTCksIG1ldGEpKG9yaWdpbmFsKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIHRoYXQgc3BlY2lmaWVzIHdoaWNoIHJlbmRlcmluZyBlbmdpbmUgdG8gdXNlIGZvciBhIG1vZGVsXG4gKiBAc3VtbWFyeSBBc3NvY2lhdGVzIGEgbW9kZWwgd2l0aCBhIHNwZWNpZmljIHJlbmRlcmluZyBlbmdpbmUgaW1wbGVtZW50YXRpb25cbiAqIFRoaXMgZGVjb3JhdG9yIGFsbG93cyB5b3UgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgcmVuZGVyaW5nIGVuZ2luZSBmb3IgYSBzcGVjaWZpYyBtb2RlbCBjbGFzcyxcbiAqIGVuYWJsaW5nIGRpZmZlcmVudCByZW5kZXJpbmcgc3RyYXRlZ2llcyBmb3IgZGlmZmVyZW50IG1vZGVscy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZW5naW5lIFRoZSBuYW1lIG9mIHRoZSByZW5kZXJpbmcgZW5naW5lIHRvIHVzZVxuICogQHJldHVybiB7RnVuY3Rpb259IEEgY2xhc3MgZGVjb3JhdG9yIGZ1bmN0aW9uXG4gKlxuICogQGZ1bmN0aW9uIHJlbmRlcmVkQnlcbiAqIEBjYXRlZ29yeSBDbGFzcyBEZWNvcmF0b3JzXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNwZWNpZnkgYSBjdXN0b20gcmVuZGVyaW5nIGVuZ2luZSBmb3IgYSBtb2RlbFxuICogQHVpbW9kZWwoKVxuICogQHJlbmRlcmVkQnkoJ3JlYWN0JylcbiAqIGNsYXNzIFJlYWN0Q29tcG9uZW50IGV4dGVuZHMgTW9kZWwge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgdGl0bGU6IHN0cmluZztcbiAqIH1cbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFN5c3RlbVxuICogICBwYXJ0aWNpcGFudCByZW5kZXJlZEJ5XG4gKiAgIHBhcnRpY2lwYW50IE1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IFJlbmRlcmluZ0VuZ2luZVxuICogICBTeXN0ZW0tPj5yZW5kZXJlZEJ5OiBhcHBseSB0byBNb2RlbFxuICogICByZW5kZXJlZEJ5LT4+TW9kZWw6IGFkZHMgZW5naW5lIG1ldGFkYXRhXG4gKiAgIE1vZGVsLT4+UmVuZGVyaW5nRW5naW5lOiB1c2VzIHNwZWNpZmllZCBlbmdpbmVcbiAqICAgUmVuZGVyaW5nRW5naW5lLT4+U3lzdGVtOiByZW5kZXJzIHdpdGggY3VzdG9tIGVuZ2luZVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyZWRCeShlbmdpbmU6IHN0cmluZykge1xuICByZXR1cm4gYXBwbHkobWV0YWRhdGEoUmVuZGVyaW5nRW5naW5lLmtleShVSUtleXMuUkVOREVSRURfQlkpLCBlbmdpbmUpKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIHRoYXQgdGFncyBhIG1vZGVsIGFzIGEgbGlzdCBpdGVtIGZvciBVSSByZW5kZXJpbmdcbiAqIEBzdW1tYXJ5IFNwZWNpZmllcyBob3cgYSBtb2RlbCBzaG91bGQgYmUgcmVuZGVyZWQgd2hlbiBkaXNwbGF5ZWQgaW4gYSBsaXN0IGNvbnRleHRcbiAqIFRoaXMgZGVjb3JhdG9yIGFwcGxpZXMgbWV0YWRhdGEgdG8gdGhlIGNsYXNzIHRoYXQgZW5hYmxlcyBpdCB0byBiZSByZW5kZXJlZCBhcyBhIGxpc3QgaXRlbVxuICogYnkgdGhlIFVJIHJlbmRlcmluZyBlbmdpbmUuIFRoZSBtb2RlbCB3aWxsIGJlIHJlbmRlcmVkIHdpdGggdGhlIHNwZWNpZmllZCB0YWcgYW5kIHByb3BlcnRpZXNcbiAqIHdoZW4gaXQgYXBwZWFycyBpbiBhIGxpc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFt0YWddIFRoZSBIVE1MIHRhZyB0byB1c2Ugd2hlbiByZW5kZXJpbmcgdGhpcyBtb2RlbCBhcyBhIGxpc3QgaXRlbSAoZGVmYXVsdHMgdG8gY2xhc3MgbmFtZSlcbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW3Byb3BzXSBBZGRpdGlvbmFsIHByb3BlcnRpZXMgdG8gcGFzcyB0byB0aGUgcmVuZGVyZWQgbGlzdCBpdGVtIGVsZW1lbnRcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIGNsYXNzIGRlY29yYXRvciBmdW5jdGlvblxuICpcbiAqIEBmdW5jdGlvbiB1aWxpc3RpdGVtXG4gKiBAY2F0ZWdvcnkgQ2xhc3MgRGVjb3JhdG9yc1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBCYXNpYyB1c2FnZSB3aXRoIGRlZmF1bHQgdGFnIChjbGFzcyBuYW1lKVxuICogQHVpbW9kZWwoKVxuICogQHVpbGlzdGl0ZW0oKVxuICogY2xhc3MgVG9kb0l0ZW0gZXh0ZW5kcyBNb2RlbCB7XG4gKiAgIEBhdHRyaWJ1dGUoKVxuICogICB0aXRsZTogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIGNvbXBsZXRlZDogYm9vbGVhbjtcbiAqIH1cbiAqXG4gKiAvLyBVc2FnZSB3aXRoIGN1c3RvbSB0YWcgYW5kIHByb3BlcnRpZXNcbiAqIEB1aW1vZGVsKClcbiAqIEB1aWxpc3RpdGVtKCdsaScsIHsgY2xhc3M6ICdsaXN0LWdyb3VwLWl0ZW0nIH0pXG4gKiBjbGFzcyBMaXN0SXRlbSBleHRlbmRzIE1vZGVsIHtcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIHRleHQ6IHN0cmluZztcbiAqIH1cbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFN5c3RlbVxuICogICBwYXJ0aWNpcGFudCB1aWxpc3RpdGVtXG4gKiAgIHBhcnRpY2lwYW50IE1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IFJlbmRlcmluZ0VuZ2luZVxuICogICBTeXN0ZW0tPj51aWxpc3RpdGVtOiBhcHBseSB0byBNb2RlbFxuICogICB1aWxpc3RpdGVtLT4+TW9kZWw6IGFkZHMgbGlzdCBpdGVtIG1ldGFkYXRhXG4gKiAgIE1vZGVsLT4+UmVuZGVyaW5nRW5naW5lOiB1c2VzIGxpc3QgaXRlbSBtZXRhZGF0YSB3aGVuIGluIGxpc3QgY29udGV4dFxuICogICBSZW5kZXJpbmdFbmdpbmUtPj5TeXN0ZW06IHJlbmRlcnMgd2l0aCBsaXN0IGl0ZW0gc3R5bGluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdWlsaXN0aXRlbSh0YWc/OiBzdHJpbmcsIHByb3BzPzogUmVjb3JkPHN0cmluZywgYW55Pikge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIHJldHVybiAob3JpZ2luYWw6IGFueSwgcHJvcGVydHlLZXk/OiBhbnkpID0+IHtcbiAgICBjb25zdCBtZXRhOiBVSUxpc3RJdGVtTW9kZWxNZXRhZGF0YSA9IHtcbiAgICAgIGl0ZW06IHtcbiAgICAgICAgdGFnOiB0YWcgfHwgb3JpZ2luYWwubmFtZSxcbiAgICAgICAgcHJvcHM6IHByb3BzLFxuICAgICAgfSxcbiAgICB9O1xuICAgIHJldHVybiBtZXRhZGF0YShSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5VSUxJU1RJVEVNKSwgbWV0YSkob3JpZ2luYWwpO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgdGhhdCBhZGRzIGV2ZW50IGhhbmRsZXJzIHRvIGEgVUkgbW9kZWxcbiAqIEBzdW1tYXJ5IFNwZWNpZmllcyBldmVudCBoYW5kbGVycyB0aGF0IHNob3VsZCBiZSBhdHRhY2hlZCB0byB0aGUgcmVuZGVyZWQgbW9kZWxcbiAqIFRoaXMgZGVjb3JhdG9yIGFsbG93cyB5b3UgdG8gZGVmaW5lIGV2ZW50IGhhbmRsZXJzIHRoYXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5XG4gKiBhdHRhY2hlZCB0byB0aGUgcmVuZGVyZWQgVUkgZWxlbWVudC4gVGhlIGhhbmRsZXJzIGFyZSBwYXNzZWQgYXMgcHJvcGVydGllc1xuICogdG8gdGhlIHJlbmRlcmluZyBlbmdpbmUuXG4gKlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbcHJvcHNdIE9iamVjdCBjb250YWluaW5nIGV2ZW50IGhhbmRsZXIgZnVuY3Rpb25zIGFuZCBvdGhlciBwcm9wZXJ0aWVzXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBjbGFzcyBkZWNvcmF0b3IgZnVuY3Rpb25cbiAqXG4gKiBAZnVuY3Rpb24gdWloYW5kbGVyc1xuICogQGNhdGVnb3J5IENsYXNzIERlY29yYXRvcnNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gQWRkIGV2ZW50IGhhbmRsZXJzIHRvIGEgbW9kZWxcbiAqIEB1aW1vZGVsKCdidXR0b24nKVxuICogQHVpaGFuZGxlcnMoe1xuICogICBvbkNsaWNrOiAoZXZlbnQpID0+IGNvbnNvbGUubG9nKCdCdXR0b24gY2xpY2tlZCcpLFxuICogICBvbk1vdXNlT3ZlcjogKGV2ZW50KSA9PiBjb25zb2xlLmxvZygnTW91c2Ugb3ZlciBidXR0b24nKSxcbiAqICAgZGlzYWJsZWQ6IGZhbHNlXG4gKiB9KVxuICogY2xhc3MgQ2xpY2thYmxlQnV0dG9uIGV4dGVuZHMgTW9kZWwge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgbGFiZWw6IHN0cmluZztcbiAqIH1cbiAqXG4gKiAvLyBBZGQgZm9ybSBzdWJtaXNzaW9uIGhhbmRsZXJzXG4gKiBAdWltb2RlbCgnZm9ybScpXG4gKiBAdWloYW5kbGVycyh7XG4gKiAgIG9uU3VibWl0OiAoZXZlbnQpID0+IHtcbiAqICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICogICAgIGNvbnNvbGUubG9nKCdGb3JtIHN1Ym1pdHRlZCcpO1xuICogICB9LFxuICogICBvblJlc2V0OiAoZXZlbnQpID0+IGNvbnNvbGUubG9nKCdGb3JtIHJlc2V0JylcbiAqIH0pXG4gKiBjbGFzcyBDb250YWN0Rm9ybSBleHRlbmRzIE1vZGVsIHtcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIGVtYWlsOiBzdHJpbmc7XG4gKiB9XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBTeXN0ZW1cbiAqICAgcGFydGljaXBhbnQgdWloYW5kbGVyc1xuICogICBwYXJ0aWNpcGFudCBNb2RlbFxuICogICBwYXJ0aWNpcGFudCBSZW5kZXJpbmdFbmdpbmVcbiAqICAgcGFydGljaXBhbnQgVUlcbiAqICAgU3lzdGVtLT4+dWloYW5kbGVyczogYXBwbHkgdG8gTW9kZWxcbiAqICAgdWloYW5kbGVycy0+Pk1vZGVsOiBhZGRzIGhhbmRsZXIgbWV0YWRhdGFcbiAqICAgTW9kZWwtPj5SZW5kZXJpbmdFbmdpbmU6IHJlcXVlc3RzIHJlbmRlcmluZyB3aXRoIGhhbmRsZXJzXG4gKiAgIFJlbmRlcmluZ0VuZ2luZS0+PlVJOiByZW5kZXJzIGVsZW1lbnQgd2l0aCBldmVudCBoYW5kbGVycyBhdHRhY2hlZFxuICogICBVSS0+Pk1vZGVsOiB0cmlnZ2VycyBoYW5kbGVycyBvbiBldmVudHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVpaGFuZGxlcnMocHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSB7XG4gIHJldHVybiAob3JpZ2luYWw6IGFueSkgPT4ge1xuICAgIGNvbnN0IG1ldGEgPSB7XG4gICAgICBoYW5kbGVyczogcHJvcHNcbiAgICB9O1xuICAgIHJldHVybiBtZXRhZGF0YShSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5IQU5ETEVSUyksIG1ldGEpKG9yaWdpbmFsKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIHRoYXQgY3JlYXRlcyBhIGxheW91dCBjb250YWluZXIgd2l0aCBncmlkIHNwZWNpZmljYXRpb25zXG4gKiBAc3VtbWFyeSBDb21iaW5lcyBVSSBtb2RlbCBmdW5jdGlvbmFsaXR5IHdpdGggbGF5b3V0IGdyaWQgY29uZmlndXJhdGlvblxuICogVGhpcyBkZWNvcmF0b3IgY3JlYXRlcyBhIFVJIG1vZGVsIHRoYXQgYWN0cyBhcyBhIGxheW91dCBjb250YWluZXIgd2l0aCBzcGVjaWZpZWRcbiAqIGNvbHVtbiBhbmQgcm93IGNvbmZpZ3VyYXRpb25zLiBJdCdzIGEgY29udmVuaWVuY2UgZGVjb3JhdG9yIHRoYXQgY29tYmluZXNcbiAqIEB1aW1vZGVsIHdpdGggbGF5b3V0LXNwZWNpZmljIHByb3BlcnRpZXMgZm9yIHJlc3BvbnNpdmUgZ3JpZCBsYXlvdXRzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIEhUTUwgdGFnIHRvIHVzZSBmb3IgdGhlIGxheW91dCBjb250YWluZXJcbiAqIEBwYXJhbSB7bnVtYmVyfSBbY29scz0xXSBOdW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgZ3JpZCBsYXlvdXRcbiAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ1tdfSBbcm93cz0xXSBOdW1iZXIgb2Ygcm93cyBvciBhcnJheSBvZiByb3cgZGVmaW5pdGlvbnNcbiAqIEBwYXJhbSB7VUlNZWRpYUJyZWFrUG9pbnRzfSBbYnJlYWtwb2ludD0nbSddIE1lZGlhIGJyZWFrcG9pbnQgZm9yIHJlc3BvbnNpdmUgYmVoYXZpb3JcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIGNsYXNzIGRlY29yYXRvciBmdW5jdGlvblxuICpcbiAqIEBmdW5jdGlvbiB1aWxheW91dFxuICogQGNhdGVnb3J5IENsYXNzIERlY29yYXRvcnNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGEgc2ltcGxlIDItY29sdW1uIGxheW91dFxuICogQHVpbGF5b3V0KCdkaXYnLCAyLCAzKVxuICogY2xhc3MgVHdvQ29sdW1uTGF5b3V0IGV4dGVuZHMgTW9kZWwge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpbGF5b3V0aXRlbSgxLCAxKVxuICogICBoZWFkZXI6IHN0cmluZztcbiAqXG4gKiAgIEBhdHRyaWJ1dGUoKVxuICogICBAdWlsYXlvdXRpdGVtKDEsIDIpXG4gKiAgIGxlZnRDb250ZW50OiBzdHJpbmc7XG4gKlxuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpbGF5b3V0aXRlbSgyLCAyKVxuICogICByaWdodENvbnRlbnQ6IHN0cmluZztcbiAqIH1cbiAqXG4gKiAvLyBDcmVhdGUgYSByZXNwb25zaXZlIGxheW91dCB3aXRoIGN1c3RvbSBicmVha3BvaW50XG4gKiBAdWlsYXlvdXQoJ3NlY3Rpb24nLCAzLCAyLCAnbCcpXG4gKiBjbGFzcyBSZXNwb25zaXZlTGF5b3V0IGV4dGVuZHMgTW9kZWwge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpbGF5b3V0aXRlbSgxLCAxKVxuICogICB0aXRsZTogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIEB1aWxheW91dGl0ZW0oMiwgMSlcbiAqICAgc3VidGl0bGU6IHN0cmluZztcbiAqIH1cbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFN5c3RlbVxuICogICBwYXJ0aWNpcGFudCB1aWxheW91dFxuICogICBwYXJ0aWNpcGFudCB1aW1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IE1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IFJlbmRlcmluZ0VuZ2luZVxuICogICBTeXN0ZW0tPj51aWxheW91dDogYXBwbHkgdG8gTW9kZWxcbiAqICAgdWlsYXlvdXQtPj51aW1vZGVsOiBjYWxsIHdpdGggbGF5b3V0IHByb3BzXG4gKiAgIHVpbW9kZWwtPj5Nb2RlbDogYWRkcyBtb2RlbCBtZXRhZGF0YSB3aXRoIGxheW91dCBjb25maWdcbiAqICAgTW9kZWwtPj5SZW5kZXJpbmdFbmdpbmU6IHJlcXVlc3RzIHJlbmRlcmluZyBhcyBsYXlvdXQgY29udGFpbmVyXG4gKiAgIFJlbmRlcmluZ0VuZ2luZS0+PlN5c3RlbTogcmVuZGVycyBncmlkIGxheW91dCB3aXRoIHNwZWNpZmllZCBkaW1lbnNpb25zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1aWxheW91dCh0YWc6IHN0cmluZywgY29sczogbnVtYmVyID0gMSwgcm93czogbnVtYmVyIHwgc3RyaW5nW10gPSAxLCBicmVha3BvaW50OiBVSU1lZGlhQnJlYWtQb2ludHNUeXBlID0gVUlNZWRpYUJyZWFrUG9pbnRzLk1FRElVTSkge1xuICByZXR1cm4gKG9yaWdpbmFsOiBhbnksIHByb3BlcnR5S2V5PzogYW55KSA9PiB7XG4gICAgcmV0dXJuIHVpbW9kZWwodGFnLCB7Y29scywgcm93cywgYnJlYWtwb2ludH0pKG9yaWdpbmFsLCBwcm9wZXJ0eUtleSk7XG4gIH07XG59IiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gTW9kdWxlIHRoYXQgZXh0ZW5kcyB0aGUgTW9kZWwgcHJvdG90eXBlIHdpdGggcmVuZGVyaW5nIGNhcGFiaWxpdGllc1xuICogQHN1bW1hcnkgQWRkcyB0aGUgcmVuZGVyIG1ldGhvZCB0byBhbGwgTW9kZWwgaW5zdGFuY2VzIGZyb20gZGVjb3JhdG9yLXZhbGlkYXRpb25cbiAqIFRoaXMgbW9kdWxlIGltcGxlbWVudHMgdGhlIFJlbmRlcmFibGUgaW50ZXJmYWNlIGZvciB0aGUgTW9kZWwgY2xhc3MgYnkgYWRkaW5nIGEgcmVuZGVyIG1ldGhvZFxuICogdG8gaXRzIHByb3RvdHlwZS4gVGhpcyBhbGxvd3MgYW55IE1vZGVsIGluc3RhbmNlIHRvIGJlIHJlbmRlcmVkIHVzaW5nIHRoZSBSZW5kZXJpbmdFbmdpbmUuXG4gKiBAbW9kdWxlIG1vZGVsL292ZXJyaWRlc1xuICogQG1lbWJlck9mIG1vZHVsZTp1aS1kZWNvcmF0b3JzL21vZGVsXG4gKi9cblxuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBSZW5kZXJpbmdFbmdpbmUgfSBmcm9tIFwiLi4vdWkvUmVuZGVyaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlbmRlcnMgdGhlIG1vZGVsIHVzaW5nIHRoZSBhcHByb3ByaWF0ZSByZW5kZXJpbmcgZW5naW5lXG4gKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgcmVuZGVyaW5nIHRvIHRoZSBSZW5kZXJpbmdFbmdpbmUgYmFzZWQgb24gbW9kZWwgbWV0YWRhdGFcbiAqIFRoaXMgbWV0aG9kIGltcGxlbWVudHMgdGhlIHJlbmRlciBtZXRob2QgZnJvbSB0aGUgUmVuZGVyYWJsZSBpbnRlcmZhY2UgZm9yIGFsbCBNb2RlbCBpbnN0YW5jZXMuXG4gKiBJdCB1c2VzIHRoZSBSZW5kZXJpbmdFbmdpbmUgdG8gZGV0ZXJtaW5lIGhvdyB0byByZW5kZXIgdGhlIG1vZGVsIGJhc2VkIG9uIGl0cyBtZXRhZGF0YS5cbiAqXG4gKiBAdGVtcGxhdGUgTSBUeXBlIG9mIHRoZSBtb2RlbCBiZWluZyByZW5kZXJlZFxuICogQHBhcmFtIHthbnlbXX0gYXJncyBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSByZW5kZXJpbmcgZW5naW5lXG4gKiBAcmV0dXJuIHthbnl9IFRoZSByZW5kZXJlZCBvdXRwdXQgaW4gdGhlIGZvcm1hdCBkZXRlcm1pbmVkIGJ5IHRoZSByZW5kZXJpbmcgZW5naW5lXG4gKi9cbk1vZGVsLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiA8TSBleHRlbmRzIE1vZGVsPih0aGlzOiBNLCAuLi5hcmdzOiBhbnlbXSkge1xuICByZXR1cm4gUmVuZGVyaW5nRW5naW5lLnJlbmRlcih0aGlzLCAuLi5hcmdzKTtcbn07XG4iLCJpbXBvcnQgXCJyZWZsZWN0LW1ldGFkYXRhXCI7XG5pbXBvcnQgeyBVSUtleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHByb3BNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7XG4gIENydWRPcGVyYXRpb25LZXlzLFxuICBVSUVsZW1lbnRNZXRhZGF0YSxcbiAgVUlMYXlvdXRJdGVtTWV0YWRhdGEsXG4gIFVJTGlzdFByb3BNZXRhZGF0YSxcbiAgVUlQcm9wTWV0YWRhdGEsXG59IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBSZW5kZXJpbmdFbmdpbmUgfSBmcm9tIFwiLi9SZW5kZXJpbmdcIjtcbmltcG9ydCB7IE9wZXJhdGlvbktleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIHRoYXQgaGlkZXMgYSBwcm9wZXJ0eSBkdXJpbmcgc3BlY2lmaWMgQ1JVRCBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBDb250cm9scyBwcm9wZXJ0eSB2aXNpYmlsaXR5IGJhc2VkIG9uIG9wZXJhdGlvbiB0eXBlXG4gKiBUaGlzIGRlY29yYXRvciBhbGxvd3MgeW91IHRvIHNwZWNpZnkgd2hpY2ggQ1JVRCBvcGVyYXRpb25zIHNob3VsZCBoaWRlIGEgcHJvcGVydHlcbiAqIGluIHRoZSBVSS4gVGhlIHByb3BlcnR5IHdpbGwgb25seSBiZSB2aXNpYmxlIGR1cmluZyBvcGVyYXRpb25zIG5vdCBzcGVjaWZpZWQuXG4gKlxuICogQHBhcmFtIG9wZXJhdGlvbnMgLSBUaGUgQ1JVRCBvcGVyYXRpb25zIGR1cmluZyB3aGljaCB0aGUgcHJvcGVydHkgc2hvdWxkIGJlIGhpZGRlblxuICogQHJldHVybiB7RnVuY3Rpb259IEEgcHJvcGVydHkgZGVjb3JhdG9yIGZ1bmN0aW9uXG4gKlxuICogQGZ1bmN0aW9uIGhpZGVPblxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gSGlkZSB0aGUgcGFzc3dvcmQgZmllbGQgZHVyaW5nIFJFQUQgb3BlcmF0aW9uc1xuICogY2xhc3MgVXNlciB7XG4gKiAgIEBhdHRyaWJ1dGUoKVxuICogICB1c2VybmFtZTogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIEBoaWRlT24oT3BlcmF0aW9uS2V5cy5SRUFEKVxuICogICBwYXNzd29yZDogc3RyaW5nO1xuICogfVxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgTW9kZWxcbiAqICAgcGFydGljaXBhbnQgaGlkZU9uXG4gKiAgIHBhcnRpY2lwYW50IFJlbmRlcmluZ0VuZ2luZVxuICogICBwYXJ0aWNpcGFudCBVSVxuICogICBNb2RlbC0+PmhpZGVPbjogQXBwbHkgdG8gcHJvcGVydHlcbiAqICAgaGlkZU9uLT4+TW9kZWw6IEFkZCBoaWRkZW4gbWV0YWRhdGFcbiAqICAgUmVuZGVyaW5nRW5naW5lLT4+TW9kZWw6IENoZWNrIGlmIHByb3BlcnR5IHNob3VsZCBiZSBoaWRkZW5cbiAqICAgTW9kZWwtPj5SZW5kZXJpbmdFbmdpbmU6IFJldHVybiBoaWRkZW4gb3BlcmF0aW9uc1xuICogICBSZW5kZXJpbmdFbmdpbmUtPj5VSTogUmVuZGVyIG9yIGhpZGUgYmFzZWQgb24gY3VycmVudCBvcGVyYXRpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhpZGVPbiguLi5vcGVyYXRpb25zOiBDcnVkT3BlcmF0aW9uS2V5c1tdKSB7XG4gIHJldHVybiBwcm9wTWV0YWRhdGE8Q3J1ZE9wZXJhdGlvbktleXNbXT4oXG4gICAgUmVuZGVyaW5nRW5naW5lLmtleShVSUtleXMuSElEREVOKSxcbiAgICBvcGVyYXRpb25zXG4gICk7XG59XG5cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIHRoYXQgc2V0cyB0aGUgb3JkZXIgb2YgYSBVSSBlbGVtZW50XG4gKiBAc3VtbWFyeSBTcGVjaWZpZXMgdGhlIHJlbmRlcmluZyBvcmRlciBmb3IgVUkgY29tcG9uZW50c1xuICogVGhpcyBkZWNvcmF0b3IgYXBwbGllcyBtZXRhZGF0YSB0byB0aGUgcHJvcGVydHkgb3IgY2xhc3MsIGluZGljYXRpbmcgaXRzIG9yZGVyIGluIHRoZSBVSSByZW5kZXJpbmcgc2VxdWVuY2UuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IFtvcmRlcj0xXSBUaGUgb3JkZXIgdmFsdWUgZm9yIHRoZSBVSSBlbGVtZW50IChkZWZhdWx0IGlzIDEpXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBwcm9wZXJ0eSBvciBjbGFzcyBkZWNvcmF0b3IgZnVuY3Rpb25cbiAqXG4gKiBAZnVuY3Rpb24gdWlvcmRlclxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gU2V0IG9yZGVyIGZvciBhIGZpZWxkXG4gKiBAdWlvcmRlcigyKVxuICogZmllbGROYW1lOiBzdHJpbmc7XG4gKlxuICogLy8gU2V0IG9yZGVyIGZvciBhIGNsYXNzXG4gKiBAdWlvcmRlcigxKVxuICogY2xhc3MgVXNlclByb2ZpbGUgeyAuLi4gfVxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgU3lzdGVtXG4gKiAgIHBhcnRpY2lwYW50IHVpb3JkZXJcbiAqICAgcGFydGljaXBhbnQgcHJvcGVydHlcbiAqICAgU3lzdGVtLT4+dWlvcmRlcjpkbyhwcm9wZXJ0eSlcbiAqICAgdWlvcmRlci0+PnByb3BlcnR5OiBzZXRzIG9yZGVyIG1ldGFkYXRhXG4gKiAgIHVpb3JkZXItPj5TeXN0ZW06IHJldHVybnMgZGVjb3JhdGVkIHByb3BlcnR5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1aW9yZGVyKG9yZGVyOiBudW1iZXIgPSAxKSB7XG4gIHJldHVybiBwcm9wTWV0YWRhdGE8bnVtYmVyPihcbiAgICBSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5PUkRFUiksXG4gICAgb3JkZXJcbiAgKTtcbn1cblxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgdGhhdCBjb21wbGV0ZWx5IGhpZGVzIGEgcHJvcGVydHkgaW4gYWxsIFVJIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IE1ha2VzIGEgcHJvcGVydHkgaW52aXNpYmxlIGluIGFsbCBDUlVEIG9wZXJhdGlvbnNcbiAqIFRoaXMgZGVjb3JhdG9yIGlzIGEgY29udmVuaWVuY2Ugd3JhcHBlciBhcm91bmQgaGlkZU9uIHRoYXQgaGlkZXMgYSBwcm9wZXJ0eVxuICogZHVyaW5nIGFsbCBDUlVEIG9wZXJhdGlvbnMgKENSRUFURSwgUkVBRCwgVVBEQVRFLCBERUxFVEUpLlxuICpcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIHByb3BlcnR5IGRlY29yYXRvciBmdW5jdGlvblxuICpcbiAqIEBmdW5jdGlvbiBoaWRkZW5cbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIENvbXBsZXRlbHkgaGlkZSB0aGUgaW50ZXJuYWxJZCBmaWVsZCBpbiB0aGUgVUlcbiAqIGNsYXNzIFByb2R1Y3Qge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgbmFtZTogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIEBoaWRkZW4oKVxuICogICBpbnRlcm5hbElkOiBzdHJpbmc7XG4gKiB9XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBNb2RlbFxuICogICBwYXJ0aWNpcGFudCBoaWRkZW5cbiAqICAgcGFydGljaXBhbnQgaGlkZU9uXG4gKiAgIHBhcnRpY2lwYW50IFJlbmRlcmluZ0VuZ2luZVxuICogICBNb2RlbC0+PmhpZGRlbjogQXBwbHkgdG8gcHJvcGVydHlcbiAqICAgaGlkZGVuLT4+aGlkZU9uOiBDYWxsIHdpdGggYWxsIG9wZXJhdGlvbnNcbiAqICAgaGlkZU9uLT4+TW9kZWw6IEFkZCBoaWRkZW4gbWV0YWRhdGFcbiAqICAgUmVuZGVyaW5nRW5naW5lLT4+TW9kZWw6IENoZWNrIGlmIHByb3BlcnR5IHNob3VsZCBiZSBoaWRkZW5cbiAqICAgTW9kZWwtPj5SZW5kZXJpbmdFbmdpbmU6IFJldHVybiBhbGwgb3BlcmF0aW9uc1xuICogICBSZW5kZXJpbmdFbmdpbmUtPj5VSTogQWx3YXlzIGhpZGUgcHJvcGVydHlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhpZGRlbigpIHtcbiAgcmV0dXJuIGhpZGVPbihcbiAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgT3BlcmF0aW9uS2V5cy5ERUxFVEVcbiAgKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIHRoYXQgc3BlY2lmaWVzIGhvdyBhIHByb3BlcnR5IHNob3VsZCBiZSByZW5kZXJlZCBhcyBhIFVJIGVsZW1lbnRcbiAqIEBzdW1tYXJ5IE1hcHMgYSBtb2RlbCBwcm9wZXJ0eSB0byBhIHNwZWNpZmljIFVJIGVsZW1lbnQgd2l0aCBjdXN0b20gcHJvcGVydGllc1xuICogVGhpcyBkZWNvcmF0b3IgYWxsb3dzIHlvdSB0byBkZWZpbmUgd2hpY2ggSFRNTCBlbGVtZW50IG9yIGNvbXBvbmVudCBzaG91bGQgYmUgdXNlZFxuICogdG8gcmVuZGVyIGEgc3BlY2lmaWMgcHJvcGVydHksIGFsb25nIHdpdGggYW55IGFkZGl0aW9uYWwgcHJvcGVydGllcyB0byBwYXNzIHRvIHRoYXQgZWxlbWVudC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdGFnIFRoZSBIVE1MIGVsZW1lbnQgb3IgY29tcG9uZW50IHRhZyBuYW1lIHRvIHVzZSBmb3IgcmVuZGVyaW5nXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IFtwcm9wc10gQWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIHBhc3MgdG8gdGhlIGVsZW1lbnRcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW3NlcmlhbGl6ZT1mYWxzZV0gV2hldGhlciB0aGUgcHJvcGVydHkgc2hvdWxkIGJlIHNlcmlhbGl6ZWRcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIHByb3BlcnR5IGRlY29yYXRvciBmdW5jdGlvblxuICpcbiAqIEBmdW5jdGlvbiB1aWVsZW1lbnRcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFJlbmRlciBhIHByb3BlcnR5IGFzIGEgdGV4dCBpbnB1dFxuICogY2xhc3MgTG9naW5Gb3JtIHtcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIEB1aWVsZW1lbnQoJ2lucHV0JywgeyB0eXBlOiAndGV4dCcsIHBsYWNlaG9sZGVyOiAnRW50ZXIgdXNlcm5hbWUnIH0pXG4gKiAgIHVzZXJuYW1lOiBzdHJpbmc7XG4gKlxuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpZWxlbWVudCgnaW5wdXQnLCB7IHR5cGU6ICdwYXNzd29yZCcsIHBsYWNlaG9sZGVyOiAnRW50ZXIgcGFzc3dvcmQnIH0pXG4gKiAgIHBhc3N3b3JkOiBzdHJpbmc7XG4gKlxuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpZWxlbWVudCgnYnV0dG9uJywgeyBjbGFzczogJ2J0bi1wcmltYXJ5JyB9KVxuICogICBzdWJtaXQ6IHN0cmluZyA9ICdMb2dpbic7XG4gKiB9XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBNb2RlbFxuICogICBwYXJ0aWNpcGFudCB1aWVsZW1lbnRcbiAqICAgcGFydGljaXBhbnQgUmVuZGVyaW5nRW5naW5lXG4gKiAgIHBhcnRpY2lwYW50IFVJXG4gKiAgIE1vZGVsLT4+dWllbGVtZW50OiBBcHBseSB0byBwcm9wZXJ0eVxuICogICB1aWVsZW1lbnQtPj5Nb2RlbDogQWRkIGVsZW1lbnQgbWV0YWRhdGFcbiAqICAgUmVuZGVyaW5nRW5naW5lLT4+TW9kZWw6IEdldCBlbGVtZW50IG1ldGFkYXRhXG4gKiAgIE1vZGVsLT4+UmVuZGVyaW5nRW5naW5lOiBSZXR1cm4gdGFnIGFuZCBwcm9wc1xuICogICBSZW5kZXJpbmdFbmdpbmUtPj5VSTogUmVuZGVyIHdpdGggc3BlY2lmaWVkIGVsZW1lbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVpZWxlbWVudChcbiAgdGFnOiBzdHJpbmcsXG4gIHByb3BzPzogUmVjb3JkPHN0cmluZywgYW55PixcbiAgc2VyaWFsaXplOiBib29sZWFuID0gZmFsc2Vcbikge1xuICByZXR1cm4gKG9yaWdpbmFsOiBhbnksIHByb3BlcnR5S2V5PzogYW55KSA9PiB7XG4gICAgY29uc3QgbWV0YWRhdGE6IFVJRWxlbWVudE1ldGFkYXRhID0ge1xuICAgICAgdGFnOiB0YWcsXG4gICAgICBzZXJpYWxpemU6IHNlcmlhbGl6ZSxcbiAgICAgIHByb3BzOiBPYmplY3QuYXNzaWduKHt9LCBwcm9wcyB8fCB7fSwge1xuICAgICAgICBuYW1lOiBwcm9wZXJ0eUtleSxcbiAgICAgIH0pLFxuICAgIH07XG5cbiAgICByZXR1cm4gcHJvcE1ldGFkYXRhKFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLkVMRU1FTlQpLCBtZXRhZGF0YSkoXG4gICAgICBvcmlnaW5hbCxcbiAgICAgIHByb3BlcnR5S2V5XG4gICAgKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIHRoYXQgbWFwcyBhIG1vZGVsIHByb3BlcnR5IHRvIGEgVUkgY29tcG9uZW50IHByb3BlcnR5XG4gKiBAc3VtbWFyeSBTcGVjaWZpZXMgaG93IGEgcHJvcGVydHkgc2hvdWxkIGJlIHBhc3NlZCB0byBhIFVJIGNvbXBvbmVudFxuICogVGhpcyBkZWNvcmF0b3IgYWxsb3dzIHlvdSB0byBkZWZpbmUgaG93IGEgbW9kZWwgcHJvcGVydHkgc2hvdWxkIGJlIG1hcHBlZCB0b1xuICogYSBwcm9wZXJ0eSBvZiB0aGUgVUkgY29tcG9uZW50IHdoZW4gcmVuZGVyaW5nLiBJdCByZXF1aXJlcyB0aGUgY2xhc3MgdG8gYmVcbiAqIGRlY29yYXRlZCB3aXRoIEB1aW1vZGVsLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbcHJvcE5hbWVdIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBwYXNzIHRvIHRoZSBjb21wb25lbnQgKGRlZmF1bHRzIHRvIHRoZSBwcm9wZXJ0eSBrZXkpXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtzdHJpbmdpZnk9ZmFsc2VdIFdoZXRoZXIgdG8gc3RyaW5naWZ5IHRoZSBwcm9wZXJ0eSB2YWx1ZVxuICogQHJldHVybiB7RnVuY3Rpb259IEEgcHJvcGVydHkgZGVjb3JhdG9yIGZ1bmN0aW9uXG4gKlxuICogQGZ1bmN0aW9uIHVpcHJvcFxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gTWFwIG1vZGVsIHByb3BlcnRpZXMgdG8gY29tcG9uZW50IHByb3BlcnRpZXNcbiAqIEB1aW1vZGVsKCd1c2VyLXByb2ZpbGUnKVxuICogY2xhc3MgVXNlclByb2ZpbGUge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpcHJvcCgpIC8vIFdpbGwgYmUgcGFzc2VkIGFzICdmdWxsTmFtZScgdG8gdGhlIGNvbXBvbmVudFxuICogICBmdWxsTmFtZTogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIEB1aXByb3AoJ3VzZXJFbWFpbCcpIC8vIFdpbGwgYmUgcGFzc2VkIGFzICd1c2VyRW1haWwnIHRvIHRoZSBjb21wb25lbnRcbiAqICAgZW1haWw6IHN0cmluZztcbiAqXG4gKiAgIEBhdHRyaWJ1dGUoKVxuICogICBAdWlwcm9wKCd1c2VyRGF0YScsIHRydWUpIC8vIFdpbGwgYmUgcGFzc2VkIGFzIHN0cmluZ2lmaWVkIEpTT05cbiAqICAgdXNlckRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gKiB9XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBNb2RlbFxuICogICBwYXJ0aWNpcGFudCB1aXByb3BcbiAqICAgcGFydGljaXBhbnQgUmVuZGVyaW5nRW5naW5lXG4gKiAgIHBhcnRpY2lwYW50IENvbXBvbmVudFxuICogICBNb2RlbC0+PnVpcHJvcDogQXBwbHkgdG8gcHJvcGVydHlcbiAqICAgdWlwcm9wLT4+TW9kZWw6IEFkZCBwcm9wIG1ldGFkYXRhXG4gKiAgIFJlbmRlcmluZ0VuZ2luZS0+Pk1vZGVsOiBHZXQgcHJvcCBtZXRhZGF0YVxuICogICBNb2RlbC0+PlJlbmRlcmluZ0VuZ2luZTogUmV0dXJuIHByb3AgbmFtZSBhbmQgc3RyaW5naWZ5IGZsYWdcbiAqICAgUmVuZGVyaW5nRW5naW5lLT4+Q29tcG9uZW50OiBQYXNzIHByb3BlcnR5IHdpdGggc3BlY2lmaWVkIG5hbWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVpcHJvcChcbiAgcHJvcE5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgc3RyaW5naWZ5OiBib29sZWFuID0gZmFsc2Vcbikge1xuICByZXR1cm4gKHRhcmdldDogYW55LCBwcm9wZXJ0eUtleTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgbWV0YWRhdGE6IFVJUHJvcE1ldGFkYXRhID0ge1xuICAgICAgbmFtZTogcHJvcE5hbWUgfHwgcHJvcGVydHlLZXksXG4gICAgICBzdHJpbmdpZnk6IHN0cmluZ2lmeSxcbiAgICB9O1xuICAgIHByb3BNZXRhZGF0YShSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5QUk9QKSwgbWV0YWRhdGEpKFxuICAgICAgdGFyZ2V0LFxuICAgICAgcHJvcGVydHlLZXlcbiAgICApO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgdGhhdCBtYXBzIGEgbmVzdGVkIG1vZGVsIHByb3BlcnR5IHRvIGEgVUkgY29tcG9uZW50IHByb3BlcnR5LlxuICogQHN1bW1hcnkgRGVmaW5lcyBob3cgYSBwYXJlbnQgY29tcG9uZW50IHNob3VsZCByZW5kZXIgdGhlIGNoaWxkIG1vZGVsIHdoZW4gbmVzdGVkLlxuICpcbiAqIFRoaXMgZGVjb3JhdG9yIGlzIHVzZWQgdG8gZGVjb3JhdGUgcHJvcGVydGllcyB0aGF0IGFyZSBuZXN0ZWQgbW9kZWxzLlxuICogV2hlbiBhcHBsaWVkLCBpdCBhbGxvd3Mgb3ZlcnJpZGluZyB0aGUgZGVmYXVsdCB0YWcgb2YgdGhlIGNoaWxkIG1vZGVsIHdpdGggdGhlIHByb3ZpZGVkIG9uZSxcbiAqIGVuYWJsaW5nIGRpZmZlcmVudCByZW5kZXJpbmcgYmVoYXZpb3Igd2hlbiB0aGUgbW9kZWwgYWN0cyBhcyBhIGNoaWxkIChuZXN0ZWQpXG4gKiBjb21wYXJlZCB0byB3aGVuIGl0IGlzIHJlbmRlcmVkIGFzIHRoZSBwYXJlbnQgbW9kZWwuXG4gKlxuICogSXQgcmVxdWlyZXMgdGhlIGNsYXNzIHRvIGJlIGRlY29yYXRlZCB3aXRoIGBAdWltb2RlbGAuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXp6IFRoZSBtb2RlbCBjbGFzcyBuYW1lIHRvIHBhc3MgdG8gdGhlIGNvbXBvbmVudCAoZGVmYXVsdHMgdG8gdGhlIHByb3BlcnR5IGtleSkuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGFnIFRoZSBIVE1MIGVsZW1lbnQgb3IgY29tcG9uZW50IHRhZyBuYW1lIHRvIG92ZXJyaWRlIHRoZSBVSSB0YWcgb2YgdGhlIG5lc3RlZCBtb2RlbFxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbcHJvcHNdIEFkZGl0aW9uYWwgcHJvcGVydGllcyB0byBwYXNzIHRvIHRoZSBlbGVtZW50XG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtzZXJpYWxpemU9ZmFsc2VdIFdoZXRoZXIgdGhlIHByb3BlcnR5IHNob3VsZCBiZSBzZXJpYWxpemVkXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBwcm9wZXJ0eSBkZWNvcmF0b3IgZnVuY3Rpb24uXG4gKlxuICogQGZ1bmN0aW9uIHVpY2hpbGRcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIE1hcCBhIG5lc3RlZCBtb2RlbCB0byBhIGNvbXBvbmVudCBwcm9wZXJ0eSB3aXRoIGEgZGlmZmVyZW50IHRhZyB3aGVuIG5lc3RlZFxuICogQHVpbW9kZWwoJ2FkZHJlc3MtY29tcG9uZW50JylcbiAqIGNsYXNzIEFkZHJlc3Mge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgc3RyZWV0OiBzdHJpbmc7XG4gKlxuICogICBAYXR0cmlidXRlKClcbiAqICAgY2l0eTogc3RyaW5nO1xuICogfVxuICpcbiAqIEB1aW1vZGVsKCd1c2VyLXByb2ZpbGUnKVxuICogY2xhc3MgVXNlclByb2ZpbGUge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpY2hpbGQoQWRkcmVzcy5uYW1lLCAnYWRkcmVzcy1jaGlsZC1jb21wb25lbnQnKVxuICogICBhZGRyZXNzOiBBZGRyZXNzO1xuICogfVxuICpcbiAqIC8vIEluIHRoaXMgZXhhbXBsZSwgdGhlIEFkZHJlc3MgbW9kZWwgaGFzIHRoZSBkZWZhdWx0IHRhZyAnYWRkcmVzcy1jb21wb25lbnQnIHdoZW4gcmVuZGVyZWQgYXMgYSByb290IGNvbXBvbmVudCxcbiAqIC8vIGJ1dCB3aGVuIHVzZWQgaW5zaWRlIFVzZXJQcm9maWxlLCBpdCBpcyByZW5kZXJlZCB3aXRoIHRoZSBvdmVycmlkZGVuIHRhZyAnYWRkcmVzcy1jaGlsZC1jb21wb25lbnQnXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBNb2RlbFxuICogICBwYXJ0aWNpcGFudCB1aWNoaWxkXG4gKiAgIHBhcnRpY2lwYW50IFJlbmRlcmluZ0VuZ2luZVxuICogICBwYXJ0aWNpcGFudCBDb21wb25lbnRcbiAqICAgTW9kZWwtPj51aWNoaWxkOiBBcHBseSB0byBwcm9wZXJ0eVxuICogICB1aWNoaWxkLT4+TW9kZWw6IEFkZCBjaGlsZCBtZXRhZGF0YVxuICogICBSZW5kZXJpbmdFbmdpbmUtPj5Nb2RlbDogR2V0IGNoaWxkIG1ldGFkYXRhXG4gKiAgIE1vZGVsLT4+UmVuZGVyaW5nRW5naW5lOiBSZXR1cm4gcHJvcCBuYW1lLCBzdHJpbmdpZnkgZmxhZywgYW5kIGNoaWxkIHRhZyBvdmVycmlkZVxuICogICBSZW5kZXJpbmdFbmdpbmUtPj5Db21wb25lbnQ6IFBhc3MgcHJvcGVydHkgd2l0aCBzcGVjaWZpZWQgbmFtZSBhbmQgcmVuZGVyIHdpdGggb3ZlcnJpZGRlbiB0YWcgaWYgbmVzdGVkXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHVpY2hpbGQoXG4gIGNsYXp6OiBzdHJpbmcsXG4gIHRhZzogc3RyaW5nLFxuICBwcm9wczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9LFxuICBpc0FycmF5OiBib29sZWFuID0gZmFsc2UsXG4gIHNlcmlhbGl6ZTogYm9vbGVhbiA9IGZhbHNlXG4pIHtcbiAgcmV0dXJuICh0YXJnZXQ6IGFueSwgcHJvcGVydHlLZXk6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IG1ldGFkYXRhOiBVSUVsZW1lbnRNZXRhZGF0YSA9IHtcbiAgICAgIHRhZzogdGFnLFxuICAgICAgc2VyaWFsaXplOiBzZXJpYWxpemUsXG4gICAgICBwcm9wczogT2JqZWN0LmFzc2lnbih7fSwgcHJvcHMgfHwge30sIHtcbiAgICAgICAgbmFtZTogY2xhenogfHwgcHJvcGVydHlLZXksXG4gICAgICB9LCBpc0FycmF5ID8ge2N1c3RvbVR5cGVzOiBbQXJyYXkubmFtZV0sIG11bHRpcGxlOiB0cnVlfSA6IHttdWx0aXBsZTogcHJvcHM/Lm11bHRpcGxlIHx8IGZhbHNlfSksXG4gICAgfTtcblxuICAgIHByb3BNZXRhZGF0YShSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5DSElMRCksIG1ldGFkYXRhKShcbiAgICAgIHRhcmdldCxcbiAgICAgIHByb3BlcnR5S2V5XG4gICAgKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIHRoYXQgbWFwcyBhIG1vZGVsIHByb3BlcnR5IHRvIGEgbGlzdCBpdGVtIGNvbXBvbmVudFxuICogQHN1bW1hcnkgU3BlY2lmaWVzIGhvdyBhIHByb3BlcnR5IHNob3VsZCBiZSByZW5kZXJlZCBpbiBhIGxpc3QgY29udGV4dFxuICogVGhpcyBkZWNvcmF0b3IgYWxsb3dzIHlvdSB0byBkZWZpbmUgaG93IGEgbW9kZWwgcHJvcGVydHkgY29udGFpbmluZyBhIGxpc3RcbiAqIHNob3VsZCBiZSByZW5kZXJlZC4gSXQgcmVxdWlyZXMgdGhlIGNsYXNzIHRvIGJlIGRlY29yYXRlZCB3aXRoIEB1aWxpc3RpdGVtLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbcHJvcE5hbWVdIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBwYXNzIHRvIHRoZSBsaXN0IGNvbXBvbmVudCAoZGVmYXVsdHMgdG8gdGhlIHByb3BlcnR5IGtleSlcbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW3Byb3BzXSBBZGRpdGlvbmFsIHByb3BlcnRpZXMgdG8gcGFzcyB0byB0aGUgbGlzdCBjb250YWluZXJcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIHByb3BlcnR5IGRlY29yYXRvciBmdW5jdGlvblxuICpcbiAqIEBmdW5jdGlvbiB1aWxpc3Rwcm9wXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBEZWZpbmUgYSBsaXN0IHByb3BlcnR5IHdpdGggY3VzdG9tIHJlbmRlcmluZ1xuICogQHVpbW9kZWwoJ3RvZG8tbGlzdCcpXG4gKiBjbGFzcyBUb2RvTGlzdCB7XG4gKiAgIEBhdHRyaWJ1dGUoKVxuICogICB0aXRsZTogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIEB1aWxpc3Rwcm9wKCdpdGVtcycsIHsgY2xhc3M6ICd0b2RvLWl0ZW1zLWNvbnRhaW5lcicgfSlcbiAqICAgaXRlbXM6IFRvZG9JdGVtW107XG4gKiB9XG4gKlxuICogQHVpbGlzdGl0ZW0oJ2xpJywgeyBjbGFzczogJ3RvZG8taXRlbScgfSlcbiAqIGNsYXNzIFRvZG9JdGVtIGV4dGVuZHMgTW9kZWwge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgdGV4dDogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIGNvbXBsZXRlZDogYm9vbGVhbjtcbiAqIH1cbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IE1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IHVpbGlzdHByb3BcbiAqICAgcGFydGljaXBhbnQgUmVuZGVyaW5nRW5naW5lXG4gKiAgIHBhcnRpY2lwYW50IExpc3RDb250YWluZXJcbiAqICAgcGFydGljaXBhbnQgTGlzdEl0ZW1zXG4gKiAgIE1vZGVsLT4+dWlsaXN0cHJvcDogQXBwbHkgdG8gcHJvcGVydHlcbiAqICAgdWlsaXN0cHJvcC0+Pk1vZGVsOiBBZGQgbGlzdCBwcm9wIG1ldGFkYXRhXG4gKiAgIFJlbmRlcmluZ0VuZ2luZS0+Pk1vZGVsOiBHZXQgbGlzdCBwcm9wIG1ldGFkYXRhXG4gKiAgIE1vZGVsLT4+UmVuZGVyaW5nRW5naW5lOiBSZXR1cm4gcHJvcCBuYW1lIGFuZCBjb250YWluZXIgcHJvcHNcbiAqICAgUmVuZGVyaW5nRW5naW5lLT4+TGlzdENvbnRhaW5lcjogQ3JlYXRlIGNvbnRhaW5lciB3aXRoIHByb3BzXG4gKiAgIFJlbmRlcmluZ0VuZ2luZS0+Pkxpc3RJdGVtczogUmVuZGVyIGVhY2ggaXRlbSB1c2luZyBAdWlsaXN0aXRlbVxuICogICBMaXN0Q29udGFpbmVyLT4+UmVuZGVyaW5nRW5naW5lOiBSZXR1cm4gcmVuZGVyZWQgbGlzdFxuICovXG5leHBvcnQgZnVuY3Rpb24gdWlsaXN0cHJvcChcbiAgcHJvcE5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgcHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4pIHtcbiAgcmV0dXJuICh0YXJnZXQ6IGFueSwgcHJvcGVydHlLZXk6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IG1ldGFkYXRhOiBQYXJ0aWFsPFVJTGlzdFByb3BNZXRhZGF0YT4gPSB7XG4gICAgICBuYW1lOiBwcm9wTmFtZSB8fCBwcm9wZXJ0eUtleSxcbiAgICAgIHByb3BzOiBwcm9wcyB8fCB7fSxcbiAgICB9O1xuICAgIHByb3BNZXRhZGF0YShSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5VSUxJU1RQUk9QKSwgbWV0YWRhdGEpKFxuICAgICAgdGFyZ2V0LFxuICAgICAgcHJvcGVydHlLZXlcbiAgICApO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgdGhhdCBwb3NpdGlvbnMgYSBwcm9wZXJ0eSBpbiBhIHNwZWNpZmljIGdyaWQgbGF5b3V0IHBvc2l0aW9uXG4gKiBAc3VtbWFyeSBTcGVjaWZpZXMgdGhlIGNvbHVtbiBhbmQgcm93IHBvc2l0aW9uIGZvciBhIHByb3BlcnR5IGluIGEgVUkgbGF5b3V0IGdyaWRcbiAqIFRoaXMgZGVjb3JhdG9yIGFsbG93cyB5b3UgdG8gZGVmaW5lIHRoZSBzcGVjaWZpYyBwb3NpdGlvbiBvZiBhIHByb3BlcnR5IHdpdGhpblxuICogYSBncmlkLWJhc2VkIGxheW91dCBzeXN0ZW0uIEl0IHNwZWNpZmllcyB3aGljaCBjb2x1bW4gYW5kIHJvdyB0aGUgcHJvcGVydHlcbiAqIHNob3VsZCBvY2N1cHkgd2hlbiByZW5kZXJlZCBpbiB0aGUgVUkuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGNvbCBUaGUgY29sdW1uIHBvc2l0aW9uIGluIHRoZSBncmlkIGxheW91dFxuICogQHBhcmFtIHtudW1iZXJ9IFtyb3c9MV0gVGhlIHJvdyBwb3NpdGlvbiBpbiB0aGUgZ3JpZCBsYXlvdXQgKGRlZmF1bHRzIHRvIDEpXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IFtwcm9wcz17fV0gQWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIHBhc3MgdG8gdGhlIGxheW91dCBpdGVtXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBwcm9wZXJ0eSBkZWNvcmF0b3IgZnVuY3Rpb25cbiAqXG4gKiBAZnVuY3Rpb24gdWlsYXlvdXRpdGVtXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBQb3NpdGlvbiBwcm9wZXJ0aWVzIGluIGEgZ3JpZCBsYXlvdXRcbiAqIEB1aW1vZGVsKCd1c2VyLWZvcm0nKVxuICogY2xhc3MgVXNlckZvcm0ge1xuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpbGF5b3V0aXRlbSgxLCAxKSAvLyBGaXJzdCBjb2x1bW4sIGZpcnN0IHJvd1xuICogICBmaXJzdE5hbWU6IHN0cmluZztcbiAqXG4gKiAgIEBhdHRyaWJ1dGUoKVxuICogICBAdWlsYXlvdXRpdGVtKDIsIDEpIC8vIFNlY29uZCBjb2x1bW4sIGZpcnN0IHJvd1xuICogICBsYXN0TmFtZTogc3RyaW5nO1xuICpcbiAqICAgQGF0dHJpYnV0ZSgpXG4gKiAgIEB1aWxheW91dGl0ZW0oMSwgMiwgeyBjb2xzcGFuOiAyIH0pIC8vIEZpcnN0IGNvbHVtbiwgc2Vjb25kIHJvdywgc3BhbnMgMiBjb2x1bW5zXG4gKiAgIGVtYWlsOiBzdHJpbmc7XG4gKlxuICogICBAYXR0cmlidXRlKClcbiAqICAgQHVpbGF5b3V0aXRlbSgxLCAzLCB7IGNsYXNzOiAnZnVsbC13aWR0aCcgfSkgLy8gRmlyc3QgY29sdW1uLCB0aGlyZCByb3cgd2l0aCBjdXN0b20gY2xhc3NcbiAqICAgYmlvOiBzdHJpbmc7XG4gKiB9XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBNb2RlbFxuICogICBwYXJ0aWNpcGFudCB1aWxheW91dGl0ZW1cbiAqICAgcGFydGljaXBhbnQgUmVuZGVyaW5nRW5naW5lXG4gKiAgIHBhcnRpY2lwYW50IExheW91dENvbnRhaW5lclxuICogICBNb2RlbC0+PnVpbGF5b3V0aXRlbTogQXBwbHkgdG8gcHJvcGVydHlcbiAqICAgdWlsYXlvdXRpdGVtLT4+TW9kZWw6IEFkZCBsYXlvdXQgaXRlbSBtZXRhZGF0YVxuICogICBSZW5kZXJpbmdFbmdpbmUtPj5Nb2RlbDogR2V0IGxheW91dCBpdGVtIG1ldGFkYXRhXG4gKiAgIE1vZGVsLT4+UmVuZGVyaW5nRW5naW5lOiBSZXR1cm4gY29sdW1uLCByb3csIGFuZCBwcm9wc1xuICogICBSZW5kZXJpbmdFbmdpbmUtPj5MYXlvdXRDb250YWluZXI6IFBvc2l0aW9uIGVsZW1lbnQgYXQgZ3JpZCBjb29yZGluYXRlc1xuICogICBMYXlvdXRDb250YWluZXItPj5SZW5kZXJpbmdFbmdpbmU6IFJldHVybiBwb3NpdGlvbmVkIGVsZW1lbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVpbGF5b3V0aXRlbShcbiAgY29sOiBudW1iZXIsXG4gIHJvdzogbnVtYmVyID0gMSxcbiAgcHJvcHM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fSxcbikge1xuICByZXR1cm4gKHRhcmdldDogYW55LCBwcm9wZXJ0eUtleTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgbWV0YWRhdGE6IFVJTGF5b3V0SXRlbU1ldGFkYXRhID0ge1xuICAgICAgbmFtZTogIHByb3BlcnR5S2V5LFxuICAgICAgY29sLFxuICAgICAgcm93LFxuICAgICAgcHJvcHM6IE9iamVjdC5hc3NpZ24oe30sIHByb3BzLCB7cm93OiByb3cgPz8gMSwgY29sOiBjb2wgPz8gMX0pLFxuICAgIH07ICBcbiAgICBwcm9wTWV0YWRhdGEoUmVuZGVyaW5nRW5naW5lLmtleShVSUtleXMuVUlMQVlPVVRJVEVNKSwgbWV0YWRhdGEpKFxuICAgICAgdGFyZ2V0LFxuICAgICAgcHJvcGVydHlLZXlcbiAgICApO1xuICB9O1xufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gQ2xhc3MgcmVwcmVzZW50aW5nIGFuIGV2ZW50IGhhbmRsZXJcbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIHN0cnVjdHVyZSBmb3IgaGFuZGxpbmcgZXZlbnRzIGluIHRoZSBVSSBkZWNvcmF0b3JzIHN5c3RlbVxuICogVGhpcyBjbGFzcyBwcm92aWRlcyBhIGZvdW5kYXRpb24gZm9yIG1hbmFnaW5nIGFuZCBwcm9jZXNzaW5nIGV2ZW50cyB0aGF0IG9jY3VyXG4gKiB3aXRoaW4gdGhlIFVJIGNvbXBvbmVudHMgZ2VuZXJhdGVkIGJ5IHRoZSBkZWNvcmF0b3JzLlxuICogQGNsYXNzIEV2ZW50SGFuZGxlclxuICogQG1lbWJlck9mIG1vZHVsZTp1aS1kZWNvcmF0b3JzL3VpXG4gKi9cbmV4cG9ydCBjbGFzcyBFdmVudEhhbmRsZXIge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgRXZlbnRIYW5kbGVyXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgbmV3IEV2ZW50SGFuZGxlciBvYmplY3RcbiAgICogVGhpcyBjb25zdHJ1Y3RvciBjdXJyZW50bHkgZG9lc24ndCB0YWtlIGFueSBwYXJhbWV0ZXJzLCBidXQgaXQgY2FuIGJlXG4gICAqIGV4dGVuZGVkIGluIHRoZSBmdXR1cmUgdG8gYWNjZXB0IGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBpZiBuZWVkZWQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHt9XG59IiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gVUkgZGVjb3JhdG9ycyBtb2R1bGUgZm9yIFR5cGVTY3JpcHQgYXBwbGljYXRpb25zXG4gKiBAc3VtbWFyeSBBIGNvbGxlY3Rpb24gb2YgZGVjb3JhdG9ycyBhbmQgdXRpbGl0aWVzIGZvciBidWlsZGluZyBVSSBjb21wb25lbnRzIGluIFR5cGVTY3JpcHQgYXBwbGljYXRpb25zLlxuICogVGhpcyBtb2R1bGUgZXhwb3J0cyBmdW5jdGlvbmFsaXR5IGZyb20gYm90aCB0aGUgbW9kZWwgYW5kIFVJIHN1Ym1vZHVsZXMsIHByb3ZpZGluZyBkZWNvcmF0b3JzIGZvclxuICogcmVuZGVyaW5nLCBjb21wb25lbnQgZGVmaW5pdGlvbiwgYW5kIFVJIHN0YXRlIG1hbmFnZW1lbnQuXG4gKiBAbW9kdWxlIHVpLWRlY29yYXRvcnNcbiAqL1xuXG5leHBvcnQgKiBmcm9tIFwiLi9tb2RlbFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdWlcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3VycmVudCBwYWNrYWdlIHZlcnNpb24gc3RyaW5nXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIGN1cnJlbnQgcGFja2FnZSB2ZXJzaW9uIGZvciByZWZlcmVuY2VcbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnVpLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBcIiMjVkVSU0lPTiMjXCI7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTs7Ozs7OztBQU9HO0lBNEJTO0FBQVosQ0FBQSxVQUFZLGtCQUFrQixFQUFBO0FBQzVCLElBQUEsa0JBQUEsQ0FBQSxPQUFBLENBQUEsR0FBQSxHQUFXO0FBQ1gsSUFBQSxrQkFBQSxDQUFBLFFBQUEsQ0FBQSxHQUFBLEdBQVk7QUFDWixJQUFBLGtCQUFBLENBQUEsT0FBQSxDQUFBLEdBQUEsR0FBVztBQUNYLElBQUEsa0JBQUEsQ0FBQSxRQUFBLENBQUEsR0FBQSxJQUFhO0FBQ2YsQ0FBQyxFQUxXLGtCQUFrQixLQUFsQixrQkFBa0IsR0FLN0IsRUFBQSxDQUFBLENBQUE7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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