@decaf-ts/db-decorators 0.6.1 → 0.6.3
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.
- package/LICENSE.md +21 -157
- package/README.md +571 -10
- package/dist/db-decorators.cjs +1599 -426
- package/dist/db-decorators.esm.cjs +1597 -428
- package/lib/esm/identity/decorators.d.ts +7 -0
- package/lib/esm/identity/decorators.js +11 -4
- package/lib/esm/identity/index.js +3 -3
- package/lib/esm/identity/utils.d.ts +36 -23
- package/lib/esm/identity/utils.js +38 -25
- package/lib/esm/index.d.ts +12 -27
- package/lib/esm/index.js +13 -28
- package/lib/esm/interfaces/BulkCrudOperator.d.ts +39 -0
- package/lib/esm/interfaces/BulkCrudOperator.js +1 -1
- package/lib/esm/interfaces/Contextual.d.ts +17 -0
- package/lib/esm/interfaces/Contextual.js +1 -1
- package/lib/esm/interfaces/CrudOperator.d.ts +26 -23
- package/lib/esm/interfaces/CrudOperator.js +1 -1
- package/lib/esm/interfaces/IRepository.d.ts +10 -2
- package/lib/esm/interfaces/IRepository.js +1 -1
- package/lib/esm/interfaces/index.js +5 -5
- package/lib/esm/model/constants.d.ts +11 -13
- package/lib/esm/model/constants.js +12 -14
- package/lib/esm/model/decorators.d.ts +112 -23
- package/lib/esm/model/decorators.js +119 -29
- package/lib/esm/model/index.d.ts +1 -0
- package/lib/esm/model/index.js +7 -6
- package/lib/esm/model/model.d.ts +2 -141
- package/lib/esm/model/model.js +2 -13
- package/lib/esm/model/overrides.d.ts +1 -0
- package/lib/esm/model/overrides.js +34 -0
- package/lib/esm/model/utils.d.ts +39 -0
- package/lib/esm/model/utils.js +42 -3
- package/lib/esm/model/validation.d.ts +51 -8
- package/lib/esm/model/validation.js +246 -107
- package/lib/esm/operations/Operations.d.ts +65 -3
- package/lib/esm/operations/Operations.js +68 -6
- package/lib/esm/operations/OperationsRegistry.d.ts +44 -16
- package/lib/esm/operations/OperationsRegistry.js +46 -18
- package/lib/esm/operations/constants.d.ts +27 -8
- package/lib/esm/operations/constants.js +16 -9
- package/lib/esm/operations/decorators.d.ts +140 -134
- package/lib/esm/operations/decorators.js +152 -137
- package/lib/esm/operations/index.js +6 -6
- package/lib/esm/operations/types.d.ts +10 -0
- package/lib/esm/operations/types.js +1 -1
- package/lib/esm/repository/BaseRepository.d.ts +322 -0
- package/lib/esm/repository/BaseRepository.js +297 -7
- package/lib/esm/repository/Context.d.ts +153 -2
- package/lib/esm/repository/Context.js +154 -6
- package/lib/esm/repository/Repository.d.ts +89 -0
- package/lib/esm/repository/Repository.js +102 -15
- package/lib/esm/repository/constants.d.ts +7 -0
- package/lib/esm/repository/constants.js +8 -1
- package/lib/esm/repository/errors.d.ts +61 -34
- package/lib/esm/repository/errors.js +62 -35
- package/lib/esm/repository/index.js +9 -9
- package/lib/esm/repository/types.d.ts +25 -0
- package/lib/esm/repository/types.js +1 -1
- package/lib/esm/repository/utils.d.ts +11 -0
- package/lib/esm/repository/utils.js +4 -4
- package/lib/esm/repository/wrappers.d.ts +2 -2
- package/lib/esm/repository/wrappers.js +5 -5
- package/lib/esm/validation/constants.d.ts +20 -5
- package/lib/esm/validation/constants.js +22 -7
- package/lib/esm/validation/decorators.d.ts +101 -19
- package/lib/esm/validation/decorators.js +109 -27
- package/lib/esm/validation/index.js +5 -5
- package/lib/esm/validation/validation.js +10 -2
- package/lib/esm/validation/validators/ReadOnlyValidator.d.ts +32 -8
- package/lib/esm/validation/validators/ReadOnlyValidator.js +34 -10
- package/lib/esm/validation/validators/TimestampValidator.d.ts +37 -3
- package/lib/esm/validation/validators/TimestampValidator.js +39 -5
- package/lib/esm/validation/validators/UpdateValidator.d.ts +28 -11
- package/lib/esm/validation/validators/UpdateValidator.js +23 -8
- package/lib/esm/validation/validators/index.js +4 -4
- package/lib/identity/decorators.cjs +8 -1
- package/lib/identity/decorators.d.ts +7 -0
- package/lib/identity/utils.cjs +35 -22
- package/lib/identity/utils.d.ts +36 -23
- package/lib/index.cjs +14 -28
- package/lib/index.d.ts +12 -27
- package/lib/interfaces/BulkCrudOperator.cjs +1 -1
- package/lib/interfaces/BulkCrudOperator.d.ts +39 -0
- package/lib/interfaces/Contextual.cjs +1 -1
- package/lib/interfaces/Contextual.d.ts +17 -0
- package/lib/interfaces/CrudOperator.cjs +1 -1
- package/lib/interfaces/CrudOperator.d.ts +26 -23
- package/lib/interfaces/IRepository.cjs +1 -1
- package/lib/interfaces/IRepository.d.ts +10 -2
- package/lib/model/constants.cjs +12 -14
- package/lib/model/constants.d.ts +11 -13
- package/lib/model/decorators.cjs +114 -24
- package/lib/model/decorators.d.ts +112 -23
- package/lib/model/index.cjs +2 -1
- package/lib/model/index.d.ts +1 -0
- package/lib/model/model.cjs +1 -13
- package/lib/model/model.d.ts +2 -141
- package/lib/model/overrides.cjs +36 -0
- package/lib/model/overrides.d.ts +1 -0
- package/lib/model/utils.cjs +40 -1
- package/lib/model/utils.d.ts +39 -0
- package/lib/model/validation.cjs +246 -104
- package/lib/model/validation.d.ts +51 -8
- package/lib/operations/Operations.cjs +66 -4
- package/lib/operations/Operations.d.ts +65 -3
- package/lib/operations/OperationsRegistry.cjs +45 -17
- package/lib/operations/OperationsRegistry.d.ts +44 -16
- package/lib/operations/constants.cjs +16 -9
- package/lib/operations/constants.d.ts +27 -8
- package/lib/operations/decorators.cjs +150 -135
- package/lib/operations/decorators.d.ts +140 -134
- package/lib/operations/types.cjs +1 -1
- package/lib/operations/types.d.ts +10 -0
- package/lib/repository/BaseRepository.cjs +291 -1
- package/lib/repository/BaseRepository.d.ts +322 -0
- package/lib/repository/Context.cjs +153 -5
- package/lib/repository/Context.d.ts +153 -2
- package/lib/repository/Repository.cjs +96 -9
- package/lib/repository/Repository.d.ts +89 -0
- package/lib/repository/constants.cjs +8 -1
- package/lib/repository/constants.d.ts +7 -0
- package/lib/repository/errors.cjs +62 -35
- package/lib/repository/errors.d.ts +61 -34
- package/lib/repository/types.cjs +1 -1
- package/lib/repository/types.d.ts +25 -0
- package/lib/repository/utils.cjs +1 -1
- package/lib/repository/utils.d.ts +11 -0
- package/lib/repository/wrappers.cjs +3 -3
- package/lib/repository/wrappers.d.ts +2 -2
- package/lib/validation/constants.cjs +21 -6
- package/lib/validation/constants.d.ts +20 -5
- package/lib/validation/decorators.cjs +102 -20
- package/lib/validation/decorators.d.ts +101 -19
- package/lib/validation/validation.cjs +9 -1
- package/lib/validation/validators/ReadOnlyValidator.cjs +33 -9
- package/lib/validation/validators/ReadOnlyValidator.d.ts +32 -8
- package/lib/validation/validators/TimestampValidator.cjs +38 -4
- package/lib/validation/validators/TimestampValidator.d.ts +37 -3
- package/lib/validation/validators/UpdateValidator.cjs +23 -8
- package/lib/validation/validators/UpdateValidator.d.ts +28 -11
- package/package.json +2 -2
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { ModelKeys, validator, Validator, DEFAULT_ERROR_MESSAGES as DEFAULT_ERROR_MESSAGES$1, Validation, Hashing, propMetadata, sf, Decoration, date, required, type, ValidationKeys,
|
|
1
|
+
import { ModelKeys, validator, Validator, DEFAULT_ERROR_MESSAGES as DEFAULT_ERROR_MESSAGES$1, Validation, Hashing, propMetadata, sf, Decoration, date, required, type, ValidationKeys, Model, ModelErrorDefinition, getValidationDecorators, toConditionalPromise, validate } from '@decaf-ts/decorator-validation';
|
|
2
2
|
import { __decorate, __metadata } from 'tslib';
|
|
3
3
|
import { isEqual, apply, Reflection, metadata } from '@decaf-ts/reflection';
|
|
4
4
|
import { ObjectAccumulator } from 'typed-object-accumulator';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* @
|
|
7
|
+
* @description Database reflection keys
|
|
8
|
+
* @summary Collection of keys used for reflection metadata in database operations
|
|
8
9
|
* @const DBKeys
|
|
9
|
-
*
|
|
10
|
-
* @memberOf module:db-decorators.Model
|
|
10
|
+
* @memberOf module:db-decorators
|
|
11
11
|
*/
|
|
12
12
|
const DBKeys = {
|
|
13
13
|
REFLECT: `${ModelKeys.REFLECT}persistence.`,
|
|
@@ -26,27 +26,35 @@ const DBKeys = {
|
|
|
26
26
|
ORIGINAL: "__originalObj",
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
|
-
* @
|
|
30
|
-
*
|
|
31
|
-
* @const
|
|
32
|
-
*
|
|
33
|
-
* @category Managers
|
|
34
|
-
* @subcategory Constants
|
|
29
|
+
* @description Default separator character for composite indexes
|
|
30
|
+
* @summary The default separator character used when concatenating multiple fields into a single index
|
|
31
|
+
* @const DefaultSeparator
|
|
32
|
+
* @memberOf module:db-decorators
|
|
35
33
|
*/
|
|
36
34
|
const DefaultSeparator = "_";
|
|
37
35
|
/**
|
|
38
|
-
* @
|
|
39
|
-
* @
|
|
40
|
-
*
|
|
41
|
-
* @memberOf module:db-decorators
|
|
36
|
+
* @description Default format for timestamp fields
|
|
37
|
+
* @summary Standard date format string used for timestamp fields in database models
|
|
38
|
+
* @const DEFAULT_TIMESTAMP_FORMAT
|
|
39
|
+
* @memberOf module:db-decorators
|
|
42
40
|
*/
|
|
43
41
|
const DEFAULT_TIMESTAMP_FORMAT = "dd/MM/yyyy HH:mm:ss:S";
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
|
-
* @
|
|
44
|
+
* @description Collection of default error messages used by validators.
|
|
45
|
+
* @summary Holds the default error messages for various validation scenarios including ID validation, readonly properties, and timestamps.
|
|
46
|
+
* @typedef {Object} ErrorMessages
|
|
47
|
+
* @property {Object} ID - Error messages for ID validation
|
|
48
|
+
* @property {string} ID.INVALID - Error message when an ID is invalid
|
|
49
|
+
* @property {string} ID.REQUIRED - Error message when an ID is missing
|
|
50
|
+
* @property {Object} READONLY - Error messages for readonly properties
|
|
51
|
+
* @property {string} READONLY.INVALID - Error message when attempting to update a readonly property
|
|
52
|
+
* @property {Object} TIMESTAMP - Error messages for timestamp validation
|
|
53
|
+
* @property {string} TIMESTAMP.REQUIRED - Error message when a timestamp is missing
|
|
54
|
+
* @property {string} TIMESTAMP.DATE - Error message when a timestamp is not a valid date
|
|
55
|
+
* @property {string} TIMESTAMP.INVALID - Error message when a timestamp is not increasing
|
|
47
56
|
* @const DEFAULT_ERROR_MESSAGES
|
|
48
|
-
*
|
|
49
|
-
* @memberOf module:db-decorators.Model
|
|
57
|
+
* @memberOf module:validation
|
|
50
58
|
*/
|
|
51
59
|
const DEFAULT_ERROR_MESSAGES = {
|
|
52
60
|
ID: {
|
|
@@ -63,9 +71,14 @@ const DEFAULT_ERROR_MESSAGES = {
|
|
|
63
71
|
},
|
|
64
72
|
};
|
|
65
73
|
/**
|
|
66
|
-
* @
|
|
74
|
+
* @description Constants used for reflection-based validation during update operations.
|
|
75
|
+
* @summary Keys used for storing and retrieving validation metadata on model properties during update operations.
|
|
76
|
+
* @typedef {Object} ValidationKeys
|
|
77
|
+
* @property {string} REFLECT - Base reflection key prefix for update validation
|
|
78
|
+
* @property {string} TIMESTAMP - Key for timestamp validation
|
|
79
|
+
* @property {string} READONLY - Key for readonly property validation
|
|
67
80
|
* @const UpdateValidationKeys
|
|
68
|
-
* @memberOf module:
|
|
81
|
+
* @memberOf module:validation
|
|
69
82
|
*/
|
|
70
83
|
const UpdateValidationKeys = {
|
|
71
84
|
REFLECT: "db.update.validation.",
|
|
@@ -74,11 +87,29 @@ const UpdateValidationKeys = {
|
|
|
74
87
|
};
|
|
75
88
|
|
|
76
89
|
/**
|
|
77
|
-
* @
|
|
78
|
-
*
|
|
90
|
+
* @description A validator that ensures properties marked as readonly cannot be modified during updates.
|
|
91
|
+
* @summary Validator for the {@link readonly} decorator that checks if a value has been changed during an update operation. It compares the new value with the old value and returns an error message if they are not equal.
|
|
92
|
+
* @param {any} value - The value to be validated
|
|
93
|
+
* @param {any} oldValue - The previous value to compare against
|
|
94
|
+
* @param {string} [message] - Optional custom error message
|
|
79
95
|
* @class ReadOnlyValidator
|
|
80
|
-
* @
|
|
81
|
-
*
|
|
96
|
+
* @example
|
|
97
|
+
* // Using ReadOnlyValidator with a readonly property
|
|
98
|
+
* class User {
|
|
99
|
+
* @readonly()
|
|
100
|
+
* id: string;
|
|
101
|
+
*
|
|
102
|
+
* name: string;
|
|
103
|
+
*
|
|
104
|
+
* constructor(id: string, name: string) {
|
|
105
|
+
* this.id = id;
|
|
106
|
+
* this.name = name;
|
|
107
|
+
* }
|
|
108
|
+
* }
|
|
109
|
+
*
|
|
110
|
+
* // This will trigger validation error when trying to update
|
|
111
|
+
* const user = new User('123', 'John');
|
|
112
|
+
* user.id = '456'; // Will be prevented by ReadOnlyValidator
|
|
82
113
|
* @category Validators
|
|
83
114
|
*/
|
|
84
115
|
let ReadOnlyValidator = class ReadOnlyValidator extends Validator {
|
|
@@ -86,17 +117,23 @@ let ReadOnlyValidator = class ReadOnlyValidator extends Validator {
|
|
|
86
117
|
super(DEFAULT_ERROR_MESSAGES.READONLY.INVALID);
|
|
87
118
|
}
|
|
88
119
|
/**
|
|
89
|
-
* @
|
|
120
|
+
* @description Implementation of the base validator's hasErrors method.
|
|
121
|
+
* @summary This method is required by the Validator interface but not used in this validator as validation only happens during updates.
|
|
122
|
+
* @param {any} value - The value to validate
|
|
123
|
+
* @param {any[]} args - Additional arguments
|
|
124
|
+
* @return {string | undefined} Always returns undefined as this validator only works during updates
|
|
90
125
|
*/
|
|
91
126
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
92
127
|
hasErrors(value, ...args) {
|
|
93
128
|
return undefined;
|
|
94
129
|
}
|
|
95
130
|
/**
|
|
96
|
-
* @
|
|
97
|
-
* @
|
|
98
|
-
* @param {any}
|
|
99
|
-
* @param {
|
|
131
|
+
* @description Checks if a value has been modified during an update operation.
|
|
132
|
+
* @summary Validates a value has not changed by comparing it with the previous value using deep equality.
|
|
133
|
+
* @param {any} value - The new value to validate
|
|
134
|
+
* @param {any} oldValue - The original value to compare against
|
|
135
|
+
* @param {string} [message] - Optional custom error message to override the default
|
|
136
|
+
* @return {string | undefined} An error message if validation fails, undefined otherwise
|
|
100
137
|
*/
|
|
101
138
|
updateHasErrors(value, oldValue, message) {
|
|
102
139
|
if (value === undefined)
|
|
@@ -112,21 +149,55 @@ ReadOnlyValidator = __decorate([
|
|
|
112
149
|
], ReadOnlyValidator);
|
|
113
150
|
|
|
114
151
|
/**
|
|
115
|
-
* @
|
|
116
|
-
*
|
|
152
|
+
* @description A validator that ensures timestamp values are only updated with newer timestamps.
|
|
153
|
+
* @summary Validates the update of a timestamp by comparing the new timestamp with the old one, ensuring the new timestamp is more recent.
|
|
154
|
+
* @param {Date|string|number} value - The timestamp value to validate
|
|
155
|
+
* @param {Date|string|number} oldValue - The previous timestamp to compare against
|
|
156
|
+
* @param {string} [message] - Optional custom error message
|
|
117
157
|
* @class TimestampValidator
|
|
118
|
-
* @
|
|
119
|
-
*
|
|
158
|
+
* @example
|
|
159
|
+
* // Using TimestampValidator with a timestamp property
|
|
160
|
+
* class Document {
|
|
161
|
+
* @timestamp()
|
|
162
|
+
* updatedAt: Date;
|
|
163
|
+
*
|
|
164
|
+
* title: string;
|
|
165
|
+
*
|
|
166
|
+
* constructor(title: string) {
|
|
167
|
+
* this.title = title;
|
|
168
|
+
* this.updatedAt = new Date();
|
|
169
|
+
* }
|
|
170
|
+
* }
|
|
171
|
+
*
|
|
172
|
+
* // This will trigger validation error when trying to update with an older timestamp
|
|
173
|
+
* const doc = new Document('My Document');
|
|
174
|
+
* const oldDate = new Date(2020, 0, 1);
|
|
175
|
+
* doc.updatedAt = oldDate; // Will be prevented by TimestampValidator
|
|
120
176
|
* @category Validators
|
|
121
177
|
*/
|
|
122
178
|
let TimestampValidator = class TimestampValidator extends Validator {
|
|
123
179
|
constructor() {
|
|
124
180
|
super(DEFAULT_ERROR_MESSAGES.TIMESTAMP.INVALID);
|
|
125
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* @description Implementation of the base validator's hasErrors method.
|
|
184
|
+
* @summary This method is required by the Validator interface but not used in this validator as validation only happens during updates.
|
|
185
|
+
* @param {any} value - The timestamp value to validate
|
|
186
|
+
* @param {any[]} args - Additional arguments
|
|
187
|
+
* @return {string | undefined} Always returns undefined as this validator only works during updates
|
|
188
|
+
*/
|
|
126
189
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
127
190
|
hasErrors(value, ...args) {
|
|
128
191
|
return undefined;
|
|
129
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* @description Validates that a timestamp is newer than its previous value.
|
|
195
|
+
* @summary Checks if a timestamp has been updated with a more recent value by converting both values to Date objects and comparing them.
|
|
196
|
+
* @param {Date|string|number} value - The new timestamp value to validate
|
|
197
|
+
* @param {Date|string|number} oldValue - The original timestamp to compare against
|
|
198
|
+
* @param {string} [message] - Optional custom error message to override the default
|
|
199
|
+
* @return {string | undefined} An error message if validation fails (new timestamp is not newer), undefined otherwise
|
|
200
|
+
*/
|
|
130
201
|
updateHasErrors(value, oldValue, message) {
|
|
131
202
|
if (value === undefined)
|
|
132
203
|
return;
|
|
@@ -148,15 +219,30 @@ TimestampValidator = __decorate([
|
|
|
148
219
|
], TimestampValidator);
|
|
149
220
|
|
|
150
221
|
/**
|
|
151
|
-
* @
|
|
152
|
-
*
|
|
153
|
-
* @param {string} [message]
|
|
154
|
-
* @param {string[]} [acceptedTypes]
|
|
155
|
-
*
|
|
222
|
+
* @description Abstract base class for validators that compare new values with old values during updates.
|
|
223
|
+
* @summary Base class for an Update validator that provides a framework for implementing validation logic that compares a new value with its previous state.
|
|
224
|
+
* @param {string} [message] - Error message. Defaults to {@link DecoratorMessages#DEFAULT}
|
|
225
|
+
* @param {string[]} [acceptedTypes] - The accepted value types by the decorator
|
|
156
226
|
* @class UpdateValidator
|
|
157
|
-
* @
|
|
158
|
-
*
|
|
159
|
-
*
|
|
227
|
+
* @example
|
|
228
|
+
* // Extending UpdateValidator to create a custom validator
|
|
229
|
+
* class MyCustomValidator extends UpdateValidator {
|
|
230
|
+
* constructor() {
|
|
231
|
+
* super("Custom validation failed");
|
|
232
|
+
* }
|
|
233
|
+
*
|
|
234
|
+
* public updateHasErrors(value: any, oldValue: any): string | undefined {
|
|
235
|
+
* // Custom validation logic
|
|
236
|
+
* if (value === oldValue) {
|
|
237
|
+
* return this.message;
|
|
238
|
+
* }
|
|
239
|
+
* return undefined;
|
|
240
|
+
* }
|
|
241
|
+
*
|
|
242
|
+
* hasErrors(value: any): string | undefined {
|
|
243
|
+
* return undefined; // Not used for update validators
|
|
244
|
+
* }
|
|
245
|
+
* }
|
|
160
246
|
* @category Validators
|
|
161
247
|
*/
|
|
162
248
|
class UpdateValidator extends Validator {
|
|
@@ -165,15 +251,24 @@ class UpdateValidator extends Validator {
|
|
|
165
251
|
}
|
|
166
252
|
}
|
|
167
253
|
|
|
254
|
+
/**
|
|
255
|
+
* @description Generates a key for update validation metadata.
|
|
256
|
+
* @summary Builds the key to store as metadata under Reflections for update validation by prefixing the provided key with the update validation prefix.
|
|
257
|
+
* @param {string} key - The base key to be prefixed
|
|
258
|
+
* @return {string} The complete metadata key for update validation
|
|
259
|
+
* @function updateKey
|
|
260
|
+
* @memberOf module:db-decorators
|
|
261
|
+
*/
|
|
168
262
|
Validation.updateKey = function (key) {
|
|
169
263
|
return UpdateValidationKeys.REFLECT + key;
|
|
170
264
|
};
|
|
171
265
|
|
|
172
266
|
/**
|
|
173
|
-
* @
|
|
174
|
-
* @
|
|
175
|
-
*
|
|
176
|
-
* @
|
|
267
|
+
* @description Database operation key constants
|
|
268
|
+
* @summary Enum defining CRUD operations and their lifecycle phases
|
|
269
|
+
* @enum {string}
|
|
270
|
+
* @readonly
|
|
271
|
+
* @memberOf module:db-decorators
|
|
177
272
|
*/
|
|
178
273
|
var OperationKeys;
|
|
179
274
|
(function (OperationKeys) {
|
|
@@ -185,6 +280,13 @@ var OperationKeys;
|
|
|
185
280
|
OperationKeys["ON"] = "on.";
|
|
186
281
|
OperationKeys["AFTER"] = "after.";
|
|
187
282
|
})(OperationKeys || (OperationKeys = {}));
|
|
283
|
+
/**
|
|
284
|
+
* @description Bulk database operation key constants
|
|
285
|
+
* @summary Enum defining bulk CRUD operations for handling multiple records at once
|
|
286
|
+
* @enum {string}
|
|
287
|
+
* @readonly
|
|
288
|
+
* @memberOf module:db-decorators
|
|
289
|
+
*/
|
|
188
290
|
var BulkCrudOperationKeys;
|
|
189
291
|
(function (BulkCrudOperationKeys) {
|
|
190
292
|
BulkCrudOperationKeys["CREATE_ALL"] = "createAll";
|
|
@@ -193,11 +295,10 @@ var BulkCrudOperationKeys;
|
|
|
193
295
|
BulkCrudOperationKeys["DELETE_ALL"] = "deleteAll";
|
|
194
296
|
})(BulkCrudOperationKeys || (BulkCrudOperationKeys = {}));
|
|
195
297
|
/**
|
|
298
|
+
* @description Grouped CRUD operations for decorator mapping
|
|
196
299
|
* @summary Maps out groups of CRUD operations for easier mapping of decorators
|
|
197
|
-
*
|
|
198
|
-
* @
|
|
199
|
-
*
|
|
200
|
-
* @memberOf module:db-decorators.Operations
|
|
300
|
+
* @const DBOperations
|
|
301
|
+
* @memberOf module:db-decorators
|
|
201
302
|
*/
|
|
202
303
|
const DBOperations = {
|
|
203
304
|
CREATE: [OperationKeys.CREATE],
|
|
@@ -215,26 +316,47 @@ const DBOperations = {
|
|
|
215
316
|
};
|
|
216
317
|
|
|
217
318
|
/**
|
|
218
|
-
* @
|
|
219
|
-
*
|
|
319
|
+
* @description Registry for database operation handlers
|
|
320
|
+
* @summary Manages and stores operation handlers for different model properties and operations
|
|
220
321
|
* @class OperationsRegistry
|
|
221
|
-
* @
|
|
222
|
-
*
|
|
223
|
-
* @
|
|
224
|
-
*
|
|
225
|
-
* @
|
|
322
|
+
* @template M - Model type
|
|
323
|
+
* @template R - Repository type
|
|
324
|
+
* @template V - Metadata type
|
|
325
|
+
* @template F - Repository flags
|
|
326
|
+
* @template C - Context type
|
|
327
|
+
* @example
|
|
328
|
+
* // Create a registry and register a handler
|
|
329
|
+
* const registry = new OperationsRegistry();
|
|
330
|
+
* registry.register(myHandler, OperationKeys.CREATE, targetModel, 'propertyName');
|
|
331
|
+
*
|
|
332
|
+
* // Get handlers for a specific operation
|
|
333
|
+
* const handlers = registry.get(targetModel.constructor.name, 'propertyName', 'onCreate');
|
|
334
|
+
*
|
|
335
|
+
* @mermaid
|
|
336
|
+
* classDiagram
|
|
337
|
+
* class OperationsRegistry {
|
|
338
|
+
* -cache: Record~string, Record~string|symbol, Record~string, Record~string, OperationHandler~~~~
|
|
339
|
+
* +get(target, propKey, operation, accum)
|
|
340
|
+
* +register(handler, operation, target, propKey)
|
|
341
|
+
* }
|
|
226
342
|
*/
|
|
227
343
|
class OperationsRegistry {
|
|
228
344
|
constructor() {
|
|
229
345
|
this.cache = {};
|
|
230
346
|
}
|
|
231
347
|
/**
|
|
232
|
-
* @
|
|
233
|
-
* @
|
|
234
|
-
* @
|
|
235
|
-
* @
|
|
236
|
-
* @
|
|
237
|
-
* @
|
|
348
|
+
* @description Retrieves operation handlers for a specific target and operation
|
|
349
|
+
* @summary Finds all registered handlers for a given target, property, and operation, including from parent classes
|
|
350
|
+
* @template M - Model type extending Model
|
|
351
|
+
* @template R - Repository type extending IRepository
|
|
352
|
+
* @template V - Metadata type
|
|
353
|
+
* @template F - Repository flags extending RepositoryFlags
|
|
354
|
+
* @template C - Context type extending Context<F>
|
|
355
|
+
* @param {string | Record<string, any>} target - The target class name or object
|
|
356
|
+
* @param {string} propKey - The property key to get handlers for
|
|
357
|
+
* @param {string} operation - The operation key to get handlers for
|
|
358
|
+
* @param {OperationHandler[]} [accum] - Accumulator for recursive calls
|
|
359
|
+
* @return {OperationHandler[] | undefined} Array of handlers or undefined if none found
|
|
238
360
|
*/
|
|
239
361
|
get(target, propKey, operation, accum) {
|
|
240
362
|
accum = accum || [];
|
|
@@ -256,11 +378,18 @@ class OperationsRegistry {
|
|
|
256
378
|
return this.get(proto, propKey, operation, accum);
|
|
257
379
|
}
|
|
258
380
|
/**
|
|
259
|
-
* @
|
|
260
|
-
* @
|
|
261
|
-
* @
|
|
262
|
-
* @
|
|
263
|
-
* @
|
|
381
|
+
* @description Registers an operation handler for a specific target and operation
|
|
382
|
+
* @summary Stores a handler in the registry for a given target, property, and operation
|
|
383
|
+
* @template M - Model type extending Model
|
|
384
|
+
* @template R - Repository type extending IRepository
|
|
385
|
+
* @template V - Metadata type
|
|
386
|
+
* @template F - Repository flags extending RepositoryFlags
|
|
387
|
+
* @template C - Context type extending Context<F>
|
|
388
|
+
* @param {OperationHandler} handler - The handler function to register
|
|
389
|
+
* @param {OperationKeys} operation - The operation key to register the handler for
|
|
390
|
+
* @param {M} target - The target model instance
|
|
391
|
+
* @param {string | symbol} propKey - The property key to register the handler for
|
|
392
|
+
* @return {void}
|
|
264
393
|
*/
|
|
265
394
|
register(handler, operation, target, propKey) {
|
|
266
395
|
const name = target.constructor.name;
|
|
@@ -278,259 +407,336 @@ class OperationsRegistry {
|
|
|
278
407
|
}
|
|
279
408
|
|
|
280
409
|
/**
|
|
281
|
-
* @
|
|
282
|
-
*
|
|
410
|
+
* @description Static utility class for database operation management
|
|
411
|
+
* @summary Provides functionality for registering, retrieving, and managing database operation handlers
|
|
283
412
|
* @class Operations
|
|
284
|
-
*
|
|
285
|
-
* @
|
|
413
|
+
* @template M - Model type
|
|
414
|
+
* @template R - Repository type
|
|
415
|
+
* @template V - Metadata type
|
|
416
|
+
* @template F - Repository flags
|
|
417
|
+
* @template C - Context type
|
|
418
|
+
* @example
|
|
419
|
+
* // Register a handler for a create operation
|
|
420
|
+
* Operations.register(myHandler, OperationKeys.CREATE, targetModel, 'propertyName');
|
|
421
|
+
*
|
|
422
|
+
* // Get handlers for a specific operation
|
|
423
|
+
* const handlers = Operations.get(targetModel.constructor.name, 'propertyName', 'onCreate');
|
|
424
|
+
*
|
|
425
|
+
* @mermaid
|
|
426
|
+
* classDiagram
|
|
427
|
+
* class Operations {
|
|
428
|
+
* -registry: OperationsRegistry
|
|
429
|
+
* +getHandlerName(handler)
|
|
430
|
+
* +key(str)
|
|
431
|
+
* +get(targetName, propKey, operation)
|
|
432
|
+
* -getOpRegistry()
|
|
433
|
+
* +register(handler, operation, target, propKey)
|
|
434
|
+
* }
|
|
435
|
+
* Operations --> OperationsRegistry : uses
|
|
286
436
|
*/
|
|
287
437
|
class Operations {
|
|
288
438
|
constructor() { }
|
|
439
|
+
/**
|
|
440
|
+
* @description Gets a unique name for an operation handler
|
|
441
|
+
* @summary Returns the name of the handler function or generates a hash if name is not available
|
|
442
|
+
* @param {OperationHandler<any, any, any, any, any>} handler - The handler function to get the name for
|
|
443
|
+
* @return {string} The name of the handler or a generated hash
|
|
444
|
+
*/
|
|
289
445
|
static getHandlerName(handler) {
|
|
290
446
|
if (handler.name)
|
|
291
447
|
return handler.name;
|
|
292
448
|
console.warn("Handler name not defined. A name will be generated, but this is not desirable. please avoid using anonymous functions");
|
|
293
449
|
return Hashing.hash(handler.toString());
|
|
294
450
|
}
|
|
451
|
+
/**
|
|
452
|
+
* @description Generates a reflection metadata key
|
|
453
|
+
* @summary Creates a fully qualified metadata key by prefixing with the reflection namespace
|
|
454
|
+
* @param {string} str - The operation key string to prefix
|
|
455
|
+
* @return {string} The fully qualified metadata key
|
|
456
|
+
*/
|
|
295
457
|
static key(str) {
|
|
296
458
|
return OperationKeys.REFLECT + str;
|
|
297
459
|
}
|
|
460
|
+
/**
|
|
461
|
+
* @description Retrieves operation handlers for a specific target and operation
|
|
462
|
+
* @summary Gets registered handlers from the operations registry for a given target, property, and operation
|
|
463
|
+
* @template M - Model type extending Model
|
|
464
|
+
* @template R - Repository type extending IRepository
|
|
465
|
+
* @template V - Metadata type, defaults to object
|
|
466
|
+
* @template F - Repository flags extending RepositoryFlags
|
|
467
|
+
* @template C - Context type extending Context<F>
|
|
468
|
+
* @param {string | Record<string, any>} targetName - The target class name or object
|
|
469
|
+
* @param {string} propKey - The property key to get handlers for
|
|
470
|
+
* @param {string} operation - The operation key to get handlers for
|
|
471
|
+
* @return {any} The registered handlers for the specified target, property, and operation
|
|
472
|
+
*/
|
|
298
473
|
static get(targetName, propKey, operation) {
|
|
299
474
|
return Operations.registry.get(targetName, propKey, operation);
|
|
300
475
|
}
|
|
476
|
+
/**
|
|
477
|
+
* @description Gets or initializes the operations registry
|
|
478
|
+
* @summary Returns the existing registry or creates a new one if it doesn't exist
|
|
479
|
+
* @return {OperationsRegistry} The operations registry instance
|
|
480
|
+
* @private
|
|
481
|
+
*/
|
|
301
482
|
static getOpRegistry() {
|
|
302
483
|
if (!Operations.registry)
|
|
303
484
|
Operations.registry = new OperationsRegistry();
|
|
304
485
|
return Operations.registry;
|
|
305
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* @description Registers an operation handler for a specific target and operation
|
|
489
|
+
* @summary Adds a handler to the operations registry for a given target, property, and operation
|
|
490
|
+
* @template V - Model type extending Model
|
|
491
|
+
* @param {OperationHandler<V, any, any>} handler - The handler function to register
|
|
492
|
+
* @param {OperationKeys} operation - The operation key to register the handler for
|
|
493
|
+
* @param {V} target - The target model instance
|
|
494
|
+
* @param {string | symbol} propKey - The property key to register the handler for
|
|
495
|
+
* @return {void}
|
|
496
|
+
*/
|
|
306
497
|
static register(handler, operation, target, propKey) {
|
|
307
498
|
Operations.getOpRegistry().register(handler, operation, target, propKey);
|
|
308
499
|
}
|
|
309
500
|
}
|
|
310
501
|
|
|
502
|
+
/**
|
|
503
|
+
* @description Internal function to register operation handlers
|
|
504
|
+
* @summary Registers an operation handler for a specific operation key on a target property
|
|
505
|
+
* @param {OperationKeys} op - The operation key to handle
|
|
506
|
+
* @param {OperationHandler<any, any, any, any, any>} handler - The handler function to register
|
|
507
|
+
* @return {PropertyDecorator} A decorator that registers the handler
|
|
508
|
+
* @function handle
|
|
509
|
+
* @category Property Decorators
|
|
510
|
+
*/
|
|
311
511
|
function handle(op, handler) {
|
|
312
512
|
return (target, propertyKey) => {
|
|
313
513
|
Operations.register(handler, op, target, propertyKey);
|
|
314
514
|
};
|
|
315
515
|
}
|
|
316
516
|
/**
|
|
317
|
-
* @
|
|
318
|
-
*
|
|
319
|
-
* @
|
|
320
|
-
* @param
|
|
321
|
-
* @param {
|
|
322
|
-
*
|
|
323
|
-
* @see on
|
|
324
|
-
*
|
|
517
|
+
* @description Decorator for handling create and update operations
|
|
518
|
+
* @summary Defines a behavior to execute during both create and update operations
|
|
519
|
+
* @template V - Type for metadata, defaults to object
|
|
520
|
+
* @param {StandardOperationHandler<any, any, V, any, any> | UpdateOperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
521
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
522
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
325
523
|
* @function onCreateUpdate
|
|
326
|
-
*
|
|
327
|
-
* @category Decorators
|
|
524
|
+
* @category Property Decorators
|
|
328
525
|
*/
|
|
329
526
|
function onCreateUpdate(handler, data) {
|
|
330
527
|
return on(DBOperations.CREATE_UPDATE, handler, data);
|
|
331
528
|
}
|
|
332
529
|
/**
|
|
333
|
-
* @
|
|
334
|
-
*
|
|
335
|
-
* @
|
|
336
|
-
* @param
|
|
337
|
-
* @param {
|
|
338
|
-
*
|
|
339
|
-
* @see on
|
|
340
|
-
*
|
|
530
|
+
* @description Decorator for handling update operations
|
|
531
|
+
* @summary Defines a behavior to execute during update operations
|
|
532
|
+
* @template V - Type for metadata, defaults to object
|
|
533
|
+
* @param {UpdateOperationHandler<any, any, V, any>} handler - The method called upon the operation
|
|
534
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
535
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
341
536
|
* @function onUpdate
|
|
342
|
-
*
|
|
343
|
-
* @category Decorators
|
|
537
|
+
* @category Property Decorators
|
|
344
538
|
*/
|
|
345
539
|
function onUpdate(handler, data) {
|
|
346
540
|
return on(DBOperations.UPDATE, handler, data);
|
|
347
541
|
}
|
|
348
542
|
/**
|
|
349
|
-
* @
|
|
350
|
-
*
|
|
351
|
-
* @
|
|
352
|
-
* @param
|
|
353
|
-
*
|
|
354
|
-
* @
|
|
355
|
-
*
|
|
543
|
+
* @description Decorator for handling create operations
|
|
544
|
+
* @summary Defines a behavior to execute during create operations
|
|
545
|
+
* @template V - Type for metadata, defaults to object
|
|
546
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
547
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
548
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
356
549
|
* @function onCreate
|
|
357
|
-
*
|
|
358
|
-
* @category Decorators
|
|
550
|
+
* @category Property Decorators
|
|
359
551
|
*/
|
|
360
552
|
function onCreate(handler, data) {
|
|
361
553
|
return on(DBOperations.CREATE, handler, data);
|
|
362
554
|
}
|
|
363
555
|
/**
|
|
364
|
-
* @
|
|
365
|
-
*
|
|
366
|
-
* @
|
|
367
|
-
* @param
|
|
368
|
-
*
|
|
369
|
-
* @
|
|
370
|
-
*
|
|
556
|
+
* @description Decorator for handling read operations
|
|
557
|
+
* @summary Defines a behavior to execute during read operations
|
|
558
|
+
* @template V - Type for metadata, defaults to object
|
|
559
|
+
* @param {IdOperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
560
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
561
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
371
562
|
* @function onRead
|
|
372
|
-
*
|
|
373
|
-
* @category Decorators
|
|
563
|
+
* @category Property Decorators
|
|
374
564
|
*/
|
|
375
565
|
function onRead(handler, data) {
|
|
376
566
|
return on(DBOperations.READ, handler, data);
|
|
377
567
|
}
|
|
378
568
|
/**
|
|
379
|
-
* @
|
|
380
|
-
*
|
|
381
|
-
* @
|
|
382
|
-
* @param
|
|
383
|
-
*
|
|
384
|
-
* @
|
|
385
|
-
*
|
|
569
|
+
* @description Decorator for handling delete operations
|
|
570
|
+
* @summary Defines a behavior to execute during delete operations
|
|
571
|
+
* @template V - Type for metadata, defaults to object
|
|
572
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
573
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
574
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
386
575
|
* @function onDelete
|
|
387
|
-
*
|
|
388
|
-
* @category Decorators
|
|
576
|
+
* @category Property Decorators
|
|
389
577
|
*/
|
|
390
578
|
function onDelete(handler, data) {
|
|
391
579
|
return on(DBOperations.DELETE, handler, data);
|
|
392
580
|
}
|
|
393
581
|
/**
|
|
394
|
-
* @
|
|
395
|
-
*
|
|
396
|
-
* @
|
|
397
|
-
* @param
|
|
398
|
-
*
|
|
399
|
-
* @
|
|
400
|
-
*
|
|
582
|
+
* @description Decorator for handling all operation types
|
|
583
|
+
* @summary Defines a behavior to execute during any database operation
|
|
584
|
+
* @template V - Type for metadata, defaults to object
|
|
585
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
586
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
587
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
401
588
|
* @function onAny
|
|
402
|
-
*
|
|
403
|
-
* @category Decorators
|
|
589
|
+
* @category Property Decorators
|
|
404
590
|
*/
|
|
405
591
|
function onAny(handler, data) {
|
|
406
592
|
return on(DBOperations.ALL, handler, data);
|
|
407
593
|
}
|
|
408
594
|
/**
|
|
409
|
-
* @
|
|
410
|
-
*
|
|
411
|
-
* @
|
|
412
|
-
* @param {
|
|
413
|
-
* @param
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
595
|
+
* @description Base decorator for handling database operations
|
|
596
|
+
* @summary Defines a behavior to execute during specified database operations
|
|
597
|
+
* @template V - Type for metadata, defaults to object
|
|
598
|
+
* @param {OperationKeys[] | DBOperations} [op=DBOperations.ALL] - One or more operation types to handle
|
|
599
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
600
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
601
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
417
602
|
* @function on
|
|
418
|
-
*
|
|
419
|
-
* @
|
|
603
|
+
* @category Property Decorators
|
|
604
|
+
* @example
|
|
605
|
+
* // Example usage:
|
|
606
|
+
* class MyModel {
|
|
607
|
+
* @on(DBOperations.CREATE, myHandler)
|
|
608
|
+
* myProperty: string;
|
|
609
|
+
* }
|
|
420
610
|
*/
|
|
421
611
|
function on(op = DBOperations.ALL, handler, data) {
|
|
422
612
|
return operation(OperationKeys.ON, op, handler, data);
|
|
423
613
|
}
|
|
424
614
|
/**
|
|
425
|
-
* @
|
|
426
|
-
*
|
|
427
|
-
* @
|
|
428
|
-
* @param
|
|
429
|
-
*
|
|
430
|
-
* @
|
|
431
|
-
*
|
|
615
|
+
* @description Decorator for handling post-create and post-update operations
|
|
616
|
+
* @summary Defines a behavior to execute after both create and update operations
|
|
617
|
+
* @template V - Type for metadata, defaults to object
|
|
618
|
+
* @param {StandardOperationHandler<any, any, V, any, any> | UpdateOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
619
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
620
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
432
621
|
* @function afterCreateUpdate
|
|
433
|
-
*
|
|
434
|
-
* @category Decorators
|
|
622
|
+
* @category Property Decorators
|
|
435
623
|
*/
|
|
436
624
|
function afterCreateUpdate(handler, data) {
|
|
437
625
|
return after(DBOperations.CREATE_UPDATE, handler, data);
|
|
438
626
|
}
|
|
439
627
|
/**
|
|
440
|
-
* @
|
|
441
|
-
*
|
|
442
|
-
* @
|
|
443
|
-
* @param
|
|
444
|
-
*
|
|
445
|
-
* @
|
|
446
|
-
*
|
|
628
|
+
* @description Decorator for handling post-update operations
|
|
629
|
+
* @summary Defines a behavior to execute after update operations
|
|
630
|
+
* @template V - Type for metadata, defaults to object
|
|
631
|
+
* @param {UpdateOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
632
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
633
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
447
634
|
* @function afterUpdate
|
|
448
|
-
*
|
|
449
|
-
* @category Decorators
|
|
635
|
+
* @category Property Decorators
|
|
450
636
|
*/
|
|
451
637
|
function afterUpdate(handler, data) {
|
|
452
638
|
return after(DBOperations.UPDATE, handler, data);
|
|
453
639
|
}
|
|
454
640
|
/**
|
|
455
|
-
* @
|
|
456
|
-
*
|
|
457
|
-
* @
|
|
458
|
-
* @param
|
|
459
|
-
*
|
|
460
|
-
* @
|
|
461
|
-
*
|
|
641
|
+
* @description Decorator for handling post-create operations
|
|
642
|
+
* @summary Defines a behavior to execute after create operations
|
|
643
|
+
* @template V - Type for metadata, defaults to object
|
|
644
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
645
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
646
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
462
647
|
* @function afterCreate
|
|
463
|
-
*
|
|
464
|
-
* @category Decorators
|
|
648
|
+
* @category Property Decorators
|
|
465
649
|
*/
|
|
466
650
|
function afterCreate(handler, data) {
|
|
467
651
|
return after(DBOperations.CREATE, handler, data);
|
|
468
652
|
}
|
|
469
653
|
/**
|
|
470
|
-
* @
|
|
471
|
-
*
|
|
472
|
-
* @
|
|
473
|
-
* @param
|
|
474
|
-
* @param {
|
|
475
|
-
*
|
|
476
|
-
* @see after
|
|
477
|
-
*
|
|
654
|
+
* @description Decorator for handling post-read operations
|
|
655
|
+
* @summary Defines a behavior to execute after read operations
|
|
656
|
+
* @template V - Type for metadata, defaults to object
|
|
657
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
658
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
659
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
478
660
|
* @function afterRead
|
|
479
|
-
*
|
|
480
|
-
* @category Decorators
|
|
661
|
+
* @category Property Decorators
|
|
481
662
|
*/
|
|
482
663
|
function afterRead(handler, data) {
|
|
483
664
|
return after(DBOperations.READ, handler, data);
|
|
484
665
|
}
|
|
485
666
|
/**
|
|
486
|
-
* @
|
|
487
|
-
*
|
|
488
|
-
* @
|
|
489
|
-
* @param
|
|
490
|
-
* @param {
|
|
491
|
-
*
|
|
492
|
-
* @see after
|
|
493
|
-
*
|
|
667
|
+
* @description Decorator for handling post-delete operations
|
|
668
|
+
* @summary Defines a behavior to execute after delete operations
|
|
669
|
+
* @template V - Type for metadata, defaults to object
|
|
670
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
671
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
672
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
494
673
|
* @function afterDelete
|
|
495
|
-
*
|
|
496
|
-
* @category Decorators
|
|
674
|
+
* @category Property Decorators
|
|
497
675
|
*/
|
|
498
676
|
function afterDelete(handler, data) {
|
|
499
677
|
return after(DBOperations.DELETE, handler, data);
|
|
500
678
|
}
|
|
501
679
|
/**
|
|
502
|
-
* @
|
|
503
|
-
*
|
|
504
|
-
* @
|
|
505
|
-
* @param
|
|
506
|
-
* @param {
|
|
507
|
-
*
|
|
508
|
-
* @see after
|
|
509
|
-
*
|
|
680
|
+
* @description Decorator for handling post-operation for all operation types
|
|
681
|
+
* @summary Defines a behavior to execute after any database operation
|
|
682
|
+
* @template V - Type for metadata, defaults to object
|
|
683
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
684
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
685
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
510
686
|
* @function afterAny
|
|
511
|
-
*
|
|
512
|
-
* @category Decorators
|
|
687
|
+
* @category Property Decorators
|
|
513
688
|
*/
|
|
514
689
|
function afterAny(handler, data) {
|
|
515
690
|
return after(DBOperations.ALL, handler, data);
|
|
516
691
|
}
|
|
517
692
|
/**
|
|
518
|
-
* @
|
|
519
|
-
*
|
|
520
|
-
* @
|
|
521
|
-
* @param {
|
|
522
|
-
*
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
* @param data
|
|
526
|
-
* @param args
|
|
693
|
+
* @description Base decorator for handling post-operation behaviors
|
|
694
|
+
* @summary Defines a behavior to execute after specified database operations
|
|
695
|
+
* @template V - Type for metadata, defaults to object
|
|
696
|
+
* @param {OperationKeys[] | DBOperations} [op=DBOperations.ALL] - One or more operation types to handle
|
|
697
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
698
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
699
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
527
700
|
* @function after
|
|
528
|
-
*
|
|
529
|
-
* @
|
|
701
|
+
* @category Property Decorators
|
|
702
|
+
* @example
|
|
703
|
+
* // Example usage:
|
|
704
|
+
* class MyModel {
|
|
705
|
+
* @after(DBOperations.CREATE, myHandler)
|
|
706
|
+
* myProperty: string;
|
|
707
|
+
* }
|
|
530
708
|
*/
|
|
531
709
|
function after(op = DBOperations.ALL, handler, data) {
|
|
532
710
|
return operation(OperationKeys.AFTER, op, handler, data);
|
|
533
711
|
}
|
|
712
|
+
/**
|
|
713
|
+
* @description Core decorator factory for operation handlers
|
|
714
|
+
* @summary Creates decorators that register handlers for database operations
|
|
715
|
+
* @template V - Type for metadata, defaults to object
|
|
716
|
+
* @param {OperationKeys.ON | OperationKeys.AFTER} baseOp - Whether the handler runs during or after the operation
|
|
717
|
+
* @param {OperationKeys[]} [operation=DBOperations.ALL] - The specific operations to handle
|
|
718
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The handler function to execute
|
|
719
|
+
* @param {V} [dataToAdd] - Optional metadata to pass to the handler
|
|
720
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
721
|
+
* @function operation
|
|
722
|
+
* @category Property Decorators
|
|
723
|
+
* @mermaid
|
|
724
|
+
* sequenceDiagram
|
|
725
|
+
* participant Client
|
|
726
|
+
* participant Decorator as @operation
|
|
727
|
+
* participant Operations as Operations Registry
|
|
728
|
+
* participant Handler
|
|
729
|
+
*
|
|
730
|
+
* Client->>Decorator: Apply to property
|
|
731
|
+
* Decorator->>Operations: Register handler
|
|
732
|
+
* Decorator->>Decorator: Store metadata
|
|
733
|
+
*
|
|
734
|
+
* Note over Client,Handler: Later, during operation execution
|
|
735
|
+
* Client->>Operations: Execute operation
|
|
736
|
+
* Operations->>Handler: Call registered handler
|
|
737
|
+
* Handler-->>Operations: Return result
|
|
738
|
+
* Operations-->>Client: Return final result
|
|
739
|
+
*/
|
|
534
740
|
function operation(baseOp, operation = DBOperations.ALL, handler, dataToAdd) {
|
|
535
741
|
return (target, propertyKey) => {
|
|
536
742
|
const name = target.constructor.name;
|
|
@@ -561,12 +767,16 @@ function operation(baseOp, operation = DBOperations.ALL, handler, dataToAdd) {
|
|
|
561
767
|
}
|
|
562
768
|
|
|
563
769
|
/**
|
|
564
|
-
* @
|
|
565
|
-
*
|
|
566
|
-
* @param {string}
|
|
567
|
-
*
|
|
568
|
-
* @
|
|
569
|
-
* @
|
|
770
|
+
* @description Base error class for the repository module
|
|
771
|
+
* @summary Abstract base error class that all other error types extend from. Provides common error handling functionality.
|
|
772
|
+
* @param {string} name - The name of the error
|
|
773
|
+
* @param {string|Error} msg - The error message or Error object
|
|
774
|
+
* @param {number} code - The HTTP status code associated with this error
|
|
775
|
+
* @class BaseError
|
|
776
|
+
* @example
|
|
777
|
+
* // This is an abstract class and should not be instantiated directly
|
|
778
|
+
* // Instead, use one of the concrete error classes:
|
|
779
|
+
* throw new ValidationError('Invalid data provided');
|
|
570
780
|
*/
|
|
571
781
|
class BaseError extends Error {
|
|
572
782
|
constructor(name, msg, code = 500) {
|
|
@@ -580,12 +790,16 @@ class BaseError extends Error {
|
|
|
580
790
|
}
|
|
581
791
|
}
|
|
582
792
|
/**
|
|
583
|
-
* @
|
|
584
|
-
*
|
|
585
|
-
* @param {string} msg
|
|
586
|
-
*
|
|
793
|
+
* @description Error thrown when validation fails
|
|
794
|
+
* @summary Represents a failure in the Model details, typically thrown when data validation fails
|
|
795
|
+
* @param {string|Error} msg - The error message or Error object
|
|
796
|
+
* @return {ValidationError} A new ValidationError instance
|
|
587
797
|
* @class ValidationError
|
|
588
|
-
* @
|
|
798
|
+
* @example
|
|
799
|
+
* // Throw a validation error when data is invalid
|
|
800
|
+
* if (!isValid(data)) {
|
|
801
|
+
* throw new ValidationError('Invalid data format');
|
|
802
|
+
* }
|
|
589
803
|
*/
|
|
590
804
|
class ValidationError extends BaseError {
|
|
591
805
|
constructor(msg) {
|
|
@@ -593,12 +807,18 @@ class ValidationError extends BaseError {
|
|
|
593
807
|
}
|
|
594
808
|
}
|
|
595
809
|
/**
|
|
596
|
-
* @
|
|
597
|
-
*
|
|
598
|
-
* @param {string} msg
|
|
599
|
-
*
|
|
810
|
+
* @description Error thrown for internal system failures
|
|
811
|
+
* @summary Represents an internal failure (should mean an error in code) with HTTP 500 status code
|
|
812
|
+
* @param {string|Error} msg - The error message or Error object
|
|
813
|
+
* @return {InternalError} A new InternalError instance
|
|
600
814
|
* @class InternalError
|
|
601
|
-
* @
|
|
815
|
+
* @example
|
|
816
|
+
* // Throw an internal error when an unexpected condition occurs
|
|
817
|
+
* try {
|
|
818
|
+
* // Some operation
|
|
819
|
+
* } catch (error) {
|
|
820
|
+
* throw new InternalError('Unexpected internal error occurred');
|
|
821
|
+
* }
|
|
602
822
|
*/
|
|
603
823
|
class InternalError extends BaseError {
|
|
604
824
|
constructor(msg) {
|
|
@@ -606,13 +826,18 @@ class InternalError extends BaseError {
|
|
|
606
826
|
}
|
|
607
827
|
}
|
|
608
828
|
/**
|
|
609
|
-
* @
|
|
610
|
-
*
|
|
611
|
-
* @param {string} msg
|
|
612
|
-
*
|
|
829
|
+
* @description Error thrown when serialization or deserialization fails
|
|
830
|
+
* @summary Represents a failure in the Model de/serialization, typically when converting between data formats
|
|
831
|
+
* @param {string|Error} msg - The error message or Error object
|
|
832
|
+
* @return {SerializationError} A new SerializationError instance
|
|
613
833
|
* @class SerializationError
|
|
614
|
-
* @
|
|
615
|
-
*
|
|
834
|
+
* @example
|
|
835
|
+
* // Throw a serialization error when JSON parsing fails
|
|
836
|
+
* try {
|
|
837
|
+
* const data = JSON.parse(invalidJson);
|
|
838
|
+
* } catch (error) {
|
|
839
|
+
* throw new SerializationError('Failed to parse JSON data');
|
|
840
|
+
* }
|
|
616
841
|
*/
|
|
617
842
|
class SerializationError extends BaseError {
|
|
618
843
|
constructor(msg) {
|
|
@@ -620,13 +845,17 @@ class SerializationError extends BaseError {
|
|
|
620
845
|
}
|
|
621
846
|
}
|
|
622
847
|
/**
|
|
623
|
-
* @
|
|
624
|
-
*
|
|
625
|
-
* @param {string} msg
|
|
626
|
-
*
|
|
848
|
+
* @description Error thrown when a requested resource is not found
|
|
849
|
+
* @summary Represents a failure in finding a model, resulting in a 404 HTTP status code
|
|
850
|
+
* @param {string|Error} msg - The error message or Error object
|
|
851
|
+
* @return {NotFoundError} A new NotFoundError instance
|
|
627
852
|
* @class NotFoundError
|
|
628
|
-
* @
|
|
629
|
-
*
|
|
853
|
+
* @example
|
|
854
|
+
* // Throw a not found error when a record doesn't exist
|
|
855
|
+
* const user = await repository.findById(id);
|
|
856
|
+
* if (!user) {
|
|
857
|
+
* throw new NotFoundError(`User with ID ${id} not found`);
|
|
858
|
+
* }
|
|
630
859
|
*/
|
|
631
860
|
class NotFoundError extends BaseError {
|
|
632
861
|
constructor(msg) {
|
|
@@ -634,13 +863,17 @@ class NotFoundError extends BaseError {
|
|
|
634
863
|
}
|
|
635
864
|
}
|
|
636
865
|
/**
|
|
637
|
-
* @
|
|
638
|
-
*
|
|
639
|
-
* @param {string} msg
|
|
640
|
-
*
|
|
866
|
+
* @description Error thrown when a conflict occurs in the storage
|
|
867
|
+
* @summary Represents a conflict in the storage, typically when trying to create a duplicate resource
|
|
868
|
+
* @param {string|Error} msg - The error message or Error object
|
|
869
|
+
* @return {ConflictError} A new ConflictError instance
|
|
641
870
|
* @class ConflictError
|
|
642
|
-
* @
|
|
643
|
-
*
|
|
871
|
+
* @example
|
|
872
|
+
* // Throw a conflict error when trying to create a duplicate record
|
|
873
|
+
* const existingUser = await repository.findByEmail(email);
|
|
874
|
+
* if (existingUser) {
|
|
875
|
+
* throw new ConflictError(`User with email ${email} already exists`);
|
|
876
|
+
* }
|
|
644
877
|
*/
|
|
645
878
|
class ConflictError extends BaseError {
|
|
646
879
|
constructor(msg) {
|
|
@@ -818,6 +1051,13 @@ const getAllPropertyDecoratorsRecursive = function (model, accum, ...prefixes) {
|
|
|
818
1051
|
return getAllPropertyDecoratorsRecursive(proto, accumulator, ...prefixes);
|
|
819
1052
|
};
|
|
820
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* @description Default configuration flags for repository operations.
|
|
1056
|
+
* @summary Provides default values for repository operation flags, excluding the timestamp property.
|
|
1057
|
+
* These flags control behavior such as context handling, validation, error handling, and more.
|
|
1058
|
+
* @const DefaultRepositoryFlags
|
|
1059
|
+
* @memberOf module:db-decorators
|
|
1060
|
+
*/
|
|
821
1061
|
const DefaultRepositoryFlags = {
|
|
822
1062
|
parentContext: undefined,
|
|
823
1063
|
childContexts: [],
|
|
@@ -830,16 +1070,95 @@ const DefaultRepositoryFlags = {
|
|
|
830
1070
|
rebuildWithTransient: true,
|
|
831
1071
|
};
|
|
832
1072
|
|
|
1073
|
+
/**
|
|
1074
|
+
* @description Default factory for creating context instances.
|
|
1075
|
+
* @summary A factory function that creates new Context instances with the provided repository flags.
|
|
1076
|
+
* It automatically adds a timestamp to the context and returns a properly typed context instance.
|
|
1077
|
+
* @const DefaultContextFactory
|
|
1078
|
+
* @memberOf module:db-decorators
|
|
1079
|
+
*/
|
|
833
1080
|
const DefaultContextFactory = (arg) => {
|
|
834
1081
|
return new Context().accumulate(Object.assign({}, arg, { timestamp: new Date() }));
|
|
835
1082
|
};
|
|
1083
|
+
/**
|
|
1084
|
+
* @description A context management class for handling repository operations.
|
|
1085
|
+
* @summary The Context class provides a mechanism for managing repository operations with flags,
|
|
1086
|
+
* parent-child relationships, and state accumulation. It allows for hierarchical context chains
|
|
1087
|
+
* and maintains operation-specific configurations while supporting type safety through generics.
|
|
1088
|
+
*
|
|
1089
|
+
* @template F - Type extending RepositoryFlags that defines the context configuration
|
|
1090
|
+
*
|
|
1091
|
+
* @param {ObjectAccumulator<F>} cache - The internal cache storing accumulated values
|
|
1092
|
+
*
|
|
1093
|
+
* @class
|
|
1094
|
+
*
|
|
1095
|
+
* @example
|
|
1096
|
+
* ```typescript
|
|
1097
|
+
* // Creating a new context with repository flags
|
|
1098
|
+
* const context = new Context<RepositoryFlags>();
|
|
1099
|
+
*
|
|
1100
|
+
* // Accumulating values
|
|
1101
|
+
* const enrichedContext = context.accumulate({
|
|
1102
|
+
* writeOperation: true,
|
|
1103
|
+
* affectedTables: ['users'],
|
|
1104
|
+
* operation: OperationKeys.CREATE
|
|
1105
|
+
* });
|
|
1106
|
+
*
|
|
1107
|
+
* // Accessing values
|
|
1108
|
+
* const isWrite = enrichedContext.get('writeOperation'); // true
|
|
1109
|
+
* const tables = enrichedContext.get('affectedTables'); // ['users']
|
|
1110
|
+
* ```
|
|
1111
|
+
*
|
|
1112
|
+
* @mermaid
|
|
1113
|
+
* sequenceDiagram
|
|
1114
|
+
* participant C as Client
|
|
1115
|
+
* participant Ctx as Context
|
|
1116
|
+
* participant Cache as ObjectAccumulator
|
|
1117
|
+
*
|
|
1118
|
+
* C->>Ctx: new Context()
|
|
1119
|
+
* Ctx->>Cache: create cache
|
|
1120
|
+
*
|
|
1121
|
+
* C->>Ctx: accumulate(value)
|
|
1122
|
+
* Ctx->>Cache: accumulate(value)
|
|
1123
|
+
* Cache-->>Ctx: updated cache
|
|
1124
|
+
* Ctx-->>C: updated context
|
|
1125
|
+
*
|
|
1126
|
+
* C->>Ctx: get(key)
|
|
1127
|
+
* Ctx->>Cache: get(key)
|
|
1128
|
+
* alt Key exists in cache
|
|
1129
|
+
* Cache-->>Ctx: value
|
|
1130
|
+
* else Key not found
|
|
1131
|
+
* Ctx->>Ctx: check parent context
|
|
1132
|
+
* alt Parent exists
|
|
1133
|
+
* Ctx->>Parent: get(key)
|
|
1134
|
+
* Parent-->>Ctx: value
|
|
1135
|
+
* else No parent
|
|
1136
|
+
* Ctx-->>C: throw error
|
|
1137
|
+
* end
|
|
1138
|
+
* end
|
|
1139
|
+
* Ctx-->>C: requested value
|
|
1140
|
+
*/
|
|
836
1141
|
class Context {
|
|
837
|
-
|
|
838
|
-
constructor(obj) {
|
|
1142
|
+
constructor() {
|
|
839
1143
|
this.cache = new ObjectAccumulator();
|
|
840
|
-
|
|
841
|
-
|
|
1144
|
+
Object.defineProperty(this, "cache", {
|
|
1145
|
+
value: new ObjectAccumulator(),
|
|
1146
|
+
writable: false,
|
|
1147
|
+
enumerable: false,
|
|
1148
|
+
configurable: true,
|
|
1149
|
+
});
|
|
842
1150
|
}
|
|
1151
|
+
static { this.factory = DefaultContextFactory; }
|
|
1152
|
+
/**
|
|
1153
|
+
* @description Accumulates new values into the context.
|
|
1154
|
+
* @summary Merges the provided value object with the existing context state,
|
|
1155
|
+
* creating a new immutable cache state.
|
|
1156
|
+
*
|
|
1157
|
+
* @template F - current accumulator type
|
|
1158
|
+
* @template V - Type extending object for the values to accumulate
|
|
1159
|
+
* @param {V} value - The object containing values to accumulate
|
|
1160
|
+
* @returns A new context instance with accumulated values
|
|
1161
|
+
*/
|
|
843
1162
|
accumulate(value) {
|
|
844
1163
|
Object.defineProperty(this, "cache", {
|
|
845
1164
|
value: this.cache.accumulate(value),
|
|
@@ -852,6 +1171,17 @@ class Context {
|
|
|
852
1171
|
get timestamp() {
|
|
853
1172
|
return this.cache.timestamp;
|
|
854
1173
|
}
|
|
1174
|
+
/**
|
|
1175
|
+
* @description Retrieves a value from the context by key.
|
|
1176
|
+
* @summary Attempts to get a value from the current context's cache.
|
|
1177
|
+
* If not found, traverses up the parent context chain.
|
|
1178
|
+
*
|
|
1179
|
+
* @template K - Type extending keyof F for the key to retrieve
|
|
1180
|
+
* @template F - Accumulator type
|
|
1181
|
+
* @param {K} key - The key to retrieve from the context
|
|
1182
|
+
* @returns The value associated with the key
|
|
1183
|
+
* @throws {Error} If the key is not found in the context chain
|
|
1184
|
+
*/
|
|
855
1185
|
get(key) {
|
|
856
1186
|
try {
|
|
857
1187
|
return this.cache.get(key);
|
|
@@ -862,15 +1192,46 @@ class Context {
|
|
|
862
1192
|
throw e;
|
|
863
1193
|
}
|
|
864
1194
|
}
|
|
1195
|
+
/**
|
|
1196
|
+
* @description Creates a child context
|
|
1197
|
+
* @summary Generates a new context instance with current context as parent
|
|
1198
|
+
*
|
|
1199
|
+
* @template M - Type extending Model
|
|
1200
|
+
* @param {OperationKeys} operation - The operation type
|
|
1201
|
+
* @param {Constructor<M>} [model] - Optional model constructor
|
|
1202
|
+
* @returns {C} New child context instance
|
|
1203
|
+
*/
|
|
865
1204
|
child(operation, model) {
|
|
866
1205
|
return Context.childFrom(this, {
|
|
867
1206
|
operation: operation,
|
|
868
1207
|
affectedTables: model ? [model] : [],
|
|
869
1208
|
});
|
|
870
1209
|
}
|
|
1210
|
+
/**
|
|
1211
|
+
* @description Creates a child context from another context
|
|
1212
|
+
* @summary Generates a new context instance with parent reference
|
|
1213
|
+
*
|
|
1214
|
+
* @template F - Type extending Repository Flags
|
|
1215
|
+
* @template C - Type extending Context<F>
|
|
1216
|
+
* @param {C} context - The parent context
|
|
1217
|
+
* @param {Partial<F>} [overrides] - Optional flag overrides
|
|
1218
|
+
* @returns {C} New child context instance
|
|
1219
|
+
*/
|
|
871
1220
|
static childFrom(context, overrides) {
|
|
872
1221
|
return Context.factory(Object.assign({}, context.cache, overrides || {}));
|
|
873
1222
|
}
|
|
1223
|
+
/**
|
|
1224
|
+
* @description Creates a new context from operation parameters
|
|
1225
|
+
* @summary Generates a context instance for specific operation
|
|
1226
|
+
*
|
|
1227
|
+
* @template F - Type extending Repository Flags
|
|
1228
|
+
* @template M - Type extending Model
|
|
1229
|
+
* @param {OperationKeys.DELETE} operation - The operation type
|
|
1230
|
+
* @param {Partial<F>} overrides - Flag overrides
|
|
1231
|
+
* @param {Constructor<M>} model - The model constructor
|
|
1232
|
+
* @param {any} args - Operation arguments
|
|
1233
|
+
* @returns {Promise<C>} Promise resolving to new context
|
|
1234
|
+
*/
|
|
874
1235
|
static async from(operation, overrides, model,
|
|
875
1236
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
876
1237
|
...args) {
|
|
@@ -879,6 +1240,33 @@ class Context {
|
|
|
879
1240
|
model: model,
|
|
880
1241
|
}));
|
|
881
1242
|
}
|
|
1243
|
+
/**
|
|
1244
|
+
* @description Prepares arguments for context operations
|
|
1245
|
+
* @summary Creates a context args object with the specified operation parameters
|
|
1246
|
+
*
|
|
1247
|
+
* @template F - Type extending {@link RepositoryFlags}
|
|
1248
|
+
* @template M - Type extending {@link Model}
|
|
1249
|
+
* @param {OperationKeys.DELETE} operation - The operation type
|
|
1250
|
+
* @param {Constructor<M>} model - The model constructor
|
|
1251
|
+
* @param {any[]} args - Operation arguments
|
|
1252
|
+
* @param {Contextual<F>} [contextual] - Optional contextual object
|
|
1253
|
+
* @param {Partial<F>} [overrides] - Optional flag overrides
|
|
1254
|
+
* @returns {Promise<ContextArgs>} Promise resolving to context arguments
|
|
1255
|
+
*
|
|
1256
|
+
* @mermaid
|
|
1257
|
+
* sequenceDiagram
|
|
1258
|
+
* participant C as Context
|
|
1259
|
+
* participant M as Model
|
|
1260
|
+
* participant A as Args
|
|
1261
|
+
*
|
|
1262
|
+
* C->>C: Receive operation request
|
|
1263
|
+
* C->>M: Validate model constructor
|
|
1264
|
+
* C->>C: Create child context
|
|
1265
|
+
* C->>A: Process operation args
|
|
1266
|
+
* A->>C: Return context args
|
|
1267
|
+
* C->>C: Apply overrides
|
|
1268
|
+
* C->>C: Return final context
|
|
1269
|
+
*/
|
|
882
1270
|
static async args(operation, model, args, contextual, overrides) {
|
|
883
1271
|
const last = args.pop();
|
|
884
1272
|
async function getContext() {
|
|
@@ -914,7 +1302,7 @@ class Context {
|
|
|
914
1302
|
*
|
|
915
1303
|
* @function prefixMethod
|
|
916
1304
|
*
|
|
917
|
-
* @memberOf module:db-decorators
|
|
1305
|
+
* @memberOf module:db-decorators
|
|
918
1306
|
*/
|
|
919
1307
|
function prefixMethod(obj, after, prefix, afterName) {
|
|
920
1308
|
async function wrapper(...args) {
|
|
@@ -968,7 +1356,7 @@ function suffixMethod(obj, before, suffix, beforeName) {
|
|
|
968
1356
|
*
|
|
969
1357
|
* @function wrapMethodWithContext
|
|
970
1358
|
*
|
|
971
|
-
* @memberOf module:db-decorators
|
|
1359
|
+
* @memberOf module:db-decorators
|
|
972
1360
|
*/
|
|
973
1361
|
function wrapMethodWithContext(obj, before, method, after, methodName) {
|
|
974
1362
|
const name = methodName ? methodName : method.name;
|
|
@@ -992,17 +1380,24 @@ function wrapMethodWithContext(obj, before, method, after, methodName) {
|
|
|
992
1380
|
}
|
|
993
1381
|
|
|
994
1382
|
/**
|
|
995
|
-
* @
|
|
996
|
-
* @
|
|
997
|
-
*
|
|
998
|
-
* @
|
|
999
|
-
*
|
|
1000
|
-
* @throws {InternalError} if no property or more than one properties are {@link id} decorated
|
|
1001
|
-
* or no value is set in that property
|
|
1002
|
-
*
|
|
1383
|
+
* @description Finds the primary key attribute for a model
|
|
1384
|
+
* @summary Searches in all the properties in the object for an {@link id} decorated property and returns the property key and metadata
|
|
1385
|
+
* @param {Model} model - The model object to search for primary key
|
|
1386
|
+
* @return {Object} An object containing the id property name and its metadata
|
|
1003
1387
|
* @function findPrimaryKey
|
|
1004
|
-
*
|
|
1005
|
-
*
|
|
1388
|
+
* @mermaid
|
|
1389
|
+
* sequenceDiagram
|
|
1390
|
+
* participant Caller
|
|
1391
|
+
* participant findPrimaryKey
|
|
1392
|
+
* participant getAllPropertyDecoratorsRecursive
|
|
1393
|
+
*
|
|
1394
|
+
* Caller->>findPrimaryKey: model
|
|
1395
|
+
* findPrimaryKey->>getAllPropertyDecoratorsRecursive: get decorators
|
|
1396
|
+
* getAllPropertyDecoratorsRecursive-->>findPrimaryKey: decorators
|
|
1397
|
+
* findPrimaryKey->>findPrimaryKey: filter ID decorators
|
|
1398
|
+
* findPrimaryKey->>findPrimaryKey: validate single ID property
|
|
1399
|
+
* findPrimaryKey-->>Caller: {id, props}
|
|
1400
|
+
* @memberOf module:db-decorators
|
|
1006
1401
|
*/
|
|
1007
1402
|
function findPrimaryKey(model) {
|
|
1008
1403
|
const decorators = getAllPropertyDecoratorsRecursive(model, undefined, DBKeys.REFLECT + DBKeys.ID);
|
|
@@ -1027,19 +1422,25 @@ function findPrimaryKey(model) {
|
|
|
1027
1422
|
};
|
|
1028
1423
|
}
|
|
1029
1424
|
/**
|
|
1030
|
-
* @
|
|
1031
|
-
* @
|
|
1032
|
-
*
|
|
1033
|
-
* @param {
|
|
1034
|
-
* @
|
|
1035
|
-
* @
|
|
1036
|
-
*
|
|
1037
|
-
*
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1425
|
+
* @description Retrieves the primary key value from a model
|
|
1426
|
+
* @summary Searches for the ID-decorated property in the model and returns its value
|
|
1427
|
+
* @param {Model} model - The model object to extract the ID from
|
|
1428
|
+
* @param {boolean} [returnEmpty=false] - Whether to return undefined if no ID value is found
|
|
1429
|
+
* @return {string | number | bigint} The primary key value
|
|
1430
|
+
* @function findModelId
|
|
1431
|
+
* @mermaid
|
|
1432
|
+
* sequenceDiagram
|
|
1433
|
+
* participant Caller
|
|
1434
|
+
* participant findModelId
|
|
1435
|
+
* participant findPrimaryKey
|
|
1436
|
+
*
|
|
1437
|
+
* Caller->>findModelId: model, returnEmpty
|
|
1438
|
+
* findModelId->>findPrimaryKey: model
|
|
1439
|
+
* findPrimaryKey-->>findModelId: {id, props}
|
|
1440
|
+
* findModelId->>findModelId: extract model[id]
|
|
1441
|
+
* findModelId->>findModelId: validate ID exists if required
|
|
1442
|
+
* findModelId-->>Caller: ID value
|
|
1443
|
+
* @memberOf module:db-decorators
|
|
1043
1444
|
*/
|
|
1044
1445
|
function findModelId(model, returnEmpty = false) {
|
|
1045
1446
|
const idProp = findPrimaryKey(model).id;
|
|
@@ -1049,12 +1450,115 @@ function findModelId(model, returnEmpty = false) {
|
|
|
1049
1450
|
return modelId;
|
|
1050
1451
|
}
|
|
1051
1452
|
|
|
1453
|
+
/**
|
|
1454
|
+
* @description Base repository implementation providing CRUD operations for models.
|
|
1455
|
+
* @summary The BaseRepository class serves as a foundation for repository implementations, providing
|
|
1456
|
+
* abstract and concrete methods for creating, reading, updating, and deleting model instances.
|
|
1457
|
+
* It handles operation lifecycles including prefix and suffix operations, and enforces decorators.
|
|
1458
|
+
* @template M - The model type extending Model
|
|
1459
|
+
* @template F - The repository flags type, defaults to RepositoryFlags
|
|
1460
|
+
* @template C - The context type, defaults to Context<F>
|
|
1461
|
+
* @param {Constructor<M>} clazz - The constructor for the model class
|
|
1462
|
+
* @class BaseRepository
|
|
1463
|
+
* @example
|
|
1464
|
+
* class UserModel extends Model {
|
|
1465
|
+
* @id()
|
|
1466
|
+
* id: string;
|
|
1467
|
+
*
|
|
1468
|
+
* @required()
|
|
1469
|
+
* name: string;
|
|
1470
|
+
* }
|
|
1471
|
+
*
|
|
1472
|
+
* class UserRepository extends BaseRepository<UserModel> {
|
|
1473
|
+
* constructor() {
|
|
1474
|
+
* super(UserModel);
|
|
1475
|
+
* }
|
|
1476
|
+
*
|
|
1477
|
+
* async create(model: UserModel): Promise<UserModel> {
|
|
1478
|
+
* // Implementation
|
|
1479
|
+
* return model;
|
|
1480
|
+
* }
|
|
1481
|
+
*
|
|
1482
|
+
* async read(key: string): Promise<UserModel> {
|
|
1483
|
+
* // Implementation
|
|
1484
|
+
* return new UserModel({ id: key, name: 'User' });
|
|
1485
|
+
* }
|
|
1486
|
+
*
|
|
1487
|
+
* async update(model: UserModel): Promise<UserModel> {
|
|
1488
|
+
* // Implementation
|
|
1489
|
+
* return model;
|
|
1490
|
+
* }
|
|
1491
|
+
*
|
|
1492
|
+
* async delete(key: string): Promise<UserModel> {
|
|
1493
|
+
* // Implementation
|
|
1494
|
+
* const model = await this.read(key);
|
|
1495
|
+
* return model;
|
|
1496
|
+
* }
|
|
1497
|
+
* }
|
|
1498
|
+
*
|
|
1499
|
+
* @mermaid
|
|
1500
|
+
* sequenceDiagram
|
|
1501
|
+
* participant C as Client
|
|
1502
|
+
* participant R as Repository
|
|
1503
|
+
* participant P as Prefix Methods
|
|
1504
|
+
* participant D as Database
|
|
1505
|
+
* participant S as Suffix Methods
|
|
1506
|
+
* participant V as Validators/Decorators
|
|
1507
|
+
*
|
|
1508
|
+
* Note over C,V: Create Operation
|
|
1509
|
+
* C->>R: create(model)
|
|
1510
|
+
* R->>P: createPrefix(model)
|
|
1511
|
+
* P->>V: enforceDBDecorators(ON)
|
|
1512
|
+
* P->>D: Database operation
|
|
1513
|
+
* D->>S: createSuffix(model)
|
|
1514
|
+
* S->>V: enforceDBDecorators(AFTER)
|
|
1515
|
+
* S->>C: Return model
|
|
1516
|
+
*
|
|
1517
|
+
* Note over C,V: Read Operation
|
|
1518
|
+
* C->>R: read(key)
|
|
1519
|
+
* R->>P: readPrefix(key)
|
|
1520
|
+
* P->>V: enforceDBDecorators(ON)
|
|
1521
|
+
* P->>D: Database operation
|
|
1522
|
+
* D->>S: readSuffix(model)
|
|
1523
|
+
* S->>V: enforceDBDecorators(AFTER)
|
|
1524
|
+
* S->>C: Return model
|
|
1525
|
+
*
|
|
1526
|
+
* Note over C,V: Update Operation
|
|
1527
|
+
* C->>R: update(model)
|
|
1528
|
+
* R->>P: updatePrefix(model)
|
|
1529
|
+
* P->>V: enforceDBDecorators(ON)
|
|
1530
|
+
* P->>D: Database operation
|
|
1531
|
+
* D->>S: updateSuffix(model)
|
|
1532
|
+
* S->>V: enforceDBDecorators(AFTER)
|
|
1533
|
+
* S->>C: Return model
|
|
1534
|
+
*
|
|
1535
|
+
* Note over C,V: Delete Operation
|
|
1536
|
+
* C->>R: delete(key)
|
|
1537
|
+
* R->>P: deletePrefix(key)
|
|
1538
|
+
* P->>V: enforceDBDecorators(ON)
|
|
1539
|
+
* P->>D: Database operation
|
|
1540
|
+
* D->>S: deleteSuffix(model)
|
|
1541
|
+
* S->>V: enforceDBDecorators(AFTER)
|
|
1542
|
+
* S->>C: Return model
|
|
1543
|
+
*/
|
|
1052
1544
|
class BaseRepository {
|
|
1545
|
+
/**
|
|
1546
|
+
* @description Gets the model class constructor.
|
|
1547
|
+
* @summary Retrieves the constructor for the model class associated with this repository.
|
|
1548
|
+
* Throws an error if no class definition is found.
|
|
1549
|
+
* @return {Constructor<M>} The constructor for the model class
|
|
1550
|
+
*/
|
|
1053
1551
|
get class() {
|
|
1054
1552
|
if (!this._class)
|
|
1055
1553
|
throw new InternalError(`No class definition found for this repository`);
|
|
1056
1554
|
return this._class;
|
|
1057
1555
|
}
|
|
1556
|
+
/**
|
|
1557
|
+
* @description Gets the primary key property name of the model.
|
|
1558
|
+
* @summary Retrieves the name of the property that serves as the primary key for the model.
|
|
1559
|
+
* If not already determined, it finds the primary key using the model's decorators.
|
|
1560
|
+
* @return The name of the primary key property
|
|
1561
|
+
*/
|
|
1058
1562
|
get pk() {
|
|
1059
1563
|
if (!this._pk) {
|
|
1060
1564
|
const { id, props } = findPrimaryKey(new this.class());
|
|
@@ -1063,6 +1567,12 @@ class BaseRepository {
|
|
|
1063
1567
|
}
|
|
1064
1568
|
return this._pk;
|
|
1065
1569
|
}
|
|
1570
|
+
/**
|
|
1571
|
+
* @description Gets the primary key properties.
|
|
1572
|
+
* @summary Retrieves the properties associated with the primary key of the model.
|
|
1573
|
+
* If not already determined, it triggers the pk getter to find the primary key properties.
|
|
1574
|
+
* @return {any} The properties of the primary key
|
|
1575
|
+
*/
|
|
1066
1576
|
get pkProps() {
|
|
1067
1577
|
if (!this._pkProps) {
|
|
1068
1578
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -1080,19 +1590,53 @@ class BaseRepository {
|
|
|
1080
1590
|
wrapMethodWithContext(self, self[name + "Prefix"], m, self[name + "Suffix"]);
|
|
1081
1591
|
});
|
|
1082
1592
|
}
|
|
1593
|
+
/**
|
|
1594
|
+
* @description Creates multiple model instances in the repository.
|
|
1595
|
+
* @summary Persists multiple model instances to the underlying data store by calling
|
|
1596
|
+
* the create method for each model in the array.
|
|
1597
|
+
* @param {M[]} models - The array of model instances to create
|
|
1598
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1599
|
+
* @return {Promise<M[]>} A promise that resolves to an array of created model instances
|
|
1600
|
+
*/
|
|
1083
1601
|
async createAll(models, ...args) {
|
|
1084
1602
|
return Promise.all(models.map((m) => this.create(m, ...args)));
|
|
1085
1603
|
}
|
|
1604
|
+
/**
|
|
1605
|
+
* @description Prepares a model for creation and executes pre-creation operations.
|
|
1606
|
+
* @summary Processes a model before it is created in the data store. This includes
|
|
1607
|
+
* creating a context, instantiating a new model instance, and enforcing any decorators
|
|
1608
|
+
* that should be applied before creation.
|
|
1609
|
+
* @param {M} model - The model instance to prepare for creation
|
|
1610
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1611
|
+
* @return A promise that resolves to an array containing the prepared model and context arguments
|
|
1612
|
+
*/
|
|
1086
1613
|
async createPrefix(model, ...args) {
|
|
1087
1614
|
const contextArgs = await Context.args(OperationKeys.CREATE, this.class, args);
|
|
1088
1615
|
model = new this.class(model);
|
|
1089
1616
|
await enforceDBDecorators(this, contextArgs.context, model, OperationKeys.CREATE, OperationKeys.ON);
|
|
1090
1617
|
return [model, ...contextArgs.args];
|
|
1091
1618
|
}
|
|
1619
|
+
/**
|
|
1620
|
+
* @description Processes a model after creation and executes post-creation operations.
|
|
1621
|
+
* @summary Finalizes a model after it has been created in the data store. This includes
|
|
1622
|
+
* enforcing any decorators that should be applied after creation.
|
|
1623
|
+
* @param {M} model - The model instance that was created
|
|
1624
|
+
* @param {C} context - The context for the operation
|
|
1625
|
+
* @return {Promise<M>} A promise that resolves to the processed model instance
|
|
1626
|
+
*/
|
|
1092
1627
|
async createSuffix(model, context) {
|
|
1093
1628
|
await enforceDBDecorators(this, context, model, OperationKeys.CREATE, OperationKeys.AFTER);
|
|
1094
1629
|
return model;
|
|
1095
1630
|
}
|
|
1631
|
+
/**
|
|
1632
|
+
* @description Prepares multiple models for creation and executes pre-creation operations.
|
|
1633
|
+
* @summary Processes multiple models before they are created in the data store. This includes
|
|
1634
|
+
* creating a context, instantiating new model instances, and enforcing any decorators
|
|
1635
|
+
* that should be applied before creation for each model.
|
|
1636
|
+
* @param {M[]} models - The array of model instances to prepare for creation
|
|
1637
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1638
|
+
* @return A promise that resolves to an array containing the prepared models and context arguments
|
|
1639
|
+
*/
|
|
1096
1640
|
async createAllPrefix(models, ...args) {
|
|
1097
1641
|
const contextArgs = await Context.args(OperationKeys.CREATE, this.class, args);
|
|
1098
1642
|
await Promise.all(models.map(async (m) => {
|
|
@@ -1102,17 +1646,50 @@ class BaseRepository {
|
|
|
1102
1646
|
}));
|
|
1103
1647
|
return [models, ...contextArgs.args];
|
|
1104
1648
|
}
|
|
1649
|
+
/**
|
|
1650
|
+
* @description Processes multiple models after creation and executes post-creation operations.
|
|
1651
|
+
* @summary Finalizes multiple models after they have been created in the data store. This includes
|
|
1652
|
+
* enforcing any decorators that should be applied after creation for each model.
|
|
1653
|
+
* @param {M[]} models - The array of model instances that were created
|
|
1654
|
+
* @param {C} context - The context for the operation
|
|
1655
|
+
* @return {Promise<M[]>} A promise that resolves to the array of processed model instances
|
|
1656
|
+
*/
|
|
1105
1657
|
async createAllSuffix(models, context) {
|
|
1106
1658
|
await Promise.all(models.map((m) => enforceDBDecorators(this, context, m, OperationKeys.CREATE, OperationKeys.AFTER)));
|
|
1107
1659
|
return models;
|
|
1108
1660
|
}
|
|
1661
|
+
/**
|
|
1662
|
+
* @description Retrieves multiple model instances from the repository by their primary keys.
|
|
1663
|
+
* @summary Fetches multiple model instances from the underlying data store using their primary keys
|
|
1664
|
+
* by calling the read method for each key in the array.
|
|
1665
|
+
* @param {string[] | number[]} keys - The array of primary keys of the models to retrieve
|
|
1666
|
+
* @param {any[]} args - Additional arguments for the read operation
|
|
1667
|
+
* @return {Promise<M[]>} A promise that resolves to an array of retrieved model instances
|
|
1668
|
+
*/
|
|
1109
1669
|
async readAll(keys, ...args) {
|
|
1110
1670
|
return await Promise.all(keys.map((id) => this.read(id, ...args)));
|
|
1111
1671
|
}
|
|
1672
|
+
/**
|
|
1673
|
+
* @description Processes a model after retrieval and executes post-read operations.
|
|
1674
|
+
* @summary Finalizes a model after it has been retrieved from the data store. This includes
|
|
1675
|
+
* enforcing any decorators that should be applied after reading.
|
|
1676
|
+
* @param {M} model - The model instance that was retrieved
|
|
1677
|
+
* @param {C} context - The context for the operation
|
|
1678
|
+
* @return {Promise<M>} A promise that resolves to the processed model instance
|
|
1679
|
+
*/
|
|
1112
1680
|
async readSuffix(model, context) {
|
|
1113
1681
|
await enforceDBDecorators(this, context, model, OperationKeys.READ, OperationKeys.AFTER);
|
|
1114
1682
|
return model;
|
|
1115
1683
|
}
|
|
1684
|
+
/**
|
|
1685
|
+
* @description Prepares for reading a model and executes pre-read operations.
|
|
1686
|
+
* @summary Processes a key before a model is read from the data store. This includes
|
|
1687
|
+
* creating a context, instantiating a new model instance with the key, and enforcing any decorators
|
|
1688
|
+
* that should be applied before reading.
|
|
1689
|
+
* @param {string} key - The primary key of the model to read
|
|
1690
|
+
* @param {any[]} args - Additional arguments for the read operation
|
|
1691
|
+
* @return A promise that resolves to an array containing the key and context arguments
|
|
1692
|
+
*/
|
|
1116
1693
|
async readPrefix(key, ...args) {
|
|
1117
1694
|
const contextArgs = await Context.args(OperationKeys.READ, this.class, args);
|
|
1118
1695
|
const model = new this.class();
|
|
@@ -1120,6 +1697,15 @@ class BaseRepository {
|
|
|
1120
1697
|
await enforceDBDecorators(this, contextArgs.context, model, OperationKeys.READ, OperationKeys.ON);
|
|
1121
1698
|
return [key, ...contextArgs.args];
|
|
1122
1699
|
}
|
|
1700
|
+
/**
|
|
1701
|
+
* @description Prepares for reading multiple models and executes pre-read operations.
|
|
1702
|
+
* @summary Processes multiple keys before models are read from the data store. This includes
|
|
1703
|
+
* creating a context, instantiating new model instances with the keys, and enforcing any decorators
|
|
1704
|
+
* that should be applied before reading for each key.
|
|
1705
|
+
* @param {string[] | number[]} keys - The array of primary keys of the models to read
|
|
1706
|
+
* @param {any[]} args - Additional arguments for the read operation
|
|
1707
|
+
* @return A promise that resolves to an array containing the keys and context arguments
|
|
1708
|
+
*/
|
|
1123
1709
|
async readAllPrefix(keys, ...args) {
|
|
1124
1710
|
const contextArgs = await Context.args(OperationKeys.READ, this.class, args);
|
|
1125
1711
|
await Promise.all(keys.map(async (k) => {
|
|
@@ -1129,17 +1715,50 @@ class BaseRepository {
|
|
|
1129
1715
|
}));
|
|
1130
1716
|
return [keys, ...contextArgs.args];
|
|
1131
1717
|
}
|
|
1718
|
+
/**
|
|
1719
|
+
* @description Processes multiple models after retrieval and executes post-read operations.
|
|
1720
|
+
* @summary Finalizes multiple models after they have been retrieved from the data store. This includes
|
|
1721
|
+
* enforcing any decorators that should be applied after reading for each model.
|
|
1722
|
+
* @param {M[]} models - The array of model instances that were retrieved
|
|
1723
|
+
* @param {C} context - The context for the operation
|
|
1724
|
+
* @return {Promise<M[]>} A promise that resolves to the array of processed model instances
|
|
1725
|
+
*/
|
|
1132
1726
|
async readAllSuffix(models, context) {
|
|
1133
1727
|
await Promise.all(models.map((m) => enforceDBDecorators(this, context, m, OperationKeys.READ, OperationKeys.AFTER)));
|
|
1134
1728
|
return models;
|
|
1135
1729
|
}
|
|
1730
|
+
/**
|
|
1731
|
+
* @description Updates multiple model instances in the repository.
|
|
1732
|
+
* @summary Updates multiple model instances in the underlying data store by calling
|
|
1733
|
+
* the update method for each model in the array.
|
|
1734
|
+
* @param {M[]} models - The array of model instances to update
|
|
1735
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
1736
|
+
* @return {Promise<M[]>} A promise that resolves to an array of updated model instances
|
|
1737
|
+
*/
|
|
1136
1738
|
async updateAll(models, ...args) {
|
|
1137
1739
|
return Promise.all(models.map((m) => this.update(m, ...args)));
|
|
1138
1740
|
}
|
|
1741
|
+
/**
|
|
1742
|
+
* @description Processes a model after update and executes post-update operations.
|
|
1743
|
+
* @summary Finalizes a model after it has been updated in the data store. This includes
|
|
1744
|
+
* enforcing any decorators that should be applied after updating.
|
|
1745
|
+
* @param {M} model - The model instance that was updated
|
|
1746
|
+
* @param {C} context - The context for the operation
|
|
1747
|
+
* @return {Promise<M>} A promise that resolves to the processed model instance
|
|
1748
|
+
*/
|
|
1139
1749
|
async updateSuffix(model, context) {
|
|
1140
1750
|
await enforceDBDecorators(this, context, model, OperationKeys.UPDATE, OperationKeys.AFTER);
|
|
1141
1751
|
return model;
|
|
1142
1752
|
}
|
|
1753
|
+
/**
|
|
1754
|
+
* @description Prepares a model for update and executes pre-update operations.
|
|
1755
|
+
* @summary Processes a model before it is updated in the data store. This includes
|
|
1756
|
+
* creating a context, validating the primary key, retrieving the existing model,
|
|
1757
|
+
* and enforcing any decorators that should be applied before updating.
|
|
1758
|
+
* @param {M} model - The model instance to prepare for update
|
|
1759
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
1760
|
+
* @return A promise that resolves to an array containing the prepared model and context arguments
|
|
1761
|
+
*/
|
|
1143
1762
|
async updatePrefix(model, ...args) {
|
|
1144
1763
|
const contextArgs = await Context.args(OperationKeys.UPDATE, this.class, args);
|
|
1145
1764
|
const id = model[this.pk];
|
|
@@ -1149,6 +1768,15 @@ class BaseRepository {
|
|
|
1149
1768
|
await enforceDBDecorators(this, contextArgs.context, model, OperationKeys.UPDATE, OperationKeys.ON, oldModel);
|
|
1150
1769
|
return [model, ...contextArgs.args];
|
|
1151
1770
|
}
|
|
1771
|
+
/**
|
|
1772
|
+
* @description Prepares multiple models for update and executes pre-update operations.
|
|
1773
|
+
* @summary Processes multiple models before they are updated in the data store. This includes
|
|
1774
|
+
* creating a context, instantiating new model instances, and enforcing any decorators
|
|
1775
|
+
* that should be applied before updating for each model.
|
|
1776
|
+
* @param {M[]} models - The array of model instances to prepare for update
|
|
1777
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
1778
|
+
* @return A promise that resolves to an array containing the prepared models and context arguments
|
|
1779
|
+
*/
|
|
1152
1780
|
async updateAllPrefix(models, ...args) {
|
|
1153
1781
|
const contextArgs = await Context.args(OperationKeys.UPDATE, this.class, args);
|
|
1154
1782
|
await Promise.all(models.map((m) => {
|
|
@@ -1158,23 +1786,65 @@ class BaseRepository {
|
|
|
1158
1786
|
}));
|
|
1159
1787
|
return [models, ...contextArgs.args];
|
|
1160
1788
|
}
|
|
1789
|
+
/**
|
|
1790
|
+
* @description Processes multiple models after update and executes post-update operations.
|
|
1791
|
+
* @summary Finalizes multiple models after they have been updated in the data store. This includes
|
|
1792
|
+
* enforcing any decorators that should be applied after updating for each model.
|
|
1793
|
+
* @param {M[]} models - The array of model instances that were updated
|
|
1794
|
+
* @param {C} context - The context for the operation
|
|
1795
|
+
* @return {Promise<M[]>} A promise that resolves to the array of processed model instances
|
|
1796
|
+
*/
|
|
1161
1797
|
async updateAllSuffix(models, context) {
|
|
1162
1798
|
await Promise.all(models.map((m) => enforceDBDecorators(this, context, m, OperationKeys.UPDATE, OperationKeys.AFTER)));
|
|
1163
1799
|
return models;
|
|
1164
1800
|
}
|
|
1801
|
+
/**
|
|
1802
|
+
* @description Deletes multiple model instances from the repository by their primary keys.
|
|
1803
|
+
* @summary Removes multiple model instances from the underlying data store using their primary keys
|
|
1804
|
+
* by calling the delete method for each key in the array.
|
|
1805
|
+
* @param {string[] | number[]} keys - The array of primary keys of the models to delete
|
|
1806
|
+
* @param {any[]} args - Additional arguments for the delete operation
|
|
1807
|
+
* @return {Promise<M[]>} A promise that resolves to an array of deleted model instances
|
|
1808
|
+
*/
|
|
1165
1809
|
async deleteAll(keys, ...args) {
|
|
1166
1810
|
return Promise.all(keys.map((k) => this.delete(k, ...args)));
|
|
1167
1811
|
}
|
|
1812
|
+
/**
|
|
1813
|
+
* @description Processes a model after deletion and executes post-delete operations.
|
|
1814
|
+
* @summary Finalizes a model after it has been deleted from the data store. This includes
|
|
1815
|
+
* enforcing any decorators that should be applied after deletion.
|
|
1816
|
+
* @param {M} model - The model instance that was deleted
|
|
1817
|
+
* @param {C} context - The context for the operation
|
|
1818
|
+
* @return {Promise<M>} A promise that resolves to the processed model instance
|
|
1819
|
+
*/
|
|
1168
1820
|
async deleteSuffix(model, context) {
|
|
1169
1821
|
await enforceDBDecorators(this, context, model, OperationKeys.DELETE, OperationKeys.AFTER);
|
|
1170
1822
|
return model;
|
|
1171
1823
|
}
|
|
1824
|
+
/**
|
|
1825
|
+
* @description Prepares for deleting a model and executes pre-delete operations.
|
|
1826
|
+
* @summary Processes a key before a model is deleted from the data store. This includes
|
|
1827
|
+
* creating a context, retrieving the model to be deleted, and enforcing any decorators
|
|
1828
|
+
* that should be applied before deletion.
|
|
1829
|
+
* @param {any} key - The primary key of the model to delete
|
|
1830
|
+
* @param {any[]} args - Additional arguments for the delete operation
|
|
1831
|
+
* @return A promise that resolves to an array containing the key and context arguments
|
|
1832
|
+
*/
|
|
1172
1833
|
async deletePrefix(key, ...args) {
|
|
1173
1834
|
const contextArgs = await Context.args(OperationKeys.DELETE, this.class, args);
|
|
1174
1835
|
const model = await this.read(key, ...contextArgs.args);
|
|
1175
1836
|
await enforceDBDecorators(this, contextArgs.context, model, OperationKeys.DELETE, OperationKeys.ON);
|
|
1176
1837
|
return [key, ...contextArgs.args];
|
|
1177
1838
|
}
|
|
1839
|
+
/**
|
|
1840
|
+
* @description Prepares for deleting multiple models and executes pre-delete operations.
|
|
1841
|
+
* @summary Processes multiple keys before models are deleted from the data store. This includes
|
|
1842
|
+
* creating a context, retrieving the models to be deleted, and enforcing any decorators
|
|
1843
|
+
* that should be applied before deletion for each model.
|
|
1844
|
+
* @param {string[] | number[]} keys - The array of primary keys of the models to delete
|
|
1845
|
+
* @param {any[]} args - Additional arguments for the delete operation
|
|
1846
|
+
* @return A promise that resolves to an array containing the keys and context arguments
|
|
1847
|
+
*/
|
|
1178
1848
|
async deleteAllPrefix(keys, ...args) {
|
|
1179
1849
|
const contextArgs = await Context.args(OperationKeys.DELETE, this.class, args);
|
|
1180
1850
|
const models = await this.readAll(keys, ...contextArgs.args);
|
|
@@ -1183,10 +1853,26 @@ class BaseRepository {
|
|
|
1183
1853
|
}));
|
|
1184
1854
|
return [keys, ...contextArgs.args];
|
|
1185
1855
|
}
|
|
1856
|
+
/**
|
|
1857
|
+
* @description Processes multiple models after deletion and executes post-delete operations.
|
|
1858
|
+
* @summary Finalizes multiple models after they have been deleted from the data store. This includes
|
|
1859
|
+
* enforcing any decorators that should be applied after deletion for each model.
|
|
1860
|
+
* @param {M[]} models - The array of model instances that were deleted
|
|
1861
|
+
* @param {C} context - The context for the operation
|
|
1862
|
+
* @return {Promise<M[]>} A promise that resolves to the array of processed model instances
|
|
1863
|
+
*/
|
|
1186
1864
|
async deleteAllSuffix(models, context) {
|
|
1187
1865
|
await Promise.all(models.map((m) => enforceDBDecorators(this, context, m, OperationKeys.DELETE, OperationKeys.AFTER)));
|
|
1188
1866
|
return models;
|
|
1189
1867
|
}
|
|
1868
|
+
/**
|
|
1869
|
+
* @description Merges two model instances into a new instance.
|
|
1870
|
+
* @summary Creates a new model instance by combining properties from an old model and a new model.
|
|
1871
|
+
* Properties from the new model override properties from the old model if they are defined.
|
|
1872
|
+
* @param {M} oldModel - The original model instance
|
|
1873
|
+
* @param {M} model - The new model instance with updated properties
|
|
1874
|
+
* @return {M} A new model instance with merged properties
|
|
1875
|
+
*/
|
|
1190
1876
|
merge(oldModel, model) {
|
|
1191
1877
|
const extract = (model) => Object.entries(model).reduce((accum, [key, val]) => {
|
|
1192
1878
|
if (typeof val !== "undefined")
|
|
@@ -1195,24 +1881,87 @@ class BaseRepository {
|
|
|
1195
1881
|
}, {});
|
|
1196
1882
|
return new this.class(Object.assign({}, extract(oldModel), extract(model)));
|
|
1197
1883
|
}
|
|
1884
|
+
/**
|
|
1885
|
+
* @description Returns a string representation of the repository.
|
|
1886
|
+
* @summary Creates a string that identifies this repository by the name of its model class.
|
|
1887
|
+
* @return {string} A string representation of the repository
|
|
1888
|
+
*/
|
|
1198
1889
|
toString() {
|
|
1199
1890
|
return `${this.class.name} Repository`;
|
|
1200
1891
|
}
|
|
1201
1892
|
}
|
|
1202
1893
|
|
|
1894
|
+
/**
|
|
1895
|
+
* @description Concrete repository implementation with validation support.
|
|
1896
|
+
* @summary The Repository class extends BaseRepository to provide additional validation
|
|
1897
|
+
* functionality. It overrides prefix methods to perform model validation before database
|
|
1898
|
+
* operations and throws ValidationError when validation fails.
|
|
1899
|
+
* @template M - The model type extending Model
|
|
1900
|
+
* @template F - The repository flags type, defaults to RepositoryFlags
|
|
1901
|
+
* @template C - The context type, defaults to Context<F>
|
|
1902
|
+
* @class Repository
|
|
1903
|
+
* @example
|
|
1904
|
+
* class UserModel extends Model {
|
|
1905
|
+
* @id()
|
|
1906
|
+
* id: string;
|
|
1907
|
+
*
|
|
1908
|
+
* @required()
|
|
1909
|
+
* @minLength(3)
|
|
1910
|
+
* name: string;
|
|
1911
|
+
* }
|
|
1912
|
+
*
|
|
1913
|
+
* class UserRepository extends Repository<UserModel> {
|
|
1914
|
+
* constructor() {
|
|
1915
|
+
* super(UserModel);
|
|
1916
|
+
* }
|
|
1917
|
+
*
|
|
1918
|
+
* async create(model: UserModel): Promise<UserModel> {
|
|
1919
|
+
* // Implementation with automatic validation
|
|
1920
|
+
* return model;
|
|
1921
|
+
* }
|
|
1922
|
+
* }
|
|
1923
|
+
*
|
|
1924
|
+
* // Using the repository
|
|
1925
|
+
* const repo = new UserRepository();
|
|
1926
|
+
* try {
|
|
1927
|
+
* const user = await repo.create({ name: 'Jo' }); // Will throw ValidationError
|
|
1928
|
+
* } catch (error) {
|
|
1929
|
+
* console.error(error); // ValidationError: name must be at least 3 characters
|
|
1930
|
+
* }
|
|
1931
|
+
*/
|
|
1203
1932
|
class Repository extends BaseRepository {
|
|
1204
1933
|
constructor(clazz) {
|
|
1205
1934
|
super(clazz);
|
|
1206
1935
|
}
|
|
1936
|
+
/**
|
|
1937
|
+
* @description Prepares a model for creation with validation.
|
|
1938
|
+
* @summary Overrides the base createPrefix method to add validation checks.
|
|
1939
|
+
* Creates a context, instantiates a new model, enforces decorators, and validates
|
|
1940
|
+
* the model before allowing creation to proceed.
|
|
1941
|
+
* @param {M} model - The model instance to prepare for creation
|
|
1942
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1943
|
+
* @return A promise that resolves to an array containing the validated model and context arguments
|
|
1944
|
+
* @throws {ValidationError} If the model fails validation
|
|
1945
|
+
*/
|
|
1207
1946
|
async createPrefix(model, ...args) {
|
|
1208
1947
|
const contextArgs = await Context.args(OperationKeys.CREATE, this.class, args);
|
|
1209
1948
|
model = new this.class(model);
|
|
1210
1949
|
await enforceDBDecorators(this, contextArgs.context, model, OperationKeys.CREATE, OperationKeys.ON);
|
|
1211
|
-
const errors = model.hasErrors();
|
|
1950
|
+
const errors = await Promise.resolve(model.hasErrors());
|
|
1212
1951
|
if (errors)
|
|
1213
1952
|
throw new ValidationError(errors.toString());
|
|
1214
1953
|
return [model, ...contextArgs.args];
|
|
1215
1954
|
}
|
|
1955
|
+
/**
|
|
1956
|
+
* @description Prepares multiple models for creation with validation.
|
|
1957
|
+
* @summary Overrides the base createAllPrefix method to add validation checks for multiple models.
|
|
1958
|
+
* Creates a context, instantiates new models, enforces decorators, and validates
|
|
1959
|
+
* each model before allowing creation to proceed. Collects validation errors from all models.
|
|
1960
|
+
* @param {M[]} models - The array of model instances to prepare for creation
|
|
1961
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1962
|
+
* @return {Promise<any[]>} A promise that resolves to an array containing the validated models and context arguments
|
|
1963
|
+
* @throws {ValidationError} If any model fails validation, with details about which models failed
|
|
1964
|
+
*/
|
|
1216
1965
|
async createAllPrefix(models, ...args) {
|
|
1217
1966
|
const contextArgs = await Context.args(OperationKeys.CREATE, this.class, args);
|
|
1218
1967
|
await Promise.all(models.map(async (m) => {
|
|
@@ -1220,9 +1969,8 @@ class Repository extends BaseRepository {
|
|
|
1220
1969
|
await enforceDBDecorators(this, contextArgs.context, m, OperationKeys.CREATE, OperationKeys.ON);
|
|
1221
1970
|
return m;
|
|
1222
1971
|
}));
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1225
|
-
.reduce((accum, e, i) => {
|
|
1972
|
+
const modelsValidation = await Promise.all(models.map((m) => Promise.resolve(m.hasErrors())));
|
|
1973
|
+
const errors = modelsValidation.reduce((accum, e, i) => {
|
|
1226
1974
|
if (e)
|
|
1227
1975
|
accum =
|
|
1228
1976
|
typeof accum === "string"
|
|
@@ -1234,6 +1982,18 @@ class Repository extends BaseRepository {
|
|
|
1234
1982
|
throw new ValidationError(errors);
|
|
1235
1983
|
return [models, ...contextArgs.args];
|
|
1236
1984
|
}
|
|
1985
|
+
/**
|
|
1986
|
+
* @description Prepares a model for update with validation.
|
|
1987
|
+
* @summary Overrides the base updatePrefix method to add validation checks.
|
|
1988
|
+
* Creates a context, validates the primary key, retrieves the existing model,
|
|
1989
|
+
* merges the old and new models, enforces decorators, and validates the model
|
|
1990
|
+
* before allowing the update to proceed.
|
|
1991
|
+
* @param {M} model - The model instance to prepare for update
|
|
1992
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
1993
|
+
* @return A promise that resolves to an array containing the validated model and context arguments
|
|
1994
|
+
* @throws {InternalError} If the model doesn't have a primary key value
|
|
1995
|
+
* @throws {ValidationError} If the model fails validation
|
|
1996
|
+
*/
|
|
1237
1997
|
async updatePrefix(model, ...args) {
|
|
1238
1998
|
const contextArgs = await Context.args(OperationKeys.UPDATE, this.class, args);
|
|
1239
1999
|
const pk = model[this.pk];
|
|
@@ -1242,11 +2002,23 @@ class Repository extends BaseRepository {
|
|
|
1242
2002
|
const oldModel = await this.read(pk);
|
|
1243
2003
|
model = this.merge(oldModel, model);
|
|
1244
2004
|
await enforceDBDecorators(this, contextArgs.context, model, OperationKeys.UPDATE, OperationKeys.ON, oldModel);
|
|
1245
|
-
const errors = model.hasErrors(oldModel);
|
|
2005
|
+
const errors = await Promise.resolve(model.hasErrors(oldModel));
|
|
1246
2006
|
if (errors)
|
|
1247
2007
|
throw new ValidationError(errors.toString());
|
|
1248
2008
|
return [model, ...contextArgs.args];
|
|
1249
2009
|
}
|
|
2010
|
+
/**
|
|
2011
|
+
* @description Prepares multiple models for update with validation.
|
|
2012
|
+
* @summary Overrides the base updateAllPrefix method to add validation checks for multiple models.
|
|
2013
|
+
* Creates a context, validates primary keys, retrieves existing models, merges old and new models,
|
|
2014
|
+
* enforces decorators, and validates each model before allowing updates to proceed.
|
|
2015
|
+
* Collects validation errors from all models.
|
|
2016
|
+
* @param {M[]} models - The array of model instances to prepare for update
|
|
2017
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
2018
|
+
* @return A promise that resolves to an array containing the validated models and context arguments
|
|
2019
|
+
* @throws {InternalError} If any model doesn't have a primary key value
|
|
2020
|
+
* @throws {ValidationError} If any model fails validation, with details about which models failed
|
|
2021
|
+
*/
|
|
1250
2022
|
async updateAllPrefix(models, ...args) {
|
|
1251
2023
|
const contextArgs = await Context.args(OperationKeys.UPDATE, this.class, args);
|
|
1252
2024
|
const ids = models.map((m) => {
|
|
@@ -1258,9 +2030,8 @@ class Repository extends BaseRepository {
|
|
|
1258
2030
|
const oldModels = await this.readAll(ids, ...contextArgs.args);
|
|
1259
2031
|
models = models.map((m, i) => this.merge(oldModels[i], m));
|
|
1260
2032
|
await Promise.all(models.map((m, i) => enforceDBDecorators(this, contextArgs.context, m, OperationKeys.UPDATE, OperationKeys.ON, oldModels[i])));
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1263
|
-
.reduce((accum, e, i) => {
|
|
2033
|
+
const modelsValidation = await Promise.all(models.map((m, i) => Promise.resolve(m.hasErrors(oldModels[i]))));
|
|
2034
|
+
const errors = modelsValidation.reduce((accum, e, i) => {
|
|
1264
2035
|
if (e)
|
|
1265
2036
|
accum =
|
|
1266
2037
|
typeof accum === "string"
|
|
@@ -1272,19 +2043,25 @@ class Repository extends BaseRepository {
|
|
|
1272
2043
|
throw new ValidationError(errors);
|
|
1273
2044
|
return [models, ...contextArgs.args];
|
|
1274
2045
|
}
|
|
2046
|
+
/**
|
|
2047
|
+
* @description Creates a reflection key for database operations.
|
|
2048
|
+
* @summary Generates a key for storing metadata in the reflection system by prefixing
|
|
2049
|
+
* the provided key with the database reflection prefix.
|
|
2050
|
+
* @param {string} key - The base key to prefix
|
|
2051
|
+
* @return {string} The prefixed reflection key
|
|
2052
|
+
*/
|
|
1275
2053
|
static key(key) {
|
|
1276
2054
|
return DBKeys.REFLECT + key;
|
|
1277
2055
|
}
|
|
1278
2056
|
}
|
|
1279
2057
|
|
|
1280
2058
|
/**
|
|
1281
|
-
*
|
|
1282
|
-
*
|
|
1283
|
-
* @param {string} [message]
|
|
1284
|
-
*
|
|
1285
|
-
* @
|
|
1286
|
-
*
|
|
1287
|
-
* @category Decorators
|
|
2059
|
+
* @description Prevents a property from being modified after initial creation.
|
|
2060
|
+
* @summary Marks the property as readonly, causing validation errors if attempts are made to modify it during updates.
|
|
2061
|
+
* @param {string} [message] - The error message to display when validation fails. Defaults to {@link DEFAULT_ERROR_MESSAGES.READONLY.INVALID}
|
|
2062
|
+
* @return {PropertyDecorator} A decorator function that can be applied to class properties
|
|
2063
|
+
* @function readonly
|
|
2064
|
+
* @category Property Decorators
|
|
1288
2065
|
*/
|
|
1289
2066
|
function readonly(message = DEFAULT_ERROR_MESSAGES.READONLY.INVALID) {
|
|
1290
2067
|
const key = Validation.updateKey(DBKeys.READONLY);
|
|
@@ -1294,13 +2071,28 @@ function readonly(message = DEFAULT_ERROR_MESSAGES.READONLY.INVALID) {
|
|
|
1294
2071
|
}))
|
|
1295
2072
|
.apply();
|
|
1296
2073
|
}
|
|
2074
|
+
/**
|
|
2075
|
+
* @description Handler function that sets a timestamp property to the current timestamp.
|
|
2076
|
+
* @summary Updates a model property with the current timestamp from the repository context.
|
|
2077
|
+
* @template M - The model type extending Model
|
|
2078
|
+
* @template R - The repository type extending IRepository
|
|
2079
|
+
* @template V - The data type for the operation
|
|
2080
|
+
* @template F - The repository flags type
|
|
2081
|
+
* @template C - The context type
|
|
2082
|
+
* @param {C} context - The repository context containing the current timestamp
|
|
2083
|
+
* @param {V} data - The data being processed
|
|
2084
|
+
* @param key - The property key to update
|
|
2085
|
+
* @param {M} model - The model instance being updated
|
|
2086
|
+
* @return {Promise<void>} A promise that resolves when the timestamp has been set
|
|
2087
|
+
* @function timestampHandler
|
|
2088
|
+
* @memberOf module:db-decorators
|
|
2089
|
+
*/
|
|
1297
2090
|
async function timestampHandler(context, data, key, model) {
|
|
1298
2091
|
model[key] = context.timestamp;
|
|
1299
2092
|
}
|
|
1300
2093
|
/**
|
|
1301
|
-
*
|
|
1302
|
-
*
|
|
1303
|
-
* Makes it a {@link date}
|
|
2094
|
+
* @description Automatically manages timestamp properties for tracking creation and update times.
|
|
2095
|
+
* @summary Marks the property as a timestamp, making it required and ensuring it's a valid date. The property will be automatically updated with the current timestamp during specified operations.
|
|
1304
2096
|
*
|
|
1305
2097
|
* Date Format:
|
|
1306
2098
|
*
|
|
@@ -1320,13 +2112,30 @@ async function timestampHandler(context, data, key, model) {
|
|
|
1320
2112
|
* S = miliseconds
|
|
1321
2113
|
* </pre>
|
|
1322
2114
|
*
|
|
1323
|
-
* @param {
|
|
1324
|
-
* @param {string} [format] The
|
|
1325
|
-
* @
|
|
1326
|
-
*
|
|
1327
|
-
* @
|
|
1328
|
-
*
|
|
1329
|
-
*
|
|
2115
|
+
* @param {OperationKeys[]} operation - The operations to act on. Defaults to {@link DBOperations.CREATE_UPDATE}
|
|
2116
|
+
* @param {string} [format] - The timestamp format. Defaults to {@link DEFAULT_TIMESTAMP_FORMAT}
|
|
2117
|
+
* @return {PropertyDecorator} A decorator function that can be applied to class properties
|
|
2118
|
+
* @function timestamp
|
|
2119
|
+
* @category Property Decorators
|
|
2120
|
+
* @mermaid
|
|
2121
|
+
* sequenceDiagram
|
|
2122
|
+
* participant C as Client
|
|
2123
|
+
* participant M as Model
|
|
2124
|
+
* participant T as TimestampDecorator
|
|
2125
|
+
* participant V as Validator
|
|
2126
|
+
*
|
|
2127
|
+
* C->>M: Create/Update model
|
|
2128
|
+
* M->>T: Process timestamp property
|
|
2129
|
+
* T->>M: Apply required validation
|
|
2130
|
+
* T->>M: Apply date format validation
|
|
2131
|
+
*
|
|
2132
|
+
* alt Update operation
|
|
2133
|
+
* T->>V: Register timestamp validator
|
|
2134
|
+
* V->>M: Validate timestamp is newer
|
|
2135
|
+
* end
|
|
2136
|
+
*
|
|
2137
|
+
* T->>M: Set current timestamp
|
|
2138
|
+
* M->>C: Return updated model
|
|
1330
2139
|
*/
|
|
1331
2140
|
function timestamp(operation = DBOperations.CREATE_UPDATE, format = DEFAULT_TIMESTAMP_FORMAT) {
|
|
1332
2141
|
const key = Validation.updateKey(DBKeys.TIMESTAMP);
|
|
@@ -1343,6 +2152,22 @@ function timestamp(operation = DBOperations.CREATE_UPDATE, format = DEFAULT_TIME
|
|
|
1343
2152
|
.define(...decorators)
|
|
1344
2153
|
.apply();
|
|
1345
2154
|
}
|
|
2155
|
+
/**
|
|
2156
|
+
* @description Handler function that serializes a property to JSON string during create and update operations.
|
|
2157
|
+
* @summary Converts a complex object property to a JSON string before storing it in the database.
|
|
2158
|
+
* @template M - The model type extending Model
|
|
2159
|
+
* @template R - The repository type extending IRepository
|
|
2160
|
+
* @template V - The data type for the operation
|
|
2161
|
+
* @template F - The repository flags type
|
|
2162
|
+
* @template C - The context type
|
|
2163
|
+
* @param {C} context - The repository context
|
|
2164
|
+
* @param {V} data - The data being processed
|
|
2165
|
+
* @param key - The property key to serialize
|
|
2166
|
+
* @param {M} model - The model instance being processed
|
|
2167
|
+
* @return {Promise<void>} A promise that resolves when the property has been serialized
|
|
2168
|
+
* @function serializeOnCreateUpdate
|
|
2169
|
+
* @memberOf module:db-decorators
|
|
2170
|
+
*/
|
|
1346
2171
|
async function serializeOnCreateUpdate(context, data, key, model) {
|
|
1347
2172
|
if (!model[key])
|
|
1348
2173
|
return;
|
|
@@ -1354,6 +2179,22 @@ async function serializeOnCreateUpdate(context, data, key, model) {
|
|
|
1354
2179
|
throw new SerializationError(`Failed to serialize ${key.toString()} property of model ${model.constructor.name}: e`);
|
|
1355
2180
|
}
|
|
1356
2181
|
}
|
|
2182
|
+
/**
|
|
2183
|
+
* @description Handler function that deserializes a property from JSON string after database operations.
|
|
2184
|
+
* @summary Converts a JSON string property back to its original complex object form after retrieving it from the database.
|
|
2185
|
+
* @template M - The model type extending Model
|
|
2186
|
+
* @template R - The repository type extending IRepository
|
|
2187
|
+
* @template V - The data type for the operation
|
|
2188
|
+
* @template F - The repository flags type
|
|
2189
|
+
* @template C - The context type
|
|
2190
|
+
* @param {C} context - The repository context
|
|
2191
|
+
* @param {V} data - The data being processed
|
|
2192
|
+
* @param key - The property key to deserialize
|
|
2193
|
+
* @param {M} model - The model instance being processed
|
|
2194
|
+
* @return {Promise<void>} A promise that resolves when the property has been deserialized
|
|
2195
|
+
* @function serializeAfterAll
|
|
2196
|
+
* @memberOf module:db-decorators
|
|
2197
|
+
*/
|
|
1357
2198
|
async function serializeAfterAll(context, data, key, model) {
|
|
1358
2199
|
if (!model[key])
|
|
1359
2200
|
return;
|
|
@@ -1367,146 +2208,323 @@ async function serializeAfterAll(context, data, key, model) {
|
|
|
1367
2208
|
}
|
|
1368
2209
|
}
|
|
1369
2210
|
/**
|
|
1370
|
-
* @
|
|
1371
|
-
* @
|
|
1372
|
-
*
|
|
2211
|
+
* @description Enables automatic JSON serialization and deserialization for complex object properties.
|
|
2212
|
+
* @summary Decorator that automatically converts complex objects to JSON strings before storing in the database and back to objects when retrieving them.
|
|
2213
|
+
* @return {PropertyDecorator} A decorator function that can be applied to class properties
|
|
1373
2214
|
* @function serialize
|
|
1374
|
-
*
|
|
1375
|
-
* @
|
|
2215
|
+
* @category Property Decorators
|
|
2216
|
+
* @mermaid
|
|
2217
|
+
* sequenceDiagram
|
|
2218
|
+
* participant C as Client
|
|
2219
|
+
* participant M as Model
|
|
2220
|
+
* participant S as SerializeDecorator
|
|
2221
|
+
* participant DB as Database
|
|
2222
|
+
*
|
|
2223
|
+
* Note over C,DB: Create/Update Flow
|
|
2224
|
+
* C->>M: Set complex object property
|
|
2225
|
+
* M->>S: Process property (create/update)
|
|
2226
|
+
* S->>M: Convert to JSON string
|
|
2227
|
+
* M->>DB: Store serialized data
|
|
2228
|
+
*
|
|
2229
|
+
* Note over C,DB: Retrieval Flow
|
|
2230
|
+
* C->>M: Request model
|
|
2231
|
+
* M->>DB: Fetch data
|
|
2232
|
+
* DB->>M: Return with serialized property
|
|
2233
|
+
* M->>S: Process property (after all ops)
|
|
2234
|
+
* S->>M: Parse JSON back to object
|
|
2235
|
+
* M->>C: Return model with deserialized property
|
|
1376
2236
|
*/
|
|
1377
2237
|
function serialize() {
|
|
1378
2238
|
return apply(onCreateUpdate(serializeOnCreateUpdate), after(DBOperations.ALL, serializeAfterAll), type([String.name, Object.name]), metadata(Repository.key(DBKeys.SERIALIZE), {}));
|
|
1379
2239
|
}
|
|
1380
2240
|
|
|
2241
|
+
/**
|
|
2242
|
+
* @description Decorator that marks a property as an ID field
|
|
2243
|
+
* @summary Creates a composite decorator that marks a property as required, readonly, and as the ID field for database operations
|
|
2244
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2245
|
+
* @function id
|
|
2246
|
+
* @category Property Decorators
|
|
2247
|
+
*/
|
|
1381
2248
|
function id() {
|
|
1382
2249
|
return apply(required(), readonly(), propMetadata(Repository.key(DBKeys.ID), {}));
|
|
1383
2250
|
}
|
|
1384
2251
|
|
|
1385
2252
|
/**
|
|
1386
|
-
* @
|
|
2253
|
+
* @description
|
|
2254
|
+
* Retrieves validation decorator definitions from a model for update operations, including
|
|
2255
|
+
* support for special handling of list decorators.
|
|
1387
2256
|
*
|
|
1388
|
-
* @
|
|
1389
|
-
*
|
|
1390
|
-
*
|
|
2257
|
+
* @summary
|
|
2258
|
+
* Iterates over the model's own enumerable properties and filters out those specified in the
|
|
2259
|
+
* `propsToIgnore` array. For each remaining property, retrieves validation decorators specific
|
|
2260
|
+
* to update operations using the `UpdateValidationKeys.REFLECT` key. Additionally, it explicitly
|
|
2261
|
+
* checks for and appends any `LIST` type decorators to ensure proper validation of collection types.
|
|
1391
2262
|
*
|
|
1392
|
-
* @
|
|
1393
|
-
* @return {ModelErrorDefinition | undefined}
|
|
2263
|
+
* @template M - A generic parameter extending the `Model` class, representing the model type being inspected.
|
|
1394
2264
|
*
|
|
1395
|
-
* @
|
|
2265
|
+
* @param {M} model - The model instance whose properties are being inspected for update-related validations.
|
|
2266
|
+
* @param {string[]} propsToIgnore - A list of property names to exclude from the validation decorator retrieval process.
|
|
2267
|
+
*
|
|
2268
|
+
* @return {ValidationPropertyDecoratorDefinition[]} An array of validation decorator definitions, including both
|
|
2269
|
+
* update-specific and list-type decorators, excluding those for ignored properties.
|
|
2270
|
+
*
|
|
2271
|
+
* @function getValidatableUpdateProps
|
|
1396
2272
|
*/
|
|
1397
|
-
function
|
|
2273
|
+
function getValidatableUpdateProps(model, propsToIgnore) {
|
|
1398
2274
|
const decoratedProperties = [];
|
|
1399
|
-
for (const prop in
|
|
1400
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
2275
|
+
for (const prop in model) {
|
|
2276
|
+
if (Object.prototype.hasOwnProperty.call(model, prop) &&
|
|
2277
|
+
!propsToIgnore.includes(prop)) {
|
|
2278
|
+
const validationPropertyDefinition = getValidationDecorators(model, prop, UpdateValidationKeys.REFLECT);
|
|
2279
|
+
const listDecorator = getValidationDecorators(model, prop).decorators.find(({ key }) => key === ValidationKeys.LIST);
|
|
2280
|
+
if (listDecorator)
|
|
2281
|
+
validationPropertyDefinition.decorators.push(listDecorator);
|
|
2282
|
+
decoratedProperties.push(validationPropertyDefinition);
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
return decoratedProperties;
|
|
2286
|
+
}
|
|
2287
|
+
function validateDecorator(newModel, oldModel, prop, decorator, async) {
|
|
2288
|
+
const validator = Validation.get(decorator.key);
|
|
2289
|
+
if (!validator) {
|
|
2290
|
+
throw new Error(`Missing validator for ${decorator.key}`);
|
|
2291
|
+
}
|
|
2292
|
+
// Skip validators that aren't UpdateValidators
|
|
2293
|
+
if (!validator.updateHasErrors)
|
|
2294
|
+
return toConditionalPromise(undefined, async);
|
|
2295
|
+
// skip async decorators if validateDecorators is called synchronously (async = false)
|
|
2296
|
+
if (!async && decorator.props.async)
|
|
2297
|
+
return toConditionalPromise(undefined, async);
|
|
2298
|
+
const decoratorProps = Object.values(decorator.props) || {};
|
|
2299
|
+
// const context = PathProxyEngine.create(obj, {
|
|
2300
|
+
// ignoreUndefined: true,
|
|
2301
|
+
// ignoreNull: true,
|
|
2302
|
+
// });
|
|
2303
|
+
const maybeError = validator.updateHasErrors(newModel[prop], oldModel[prop], ...decoratorProps);
|
|
2304
|
+
return toConditionalPromise(maybeError, async);
|
|
2305
|
+
}
|
|
2306
|
+
function validateDecorators(newModel, oldModel, prop, decorators, async) {
|
|
2307
|
+
const result = {};
|
|
2308
|
+
for (const decorator of decorators) {
|
|
2309
|
+
// skip async decorators if validateDecorators is called synchronously (async = false)
|
|
2310
|
+
if (!async && decorator.props.async)
|
|
1408
2311
|
continue;
|
|
1409
|
-
let
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
const
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
2312
|
+
let validationErrors = validateDecorator(newModel, oldModel, prop, decorator, async);
|
|
2313
|
+
/*
|
|
2314
|
+
If the decorator is a list, each element must be checked.
|
|
2315
|
+
When 'async' is true, the 'err' will always be a pending promise initially,
|
|
2316
|
+
so the '!err' check will evaluate to false (even if the promise later resolves with no errors)
|
|
2317
|
+
*/
|
|
2318
|
+
if (decorator.key === ValidationKeys.LIST && (!validationErrors || async)) {
|
|
2319
|
+
const newPropValue = newModel[prop];
|
|
2320
|
+
const oldPropValue = oldModel[prop];
|
|
2321
|
+
const newValues = newPropValue instanceof Set ? [...newPropValue] : newPropValue;
|
|
2322
|
+
const oldValues = oldPropValue instanceof Set ? [...oldPropValue] : oldPropValue;
|
|
2323
|
+
if (newValues && newValues.length > 0) {
|
|
2324
|
+
const types = decorator.props.class ||
|
|
2325
|
+
decorator.props.clazz ||
|
|
2326
|
+
decorator.props.customTypes;
|
|
2327
|
+
const allowedTypes = [types].flat().map((t) => String(t).toLowerCase());
|
|
2328
|
+
const errs = newValues.map((childValue) => {
|
|
2329
|
+
// find by id so the list elements order doesn't matter
|
|
2330
|
+
const id = findModelId(childValue, true);
|
|
2331
|
+
if (!id)
|
|
2332
|
+
return "Failed to find model id";
|
|
2333
|
+
const oldModel = oldValues.find((el) => id === findModelId(el, true));
|
|
2334
|
+
if (Model.isModel(childValue)) {
|
|
2335
|
+
return childValue.hasErrors(oldModel);
|
|
2336
|
+
}
|
|
2337
|
+
return allowedTypes.includes(typeof childValue)
|
|
2338
|
+
? undefined
|
|
2339
|
+
: "Value has no validatable type";
|
|
2340
|
+
});
|
|
2341
|
+
if (async) {
|
|
2342
|
+
validationErrors = Promise.all(errs).then((result) => {
|
|
2343
|
+
const allEmpty = result.every((r) => !r);
|
|
2344
|
+
return allEmpty ? undefined : result;
|
|
2345
|
+
});
|
|
2346
|
+
}
|
|
2347
|
+
else {
|
|
2348
|
+
const allEmpty = errs.every((r) => !r);
|
|
2349
|
+
validationErrors = errs.length > 0 && !allEmpty ? errs : undefined;
|
|
2350
|
+
}
|
|
1420
2351
|
}
|
|
1421
2352
|
}
|
|
1422
|
-
if (
|
|
1423
|
-
result =
|
|
1424
|
-
|
|
2353
|
+
if (validationErrors)
|
|
2354
|
+
result[decorator.key] = validationErrors;
|
|
2355
|
+
}
|
|
2356
|
+
if (!async)
|
|
2357
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
2358
|
+
const keys = Object.keys(result);
|
|
2359
|
+
const promises = Object.values(result);
|
|
2360
|
+
return Promise.all(promises).then((resolvedValues) => {
|
|
2361
|
+
const res = {};
|
|
2362
|
+
for (let i = 0; i < resolvedValues.length; i++) {
|
|
2363
|
+
const val = resolvedValues[i];
|
|
2364
|
+
if (val !== undefined) {
|
|
2365
|
+
res[keys[i]] = val;
|
|
2366
|
+
}
|
|
1425
2367
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
2368
|
+
return Object.keys(res).length > 0 ? res : undefined;
|
|
2369
|
+
});
|
|
2370
|
+
}
|
|
2371
|
+
/**
|
|
2372
|
+
* @description Validates changes between two model versions
|
|
2373
|
+
* @summary Compares an old and new model version to validate update operations
|
|
2374
|
+
* @template M - Type extending Model
|
|
2375
|
+
* @param {M} oldModel - The original model version
|
|
2376
|
+
* @param {M} newModel - The updated model version
|
|
2377
|
+
* @param {boolean} async - A flag indicating whether validation should be asynchronous.
|
|
2378
|
+
* @param {...string[]} exceptions - Properties to exclude from validation
|
|
2379
|
+
* @return {ModelErrorDefinition|undefined} Error definition if validation fails, undefined otherwise
|
|
2380
|
+
* @function validateCompare
|
|
2381
|
+
* @memberOf module:db-decorators
|
|
2382
|
+
* @mermaid
|
|
2383
|
+
* sequenceDiagram
|
|
2384
|
+
* participant Caller
|
|
2385
|
+
* participant validateCompare
|
|
2386
|
+
* participant Reflection
|
|
2387
|
+
* participant Validation
|
|
2388
|
+
*
|
|
2389
|
+
* Caller->>validateCompare: oldModel, newModel, exceptions
|
|
2390
|
+
* validateCompare->>Reflection: get decorated properties
|
|
2391
|
+
* Reflection-->>validateCompare: property decorators
|
|
2392
|
+
* loop For each decorated property
|
|
2393
|
+
* validateCompare->>Validation: get validator
|
|
2394
|
+
* Validation-->>validateCompare: validator
|
|
2395
|
+
* validateCompare->>validateCompare: validate property update
|
|
2396
|
+
* end
|
|
2397
|
+
* loop For nested models
|
|
2398
|
+
* validateCompare->>validateCompare: validate nested models
|
|
2399
|
+
* end
|
|
2400
|
+
* validateCompare-->>Caller: validation errors or undefined
|
|
2401
|
+
*/
|
|
2402
|
+
function validateCompare(oldModel, newModel, async, ...exceptions) {
|
|
2403
|
+
const decoratedProperties = getValidatableUpdateProps(newModel, exceptions);
|
|
2404
|
+
const result = {};
|
|
2405
|
+
const nestedErrors = {};
|
|
2406
|
+
for (const { prop, decorators } of decoratedProperties) {
|
|
2407
|
+
const propKey = String(prop);
|
|
2408
|
+
let propValue = newModel[prop];
|
|
2409
|
+
if (!decorators?.length)
|
|
1438
2410
|
continue;
|
|
1439
|
-
|
|
1440
|
-
const
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
if (
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
default:
|
|
1465
|
-
throw new Error(`Invalid attribute type ${c}`);
|
|
1466
|
-
}
|
|
1467
|
-
err = currentList
|
|
1468
|
-
.map((v) => {
|
|
1469
|
-
const id = findModelId(v, true);
|
|
1470
|
-
if (!id)
|
|
1471
|
-
return "Failed to find model id";
|
|
1472
|
-
const oldModel = oldList.find((el) => id === findModelId(el, true));
|
|
1473
|
-
if (!oldModel)
|
|
1474
|
-
return; // nothing to compare with
|
|
1475
|
-
return v.hasErrors(oldModel);
|
|
1476
|
-
})
|
|
1477
|
-
.filter((e) => !!e);
|
|
1478
|
-
if (!err?.length) {
|
|
1479
|
-
// if the result is an empty list...
|
|
1480
|
-
err = undefined;
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
break;
|
|
1485
|
-
default:
|
|
1486
|
-
try {
|
|
1487
|
-
if (newModel[prop] &&
|
|
1488
|
-
oldModel[prop])
|
|
1489
|
-
err = newModel[prop].hasErrors(oldModel[prop]);
|
|
1490
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1491
|
-
}
|
|
1492
|
-
catch (e) {
|
|
1493
|
-
console.warn(sf("Model should be validatable but its not"));
|
|
1494
|
-
}
|
|
2411
|
+
// Get the default type validator
|
|
2412
|
+
const designTypeDec = decorators.find((d) => [ModelKeys.TYPE, ValidationKeys.TYPE].includes(d.key));
|
|
2413
|
+
if (!designTypeDec)
|
|
2414
|
+
continue;
|
|
2415
|
+
const designType = designTypeDec.props.name;
|
|
2416
|
+
// Handle array or Set types and enforce the presence of @list decorator
|
|
2417
|
+
if ([Array.name, Set.name].includes(designType)) {
|
|
2418
|
+
const { decorators } = Reflection.getPropertyDecorators(ValidationKeys.REFLECT, newModel, propKey);
|
|
2419
|
+
if (!decorators.some((d) => d.key === ValidationKeys.LIST)) {
|
|
2420
|
+
result[propKey] = {
|
|
2421
|
+
[ValidationKeys.TYPE]: `Array or Set property '${propKey}' requires a @list decorator`,
|
|
2422
|
+
};
|
|
2423
|
+
continue;
|
|
2424
|
+
}
|
|
2425
|
+
if (propValue &&
|
|
2426
|
+
!(Array.isArray(propValue) || propValue instanceof Set)) {
|
|
2427
|
+
result[propKey] = {
|
|
2428
|
+
[ValidationKeys.TYPE]: `Property '${String(prop)}' must be either an array or a Set`,
|
|
2429
|
+
};
|
|
2430
|
+
continue;
|
|
2431
|
+
}
|
|
2432
|
+
// Remove design:type decorator, since @list decorator already ensures type
|
|
2433
|
+
for (let i = decorators.length - 1; i >= 0; i--) {
|
|
2434
|
+
if (decorators[i].key === ModelKeys.TYPE) {
|
|
2435
|
+
decorators.splice(i, 1);
|
|
1495
2436
|
}
|
|
1496
2437
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
2438
|
+
propValue = propValue instanceof Set ? [...propValue] : propValue;
|
|
2439
|
+
}
|
|
2440
|
+
const propErrors = validateDecorators(newModel, oldModel, propKey, decorators, async) || {};
|
|
2441
|
+
// Check for nested properties.
|
|
2442
|
+
// To prevent unnecessary processing, "propValue" must be defined and validatable
|
|
2443
|
+
const isConstr = Model.isPropertyModel(newModel, propKey);
|
|
2444
|
+
// if propValue !== undefined, null
|
|
2445
|
+
if (propValue && isConstr) {
|
|
2446
|
+
const instance = propValue;
|
|
2447
|
+
const isInvalidModel = typeof instance !== "object" ||
|
|
2448
|
+
!instance.hasErrors ||
|
|
2449
|
+
typeof instance.hasErrors !== "function";
|
|
2450
|
+
if (isInvalidModel) {
|
|
2451
|
+
// propErrors[ValidationKeys.TYPE] =
|
|
2452
|
+
// "Model should be validatable but it's not.";
|
|
2453
|
+
console.warn("Model should be validatable but it's not.");
|
|
2454
|
+
}
|
|
2455
|
+
else {
|
|
2456
|
+
nestedErrors[propKey] = instance.hasErrors(oldModel[prop]);
|
|
1500
2457
|
}
|
|
1501
2458
|
}
|
|
2459
|
+
// Add to the result if we have any errors
|
|
2460
|
+
// Async mode returns a Promise that resolves to undefined when no errors exist
|
|
2461
|
+
if (Object.keys(propErrors).length > 0 || async)
|
|
2462
|
+
result[propKey] = propErrors;
|
|
2463
|
+
// Then merge any nested errors
|
|
2464
|
+
if (!async) {
|
|
2465
|
+
Object.entries(nestedErrors[propKey] || {}).forEach(([key, error]) => {
|
|
2466
|
+
if (error !== undefined) {
|
|
2467
|
+
result[`${propKey}.${key}`] = error;
|
|
2468
|
+
}
|
|
2469
|
+
});
|
|
2470
|
+
}
|
|
1502
2471
|
}
|
|
1503
|
-
|
|
2472
|
+
// Synchronous return
|
|
2473
|
+
if (!async) {
|
|
2474
|
+
return (Object.keys(result).length > 0
|
|
2475
|
+
? new ModelErrorDefinition(result)
|
|
2476
|
+
: undefined);
|
|
2477
|
+
}
|
|
2478
|
+
const merged = result; // TODO: apply filtering
|
|
2479
|
+
const keys = Object.keys(merged);
|
|
2480
|
+
const promises = Object.values(merged);
|
|
2481
|
+
return Promise.allSettled(promises).then(async (results) => {
|
|
2482
|
+
const result = {};
|
|
2483
|
+
for (const [parentProp, nestedErrPromise] of Object.entries(nestedErrors)) {
|
|
2484
|
+
const nestedPropDecErrors = (await nestedErrPromise);
|
|
2485
|
+
if (nestedPropDecErrors)
|
|
2486
|
+
Object.entries(nestedPropDecErrors).forEach(([nestedProp, nestedPropDecError]) => {
|
|
2487
|
+
if (nestedPropDecError !== undefined) {
|
|
2488
|
+
const nestedKey = [parentProp, nestedProp].join(".");
|
|
2489
|
+
result[nestedKey] = nestedPropDecError;
|
|
2490
|
+
}
|
|
2491
|
+
});
|
|
2492
|
+
}
|
|
2493
|
+
for (let i = 0; i < results.length; i++) {
|
|
2494
|
+
const key = keys[i];
|
|
2495
|
+
const res = results[i];
|
|
2496
|
+
if (res.status === "fulfilled" && res.value !== undefined) {
|
|
2497
|
+
result[key] = res.value;
|
|
2498
|
+
}
|
|
2499
|
+
else if (res.status === "rejected") {
|
|
2500
|
+
result[key] =
|
|
2501
|
+
res.reason instanceof Error
|
|
2502
|
+
? res.reason.message
|
|
2503
|
+
: String(res.reason || "Validation failed");
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
return Object.keys(result).length > 0
|
|
2507
|
+
? new ModelErrorDefinition(result)
|
|
2508
|
+
: undefined;
|
|
2509
|
+
});
|
|
1504
2510
|
}
|
|
1505
2511
|
|
|
1506
2512
|
/**
|
|
1507
|
-
*
|
|
1508
|
-
* @
|
|
1509
|
-
* @
|
|
2513
|
+
* @description Hashes a property value during create or update operations
|
|
2514
|
+
* @summary Callback function used by the hash decorator to apply hashing to a property value
|
|
2515
|
+
* @template M - Type extending Model
|
|
2516
|
+
* @template R - Type extending IRepository
|
|
2517
|
+
* @template V - Type for metadata
|
|
2518
|
+
* @template F - Type extending RepositoryFlags
|
|
2519
|
+
* @template C - Type extending Context
|
|
2520
|
+
* @param {C} context - The operation context
|
|
2521
|
+
* @param {V} data - Metadata for the operation
|
|
2522
|
+
* @param key - The property key to hash
|
|
2523
|
+
* @param {M} model - The model being processed
|
|
2524
|
+
* @param {M} [oldModel] - The previous model state (for updates)
|
|
2525
|
+
* @return {void}
|
|
2526
|
+
* @function hashOnCreateUpdate
|
|
2527
|
+
* @memberOf module:db-decorators
|
|
1510
2528
|
*/
|
|
1511
2529
|
function hashOnCreateUpdate(context, data, key, model, oldModel) {
|
|
1512
2530
|
if (typeof model[key] === "undefined")
|
|
@@ -1516,9 +2534,32 @@ function hashOnCreateUpdate(context, data, key, model, oldModel) {
|
|
|
1516
2534
|
return;
|
|
1517
2535
|
model[key] = hash;
|
|
1518
2536
|
}
|
|
2537
|
+
/**
|
|
2538
|
+
* @description Creates a decorator that hashes a property value
|
|
2539
|
+
* @summary Decorator that automatically hashes a property value during create and update operations
|
|
2540
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2541
|
+
* @function hash
|
|
2542
|
+
* @category Property Decorators
|
|
2543
|
+
*/
|
|
1519
2544
|
function hash() {
|
|
1520
2545
|
return apply(onCreateUpdate(hashOnCreateUpdate), propMetadata(Repository.key(DBKeys.HASH), {}));
|
|
1521
2546
|
}
|
|
2547
|
+
/**
|
|
2548
|
+
* @description Composes a property value from other properties during create or update operations
|
|
2549
|
+
* @summary Callback function used by composed decorators to generate a property value from other properties
|
|
2550
|
+
* @template M - Type extending Model
|
|
2551
|
+
* @template R - Type extending IRepository
|
|
2552
|
+
* @template V - Type extending ComposedFromMetadata
|
|
2553
|
+
* @template F - Type extending RepositoryFlags
|
|
2554
|
+
* @template C - Type extending Context
|
|
2555
|
+
* @param {C} context - The operation context
|
|
2556
|
+
* @param {V} data - Metadata for the composition
|
|
2557
|
+
* @param key - The property key to set the composed value on
|
|
2558
|
+
* @param {M} model - The model being processed
|
|
2559
|
+
* @return {void}
|
|
2560
|
+
* @function composedFromCreateUpdate
|
|
2561
|
+
* @memberOf module:db-decorators
|
|
2562
|
+
*/
|
|
1522
2563
|
function composedFromCreateUpdate(context, data, key, model) {
|
|
1523
2564
|
try {
|
|
1524
2565
|
const { args, type, prefix, suffix, separator } = data;
|
|
@@ -1541,6 +2582,19 @@ function composedFromCreateUpdate(context, data, key, model) {
|
|
|
1541
2582
|
throw new InternalError(`Failed to compose value: ${e}`);
|
|
1542
2583
|
}
|
|
1543
2584
|
}
|
|
2585
|
+
/**
|
|
2586
|
+
* @description Creates a decorator that composes a property value from other properties
|
|
2587
|
+
* @summary Base function for creating property composition decorators
|
|
2588
|
+
* @param {string[]} args - Property names to compose from
|
|
2589
|
+
* @param {boolean} [hashResult=false] - Whether to hash the composed result
|
|
2590
|
+
* @param {string} [separator=DefaultSeparator] - Character used to join the composed values
|
|
2591
|
+
* @param {"keys"|"values"} [type="values"] - Whether to use property keys or values
|
|
2592
|
+
* @param {string} [prefix=""] - Optional prefix to add to the composed value
|
|
2593
|
+
* @param {string} [suffix=""] - Optional suffix to add to the composed value
|
|
2594
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2595
|
+
* @function composedFrom
|
|
2596
|
+
* @category PropertyDecorators
|
|
2597
|
+
*/
|
|
1544
2598
|
function composedFrom(args, hashResult = false, separator = DefaultSeparator, type = "values", prefix = "", suffix = "") {
|
|
1545
2599
|
const data = {
|
|
1546
2600
|
args: args,
|
|
@@ -1558,27 +2612,65 @@ function composedFrom(args, hashResult = false, separator = DefaultSeparator, ty
|
|
|
1558
2612
|
decorators.push(hash());
|
|
1559
2613
|
return apply(...decorators);
|
|
1560
2614
|
}
|
|
2615
|
+
/**
|
|
2616
|
+
* @description Creates a decorator that composes a property value from property keys
|
|
2617
|
+
* @summary Decorator that generates a property value by joining the names of other properties
|
|
2618
|
+
* @param {string[]} args - Property names to compose from
|
|
2619
|
+
* @param {string} [separator=DefaultSeparator] - Character used to join the property names
|
|
2620
|
+
* @param {boolean} [hash=false] - Whether to hash the composed result
|
|
2621
|
+
* @param {string} [prefix=""] - Optional prefix to add to the composed value
|
|
2622
|
+
* @param {string} [suffix=""] - Optional suffix to add to the composed value
|
|
2623
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2624
|
+
* @function composedFromKeys
|
|
2625
|
+
* @category PropertyDecorators
|
|
2626
|
+
*/
|
|
1561
2627
|
function composedFromKeys(args, separator = DefaultSeparator, hash = false, prefix = "", suffix = "") {
|
|
1562
2628
|
return composedFrom(args, hash, separator, "keys", prefix, suffix);
|
|
1563
2629
|
}
|
|
2630
|
+
/**
|
|
2631
|
+
* @description Creates a decorator that composes a property value from property values
|
|
2632
|
+
* @summary Decorator that generates a property value by joining the values of other properties
|
|
2633
|
+
* @param {string[]} args - Property names whose values will be composed
|
|
2634
|
+
* @param {string} [separator=DefaultSeparator] - Character used to join the property values
|
|
2635
|
+
* @param {boolean} [hash=false] - Whether to hash the composed result
|
|
2636
|
+
* @param {string} [prefix=""] - Optional prefix to add to the composed value
|
|
2637
|
+
* @param {string} [suffix=""] - Optional suffix to add to the composed value
|
|
2638
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2639
|
+
* @function composed
|
|
2640
|
+
* @category PropertyDecorators
|
|
2641
|
+
*/
|
|
1564
2642
|
function composed(args, separator = DefaultSeparator, hash = false, prefix = "", suffix = "") {
|
|
1565
2643
|
return composedFrom(args, hash, separator, "values", prefix, suffix);
|
|
1566
2644
|
}
|
|
1567
2645
|
/**
|
|
1568
|
-
* Creates a
|
|
1569
|
-
*
|
|
1570
|
-
* @param {CrudOperations} operation - The type of operation
|
|
1571
|
-
* @
|
|
1572
|
-
*
|
|
2646
|
+
* @description Creates a function that updates a version property during operations
|
|
2647
|
+
* @summary Factory function that generates a callback for incrementing version numbers
|
|
2648
|
+
* @param {CrudOperations} operation - The type of operation (CREATE or UPDATE)
|
|
2649
|
+
* @return {Function} A callback function that updates the version property
|
|
1573
2650
|
* @template M - Type extending Model
|
|
1574
|
-
* @template
|
|
1575
|
-
*
|
|
1576
|
-
* @
|
|
1577
|
-
* @
|
|
1578
|
-
* @
|
|
1579
|
-
* @
|
|
1580
|
-
* @
|
|
1581
|
-
*
|
|
2651
|
+
* @template R - Type extending IRepository
|
|
2652
|
+
* @template V - Type for metadata
|
|
2653
|
+
* @template F - Type extending RepositoryFlags
|
|
2654
|
+
* @template C - Type extending Context
|
|
2655
|
+
* @function versionCreateUpdate
|
|
2656
|
+
* @memberOf module:db-decorators
|
|
2657
|
+
* @mermaid
|
|
2658
|
+
* sequenceDiagram
|
|
2659
|
+
* participant Caller
|
|
2660
|
+
* participant versionCreateUpdate
|
|
2661
|
+
*
|
|
2662
|
+
* Caller->>versionCreateUpdate: operation
|
|
2663
|
+
* versionCreateUpdate-->>Caller: callback function
|
|
2664
|
+
* Note over Caller,versionCreateUpdate: When callback is executed:
|
|
2665
|
+
* Caller->>versionCreateUpdate: context, data, key, model
|
|
2666
|
+
* alt operation is CREATE
|
|
2667
|
+
* versionCreateUpdate->>versionCreateUpdate: set version to 1
|
|
2668
|
+
* else operation is UPDATE
|
|
2669
|
+
* versionCreateUpdate->>versionCreateUpdate: increment version
|
|
2670
|
+
* else invalid operation
|
|
2671
|
+
* versionCreateUpdate->>versionCreateUpdate: throw error
|
|
2672
|
+
* end
|
|
2673
|
+
* versionCreateUpdate-->>Caller: void
|
|
1582
2674
|
*/
|
|
1583
2675
|
function versionCreateUpdate(operation) {
|
|
1584
2676
|
return function versionCreateUpdate(context, data, key, model) {
|
|
@@ -1600,18 +2692,22 @@ function versionCreateUpdate(operation) {
|
|
|
1600
2692
|
};
|
|
1601
2693
|
}
|
|
1602
2694
|
/**
|
|
1603
|
-
* @description Creates a decorator for versioning a property in a model
|
|
1604
|
-
* @summary This decorator applies multiple sub-decorators to handle version management during create and update operations
|
|
1605
|
-
*
|
|
1606
|
-
* @
|
|
1607
|
-
*
|
|
1608
|
-
* - Applies a version update on create operations
|
|
1609
|
-
* - Applies a version update on update operations
|
|
1610
|
-
* - Adds metadata indicating this property is used for versioning
|
|
2695
|
+
* @description Creates a decorator for versioning a property in a model
|
|
2696
|
+
* @summary This decorator applies multiple sub-decorators to handle version management during create and update operations
|
|
2697
|
+
* @return {PropertyDecorator} A composite decorator that sets the type to Number, manages version updates, and adds versioning metadata
|
|
2698
|
+
* @function version
|
|
2699
|
+
* @category PropertyDecorators
|
|
1611
2700
|
*/
|
|
1612
2701
|
function version() {
|
|
1613
2702
|
return apply(type(Number.name), onCreate(versionCreateUpdate(OperationKeys.CREATE)), onUpdate(versionCreateUpdate(OperationKeys.UPDATE)), propMetadata(Repository.key(DBKeys.VERSION), true));
|
|
1614
2703
|
}
|
|
2704
|
+
/**
|
|
2705
|
+
* @description Creates a decorator that marks a property as transient
|
|
2706
|
+
* @summary Decorator that indicates a property should not be persisted to the database
|
|
2707
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2708
|
+
* @function transient
|
|
2709
|
+
* @category PropertyDecorators
|
|
2710
|
+
*/
|
|
1615
2711
|
function transient() {
|
|
1616
2712
|
return function transient(model, attribute) {
|
|
1617
2713
|
propMetadata(Repository.key(DBKeys.TRANSIENT), true)(model, attribute);
|
|
@@ -1619,21 +2715,81 @@ function transient() {
|
|
|
1619
2715
|
};
|
|
1620
2716
|
}
|
|
1621
2717
|
|
|
2718
|
+
/**
|
|
2719
|
+
* @description Validates the model and checks for errors
|
|
2720
|
+
* @summary Validates the current model state and optionally compares with a previous version
|
|
2721
|
+
* @template M - Type extending Model
|
|
2722
|
+
* @param {M|any} [previousVersion] - Optional previous version of the model for comparison
|
|
2723
|
+
* @param {...any[]} exclusions - Properties to exclude from validation
|
|
2724
|
+
* @return {ModelErrorDefinition|undefined} Error definition if validation fails, undefined otherwise
|
|
2725
|
+
* @function hasErrors
|
|
2726
|
+
* @memberOf module:db-decorators
|
|
2727
|
+
*/
|
|
2728
|
+
// @ts-expect-error Overriding Model prototype method with dynamic conditional return type.
|
|
1622
2729
|
Model.prototype.hasErrors = function (previousVersion, ...exclusions) {
|
|
1623
2730
|
if (previousVersion && !(previousVersion instanceof Model)) {
|
|
1624
2731
|
exclusions.unshift(previousVersion);
|
|
1625
2732
|
previousVersion = undefined;
|
|
1626
2733
|
}
|
|
1627
|
-
const
|
|
2734
|
+
const async = this.isAsync();
|
|
2735
|
+
const errs = validate(this, async, ...exclusions);
|
|
2736
|
+
if (async) {
|
|
2737
|
+
return Promise.resolve(errs).then((resolvedErrs) => {
|
|
2738
|
+
if (resolvedErrs || !previousVersion) {
|
|
2739
|
+
return resolvedErrs;
|
|
2740
|
+
}
|
|
2741
|
+
return validateCompare(previousVersion, this, async, ...exclusions);
|
|
2742
|
+
});
|
|
2743
|
+
}
|
|
1628
2744
|
if (errs || !previousVersion)
|
|
1629
2745
|
return errs;
|
|
1630
|
-
|
|
2746
|
+
// @ts-expect-error Overriding Model prototype method with dynamic conditional return type.
|
|
2747
|
+
return validateCompare(previousVersion, this, async, ...exclusions);
|
|
1631
2748
|
};
|
|
1632
2749
|
|
|
2750
|
+
/**
|
|
2751
|
+
* @description Checks if a model is marked as transient
|
|
2752
|
+
* @summary Determines whether a model class has been decorated with the transient decorator
|
|
2753
|
+
* @template M - Type extending Model
|
|
2754
|
+
* @param {M} model - The model instance to check
|
|
2755
|
+
* @return {boolean} True if the model is transient, false otherwise
|
|
2756
|
+
* @function isTransient
|
|
2757
|
+
* @memberOf module:db-decorators
|
|
2758
|
+
*/
|
|
1633
2759
|
function isTransient(model) {
|
|
1634
2760
|
return !!(Reflect.getMetadata(Repository.key(DBKeys.TRANSIENT), model.constructor) ||
|
|
1635
2761
|
Reflect.getMetadata(Repository.key(DBKeys.TRANSIENT), Model.get(model.constructor.name)));
|
|
1636
2762
|
}
|
|
2763
|
+
/**
|
|
2764
|
+
* @description Separates transient properties from a model
|
|
2765
|
+
* @summary Extracts properties marked as transient into a separate object
|
|
2766
|
+
* @template M - Type extending Model
|
|
2767
|
+
* @param {M} model - The model instance to process
|
|
2768
|
+
* @return {Object} Object containing the model without transient properties and a separate transient object
|
|
2769
|
+
* @property {M} model - The model with transient properties removed
|
|
2770
|
+
* @property {Record<string, any>} [transient] - Object containing the transient properties
|
|
2771
|
+
* @function modelToTransient
|
|
2772
|
+
* @memberOf module:db-decorators
|
|
2773
|
+
* @mermaid
|
|
2774
|
+
* sequenceDiagram
|
|
2775
|
+
* participant Caller
|
|
2776
|
+
* participant modelToTransient
|
|
2777
|
+
* participant isTransient
|
|
2778
|
+
* participant getAllPropertyDecoratorsRecursive
|
|
2779
|
+
*
|
|
2780
|
+
* Caller->>modelToTransient: model
|
|
2781
|
+
* modelToTransient->>isTransient: check if model is transient
|
|
2782
|
+
* isTransient-->>modelToTransient: transient status
|
|
2783
|
+
* alt model is not transient
|
|
2784
|
+
* modelToTransient-->>Caller: {model}
|
|
2785
|
+
* else model is transient
|
|
2786
|
+
* modelToTransient->>getAllPropertyDecoratorsRecursive: get transient properties
|
|
2787
|
+
* getAllPropertyDecoratorsRecursive-->>modelToTransient: property decorators
|
|
2788
|
+
* modelToTransient->>modelToTransient: separate properties
|
|
2789
|
+
* modelToTransient->>Model.build: rebuild model without transient props
|
|
2790
|
+
* modelToTransient-->>Caller: {model, transient}
|
|
2791
|
+
* end
|
|
2792
|
+
*/
|
|
1637
2793
|
function modelToTransient(model) {
|
|
1638
2794
|
if (!isTransient(model))
|
|
1639
2795
|
return { model: model };
|
|
@@ -1659,5 +2815,18 @@ function modelToTransient(model) {
|
|
|
1659
2815
|
return result;
|
|
1660
2816
|
}
|
|
1661
2817
|
|
|
1662
|
-
|
|
1663
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGItZGVjb3JhdG9ycy5lc20uY2pzIiwic291cmNlcyI6WyIuLi9zcmMvbW9kZWwvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vY29uc3RhbnRzLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vdmFsaWRhdG9ycy9SZWFkT25seVZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL3ZhbGlkYXRvcnMvVGltZXN0YW1wVmFsaWRhdG9yLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vdmFsaWRhdG9ycy9VcGRhdGVWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi92YWxpZGF0aW9uLnRzIiwiLi4vc3JjL29wZXJhdGlvbnMvY29uc3RhbnRzLnRzIiwiLi4vc3JjL29wZXJhdGlvbnMvT3BlcmF0aW9uc1JlZ2lzdHJ5LnRzIiwiLi4vc3JjL29wZXJhdGlvbnMvT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9vcGVyYXRpb25zL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvcmVwb3NpdG9yeS9lcnJvcnMudHMiLCIuLi9zcmMvcmVwb3NpdG9yeS91dGlscy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L2NvbnN0YW50cy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L0NvbnRleHQudHMiLCIuLi9zcmMvcmVwb3NpdG9yeS93cmFwcGVycy50cyIsIi4uL3NyYy9pZGVudGl0eS91dGlscy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L0Jhc2VSZXBvc2l0b3J5LnRzIiwiLi4vc3JjL3JlcG9zaXRvcnkvUmVwb3NpdG9yeS50cyIsIi4uL3NyYy92YWxpZGF0aW9uL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvaWRlbnRpdHkvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9tb2RlbC92YWxpZGF0aW9uLnRzIiwiLi4vc3JjL21vZGVsL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvbW9kZWwvbW9kZWwudHMiLCIuLi9zcmMvbW9kZWwvdXRpbHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTW9kZWxLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IEhvbGRzIHRoZSBNb2RlbCByZWZsZWN0aW9uIGtleXNcbiAqIEBjb25zdCBEQktleXNcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuTW9kZWxcbiAqL1xuZXhwb3J0IGNvbnN0IERCS2V5cyA9IHtcbiAgUkVGTEVDVDogYCR7TW9kZWxLZXlzLlJFRkxFQ1R9cGVyc2lzdGVuY2UuYCxcbiAgUkVQT1NJVE9SWTogXCJyZXBvc2l0b3J5XCIsXG4gIENMQVNTOiBcIl9jbGFzc1wiLFxuICBJRDogXCJpZFwiLFxuICBJTkRFWDogXCJpbmRleFwiLFxuICBVTklRVUU6IFwidW5pcXVlXCIsXG4gIFNFUklBTElaRTogXCJzZXJpYWxpemVcIixcbiAgUkVBRE9OTFk6IFwicmVhZG9ubHlcIixcbiAgVElNRVNUQU1QOiBcInRpbWVzdGFtcFwiLFxuICBUUkFOU0lFTlQ6IFwidHJhbnNpZW50XCIsXG4gIEhBU0g6IFwiaGFzaFwiLFxuICBDT01QT1NFRDogXCJjb21wb3NlZFwiLFxuICBWRVJTSU9OOiBcInZlcnNpb25cIixcbiAgT1JJR0lOQUw6IFwiX19vcmlnaW5hbE9ialwiLFxufTtcblxuLyoqXG4gKiBAc3VtbWFyeSBUaGUgZGVmYXVsdCBzZXBhcmF0b3Igd2hlbiBjb25jYXRlbmF0aW5nIGluZGV4ZXNcbiAqXG4gKiBAY29uc3QgRGVmYXVsdEluZGV4U2VwYXJhdG9yXG4gKlxuICogQGNhdGVnb3J5IE1hbmFnZXJzXG4gKiBAc3ViY2F0ZWdvcnkgQ29uc3RhbnRzXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0U2VwYXJhdG9yID0gXCJfXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgSG9sZHMgdGhlIGRlZmF1bHQgdGltZXN0YW1wIGRhdGUgZm9ybWF0XG4gKiBAY29uc3RhbnQgREVGQVVMVF9USU1FU1RBTVBfRk9STUFUXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLk1vZGVsXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX1RJTUVTVEFNUF9GT1JNQVQgPSBcImRkL01NL3l5eXkgSEg6bW06c3M6U1wiO1xuIiwiaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIi4uL21vZGVsL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IGhvbGRzIHRoZSBkZWZhdWx0IGVycm9yIG1lc3NhZ2VzXG4gKiBAY29uc3QgREVGQVVMVF9FUlJPUl9NRVNTQUdFU1xuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5Nb2RlbFxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyA9IHtcbiAgSUQ6IHtcbiAgICBJTlZBTElEOiBcIlRoaXMgSWQgaXMgaW52YWxpZFwiLFxuICAgIFJFUVVJUkVEOiBcIlRoZSBJZCBpcyBtYW5kYXRvcnlcIixcbiAgfSxcbiAgUkVBRE9OTFk6IHtcbiAgICBJTlZBTElEOiBcIlRoaXMgY2Fubm90IGJlIHVwZGF0ZWRcIixcbiAgfSxcbiAgVElNRVNUQU1QOiB7XG4gICAgUkVRVUlSRUQ6IFwiVGltZXN0YW1wIGlzIE1hbmRhdG9yeVwiLFxuICAgIERBVEU6IFwiVGhlIFRpbWVzdGFtcCBtdXN0IHRoZSBhIHZhbGlkIGRhdGVcIixcbiAgICBJTlZBTElEOiBcIlRoaXMgdmFsdWUgbXVzdCBhbHdheXMgaW5jcmVhc2VcIixcbiAgfSxcbn07XG5cbi8qKlxuICogQHN1bW1hcnkgVXBkYXRlIHJlZmxlY3Rpb24ga2V5c1xuICogQGNvbnN0IFVwZGF0ZVZhbGlkYXRpb25LZXlzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuT3BlcmF0aW9uc1xuICovXG5leHBvcnQgY29uc3QgVXBkYXRlVmFsaWRhdGlvbktleXMgPSB7XG4gIFJFRkxFQ1Q6IFwiZGIudXBkYXRlLnZhbGlkYXRpb24uXCIsXG4gIFRJTUVTVEFNUDogREJLZXlzLlRJTUVTVEFNUCxcbiAgUkVBRE9OTFk6IERCS2V5cy5SRUFET05MWSxcbn07XG4iLCJpbXBvcnQgeyB2YWxpZGF0b3IsIFZhbGlkYXRvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMsIFVwZGF0ZVZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgaXNFcXVhbCB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFZhbGlkYXRvciBmb3IgdGhlIHtAbGluayByZWFkb25seX0gZGVjb3JhdG9yXG4gKlxuICogQGNsYXNzIFJlYWRPbmx5VmFsaWRhdG9yXG4gKiBAZXh0ZW5kcyBWYWxpZGF0b3JcbiAqXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdG9yc1xuICovXG5AdmFsaWRhdG9yKFVwZGF0ZVZhbGlkYXRpb25LZXlzLlJFQURPTkxZKVxuZXhwb3J0IGNsYXNzIFJlYWRPbmx5VmFsaWRhdG9yIGV4dGVuZHMgVmFsaWRhdG9yIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5SRUFET05MWS5JTlZBTElEKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaW5oZXJpdERvY1xuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBoYXNFcnJvcnModmFsdWU6IGFueSwgLi4uYXJnczogYW55W10pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIGEgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkXG4gICAqIEBwYXJhbSB7YW55fSB2YWx1ZVxuICAgKiBAcGFyYW0ge2FueX0gb2xkVmFsdWVcbiAgICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSB0aGUgZXJyb3IgbWVzc2FnZSBvdmVycmlkZVxuICAgKi9cbiAgcHVibGljIHVwZGF0ZUhhc0Vycm9ycyhcbiAgICB2YWx1ZTogYW55LFxuICAgIG9sZFZhbHVlOiBhbnksXG4gICAgbWVzc2FnZT86IHN0cmluZyxcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgcmV0dXJuIGlzRXF1YWwodmFsdWUsIG9sZFZhbHVlKVxuICAgICAgPyB1bmRlZmluZWRcbiAgICAgIDogdGhpcy5nZXRNZXNzYWdlKG1lc3NhZ2UgfHwgdGhpcy5tZXNzYWdlKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgdmFsaWRhdG9yLCBWYWxpZGF0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBERUZBVUxUX0VSUk9SX01FU1NBR0VTLCBVcGRhdGVWYWxpZGF0aW9uS2V5cyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBWYWxpZGF0ZXMgdGhlIHVwZGF0ZSBvZiBhIHRpbWVzdGFtcFxuICpcbiAqIEBjbGFzcyBUaW1lc3RhbXBWYWxpZGF0b3JcbiAqIEBleHRlbmRzIFZhbGlkYXRvclxuICpcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbkB2YWxpZGF0b3IoVXBkYXRlVmFsaWRhdGlvbktleXMuVElNRVNUQU1QKVxuZXhwb3J0IGNsYXNzIFRpbWVzdGFtcFZhbGlkYXRvciBleHRlbmRzIFZhbGlkYXRvciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKERFRkFVTFRfRVJST1JfTUVTU0FHRVMuVElNRVNUQU1QLklOVkFMSUQpO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBoYXNFcnJvcnModmFsdWU6IGFueSwgLi4uYXJnczogYW55W10pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBwdWJsaWMgdXBkYXRlSGFzRXJyb3JzKFxuICAgIHZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVtYmVyLFxuICAgIG9sZFZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1lc3NhZ2U/OiBzdHJpbmdcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgbWVzc2FnZSA9IG1lc3NhZ2UgfHwgdGhpcy5nZXRNZXNzYWdlKG1lc3NhZ2UgfHwgdGhpcy5tZXNzYWdlKTtcblxuICAgIHRyeSB7XG4gICAgICB2YWx1ZSA9IG5ldyBEYXRlKHZhbHVlKTtcbiAgICAgIG9sZFZhbHVlID0gbmV3IERhdGUob2xkVmFsdWUpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZSA8PSBvbGRWYWx1ZSA/IG1lc3NhZ2UgOiB1bmRlZmluZWQ7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIERFRkFVTFRfRVJST1JfTUVTU0FHRVMgYXMgRGVjb3JhdG9yTWVzc2FnZXMsXG4gIFZhbGlkYXRvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IEJhc2UgY2xhc3MgZm9yIGFuIFVwZGF0ZSB2YWxpZGF0b3JcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIGVycm9yIG1lc3NhZ2UuIGRlZmF1bHRzIHRvIHtAbGluayBEZWNvcmF0b3JNZXNzYWdlcyNERUZBVUxUfVxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2FjY2VwdGVkVHlwZXNdIHRoZSBhY2NlcHRlZCB2YWx1ZSB0eXBlcyBieSB0aGUgZGVjb3JhdG9yXG4gKlxuICogQGNsYXNzIFVwZGF0ZVZhbGlkYXRvclxuICogQGFic3RyYWN0XG4gKiBAZXh0ZW5kcyBWYWxpZGF0b3JcbiAqXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdG9yc1xuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVXBkYXRlVmFsaWRhdG9yIGV4dGVuZHMgVmFsaWRhdG9yIHtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyA9IERlY29yYXRvck1lc3NhZ2VzLkRFRkFVTFQsXG4gICAgLi4uYWNjZXB0ZWRUeXBlczogc3RyaW5nW11cbiAgKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgLi4uYWNjZXB0ZWRUeXBlcyk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgdmFsaWRhdGVzIGEgdmFsdWUgYnkgY29tcGFyaW5nIHRvIGl0cyBvbGQgdmVyc2lvblxuICAgKiBAcGFyYW0ge2FueX0gdmFsdWVcbiAgICogQHBhcmFtIHthbnl9IG9sZFZhbHVlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3NcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCB1cGRhdGVIYXNFcnJvcnMoXG4gICAgdmFsdWU6IGFueSxcbiAgICBvbGRWYWx1ZTogYW55LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZDtcbn1cbiIsImltcG9ydCB7XG4gIFZhbGlkYXRvcixcbiAgVmFsaWRhdGlvbixcbiAgVmFsaWRhdG9yRGVmaW5pdGlvbixcbiAgSVZhbGlkYXRvclJlZ2lzdHJ5LFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBVcGRhdGVWYWxpZGF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG5WYWxpZGF0aW9uLnVwZGF0ZUtleSA9IGZ1bmN0aW9uIChrZXk6IHN0cmluZykge1xuICByZXR1cm4gVXBkYXRlVmFsaWRhdGlvbktleXMuUkVGTEVDVCArIGtleTtcbn07XG5cbmRlY2xhcmUgbW9kdWxlIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCIge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgZGVjbGFyZSBjbGFzcyBWYWxpZGF0aW9uIHtcbiAgICBwcml2YXRlIHN0YXRpYyBhY3RpbmdWYWxpZGF0b3JSZWdpc3RyeT87XG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpO1xuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIGFjdGluZyBWYWxpZGF0b3JSZWdpc3RyeVxuICAgICAqXG4gICAgICogQHBhcmFtIHtJVmFsaWRhdG9yUmVnaXN0cnl9IHZhbGlkYXRvclJlZ2lzdHJ5IHRoZSBuZXcgaW1wbGVtZW50YXRpb24gb2YgdGhlIHZhbGlkYXRvciBSZWdpc3RyeVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb24oVmFsaWRhdG9yKTogVmFsaWRhdG9yfSBbbWlncmF0aW9uSGFuZGxlcl0gdGhlIG1ldGhvZCB0byBtYXAgdGhlIHZhbGlkYXRvciBpZiByZXF1aXJlZDtcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0UmVnaXN0cnkoXG4gICAgICB2YWxpZGF0b3JSZWdpc3RyeTogSVZhbGlkYXRvclJlZ2lzdHJ5PFZhbGlkYXRvcj4sXG4gICAgICBtaWdyYXRpb25IYW5kbGVyPzogKHZhbGlkYXRvcjogVmFsaWRhdG9yKSA9PiBWYWxpZGF0b3JcbiAgICApOiB2b2lkO1xuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIGN1cnJlbnQgVmFsaWRhdG9yUmVnaXN0cnlcbiAgICAgKlxuICAgICAqIEByZXR1cm4gSVZhbGlkYXRvclJlZ2lzdHJ5LCBkZWZhdWx0cyB0byB7QGxpbmsgVmFsaWRhdG9yUmVnaXN0cnl9XG4gICAgICovXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0UmVnaXN0cnk7XG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgUmV0cmlldmVzIGEgdmFsaWRhdG9yXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsaWRhdG9yS2V5IG9uZSBvZiB0aGUge0BsaW5rIFZhbGlkYXRpb25LZXlzfVxuICAgICAqIEByZXR1cm4ge1ZhbGlkYXRvciB8IHVuZGVmaW5lZH0gdGhlIHJlZ2lzdGVyZWQgVmFsaWRhdG9yIG9yIHVuZGVmaW5lZCBpZiB0aGVyZSBpcyBub25vIG1hdGNoaW5nIHRoZSBwcm92aWRlZCBrZXlcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0PFQgZXh0ZW5kcyBWYWxpZGF0b3I+KHZhbGlkYXRvcktleTogc3RyaW5nKTogVCB8IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBSZWdpc3RlcnMgdGhlIHByb3ZpZGVkIHZhbGlkYXRvcnMgb250byB0aGUgcmVnaXN0cnlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7VFtdIHwgVmFsaWRhdG9yRGVmaW5pdGlvbltdfSB2YWxpZGF0b3JcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVnaXN0ZXI8VCBleHRlbmRzIFZhbGlkYXRvcj4oXG4gICAgICAuLi52YWxpZGF0b3I6IChWYWxpZGF0b3JEZWZpbml0aW9uIHwgVClbXVxuICAgICk6IHZvaWQ7XG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgQnVpbGRzIHRoZSBrZXkgdG8gc3RvcmUgYXMgTWV0YWRhdGEgdW5kZXIgUmVmbGVjdGlvbnNcbiAgICAgKiBAZGVzY3JpcHRpb24gY29uY2F0ZW5hdGVzIHtAbGluayBWYWxpZGF0aW9uS2V5cyNSRUZMRUNUfSB3aXRoIHRoZSBwcm92aWRlZCBrZXlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAgICAgKi9cbiAgICBzdGF0aWMga2V5KGtleTogc3RyaW5nKTogc3RyaW5nO1xuXG4gICAgc3RhdGljIHVwZGF0ZUtleShrZXk6IHN0cmluZyk6IHN0cmluZztcbiAgfVxufVxuIiwiLyoqXG4gKiBAc3VtbWFyeSBTZXQgb2YgY29uc3RhbnRzIHRvIGRlZmluZSBkYiBDUlVEIG9wZXJhdGlvbnMgYW5kIHRoZWlyIGVxdWl2YWxlbnQgJ29uJyBhbmQgJ2FmdGVyJyBwaGFzZXNcbiAqIEBjb25zdCBPcGVyYXRpb25LZXlzXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLk9wZXJhdGlvbnNcbiAqL1xuZXhwb3J0IGVudW0gT3BlcmF0aW9uS2V5cyB7XG4gIFJFRkxFQ1QgPSBcImRlY2FmLm1vZGVsLmRiLm9wZXJhdGlvbnMuXCIsXG4gIENSRUFURSA9IFwiY3JlYXRlXCIsXG4gIFJFQUQgPSBcInJlYWRcIixcbiAgVVBEQVRFID0gXCJ1cGRhdGVcIixcbiAgREVMRVRFID0gXCJkZWxldGVcIixcbiAgT04gPSBcIm9uLlwiLFxuICBBRlRFUiA9IFwiYWZ0ZXIuXCIsXG59XG5cbmV4cG9ydCB0eXBlIENydWRPcGVyYXRpb25zID1cbiAgfCBPcGVyYXRpb25LZXlzLkNSRUFURVxuICB8IE9wZXJhdGlvbktleXMuUkVBRFxuICB8IE9wZXJhdGlvbktleXMuVVBEQVRFXG4gIHwgT3BlcmF0aW9uS2V5cy5ERUxFVEU7XG5cbmV4cG9ydCBlbnVtIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB7XG4gIENSRUFURV9BTEwgPSBcImNyZWF0ZUFsbFwiLFxuICBSRUFEX0FMTCA9IFwicmVhZEFsbFwiLFxuICBVUERBVEVfQUxMID0gXCJ1cGRhdGVBbGxcIixcbiAgREVMRVRFX0FMTCA9IFwiZGVsZXRlQWxsXCIsXG59XG5cbmV4cG9ydCB0eXBlIEJ1bGtDcnVkT3BlcmF0aW9ucyA9XG4gIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzLkNSRUFURV9BTExcbiAgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuUkVBRF9BTExcbiAgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuVVBEQVRFX0FMTFxuICB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5ERUxFVEVfQUxMO1xuXG4vKipcbiAqIEBzdW1tYXJ5IE1hcHMgb3V0IGdyb3VwcyBvZiBDUlVEIG9wZXJhdGlvbnMgZm9yIGVhc2llciBtYXBwaW5nIG9mIGRlY29yYXRvcnNcbiAqXG4gKiBAY29uc3RhbnQgREJPcGVyYXRpb25zXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLk9wZXJhdGlvbnNcbiAqL1xuZXhwb3J0IGNvbnN0IERCT3BlcmF0aW9uczogUmVjb3JkPHN0cmluZywgQ3J1ZE9wZXJhdGlvbnNbXT4gPSB7XG4gIENSRUFURTogW09wZXJhdGlvbktleXMuQ1JFQVRFXSxcbiAgUkVBRDogW09wZXJhdGlvbktleXMuUkVBRF0sXG4gIFVQREFURTogW09wZXJhdGlvbktleXMuVVBEQVRFXSxcbiAgREVMRVRFOiBbT3BlcmF0aW9uS2V5cy5ERUxFVEVdLFxuICBDUkVBVEVfVVBEQVRFOiBbT3BlcmF0aW9uS2V5cy5DUkVBVEUsIE9wZXJhdGlvbktleXMuVVBEQVRFXSxcbiAgUkVBRF9DUkVBVEU6IFtPcGVyYXRpb25LZXlzLlJFQUQsIE9wZXJhdGlvbktleXMuQ1JFQVRFXSxcbiAgQUxMOiBbXG4gICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgIE9wZXJhdGlvbktleXMuREVMRVRFLFxuICBdLFxufTtcbiIsImltcG9ydCB7IE9wZXJhdGlvbkhhbmRsZXIgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9JUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgT3BlcmF0aW9ucyB9IGZyb20gXCIuL09wZXJhdGlvbnNcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuLi9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IEhvbGRzIHRoZSByZWdpc3RlcmVkIG9wZXJhdGlvbiBoYW5kbGVyc1xuICpcbiAqIEBjbGFzcyBPcGVyYXRpb25zUmVnaXN0cnlcbiAqIEBpbXBsZW1lbnRzIElSZWdpc3RyeTxPcGVyYXRpb25IYW5kbGVyPGFueT4+XG4gKlxuICogQHNlZSBPcGVyYXRpb25IYW5kbGVyXG4gKlxuICogQGNhdGVnb3J5IE9wZXJhdGlvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIE9wZXJhdGlvbnNSZWdpc3RyeSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGU6IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgUmVjb3JkPFxuICAgICAgc3RyaW5nIHwgc3ltYm9sLFxuICAgICAgUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgYW55LCBhbnksIGFueT4+PlxuICAgID5cbiAgPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSByZXRyaWV2ZXMgYW4ge0BsaW5rIE9wZXJhdGlvbkhhbmRsZXJ9IGlmIGl0IGV4aXN0c1xuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFyZ2V0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wS2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcGVyYXRpb25cbiAgICogQHBhcmFtIGFjY3VtXG4gICAqIEByZXR1cm4ge09wZXJhdGlvbkhhbmRsZXIgfCB1bmRlZmluZWR9XG4gICAqL1xuICBnZXQ8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgICBWLFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4gID4oXG4gICAgdGFyZ2V0OiBzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIHByb3BLZXk6IHN0cmluZyxcbiAgICBvcGVyYXRpb246IHN0cmluZyxcbiAgICBhY2N1bT86IE9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz5bXVxuICApOiBPcGVyYXRpb25IYW5kbGVyPE0sIFIsIFYsIEYsIEM+W10gfCB1bmRlZmluZWQge1xuICAgIGFjY3VtID0gYWNjdW0gfHwgW107XG4gICAgbGV0IG5hbWU7XG4gICAgdHJ5IHtcbiAgICAgIG5hbWUgPSB0eXBlb2YgdGFyZ2V0ID09PSBcInN0cmluZ1wiID8gdGFyZ2V0IDogdGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICBhY2N1bS51bnNoaWZ0KFxuICAgICAgICAuLi5PYmplY3QudmFsdWVzKHRoaXMuY2FjaGVbbmFtZV1bcHJvcEtleV1bb3BlcmF0aW9uXSB8fCBbXSlcbiAgICAgICk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgdGFyZ2V0ID09PSBcInN0cmluZ1wiIHx8XG4gICAgICAgIHRhcmdldCA9PT0gT2JqZWN0LnByb3RvdHlwZSB8fFxuICAgICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGFyZ2V0KSA9PT0gT2JqZWN0LnByb3RvdHlwZVxuICAgICAgKVxuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgfVxuXG4gICAgbGV0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRhcmdldCk7XG4gICAgaWYgKHByb3RvLmNvbnN0cnVjdG9yLm5hbWUgPT09IG5hbWUpIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvKTtcblxuICAgIHJldHVybiB0aGlzLmdldDxNLCBSLCBWLCBGLCBDPihwcm90bywgcHJvcEtleSwgb3BlcmF0aW9uLCBhY2N1bSk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgUmVnaXN0ZXJzIGFuIHtAbGluayBPcGVyYXRpb25IYW5kbGVyfVxuICAgKiBAcGFyYW0ge09wZXJhdGlvbkhhbmRsZXJ9IGhhbmRsZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wZXJhdGlvblxuICAgKiBAcGFyYW0ge3t9fSB0YXJnZXRcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBzeW1ib2x9IHByb3BLZXlcbiAgICovXG4gIHJlZ2lzdGVyPFxuICAgIE0gZXh0ZW5kcyBNb2RlbCxcbiAgICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gICAgVixcbiAgICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICAgIEMgZXh0ZW5kcyBDb250ZXh0PEY+LFxuICA+KFxuICAgIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz4sXG4gICAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzLFxuICAgIHRhcmdldDogTSxcbiAgICBwcm9wS2V5OiBzdHJpbmcgfCBzeW1ib2xcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgbmFtZSA9IHRhcmdldC5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgIGNvbnN0IGhhbmRsZXJOYW1lID0gT3BlcmF0aW9ucy5nZXRIYW5kbGVyTmFtZShoYW5kbGVyKTtcblxuICAgIGlmICghdGhpcy5jYWNoZVtuYW1lXSkgdGhpcy5jYWNoZVtuYW1lXSA9IHt9O1xuICAgIGlmICghdGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XSkgdGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XSA9IHt9O1xuICAgIGlmICghdGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XVtvcGVyYXRpb25dKVxuICAgICAgdGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XVtvcGVyYXRpb25dID0ge307XG4gICAgaWYgKHRoaXMuY2FjaGVbbmFtZV1bcHJvcEtleV1bb3BlcmF0aW9uXVtoYW5kbGVyTmFtZV0pIHJldHVybjtcbiAgICB0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldW29wZXJhdGlvbl1baGFuZGxlck5hbWVdID0gaGFuZGxlcjtcbiAgfVxufVxuIiwiaW1wb3J0IHsgSGFzaGluZywgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25IYW5kbGVyIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IE9wZXJhdGlvbnNSZWdpc3RyeSB9IGZyb20gXCIuL09wZXJhdGlvbnNSZWdpc3RyeVwiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlc1wiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuLi9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFN0YXRpYyBjbGFzcyBob2xkaW5nIGNvbW1vbiBPcGVyYXRpb24gRnVuY3Rpb25hbGl0eVxuICpcbiAqIEBjbGFzcyBPcGVyYXRpb25zXG4gKlxuICogQGNhdGVnb3J5IE9wZXJhdGlvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIE9wZXJhdGlvbnMge1xuICBwcml2YXRlIHN0YXRpYyByZWdpc3RyeTogT3BlcmF0aW9uc1JlZ2lzdHJ5O1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fVxuXG4gIHN0YXRpYyBnZXRIYW5kbGVyTmFtZShoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBhbnksIGFueSwgYW55Pikge1xuICAgIGlmIChoYW5kbGVyLm5hbWUpIHJldHVybiBoYW5kbGVyLm5hbWU7XG5cbiAgICBjb25zb2xlLndhcm4oXG4gICAgICBcIkhhbmRsZXIgbmFtZSBub3QgZGVmaW5lZC4gQSBuYW1lIHdpbGwgYmUgZ2VuZXJhdGVkLCBidXQgdGhpcyBpcyBub3QgZGVzaXJhYmxlLiBwbGVhc2UgYXZvaWQgdXNpbmcgYW5vbnltb3VzIGZ1bmN0aW9uc1wiXG4gICAgKTtcbiAgICByZXR1cm4gSGFzaGluZy5oYXNoKGhhbmRsZXIudG9TdHJpbmcoKSk7XG4gIH1cblxuICBzdGF0aWMga2V5KHN0cjogc3RyaW5nKSB7XG4gICAgcmV0dXJuIE9wZXJhdGlvbktleXMuUkVGTEVDVCArIHN0cjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQ8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgICBWID0gb2JqZWN0LFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuICA+KFxuICAgIHRhcmdldE5hbWU6IHN0cmluZyB8IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgcHJvcEtleTogc3RyaW5nLFxuICAgIG9wZXJhdGlvbjogc3RyaW5nXG4gICkge1xuICAgIHJldHVybiBPcGVyYXRpb25zLnJlZ2lzdHJ5LmdldDxNLCBSLCBWLCBGLCBDPihcbiAgICAgIHRhcmdldE5hbWUsXG4gICAgICBwcm9wS2V5LFxuICAgICAgb3BlcmF0aW9uXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldE9wUmVnaXN0cnkoKSB7XG4gICAgaWYgKCFPcGVyYXRpb25zLnJlZ2lzdHJ5KSBPcGVyYXRpb25zLnJlZ2lzdHJ5ID0gbmV3IE9wZXJhdGlvbnNSZWdpc3RyeSgpO1xuICAgIHJldHVybiBPcGVyYXRpb25zLnJlZ2lzdHJ5O1xuICB9XG5cbiAgc3RhdGljIHJlZ2lzdGVyPFYgZXh0ZW5kcyBNb2RlbD4oXG4gICAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxWLCBhbnksIGFueT4sXG4gICAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzLFxuICAgIHRhcmdldDogVixcbiAgICBwcm9wS2V5OiBzdHJpbmcgfCBzeW1ib2xcbiAgKSB7XG4gICAgT3BlcmF0aW9ucy5nZXRPcFJlZ2lzdHJ5KCkucmVnaXN0ZXIoXG4gICAgICBoYW5kbGVyIGFzIGFueSxcbiAgICAgIG9wZXJhdGlvbixcbiAgICAgIHRhcmdldCxcbiAgICAgIHByb3BLZXlcbiAgICApO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBJZE9wZXJhdGlvbkhhbmRsZXIsXG4gIE9wZXJhdGlvbkhhbmRsZXIsXG4gIFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcixcbiAgVXBkYXRlT3BlcmF0aW9uSGFuZGxlcixcbn0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERCT3BlcmF0aW9ucywgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9ucyB9IGZyb20gXCIuL09wZXJhdGlvbnNcIjtcbmltcG9ydCB7IGFwcGx5IH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBwcm9wTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5cbmZ1bmN0aW9uIGhhbmRsZShcbiAgb3A6IE9wZXJhdGlvbktleXMsXG4gIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIGFueSwgYW55LCBhbnk+XG4pIHtcbiAgcmV0dXJuICh0YXJnZXQ6IGFueSwgcHJvcGVydHlLZXk6IHN0cmluZykgPT4ge1xuICAgIE9wZXJhdGlvbnMucmVnaXN0ZXIoaGFuZGxlciwgb3AsIHRhcmdldCwgcHJvcGVydHlLZXkpO1xuICB9O1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IG9uIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuQ1JFQVRFX1VQREFURX1cbiAqXG4gKiBAcGFyYW0ge09uT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqIEBwYXJhbSB7YW55W119IFthcmdzXSBBcmd1bWVudHMgdGhhdCB3aWxsIGJlIHBhc3NlZCBpbiBvcmRlciB0byB0aGUgaGFuZGxlciBtZXRob2RcbiAqXG4gKiBAc2VlIG9uXG4gKlxuICogQGZ1bmN0aW9uIG9uQ3JlYXRlVXBkYXRlXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uQ3JlYXRlVXBkYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOlxuICAgIHwgU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT5cbiAgICB8IFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gb24oREJPcGVyYXRpb25zLkNSRUFURV9VUERBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3VyIHRvIHNldCBvbiB0aGUgZGVmaW5lZCB7QGxpbmsgREJPcGVyYXRpb25zLlVQREFURX1cbiAqXG4gKiBAcGFyYW0ge09uT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqIEBwYXJhbSB7YW55W119IFthcmdzXSBBcmd1bWVudHMgdGhhdCB3aWxsIGJlIHBhc3NlZCBpbiBvcmRlciB0byB0aGUgaGFuZGxlciBtZXRob2RcbiAqXG4gKiBAc2VlIG9uXG4gKlxuICogQGZ1bmN0aW9uIG9uVXBkYXRlXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uVXBkYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBvbihEQk9wZXJhdGlvbnMuVVBEQVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgb24gdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5DUkVBVEV9XG4gKlxuICogQHBhcmFtIHtPbk9wZXJhdGlvbkhhbmRsZXI8YW55Pn0gaGFuZGxlciBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSBkYXRhXG4gKlxuICogQHNlZSBvblxuICpcbiAqIEBmdW5jdGlvbiBvbkNyZWF0ZVxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbkNyZWF0ZTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIG9uKERCT3BlcmF0aW9ucy5DUkVBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IG9uIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuUkVBRH1cbiAqXG4gKiBAcGFyYW0ge09uT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqXG4gKiBAc2VlIG9uXG4gKlxuICogQGZ1bmN0aW9uIG9uUmVhZFxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvblJlYWQ8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IElkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIG9uKERCT3BlcmF0aW9ucy5SRUFELCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3VyIHRvIHNldCBvbiB0aGUgZGVmaW5lZCB7QGxpbmsgREJPcGVyYXRpb25zLkRFTEVURX1cbiAqXG4gKiBAcGFyYW0ge09uT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqXG4gKiBAc2VlIG9uXG4gKlxuICogQGZ1bmN0aW9uIG9uRGVsZXRlXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uRGVsZXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gb24oREJPcGVyYXRpb25zLkRFTEVURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgb24gdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5ERUxFVEV9XG4gKlxuICogQHBhcmFtIHtPbk9wZXJhdGlvbkhhbmRsZXI8YW55Pn0gaGFuZGxlciBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSBkYXRhXG4gKlxuICogQHNlZSBvblxuICpcbiAqIEBmdW5jdGlvbiBvbkFueVxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbkFueTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIG9uKERCT3BlcmF0aW9ucy5BTEwsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IG9uIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnN9XG4gKlxuICogQHBhcmFtIHtPcGVyYXRpb25LZXlzW10gfCBEQk9wZXJhdGlvbnN9IG9wIE9uZSBvZiB7QGxpbmsgREJPcGVyYXRpb25zfVxuICogQHBhcmFtIHtPbk9wZXJhdGlvbkhhbmRsZXI8YW55Pn0gaGFuZGxlciBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSBkYXRhXG4gKlxuICogZXg6IGhhbmRsZXIoLi4uYXJncywgLi4ucHJvcHMubWFwKHAgPT4gdGFyZ2V0W3BdKSlcbiAqXG4gKiBAZnVuY3Rpb24gb25cbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb248ViA9IG9iamVjdD4oXG4gIG9wOiBPcGVyYXRpb25LZXlzW10gPSBEQk9wZXJhdGlvbnMuQUxMLFxuICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIG9wZXJhdGlvbihPcGVyYXRpb25LZXlzLk9OLCBvcCwgaGFuZGxlciwgZGF0YSk7XG59XG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IGFmdGVyIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuQ1JFQVRFX1VQREFURX1cbiAqXG4gKiBAcGFyYW0ge0FmdGVyT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqXG4gKiBAc2VlIGFmdGVyXG4gKlxuICogQGZ1bmN0aW9uIGFmdGVyQ3JlYXRlVXBkYXRlXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyQ3JlYXRlVXBkYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOlxuICAgIHwgU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT5cbiAgICB8IFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YTogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuQ1JFQVRFX1VQREFURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgYWZ0ZXIgdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5VUERBVEV9XG4gKlxuICogQHBhcmFtIHtBZnRlck9wZXJhdGlvbkhhbmRsZXI8YW55Pn0gaGFuZGxlciBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSBkYXRhXG4gKlxuICogQHNlZSBhZnRlclxuICpcbiAqIEBmdW5jdGlvbiBhZnRlclVwZGF0ZVxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlclVwZGF0ZTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogVXBkYXRlT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5VUERBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IGFmdGVyIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuQ1JFQVRFfVxuICpcbiAqIEBwYXJhbSB7QWZ0ZXJPcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICpcbiAqIEBzZWUgYWZ0ZXJcbiAqXG4gKiBAZnVuY3Rpb24gYWZ0ZXJDcmVhdGVcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYWZ0ZXJDcmVhdGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5DUkVBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IGFmdGVyIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuUkVBRH1cbiAqXG4gKiBAcGFyYW0ge0FmdGVyT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqIEBwYXJhbSB7YW55W119IFthcmdzXSBBcmd1bWVudHMgdGhhdCB3aWxsIGJlIHBhc3NlZCBpbiBvcmRlciB0byB0aGUgaGFuZGxlciBtZXRob2RcbiAqXG4gKiBAc2VlIGFmdGVyXG4gKlxuICogQGZ1bmN0aW9uIGFmdGVyUmVhZFxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlclJlYWQ8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuUkVBRCwgaGFuZGxlciwgZGF0YSk7XG59XG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IGFmdGVyIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuREVMRVRFfVxuICpcbiAqIEBwYXJhbSB7QWZ0ZXJPcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICogQHBhcmFtIHthbnlbXX0gW2FyZ3NdIEFyZ3VtZW50cyB0aGF0IHdpbGwgYmUgcGFzc2VkIGluIG9yZGVyIHRvIHRoZSBoYW5kbGVyIG1ldGhvZFxuICpcbiAqIEBzZWUgYWZ0ZXJcbiAqXG4gKiBAZnVuY3Rpb24gYWZ0ZXJEZWxldGVcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYWZ0ZXJEZWxldGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuREVMRVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3VyIHRvIHNldCBhZnRlciB0aGUgZGVmaW5lZCB7QGxpbmsgREJPcGVyYXRpb25zLkRFTEVURX1cbiAqXG4gKiBAcGFyYW0ge0FmdGVyT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqIEBwYXJhbSB7YW55W119IFthcmdzXSBBcmd1bWVudHMgdGhhdCB3aWxsIGJlIHBhc3NlZCBpbiBvcmRlciB0byB0aGUgaGFuZGxlciBtZXRob2RcbiAqXG4gKiBAc2VlIGFmdGVyXG4gKlxuICogQGZ1bmN0aW9uIGFmdGVyQW55XG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyQW55PFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gYWZ0ZXIoREJPcGVyYXRpb25zLkFMTCwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgb24gdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9uc31cbiAqXG4gKiBAcGFyYW0ge09wZXJhdGlvbktleXNbXSB8IERCT3BlcmF0aW9uc30gb3AgT25lIG9mIHtAbGluayBEQk9wZXJhdGlvbnN9XG4gKiBAcGFyYW0ge0FmdGVyT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICpcbiAqIGV4OiBoYW5kbGVyKC4uLmFyZ3MsIC4uLnByb3BzLm1hcChwID0+IHRhcmdldFtwXSkpXG4gKlxuICogQHBhcmFtIGRhdGFcbiAqIEBwYXJhbSBhcmdzXG4gKiBAZnVuY3Rpb24gYWZ0ZXJcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYWZ0ZXI8ViA9IG9iamVjdD4oXG4gIG9wOiBPcGVyYXRpb25LZXlzW10gPSBEQk9wZXJhdGlvbnMuQUxMLFxuICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIG9wZXJhdGlvbihPcGVyYXRpb25LZXlzLkFGVEVSLCBvcCwgaGFuZGxlciwgZGF0YSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvcGVyYXRpb248ViA9IG9iamVjdD4oXG4gIGJhc2VPcDogT3BlcmF0aW9uS2V5cy5PTiB8IE9wZXJhdGlvbktleXMuQUZURVIsXG4gIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5c1tdID0gREJPcGVyYXRpb25zLkFMTCxcbiAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhVG9BZGQ/OiBWXG4pIHtcbiAgcmV0dXJuICh0YXJnZXQ6IG9iamVjdCwgcHJvcGVydHlLZXk/OiBhbnkpID0+IHtcbiAgICBjb25zdCBuYW1lID0gdGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgY29uc3QgZGVjb3JhdG9ycyA9IG9wZXJhdGlvbi5yZWR1Y2UoKGFjY3VtOiBhbnlbXSwgb3ApID0+IHtcbiAgICAgIGNvbnN0IGNvbXBvdW5kS2V5ID0gYmFzZU9wICsgb3A7XG4gICAgICBsZXQgZGF0YSA9IFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICAgIE9wZXJhdGlvbnMua2V5KGNvbXBvdW5kS2V5KSxcbiAgICAgICAgdGFyZ2V0LFxuICAgICAgICBwcm9wZXJ0eUtleVxuICAgICAgKTtcbiAgICAgIGlmICghZGF0YSlcbiAgICAgICAgZGF0YSA9IHtcbiAgICAgICAgICBvcGVyYXRpb246IG9wLFxuICAgICAgICAgIGhhbmRsZXJzOiB7fSxcbiAgICAgICAgfTtcblxuICAgICAgY29uc3QgaGFuZGxlcktleSA9IE9wZXJhdGlvbnMuZ2V0SGFuZGxlck5hbWUoaGFuZGxlcik7XG5cbiAgICAgIGlmIChcbiAgICAgICAgIWRhdGEuaGFuZGxlcnNbbmFtZV0gfHxcbiAgICAgICAgIWRhdGEuaGFuZGxlcnNbbmFtZV1bcHJvcGVydHlLZXldIHx8XG4gICAgICAgICEoaGFuZGxlcktleSBpbiBkYXRhLmhhbmRsZXJzW25hbWVdW3Byb3BlcnR5S2V5XSlcbiAgICAgICkge1xuICAgICAgICBkYXRhLmhhbmRsZXJzW25hbWVdID0gZGF0YS5oYW5kbGVyc1tuYW1lXSB8fCB7fTtcbiAgICAgICAgZGF0YS5oYW5kbGVyc1tuYW1lXVtwcm9wZXJ0eUtleV0gPVxuICAgICAgICAgIGRhdGEuaGFuZGxlcnNbbmFtZV1bcHJvcGVydHlLZXldIHx8IHt9O1xuICAgICAgICBkYXRhLmhhbmRsZXJzW25hbWVdW3Byb3BlcnR5S2V5XVtoYW5kbGVyS2V5XSA9IHtcbiAgICAgICAgICBkYXRhOiBkYXRhVG9BZGQsXG4gICAgICAgIH07XG5cbiAgICAgICAgYWNjdW0ucHVzaChcbiAgICAgICAgICBoYW5kbGUoY29tcG91bmRLZXkgYXMgT3BlcmF0aW9uS2V5cywgaGFuZGxlciksXG4gICAgICAgICAgcHJvcE1ldGFkYXRhKE9wZXJhdGlvbnMua2V5KGNvbXBvdW5kS2V5KSwgZGF0YSlcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LCBbXSk7XG4gICAgcmV0dXJuIGFwcGx5KC4uLmRlY29yYXRvcnMpKHRhcmdldCwgcHJvcGVydHlLZXkpO1xuICB9O1xufVxuIiwiLyoqXG4gKiBAc3VtbWFyeSBCYXNlIEVycm9yXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBCYXNlRExURXJyb3JcbiAqIEBleHRlbmRzIEVycm9yXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIHJlYWRvbmx5IGNvZGUhOiBudW1iZXI7XG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihuYW1lOiBzdHJpbmcsIG1zZzogc3RyaW5nIHwgRXJyb3IsIGNvZGU6IG51bWJlciA9IDUwMCkge1xuICAgIGlmIChtc2cgaW5zdGFuY2VvZiBCYXNlRXJyb3IpIHJldHVybiBtc2c7XG4gICAgY29uc3QgbWVzc2FnZSA9IGBbJHtuYW1lfV0gJHttc2cgaW5zdGFuY2VvZiBFcnJvciA/IG1zZy5tZXNzYWdlIDogbXNnfWA7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgdGhpcy5jb2RlID0gY29kZTtcbiAgICBpZiAobXNnIGluc3RhbmNlb2YgRXJyb3IpIHRoaXMuc3RhY2sgPSBtc2cuc3RhY2s7XG4gIH1cbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSBpbiB0aGUgTW9kZWwgZGV0YWlsc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgVmFsaWRhdGlvbkVycm9yXG4gKiBAZXh0ZW5kcyBCYXNlRXJyb3JcbiAqL1xuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb25FcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihWYWxpZGF0aW9uRXJyb3IubmFtZSwgbXNnLCA0MjIpO1xuICB9XG59XG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW4gaW50ZXJuYWwgZmFpbHVyZSAoc2hvdWxkIG1lYW4gYW4gZXJyb3IgaW4gY29kZSlcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIEludGVybmFsRXJyb3JcbiAqIEBleHRlbmRzIEJhc2VFcnJvclxuICovXG5leHBvcnQgY2xhc3MgSW50ZXJuYWxFcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihJbnRlcm5hbEVycm9yLm5hbWUsIG1zZywgNTAwKTtcbiAgfVxufVxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSBpbiB0aGUgTW9kZWwgZGUvc2VyaWFsaXphdGlvblxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgU2VyaWFsaXphdGlvbkVycm9yXG4gKiBAZXh0ZW5kcyBCYXNlRXJyb3JcbiAqXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXJpYWxpemF0aW9uRXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoU2VyaWFsaXphdGlvbkVycm9yLm5hbWUsIG1zZywgNDIyKTtcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIGZpbmRpbmcgYSBtb2RlbFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgTm90Rm91bmRFcnJvclxuICogQGV4dGVuZHMgQmFzZUVycm9yXG4gKlxuICovXG5leHBvcnQgY2xhc3MgTm90Rm91bmRFcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihOb3RGb3VuZEVycm9yLm5hbWUsIG1zZywgNDA0KTtcbiAgfVxufVxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgY29uZmxpY3QgaW4gdGhlIHN0b3JhZ2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIENvbmZsaWN0RXJyb3JcbiAqIEBleHRlbmRzIEJhc2VFcnJvclxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIENvbmZsaWN0RXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoQ29uZmxpY3RFcnJvci5uYW1lLCBtc2csIDQwOSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IE9wZXJhdGlvbnMgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9PcGVyYXRpb25zXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25IYW5kbGVyLCBVcGRhdGVPcGVyYXRpb25IYW5kbGVyIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvdHlwZXNcIjtcbmltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9jb25zdGFudHNcIjtcbmltcG9ydCB7IERlY29yYXRvck1ldGFkYXRhLCBSZWZsZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwsIE1vZGVsS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiLi9Db250ZXh0XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgdHlwZSBDb250ZXh0QXJnczxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPiA9IHtcbiAgY29udGV4dDogQztcbiAgYXJnczogYW55W107XG59O1xuXG4vKipcbiAqIEBzdW1tYXJ5IHJldHJpZXZlcyB0aGUgYXJndW1lbnRzIGZvciB0aGUgaGFuZGxlclxuICogQHBhcmFtIHthbnl9IGRlYyB0aGUgZGVjb3JhdG9yXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcCB0aGUgcHJvcGVydHkgbmFtZVxuICogQHBhcmFtIHt7fX0gbSB0aGUgbW9kZWxcbiAqIEBwYXJhbSB7e319IFthY2N1bV0gYWNjdW11bGF0b3IgdXNlZCBmb3IgaW50ZXJuYWwgcmVjdXJzaXZlbmVzc1xuICpcbiAqIEBmdW5jdGlvbiBnZXRIYW5kbGVyQXJnc1xuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLlJlcG9zaXRvcnlcbiAqL1xuZXhwb3J0IGNvbnN0IGdldEhhbmRsZXJBcmdzID0gZnVuY3Rpb24gKFxuICBkZWM6IGFueSxcbiAgcHJvcDogc3RyaW5nLFxuICBtOiBDb25zdHJ1Y3Rvcjxhbnk+LFxuICBhY2N1bT86IFJlY29yZDxzdHJpbmcsIHsgYXJnczogc3RyaW5nW10gfT5cbik6IFJlY29yZDxzdHJpbmcsIHsgYXJnczogc3RyaW5nW10gfT4gfCB2b2lkIHtcbiAgY29uc3QgbmFtZSA9IG0uY29uc3RydWN0b3IubmFtZTtcbiAgaWYgKCFuYW1lKSB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkNvdWxkIG5vdCBkZXRlcm1pbmUgbW9kZWwgY2xhc3NcIik7XG4gIGFjY3VtID0gYWNjdW0gfHwge307XG5cbiAgaWYgKGRlYy5wcm9wcy5oYW5kbGVyc1tuYW1lXSAmJiBkZWMucHJvcHMuaGFuZGxlcnNbbmFtZV1bcHJvcF0pXG4gICAgYWNjdW0gPSB7IC4uLmRlYy5wcm9wcy5oYW5kbGVyc1tuYW1lXVtwcm9wXSwgLi4uYWNjdW0gfTtcblxuICBsZXQgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YobSk7XG4gIGlmIChwcm90byA9PT0gT2JqZWN0LnByb3RvdHlwZSkgcmV0dXJuIGFjY3VtO1xuICBpZiAocHJvdG8uY29uc3RydWN0b3IubmFtZSA9PT0gbmFtZSkgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pO1xuXG4gIHJldHVybiBnZXRIYW5kbGVyQXJncyhkZWMsIHByb3AsIHByb3RvLCBhY2N1bSk7XG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0ge0lSZXBvc2l0b3J5PFQ+fSByZXBvXG4gKiBAcGFyYW0gY29udGV4dFxuICogQHBhcmFtIHtUfSBtb2RlbFxuICogQHBhcmFtIG9wZXJhdGlvblxuICogQHBhcmFtIHByZWZpeFxuICpcbiAqIEBwYXJhbSBvbGRNb2RlbFxuICogQGZ1bmN0aW9uIGVuZm9yY2VEQlByb3BlcnR5RGVjb3JhdG9yc0FzeW5jXG4gKlxuICogQG1lbWJlck9mIGRiLWRlY29yYXRvcnMudXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGVuZm9yY2VEQkRlY29yYXRvcnM8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICBWIGV4dGVuZHMgb2JqZWN0ID0gb2JqZWN0LFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KFxuICByZXBvOiBSLFxuICBjb250ZXh0OiBDLFxuICBtb2RlbDogTSxcbiAgb3BlcmF0aW9uOiBzdHJpbmcsXG4gIHByZWZpeDogc3RyaW5nLFxuICBvbGRNb2RlbD86IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBkZWNvcmF0b3JzOiBSZWNvcmQ8c3RyaW5nLCBEZWNvcmF0b3JNZXRhZGF0YVtdPiB8IHVuZGVmaW5lZCA9XG4gICAgZ2V0RGJEZWNvcmF0b3JzKG1vZGVsLCBvcGVyYXRpb24sIHByZWZpeCk7XG5cbiAgaWYgKCFkZWNvcmF0b3JzKSByZXR1cm47XG5cbiAgZm9yIChjb25zdCBwcm9wIGluIGRlY29yYXRvcnMpIHtcbiAgICBjb25zdCBkZWNzOiBEZWNvcmF0b3JNZXRhZGF0YVtdID0gZGVjb3JhdG9yc1twcm9wXTtcbiAgICBmb3IgKGNvbnN0IGRlYyBvZiBkZWNzKSB7XG4gICAgICBjb25zdCB7IGtleSB9ID0gZGVjO1xuICAgICAgY29uc3QgaGFuZGxlcnM6IE9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz5bXSB8IHVuZGVmaW5lZCA9XG4gICAgICAgIE9wZXJhdGlvbnMuZ2V0PE0sIFIsIFYsIEYsIEM+KG1vZGVsLCBwcm9wLCBwcmVmaXggKyBrZXkpO1xuICAgICAgaWYgKCFoYW5kbGVycyB8fCAhaGFuZGxlcnMubGVuZ3RoKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgQ291bGQgbm90IGZpbmQgcmVnaXN0ZXJlZCBoYW5kbGVyIGZvciB0aGUgb3BlcmF0aW9uICR7cHJlZml4ICsga2V5fSB1bmRlciBwcm9wZXJ0eSAke3Byb3B9YFxuICAgICAgICApO1xuXG4gICAgICBjb25zdCBoYW5kbGVyQXJncyA9IGdldEhhbmRsZXJBcmdzKGRlYywgcHJvcCwgbW9kZWwgYXMgYW55KTtcblxuICAgICAgaWYgKCFoYW5kbGVyQXJncyB8fCBPYmplY3QudmFsdWVzKGhhbmRsZXJBcmdzKS5sZW5ndGggIT09IGhhbmRsZXJzLmxlbmd0aClcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJBcmdzIGFuZCBoYW5kbGVycyBsZW5ndGggZG8gbm90IG1hdGNoXCIpO1xuXG4gICAgICBsZXQgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxNLCBSLCBWLCBGLCBDPjtcbiAgICAgIGxldCBkYXRhOiBhbnk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhhbmRsZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGhhbmRsZXIgPSBoYW5kbGVyc1tpXTtcbiAgICAgICAgZGF0YSA9IE9iamVjdC52YWx1ZXMoaGFuZGxlckFyZ3MpW2ldO1xuXG4gICAgICAgIGNvbnN0IGFyZ3M6IGFueVtdID0gW2NvbnRleHQsIGRhdGEuZGF0YSwgcHJvcCwgbW9kZWxdO1xuXG4gICAgICAgIGlmIChvcGVyYXRpb24gPT09IE9wZXJhdGlvbktleXMuVVBEQVRFICYmIHByZWZpeCA9PT0gT3BlcmF0aW9uS2V5cy5PTikge1xuICAgICAgICAgIGlmICghb2xkTW9kZWwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk1pc3Npbmcgb2xkIG1vZGVsIGZvciB1cGRhdGUgb3BlcmF0aW9uXCIpO1xuICAgICAgICAgIGFyZ3MucHVzaChvbGRNb2RlbCk7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCAoaGFuZGxlciBhcyBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPE0sIFIsIFYsIEYsIEM+KS5hcHBseShcbiAgICAgICAgICAgIHJlcG8sXG4gICAgICAgICAgICBhcmdzIGFzIFtDLCBWLCBrZXlvZiBNLCBNLCBNXVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgICBjb25zdCBtc2cgPSBgRmFpbGVkIHRvIGV4ZWN1dGUgaGFuZGxlciAke2hhbmRsZXIubmFtZX0gZm9yICR7cHJvcH0gb24gJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfSBkdWUgdG8gZXJyb3I6ICR7ZX1gO1xuICAgICAgICAgIGlmIChjb250ZXh0LmdldChcImJyZWFrT25IYW5kbGVyRXJyb3JcIikpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKG1zZyk7XG4gICAgICAgICAgY29uc29sZS5sb2cobXNnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFNwZWNpZmljIGZvciBEQiBEZWNvcmF0b3JzXG4gKiBAcGFyYW0ge1R9IG1vZGVsXG4gKiBAcGFyYW0ge3N0cmluZ30gb3BlcmF0aW9uIENSVUQge0BsaW5rIE9wZXJhdGlvbktleXN9XG4gKiBAcGFyYW0ge3N0cmluZ30gW2V4dHJhUHJlZml4XVxuICpcbiAqIEBmdW5jdGlvbiBnZXREYlByb3BlcnR5RGVjb3JhdG9yc1xuICpcbiAqIEBtZW1iZXJPZiBkYi1kZWNvcmF0b3JzLnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREYkRlY29yYXRvcnM8VCBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IFQsXG4gIG9wZXJhdGlvbjogc3RyaW5nLFxuICBleHRyYVByZWZpeD86IHN0cmluZ1xuKTogUmVjb3JkPHN0cmluZywgRGVjb3JhdG9yTWV0YWRhdGFbXT4gfCB1bmRlZmluZWQge1xuICBjb25zdCBkZWNvcmF0b3JzOiBSZWNvcmQ8c3RyaW5nLCBEZWNvcmF0b3JNZXRhZGF0YVtdPiB8IHVuZGVmaW5lZCA9XG4gICAgUmVmbGVjdGlvbi5nZXRBbGxQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICBtb2RlbCxcbiAgICAgIC8vIHVuZGVmaW5lZCxcbiAgICAgIE9wZXJhdGlvbktleXMuUkVGTEVDVCArIChleHRyYVByZWZpeCA/IGV4dHJhUHJlZml4IDogXCJcIilcbiAgICApO1xuICBpZiAoIWRlY29yYXRvcnMpIHJldHVybjtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKGRlY29yYXRvcnMpLnJlZHVjZShcbiAgICAoYWNjdW06IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhW10+IHwgdW5kZWZpbmVkLCBkZWNvcmF0b3IpID0+IHtcbiAgICAgIGNvbnN0IGRlYyA9IGRlY29yYXRvcnNbZGVjb3JhdG9yXS5maWx0ZXIoKGQpID0+IGQua2V5ID09PSBvcGVyYXRpb24pO1xuICAgICAgaWYgKGRlYyAmJiBkZWMubGVuZ3RoKSB7XG4gICAgICAgIGlmICghYWNjdW0pIGFjY3VtID0ge307XG4gICAgICAgIGFjY3VtW2RlY29yYXRvcl0gPSBkZWM7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdW07XG4gICAgfSxcbiAgICB1bmRlZmluZWRcbiAgKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIGRlY29yYXRvcnMgZm9yIGFuIG9iamVjdCdzIHByb3BlcnRpZXMgcHJlZml4ZWQgYnkge0BwYXJhbSBwcmVmaXhlc30gcmVjdXJzaXZlbHlcbiAqIEBwYXJhbSBtb2RlbFxuICogQHBhcmFtIGFjY3VtXG4gKiBAcGFyYW0gcHJlZml4ZXNcbiAqXG4gKiBAZnVuY3Rpb24gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuUmVwb3NpdG9yeVxuICovXG5leHBvcnQgY29uc3QgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlID0gZnVuY3Rpb24gPFQgZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBULFxuICBhY2N1bTogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSB8IHVuZGVmaW5lZCxcbiAgLi4ucHJlZml4ZXM6IHN0cmluZ1tdXG4pOiB7IFtpbmRleGVyOiBzdHJpbmddOiBhbnlbXSB9IHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgYWNjdW11bGF0b3IgPSBhY2N1bSB8fCB7fTtcbiAgY29uc3QgbWVyZ2VEZWNvcmF0b3JzID0gZnVuY3Rpb24gKGRlY3M6IHsgW2luZGV4ZXI6IHN0cmluZ106IGFueVtdIH0pIHtcbiAgICBjb25zdCBwdXNoT3JTcXVhc2ggPSAoa2V5OiBzdHJpbmcsIC4uLnZhbHVlczogYW55W10pID0+IHtcbiAgICAgIHZhbHVlcy5mb3JFYWNoKCh2YWwpID0+IHtcbiAgICAgICAgbGV0IG1hdGNoOiBhbnk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAhKG1hdGNoID0gYWNjdW11bGF0b3Jba2V5XS5maW5kKChlKSA9PiBlLmtleSA9PT0gdmFsLmtleSkpIHx8XG4gICAgICAgICAgbWF0Y2gucHJvcHMub3BlcmF0aW9uICE9PSB2YWwucHJvcHMub3BlcmF0aW9uXG4gICAgICAgICkge1xuICAgICAgICAgIGFjY3VtdWxhdG9yW2tleV0ucHVzaCh2YWwpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWwua2V5ID09PSBNb2RlbEtleXMuVFlQRSkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHsgaGFuZGxlcnMsIG9wZXJhdGlvbiB9ID0gdmFsLnByb3BzO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAhb3BlcmF0aW9uIHx8XG4gICAgICAgICAgIW9wZXJhdGlvbi5tYXRjaChcbiAgICAgICAgICAgIG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgIGBeKDo/JHtPcGVyYXRpb25LZXlzLk9OfXwke09wZXJhdGlvbktleXMuQUZURVJ9KSg6PyR7T3BlcmF0aW9uS2V5cy5DUkVBVEV9fCR7T3BlcmF0aW9uS2V5cy5SRUFEfXwke09wZXJhdGlvbktleXMuVVBEQVRFfXwke09wZXJhdGlvbktleXMuREVMRVRFfSkkYFxuICAgICAgICAgICAgKVxuICAgICAgICAgIClcbiAgICAgICAgKSB7XG4gICAgICAgICAgYWNjdW11bGF0b3Jba2V5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYWNjdW1IYW5kbGVycyA9IG1hdGNoLnByb3BzLmhhbmRsZXJzO1xuXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKGhhbmRsZXJzKS5mb3JFYWNoKChbY2xhenosIGhhbmRsZXJEZWZdKSA9PiB7XG4gICAgICAgICAgaWYgKCEoY2xhenogaW4gYWNjdW1IYW5kbGVycykpIHtcbiAgICAgICAgICAgIGFjY3VtSGFuZGxlcnNbY2xhenpdID0gaGFuZGxlckRlZjtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBPYmplY3QuZW50cmllcyhoYW5kbGVyRGVmIGFzIG9iamVjdCkuZm9yRWFjaChcbiAgICAgICAgICAgIChbaGFuZGxlclByb3AsIGhhbmRsZXJdKSA9PiB7XG4gICAgICAgICAgICAgIGlmICghKGhhbmRsZXJQcm9wIGluIGFjY3VtSGFuZGxlcnNbY2xhenpdKSkge1xuICAgICAgICAgICAgICAgIGFjY3VtSGFuZGxlcnNbY2xhenpdW2hhbmRsZXJQcm9wXSA9IGhhbmRsZXI7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMoaGFuZGxlciBhcyBvYmplY3QpLmZvckVhY2goXG4gICAgICAgICAgICAgICAgKFtoYW5kbGVyS2V5LCBhcmdzT2JqXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCEoaGFuZGxlcktleSBpbiBhY2N1bUhhbmRsZXJzW2NsYXp6XVtoYW5kbGVyUHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGFjY3VtSGFuZGxlcnNbY2xhenpdW2hhbmRsZXJQcm9wXVtoYW5kbGVyS2V5XSA9IGFyZ3NPYmo7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICAgICAgYFNraXBwaW5nIGhhbmRsZXIgcmVnaXN0cmF0aW9uIGZvciAke2NsYXp6fSB1bmRlciBwcm9wICR7aGFuZGxlclByb3B9IGJlY2F1c2UgaGFuZGxlciBpcyB0aGUgc2FtZWBcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIE9iamVjdC5lbnRyaWVzKGRlY3MpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgYWNjdW11bGF0b3Jba2V5XSA9IGFjY3VtdWxhdG9yW2tleV0gfHwgW107XG4gICAgICBwdXNoT3JTcXVhc2goa2V5LCAuLi52YWx1ZSk7XG4gICAgfSk7XG4gIH07XG5cbiAgY29uc3QgZGVjczogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSB8IHVuZGVmaW5lZCA9XG4gICAgUmVmbGVjdGlvbi5nZXRBbGxQcm9wZXJ0eURlY29yYXRvcnMobW9kZWwsIC4uLnByZWZpeGVzKTtcbiAgaWYgKGRlY3MpIG1lcmdlRGVjb3JhdG9ycyhkZWNzKTtcblxuICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKG1vZGVsKSA9PT0gT2JqZWN0LnByb3RvdHlwZSkgcmV0dXJuIGFjY3VtdWxhdG9yO1xuXG4gIC8vIGNvbnN0IG5hbWUgPSBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lO1xuICBjb25zdCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihtb2RlbCk7XG4gIGlmICghcHJvdG8pIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgLy8gaWYgKHByb3RvLmNvbnN0cnVjdG9yICYmIHByb3RvLmNvbnN0cnVjdG9yLm5hbWUgPT09IG5hbWUpXG4gIC8vICAgICBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihwcm90bylcbiAgcmV0dXJuIGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZShwcm90bywgYWNjdW11bGF0b3IsIC4uLnByZWZpeGVzKTtcbn07XG4iLCJpbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY29uc3QgRGVmYXVsdFJlcG9zaXRvcnlGbGFnczogT21pdDxSZXBvc2l0b3J5RmxhZ3MsIFwidGltZXN0YW1wXCI+ID0ge1xuICBwYXJlbnRDb250ZXh0OiB1bmRlZmluZWQsXG4gIGNoaWxkQ29udGV4dHM6IFtdLFxuICBpZ25vcmVkVmFsaWRhdGlvblByb3BlcnRpZXM6IFtdLFxuICBjYWxsQXJnczogW10sXG4gIHdyaXRlT3BlcmF0aW9uOiBmYWxzZSxcbiAgYWZmZWN0ZWRUYWJsZXM6IFtdLFxuICBvcGVyYXRpb246IHVuZGVmaW5lZCxcbiAgYnJlYWtPbkhhbmRsZXJFcnJvcjogdHJ1ZSxcbiAgcmVidWlsZFdpdGhUcmFuc2llbnQ6IHRydWUsXG59O1xuIiwiaW1wb3J0IHsgQ29udGV4dEFyZ3MgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgQ29udGV4dHVhbCB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL0NvbnRleHR1YWxcIjtcbmltcG9ydCB7IE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9jb25zdGFudHNcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERlZmF1bHRSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IE9iamVjdEFjY3VtdWxhdG9yIH0gZnJvbSBcInR5cGVkLW9iamVjdC1hY2N1bXVsYXRvclwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IHR5cGUgQ29udGV4dEZhY3Rvcnk8RiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncz4gPSA8QyBleHRlbmRzIENvbnRleHQ8Rj4+KFxuICBhcmc6IE9taXQ8RiwgXCJ0aW1lc3RhbXBcIj5cbikgPT4gQztcblxuZXhwb3J0IGNvbnN0IERlZmF1bHRDb250ZXh0RmFjdG9yeTogQ29udGV4dEZhY3Rvcnk8YW55PiA9IDxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4+KFxuICBhcmc6IE9taXQ8RiwgXCJ0aW1lc3RhbXBcIj5cbikgPT4ge1xuICByZXR1cm4gbmV3IENvbnRleHQ8Rj4oKS5hY2N1bXVsYXRlKFxuICAgIE9iamVjdC5hc3NpZ24oe30sIGFyZywgeyB0aW1lc3RhbXA6IG5ldyBEYXRlKCkgfSkgYXMgRlxuICApIGFzIEM7XG59O1xuXG5leHBvcnQgY2xhc3MgQ29udGV4dDxGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzPiB7XG4gIHN0YXRpYyBmYWN0b3J5OiBDb250ZXh0RmFjdG9yeTxhbnk+ID0gRGVmYXVsdENvbnRleHRGYWN0b3J5O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGU6IEYgJiBPYmplY3RBY2N1bXVsYXRvcjxGPiA9XG4gICAgbmV3IE9iamVjdEFjY3VtdWxhdG9yKCkgYXMgRiAmIE9iamVjdEFjY3VtdWxhdG9yPEY+O1xuXG4gIGNvbnN0cnVjdG9yKG9iaj86IEYpIHtcbiAgICBpZiAob2JqKSByZXR1cm4gdGhpcy5hY2N1bXVsYXRlKG9iaik7XG4gIH1cblxuICBhY2N1bXVsYXRlPFYgZXh0ZW5kcyBvYmplY3Q+KHZhbHVlOiBWKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIFwiY2FjaGVcIiwge1xuICAgICAgdmFsdWU6IHRoaXMuY2FjaGUuYWNjdW11bGF0ZSh2YWx1ZSksXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcyBhcyB1bmtub3duIGFzIENvbnRleHQ8RiAmIFY+O1xuICB9XG5cbiAgZ2V0IHRpbWVzdGFtcCgpIHtcbiAgICByZXR1cm4gdGhpcy5jYWNoZS50aW1lc3RhbXA7XG4gIH1cblxuICBnZXQ8SyBleHRlbmRzIGtleW9mIEY+KGtleTogSyk6IEZbS10ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQoa2V5KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAodGhpcy5jYWNoZS5wYXJlbnRDb250ZXh0KSByZXR1cm4gdGhpcy5jYWNoZS5wYXJlbnRDb250ZXh0LmdldChrZXkpO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICBjaGlsZDxNIGV4dGVuZHMgTW9kZWwsIEMgZXh0ZW5kcyBDb250ZXh0PEY+PihcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgbW9kZWw/OiBDb25zdHJ1Y3RvcjxNPlxuICApOiBDIHtcbiAgICByZXR1cm4gQ29udGV4dC5jaGlsZEZyb208RiwgQz4oXG4gICAgICB0aGlzIGFzIHVua25vd24gYXMgQyxcbiAgICAgIHtcbiAgICAgICAgb3BlcmF0aW9uOiBvcGVyYXRpb24sXG4gICAgICAgIGFmZmVjdGVkVGFibGVzOiBtb2RlbCA/IFttb2RlbF0gOiBbXSxcbiAgICAgIH0gYXMgdW5rbm93biBhcyBQYXJ0aWFsPEY+XG4gICAgKTtcbiAgfVxuXG4gIHN0YXRpYyBjaGlsZEZyb208RiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncywgQyBleHRlbmRzIENvbnRleHQ8Rj4+KFxuICAgIGNvbnRleHQ6IEMsXG4gICAgb3ZlcnJpZGVzPzogUGFydGlhbDxGPlxuICApOiBDIHtcbiAgICByZXR1cm4gQ29udGV4dC5mYWN0b3J5KFxuICAgICAgT2JqZWN0LmFzc2lnbih7fSwgY29udGV4dC5jYWNoZSwgb3ZlcnJpZGVzIHx8IHt9KVxuICAgICkgYXMgdW5rbm93biBhcyBDO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGZyb208XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4gID4oXG4gICAgb3BlcmF0aW9uOlxuICAgICAgfCBPcGVyYXRpb25LZXlzLkNSRUFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLlJFQURcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5VUERBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgb3ZlcnJpZGVzOiBQYXJ0aWFsPEY+LFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPixcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxDPiB7XG4gICAgcmV0dXJuIENvbnRleHQuZmFjdG9yeShcbiAgICAgIE9iamVjdC5hc3NpZ24oe30sIERlZmF1bHRSZXBvc2l0b3J5RmxhZ3MsIG92ZXJyaWRlcywge1xuICAgICAgICBvcGVyYXRpb246IG9wZXJhdGlvbixcbiAgICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgfSlcbiAgICApIGFzIEM7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgYXJnczxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyxcbiAgPihcbiAgICBvcGVyYXRpb246XG4gICAgICB8IE9wZXJhdGlvbktleXMuQ1JFQVRFXG4gICAgICB8IE9wZXJhdGlvbktleXMuUkVBRFxuICAgICAgfCBPcGVyYXRpb25LZXlzLlVQREFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgYXJnczogYW55W10sXG4gICAgY29udGV4dHVhbD86IENvbnRleHR1YWw8Rj4sXG4gICAgb3ZlcnJpZGVzPzogUGFydGlhbDxGPlxuICApOiBQcm9taXNlPENvbnRleHRBcmdzPEYsIEM+PiB7XG4gICAgY29uc3QgbGFzdCA9IGFyZ3MucG9wKCk7XG5cbiAgICBhc3luYyBmdW5jdGlvbiBnZXRDb250ZXh0KCkge1xuICAgICAgaWYgKGNvbnRleHR1YWwpXG4gICAgICAgIHJldHVybiBjb250ZXh0dWFsLmNvbnRleHQob3BlcmF0aW9uLCBvdmVycmlkZXMgfHwge30sIG1vZGVsLCAuLi5hcmdzKTtcbiAgICAgIHJldHVybiBDb250ZXh0LmZyb20ob3BlcmF0aW9uLCBvdmVycmlkZXMgfHwge30sIG1vZGVsLCAuLi5hcmdzKTtcbiAgICB9XG5cbiAgICBsZXQgYzogQztcbiAgICBpZiAobGFzdCkge1xuICAgICAgaWYgKGxhc3QgaW5zdGFuY2VvZiBDb250ZXh0KSB7XG4gICAgICAgIGMgPSBsYXN0IGFzIEM7XG4gICAgICAgIGFyZ3MucHVzaChsYXN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGMgPSAoYXdhaXQgZ2V0Q29udGV4dCgpKSBhcyBDO1xuICAgICAgICBhcmdzLnB1c2gobGFzdCwgYyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGMgPSAoYXdhaXQgZ2V0Q29udGV4dCgpKSBhcyBDO1xuICAgICAgYXJncy5wdXNoKGMpO1xuICAgIH1cblxuICAgIHJldHVybiB7IGNvbnRleHQ6IGMsIGFyZ3M6IGFyZ3MgfTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuL0NvbnRleHRcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBVdGlsIG1ldGhvZCB0byBjaGFuZ2UgYSBtZXRob2Qgb2YgYW4gb2JqZWN0IHByZWZpeGluZyBpdCB3aXRoIGFub3RoZXJcbiAqIEBwYXJhbSB7YW55fSBvYmogVGhlIEJhc2UgT2JqZWN0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBhZnRlciBUaGUgb3JpZ2luYWwgbWV0aG9kXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVmaXggVGhlIFByZWZpeCBtZXRob2QuIFRoZSBvdXRwdXQgd2lsbCBiZSB1c2VkIGFzIGFyZ3VtZW50cyBpbiB0aGUgb3JpZ2luYWwgbWV0aG9kXG4gKiBAcGFyYW0ge3N0cmluZ30gW2FmdGVyTmFtZV0gV2hlbiB0aGUgYWZ0ZXIgZnVuY3Rpb24gYW5tZSBjYW5ub3QgYmUgZXh0cmFjdGVkLCBwYXNzIGl0IGhlcmVcbiAqXG4gKiBAZnVuY3Rpb24gcHJlZml4TWV0aG9kXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLlJlcG9zaXRvcnlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZWZpeE1ldGhvZChcbiAgb2JqOiBhbnksXG4gIGFmdGVyOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgcHJlZml4OiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgYWZ0ZXJOYW1lPzogc3RyaW5nXG4pIHtcbiAgYXN5bmMgZnVuY3Rpb24gd3JhcHBlcih0aGlzOiBhbnksIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShwcmVmaXguY2FsbCh0aGlzLCAuLi5hcmdzKSk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShhZnRlci5hcHBseSh0aGlzLCByZXN1bHRzKSk7XG4gIH1cbiAgY29uc3Qgd3JhcHBlZCA9IHdyYXBwZXIuYmluZChvYmopO1xuICBjb25zdCBuYW1lID0gYWZ0ZXJOYW1lID8gYWZ0ZXJOYW1lIDogYWZ0ZXIubmFtZTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdyYXBwZWQsIFwibmFtZVwiLCB7XG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgd3JpdGFibGU6IGZhbHNlLFxuICAgIHZhbHVlOiBuYW1lLFxuICB9KTtcbiAgb2JqW25hbWVdID0gd3JhcHBlZDtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBVdGlsIG1ldGhvZCB0byBjaGFuZ2UgYSBtZXRob2Qgb2YgYW4gb2JqZWN0IHN1ZmZpeGluZyBpdCB3aXRoIGFub3RoZXJcbiAqIEBwYXJhbSB7YW55fSBvYmogVGhlIEJhc2UgT2JqZWN0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBiZWZvcmUgVGhlIG9yaWdpbmFsIG1ldGhvZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gc3VmZml4IFRoZSBQcmVmaXggbWV0aG9kLiBUaGUgb3V0cHV0IHdpbGwgYmUgdXNlZCBhcyBhcmd1bWVudHMgaW4gdGhlIG9yaWdpbmFsIG1ldGhvZFxuICogQHBhcmFtIHtzdHJpbmd9IFtiZWZvcmVOYW1lXSBXaGVuIHRoZSBhZnRlciBmdW5jdGlvbiBhbm1lIGNhbm5vdCBiZSBleHRyYWN0ZWQsIHBhc3MgaXQgaGVyZVxuICpcbiAqIEBmdW5jdGlvbiBzdWZmaXhNZXRob2RcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuUmVwb3NpdG9yeVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3VmZml4TWV0aG9kKFxuICBvYmo6IGFueSxcbiAgYmVmb3JlOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgc3VmZml4OiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgYmVmb3JlTmFtZT86IHN0cmluZ1xuKSB7XG4gIGFzeW5jIGZ1bmN0aW9uIHdyYXBwZXIodGhpczogYW55LCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLnJlc29sdmUoYmVmb3JlLmNhbGwodGhpcywgLi4uYXJncykpO1xuICAgIHJldHVybiBzdWZmaXguY2FsbCh0aGlzLCAuLi5yZXN1bHRzKTtcbiAgfVxuICBjb25zdCB3cmFwcGVkID0gd3JhcHBlci5iaW5kKG9iaik7XG4gIGNvbnN0IG5hbWUgPSBiZWZvcmVOYW1lID8gYmVmb3JlTmFtZSA6IGJlZm9yZS5uYW1lO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkod3JhcHBlZCwgXCJuYW1lXCIsIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IG5hbWUsXG4gIH0pO1xuICBvYmpbbmFtZV0gPSB3cmFwcGVkO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFV0aWwgbWV0aG9kIHRvIHdyYXAgYSBtZXRob2Qgb2YgYW4gb2JqZWN0IHdpdGggYWRkaXRpb25hbCBsb2dpY1xuICpcbiAqIEBwYXJhbSB7YW55fSBvYmogVGhlIEJhc2UgT2JqZWN0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBiZWZvcmUgdGhlIG1ldGhvZCB0byBiZSBwcmVmaXhlZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gbWV0aG9kIHRoZSBtZXRob2QgdG8gYmUgd3JhcHBlZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gYWZ0ZXIgVGhlIG1ldGhvZCB0byBiZSBzdWZmaXhlZFxuICogQHBhcmFtIHtzdHJpbmd9IFttZXRob2ROYW1lXSBXaGVuIHRoZSBhZnRlciBmdW5jdGlvbiBhbm1lIGNhbm5vdCBiZSBleHRyYWN0ZWQsIHBhc3MgaXQgaGVyZVxuICpcbiAqIEBmdW5jdGlvbiB3cmFwTWV0aG9kV2l0aENvbnRleHRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuUmVwb3NpdG9yeVxuICovXG5leHBvcnQgZnVuY3Rpb24gd3JhcE1ldGhvZFdpdGhDb250ZXh0KFxuICBvYmo6IGFueSxcbiAgYmVmb3JlOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgbWV0aG9kOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgYWZ0ZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBtZXRob2ROYW1lPzogc3RyaW5nXG4pIHtcbiAgY29uc3QgbmFtZSA9IG1ldGhvZE5hbWUgPyBtZXRob2ROYW1lIDogbWV0aG9kLm5hbWU7XG4gIG9ialtuYW1lXSA9IG5ldyBQcm94eShvYmpbbmFtZV0sIHtcbiAgICBhcHBseTogYXN5bmMgKHRhcmdldCwgdGhpc0FyZywgYXJnQXJyYXkpID0+IHtcbiAgICAgIGxldCB0cmFuc2Zvcm1lZEFyZ3MgPSBiZWZvcmUuY2FsbCh0aGlzQXJnLCAuLi5hcmdBcnJheSk7XG4gICAgICBpZiAodHJhbnNmb3JtZWRBcmdzIGluc3RhbmNlb2YgUHJvbWlzZSlcbiAgICAgICAgdHJhbnNmb3JtZWRBcmdzID0gYXdhaXQgdHJhbnNmb3JtZWRBcmdzO1xuICAgICAgY29uc3QgY29udGV4dCA9IHRyYW5zZm9ybWVkQXJnc1t0cmFuc2Zvcm1lZEFyZ3MubGVuZ3RoIC0gMV0gYXMgYW55O1xuICAgICAgaWYgKCEoY29udGV4dCBpbnN0YW5jZW9mIENvbnRleHQpKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk1pc3NpbmcgYSBjb250ZXh0XCIpO1xuICAgICAgbGV0IHJlc3VsdHMgPSBhd2FpdCB0YXJnZXQuY2FsbCh0aGlzQXJnLCAuLi50cmFuc2Zvcm1lZEFyZ3MpO1xuICAgICAgaWYgKHJlc3VsdHMgaW5zdGFuY2VvZiBQcm9taXNlKSByZXN1bHRzID0gYXdhaXQgcmVzdWx0cztcbiAgICAgIHJlc3VsdHMgPSBhZnRlci5jYWxsKHRoaXNBcmcsIHJlc3VsdHMsIGNvbnRleHQpO1xuICAgICAgaWYgKHJlc3VsdHMgaW5zdGFuY2VvZiBQcm9taXNlKSByZXN1bHRzID0gYXdhaXQgcmVzdWx0cztcbiAgICAgIHJldHVybiByZXN1bHRzO1xuICAgIH0sXG4gIH0pO1xufVxuIiwiaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIi4uL21vZGVsL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvdXRpbHNcIjtcbmltcG9ydCB7IE1vZGVsLCBNb2RlbEtleXMsIHNmIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L2Vycm9yc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIHByaW1hcnkga2V5IGF0dHJpYnV0ZSBmb3IgYSB7QGxpbmsgTW9kZWx9XG4gKiBAZGVzY3JpcHRpb24gc2VhcmNoZXMgaW4gYWxsIHRoZSBwcm9wZXJ0aWVzIGluIHRoZSBvYmplY3QgZm9yIGFuIHtAbGluayBpZH0gZGVjb3JhdGVkIHByb3BlcnR5XG4gKlxuICogQHBhcmFtIHtNb2RlbH0gbW9kZWxcbiAqXG4gKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBpZiBubyBwcm9wZXJ0eSBvciBtb3JlIHRoYW4gb25lIHByb3BlcnRpZXMgYXJlIHtAbGluayBpZH0gZGVjb3JhdGVkXG4gKiBvciBubyB2YWx1ZSBpcyBzZXQgaW4gdGhhdCBwcm9wZXJ0eVxuICpcbiAqIEBmdW5jdGlvbiBmaW5kUHJpbWFyeUtleVxuICpcbiAqIEBjYXRlZ29yeSBtYW5hZ2Vyc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFByaW1hcnlLZXk8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSkge1xuICBjb25zdCBkZWNvcmF0b3JzID0gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlKFxuICAgIG1vZGVsLFxuICAgIHVuZGVmaW5lZCxcbiAgICBEQktleXMuUkVGTEVDVCArIERCS2V5cy5JRFxuICApO1xuICBjb25zdCBpZERlY29yYXRvcnMgPSBPYmplY3QuZW50cmllcyhkZWNvcmF0b3JzIGFzIG9iamVjdCkucmVkdWNlKFxuICAgIChhY2N1bTogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSwgW3Byb3AsIGRlY3NdKSA9PiB7XG4gICAgICBjb25zdCBmaWx0ZXJlZCA9IChkZWNzIGFzIHsga2V5OiBzdHJpbmcgfVtdKS5maWx0ZXIoXG4gICAgICAgIChkKSA9PiBkLmtleSAhPT0gTW9kZWxLZXlzLlRZUEVcbiAgICAgICk7XG4gICAgICBpZiAoZmlsdGVyZWQgJiYgZmlsdGVyZWQubGVuZ3RoKSB7XG4gICAgICAgIGFjY3VtW3Byb3BdID0gYWNjdW1bcHJvcF0gfHwgW107XG4gICAgICAgIGFjY3VtW3Byb3BdLnB1c2goLi4uZmlsdGVyZWQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sXG4gICAge31cbiAgKTtcblxuICBpZiAoIWlkRGVjb3JhdG9ycyB8fCAhT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJDb3VsZCBub3QgZmluZCBJRCBkZWNvcmF0ZWQgUHJvcGVydHlcIik7XG4gIGlmIChPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpLmxlbmd0aCA+IDEpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3Ioc2YoT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKS5qb2luKFwiLCBcIikpKTtcbiAgY29uc3QgaWRQcm9wID0gT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKVswXTtcbiAgaWYgKCFpZFByb3ApIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiQ291bGQgbm90IGZpbmQgSUQgZGVjb3JhdGVkIFByb3BlcnR5XCIpO1xuICByZXR1cm4ge1xuICAgIGlkOiBpZFByb3AgYXMga2V5b2YgTSxcbiAgICBwcm9wczogaWREZWNvcmF0b3JzW2lkUHJvcF1bMF0ucHJvcHMsXG4gIH07XG59XG5cbi8qKlxuICogQHN1bW1hcnkgUmV0dXJucyB0aGUgcHJpbWFyeSBrZXkgdmFsdWUgZm9yIGEge0BsaW5rIE1vZGVsfVxuICogQGRlc2NyaXB0aW9uIHNlYXJjaGVzIGluIGFsbCB0aGUgcHJvcGVydGllcyBpbiB0aGUgb2JqZWN0IGZvciBhbiB7QGxpbmsgcGt9IGRlY29yYXRlZCBwcm9wZXJ0eVxuICpcbiAqIEBwYXJhbSB7TW9kZWx9IG1vZGVsXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXR1cm5FbXB0eV1cbiAqIEByZXR1cm4ge3N0cmluZyB8IG51bWJlciB8IGJpZ2ludH0gcHJpbWFyeSBrZXlcbiAqXG4gKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBpZiBubyBwcm9wZXJ0eSBvciBtb3JlIHRoYW4gb25lIHByb3BlcnRpZXMgYXJlIHtAbGluayBwa30gZGVjb3JhdGVkXG4gKiBAdGhyb3dzIHtOb3RGb3VuZEVycm9yfSByZXR1cm5FbXB0eSBpcyBmYWxzZSBhbmQgbm8gdmFsdWUgaXMgc2V0IG9uIHRoZSB7QGxpbmsgcGt9IGRlY29yYXRlZCBwcm9wZXJ0eVxuICpcbiAqIEBmdW5jdGlvbiBmaW5kTW9kZWxJRFxuICpcbiAqIEBjYXRlZ29yeSBtYW5hZ2Vyc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZE1vZGVsSWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0sXG4gIHJldHVybkVtcHR5ID0gZmFsc2Vcbik6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCB7XG4gIGNvbnN0IGlkUHJvcCA9IGZpbmRQcmltYXJ5S2V5KG1vZGVsKS5pZDtcbiAgY29uc3QgbW9kZWxJZCA9IG1vZGVsW2lkUHJvcF07XG4gIGlmICh0eXBlb2YgbW9kZWxJZCA9PT0gXCJ1bmRlZmluZWRcIiAmJiAhcmV0dXJuRW1wdHkpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgTm8gdmFsdWUgZm9yIHRoZSBJZCBpcyBkZWZpbmVkIHVuZGVyIHRoZSBwcm9wZXJ0eSAke2lkUHJvcCBhcyBzdHJpbmd9YFxuICAgICk7XG4gIHJldHVybiBtb2RlbElkIGFzIHN0cmluZyB8IG51bWJlciB8IGJpZ2ludDtcbn1cbiIsImltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGVuZm9yY2VEQkRlY29yYXRvcnMgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgd3JhcE1ldGhvZFdpdGhDb250ZXh0IH0gZnJvbSBcIi4vd3JhcHBlcnNcIjtcbmltcG9ydCB7IGZpbmRQcmltYXJ5S2V5IH0gZnJvbSBcIi4uL2lkZW50aXR5L3V0aWxzXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4vQ29udGV4dFwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VSZXBvc2l0b3J5PFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4gaW1wbGVtZW50cyBJUmVwb3NpdG9yeTxNLCBGLCBDPlxue1xuICBwcml2YXRlIHJlYWRvbmx5IF9jbGFzcyE6IENvbnN0cnVjdG9yPE0+O1xuICBwcml2YXRlIF9wayE6IGtleW9mIE07XG4gIHByaXZhdGUgX3BrUHJvcHMhOiBhbnk7XG5cbiAgZ2V0IGNsYXNzKCkge1xuICAgIGlmICghdGhpcy5fY2xhc3MpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgTm8gY2xhc3MgZGVmaW5pdGlvbiBmb3VuZCBmb3IgdGhpcyByZXBvc2l0b3J5YCk7XG4gICAgcmV0dXJuIHRoaXMuX2NsYXNzO1xuICB9XG5cbiAgZ2V0IHBrKCk6IGtleW9mIE0ge1xuICAgIGlmICghdGhpcy5fcGspIHtcbiAgICAgIGNvbnN0IHsgaWQsIHByb3BzIH0gPSBmaW5kUHJpbWFyeUtleShuZXcgdGhpcy5jbGFzcygpKTtcbiAgICAgIHRoaXMuX3BrID0gaWQ7XG4gICAgICB0aGlzLl9wa1Byb3BzID0gcHJvcHM7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9waztcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgcGtQcm9wcygpOiBhbnkge1xuICAgIGlmICghdGhpcy5fcGtQcm9wcykge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgY29uc3QgcGsgPSB0aGlzLnBrO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fcGtQcm9wcztcbiAgfVxuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihjbGF6ej86IENvbnN0cnVjdG9yPE0+KSB7XG4gICAgaWYgKGNsYXp6KSB0aGlzLl9jbGFzcyA9IGNsYXp6O1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIFt0aGlzLmNyZWF0ZSwgdGhpcy5yZWFkLCB0aGlzLnVwZGF0ZSwgdGhpcy5kZWxldGVdLmZvckVhY2goKG0pID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBtLm5hbWU7XG4gICAgICB3cmFwTWV0aG9kV2l0aENvbnRleHQoXG4gICAgICAgIHNlbGYsXG4gICAgICAgIChzZWxmIGFzIGFueSlbbmFtZSArIFwiUHJlZml4XCJdLFxuICAgICAgICBtLFxuICAgICAgICAoc2VsZiBhcyBhbnkpW25hbWUgKyBcIlN1ZmZpeFwiXVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFic3RyYWN0IGNyZWF0ZShtb2RlbDogTSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+O1xuXG4gIGFzeW5jIGNyZWF0ZUFsbChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIHJldHVybiBQcm9taXNlLmFsbChtb2RlbHMubWFwKChtKSA9PiB0aGlzLmNyZWF0ZShtLCAuLi5hcmdzKSkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZVByZWZpeChtb2RlbDogTSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJnczxNLCBDLCBGPihcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIG1vZGVsID0gbmV3IHRoaXMuY2xhc3MobW9kZWwpO1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgKTtcbiAgICByZXR1cm4gW21vZGVsLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBjcmVhdGVTdWZmaXgobW9kZWw6IE0sIGNvbnRleHQ6IEMpIHtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZUFsbFByZWZpeChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJnczxNLCBDLCBGPihcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcChhc3luYyAobSkgPT4ge1xuICAgICAgICBtID0gbmV3IHRoaXMuY2xhc3MobSk7XG4gICAgICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gbTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICByZXR1cm4gW21vZGVscywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlQWxsU3VmZml4KG1vZGVsczogTVtdLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PlxuICAgICAgICBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVscztcbiAgfVxuXG4gIGFic3RyYWN0IHJlYWQoa2V5OiBzdHJpbmcgfCBudW1iZXIsIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNPjtcblxuICBhc3luYyByZWFkQWxsKGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNW10+IHtcbiAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwoa2V5cy5tYXAoKGlkKSA9PiB0aGlzLnJlYWQoaWQsIC4uLmFyZ3MpKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcmVhZFN1ZmZpeChtb2RlbDogTSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJlYWRQcmVmaXgoa2V5OiBzdHJpbmcsIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgbW9kZWw6IE0gPSBuZXcgdGhpcy5jbGFzcygpO1xuICAgIG1vZGVsW3RoaXMucGtdID0ga2V5IGFzIGFueTtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICApO1xuICAgIHJldHVybiBba2V5LCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyByZWFkQWxsUHJlZml4KGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBrZXlzLm1hcChhc3luYyAoaykgPT4ge1xuICAgICAgICBjb25zdCBtID0gbmV3IHRoaXMuY2xhc3MoKTtcbiAgICAgICAgbVt0aGlzLnBrXSA9IGsgYXMgYW55O1xuICAgICAgICByZXR1cm4gZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICAgICApO1xuICAgICAgfSlcbiAgICApO1xuICAgIHJldHVybiBba2V5cywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcmVhZEFsbFN1ZmZpeChtb2RlbHM6IE1bXSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcCgobSkgPT5cbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWxzO1xuICB9XG5cbiAgYWJzdHJhY3QgdXBkYXRlKG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT47XG5cbiAgYXN5bmMgdXBkYXRlQWxsKG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnkpOiBQcm9taXNlPE1bXT4ge1xuICAgIHJldHVybiBQcm9taXNlLmFsbChtb2RlbHMubWFwKChtKSA9PiB0aGlzLnVwZGF0ZShtLCAuLi5hcmdzKSkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHVwZGF0ZVN1ZmZpeChtb2RlbDogTSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgdXBkYXRlUHJlZml4KG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgaWQgPSBtb2RlbFt0aGlzLnBrXTtcbiAgICBpZiAoIWlkKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBObyB2YWx1ZSBmb3IgdGhlIElkIGlzIGRlZmluZWQgdW5kZXIgdGhlIHByb3BlcnR5ICR7dGhpcy5wayBhcyBzdHJpbmd9YFxuICAgICAgKTtcbiAgICBjb25zdCBvbGRNb2RlbCA9IGF3YWl0IHRoaXMucmVhZChpZCBhcyBzdHJpbmcpO1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLk9OLFxuICAgICAgb2xkTW9kZWxcbiAgICApO1xuICAgIHJldHVybiBbbW9kZWwsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHVwZGF0ZUFsbFByZWZpeChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJnczxNLCBDLCBGPihcbiAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcCgobSkgPT4ge1xuICAgICAgICBtID0gbmV3IHRoaXMuY2xhc3MobSk7XG4gICAgICAgIGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gbTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICByZXR1cm4gW21vZGVscywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgdXBkYXRlQWxsU3VmZml4KG1vZGVsczogTVtdLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PlxuICAgICAgICBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVscztcbiAgfVxuXG4gIGFic3RyYWN0IGRlbGV0ZShrZXk6IHN0cmluZyB8IG51bWJlciwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+O1xuXG4gIGFzeW5jIGRlbGV0ZUFsbChrZXlzOiBzdHJpbmdbXSB8IG51bWJlcltdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKGtleXMubWFwKChrKSA9PiB0aGlzLmRlbGV0ZShrLCAuLi5hcmdzKSkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGRlbGV0ZVN1ZmZpeChtb2RlbDogTSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZGVsZXRlUHJlZml4KGtleTogYW55LCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgbW9kZWwgPSBhd2FpdCB0aGlzLnJlYWQoa2V5LCAuLi5jb250ZXh0QXJncy5hcmdzKTtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICk7XG4gICAgcmV0dXJuIFtrZXksIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGRlbGV0ZUFsbFByZWZpeChrZXlzOiBzdHJpbmdbXSB8IG51bWJlcltdLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgbW9kZWxzID0gYXdhaXQgdGhpcy5yZWFkQWxsKGtleXMsIC4uLmNvbnRleHRBcmdzLmFyZ3MpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcChhc3luYyAobSkgPT4ge1xuICAgICAgICByZXR1cm4gZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICk7XG4gICAgcmV0dXJuIFtrZXlzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVBbGxTdWZmaXgobW9kZWxzOiBNW10sIGNvbnRleHQ6IEMpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0pID0+XG4gICAgICAgIGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWxzO1xuICB9XG5cbiAgcHJvdGVjdGVkIG1lcmdlKG9sZE1vZGVsOiBNLCBtb2RlbDogTSk6IE0ge1xuICAgIGNvbnN0IGV4dHJhY3QgPSAobW9kZWw6IE0pID0+XG4gICAgICBPYmplY3QuZW50cmllcyhtb2RlbCkucmVkdWNlKChhY2N1bTogUmVjb3JkPHN0cmluZywgYW55PiwgW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIHZhbCAhPT0gXCJ1bmRlZmluZWRcIikgYWNjdW1ba2V5XSA9IHZhbDtcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSwge30pO1xuXG4gICAgcmV0dXJuIG5ldyB0aGlzLmNsYXNzKE9iamVjdC5hc3NpZ24oe30sIGV4dHJhY3Qob2xkTW9kZWwpLCBleHRyYWN0KG1vZGVsKSkpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIGAke3RoaXMuY2xhc3MubmFtZX0gUmVwb3NpdG9yeWA7XG4gIH1cbn1cbiIsImltcG9ydCB7IGVuZm9yY2VEQkRlY29yYXRvcnMgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciwgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBCYXNlUmVwb3NpdG9yeSB9IGZyb20gXCIuL0Jhc2VSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBEQktleXMgfSBmcm9tIFwiLi4vbW9kZWwvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4vQ29udGV4dFwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlcG9zaXRvcnk8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPiBleHRlbmRzIEJhc2VSZXBvc2l0b3J5PE0sIEYsIEM+IHtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGNsYXp6PzogQ29uc3RydWN0b3I8TT4pIHtcbiAgICBzdXBlcihjbGF6eik7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlUHJlZml4KFxuICAgIG1vZGVsOiBNLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8W00sIC4uLmFueVtdXT4ge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgbW9kZWwgPSBuZXcgdGhpcy5jbGFzcyhtb2RlbCk7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9ycyhcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICApO1xuXG4gICAgY29uc3QgZXJyb3JzID0gbW9kZWwuaGFzRXJyb3JzKCk7XG4gICAgaWYgKGVycm9ycykgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihlcnJvcnMudG9TdHJpbmcoKSk7XG5cbiAgICByZXR1cm4gW21vZGVsLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGxQcmVmaXgoXG4gICAgbW9kZWxzOiBNW10sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxhbnlbXT4ge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKGFzeW5jIChtKSA9PiB7XG4gICAgICAgIG0gPSBuZXcgdGhpcy5jbGFzcyhtKTtcbiAgICAgICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9ycyhcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IGVycm9ycyA9IG1vZGVsc1xuICAgICAgLm1hcCgobSkgPT4gbS5oYXNFcnJvcnMoKSlcbiAgICAgIC5yZWR1Y2UoKGFjY3VtOiBzdHJpbmcgfCB1bmRlZmluZWQsIGUsIGkpID0+IHtcbiAgICAgICAgaWYgKGUpXG4gICAgICAgICAgYWNjdW0gPVxuICAgICAgICAgICAgdHlwZW9mIGFjY3VtID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgID8gYWNjdW0gKyBgXFxuIC0gJHtpfTogJHtlLnRvU3RyaW5nKCl9YFxuICAgICAgICAgICAgICA6IGAgLSAke2l9OiAke2UudG9TdHJpbmcoKX1gO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LCB1bmRlZmluZWQpO1xuICAgIGlmIChlcnJvcnMpIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoZXJyb3JzKTtcbiAgICByZXR1cm4gW21vZGVscywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlUHJlZml4KFxuICAgIG1vZGVsOiBNLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8W00sIC4uLmFyZ3M6IGFueVtdXT4ge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgcGsgPSAobW9kZWwgYXMgYW55KVt0aGlzLnBrXTtcbiAgICBpZiAoIXBrKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBObyB2YWx1ZSBmb3IgdGhlIElkIGlzIGRlZmluZWQgdW5kZXIgdGhlIHByb3BlcnR5ICR7dGhpcy5wayBhcyBzdHJpbmd9YFxuICAgICAgKTtcblxuICAgIGNvbnN0IG9sZE1vZGVsOiBNID0gYXdhaXQgdGhpcy5yZWFkKHBrKTtcblxuICAgIG1vZGVsID0gdGhpcy5tZXJnZShvbGRNb2RlbCwgbW9kZWwpO1xuXG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9ycyhcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuT04sXG4gICAgICBvbGRNb2RlbFxuICAgICk7XG5cbiAgICBjb25zdCBlcnJvcnMgPSBtb2RlbC5oYXNFcnJvcnMob2xkTW9kZWwgYXMgYW55KTtcbiAgICBpZiAoZXJyb3JzKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGVycm9ycy50b1N0cmluZygpKTtcbiAgICByZXR1cm4gW21vZGVsLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyB1cGRhdGVBbGxQcmVmaXgobW9kZWxzOiBNW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBpZHMgPSBtb2RlbHMubWFwKChtKSA9PiB7XG4gICAgICBjb25zdCBpZCA9IG1bdGhpcy5wa107XG4gICAgICBpZiAodHlwZW9mIGlkID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgTm8gdmFsdWUgZm9yIHRoZSBJZCBpcyBkZWZpbmVkIHVuZGVyIHRoZSBwcm9wZXJ0eSAke3RoaXMucGsgYXMgc3RyaW5nfWBcbiAgICAgICAgKTtcbiAgICAgIHJldHVybiBpZCBhcyBzdHJpbmc7XG4gICAgfSk7XG4gICAgY29uc3Qgb2xkTW9kZWxzOiBNW10gPSBhd2FpdCB0aGlzLnJlYWRBbGwoaWRzLCAuLi5jb250ZXh0QXJncy5hcmdzKTtcbiAgICBtb2RlbHMgPSBtb2RlbHMubWFwKChtLCBpKSA9PiB0aGlzLm1lcmdlKG9sZE1vZGVsc1tpXSwgbSkpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcCgobSwgaSkgPT5cbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9ycyhcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OLFxuICAgICAgICAgIG9sZE1vZGVsc1tpXVxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcblxuICAgIGNvbnN0IGVycm9ycyA9IG1vZGVsc1xuICAgICAgLm1hcCgobSwgaSkgPT4gbS5oYXNFcnJvcnMob2xkTW9kZWxzW2ldIGFzIGFueSkpXG4gICAgICAucmVkdWNlKChhY2N1bTogc3RyaW5nIHwgdW5kZWZpbmVkLCBlLCBpKSA9PiB7XG4gICAgICAgIGlmIChlKVxuICAgICAgICAgIGFjY3VtID1cbiAgICAgICAgICAgIHR5cGVvZiBhY2N1bSA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICA/IGFjY3VtICsgYFxcbiAtICR7aX06ICR7ZS50b1N0cmluZygpfWBcbiAgICAgICAgICAgICAgOiBgIC0gJHtpfTogJHtlLnRvU3RyaW5nKCl9YDtcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSwgdW5kZWZpbmVkKTtcbiAgICBpZiAoZXJyb3JzKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGVycm9ycyk7XG4gICAgcmV0dXJuIFttb2RlbHMsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgc3RhdGljIGtleShrZXk6IHN0cmluZykge1xuICAgIHJldHVybiBEQktleXMuUkVGTEVDVCArIGtleTtcbiAgfVxufVxuIiwiaW1wb3J0IFwiLi92YWxpZGF0aW9uXCI7XG5pbXBvcnQge1xuICBkYXRlLFxuICBEZWNvcmF0aW9uLFxuICBNb2RlbCxcbiAgcHJvcE1ldGFkYXRhLFxuICByZXF1aXJlZCxcbiAgdHlwZSxcbiAgVmFsaWRhdGlvbixcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgREJLZXlzLCBERUZBVUxUX1RJTUVTVEFNUF9GT1JNQVQgfSBmcm9tIFwiLi4vbW9kZWwvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBERUZBVUxUX0VSUk9SX01FU1NBR0VTIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBEQk9wZXJhdGlvbnMsIE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9jb25zdGFudHNcIjtcbmltcG9ydCB7IGFmdGVyLCBvbiwgb25DcmVhdGVVcGRhdGUgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL0lSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBTZXJpYWxpemF0aW9uRXJyb3IgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9lcnJvcnNcIjtcbmltcG9ydCB7IGFwcGx5LCBtZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvQ29udGV4dFwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvdHlwZXNcIjtcblxuLyoqXG4gKiBNYXJrcyB0aGUgcHJvcGVydHkgYXMgcmVhZG9ubHkuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSB0aGUgZXJyb3IgbWVzc2FnZS4gRGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfRVJST1JfTUVTU0FHRVMuUkVBRE9OTFkuSU5WQUxJRH1cbiAqXG4gKiBAZGVjb3JhdG9yIHJlYWRvbmx5XG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRvbmx5KFxuICBtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLlJFQURPTkxZLklOVkFMSURcbikge1xuICBjb25zdCBrZXkgPSBWYWxpZGF0aW9uLnVwZGF0ZUtleShEQktleXMuUkVBRE9OTFkpO1xuICByZXR1cm4gRGVjb3JhdGlvbi5mb3Ioa2V5KVxuICAgIC5kZWZpbmUoXG4gICAgICBwcm9wTWV0YWRhdGEoa2V5LCB7XG4gICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICB9KVxuICAgIClcbiAgICAuYXBwbHkoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRpbWVzdGFtcEhhbmRsZXI8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICBWLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgKG1vZGVsIGFzIGFueSlba2V5XSA9IGNvbnRleHQudGltZXN0YW1wO1xufVxuXG4vKipcbiAqIE1hcmtzIHRoZSBwcm9wZXJ0eSBhcyB0aW1lc3RhbXAuXG4gKiBNYWtlcyBpdCB7QGxpbmsgcmVxdWlyZWR9XG4gKiBNYWtlcyBpdCBhIHtAbGluayBkYXRlfVxuICpcbiAqIERhdGUgRm9ybWF0OlxuICpcbiAqIDxwcmU+XG4gKiAgICAgIFVzaW5nIHNpbWlsYXIgZm9ybWF0dGluZyBhcyBNb21lbnQuanMsIENsYXNzIERhdGVUaW1lRm9ybWF0dGVyIChKYXZhKSwgYW5kIENsYXNzIFNpbXBsZURhdGVGb3JtYXQgKEphdmEpLFxuICogICAgICBJIGltcGxlbWVudGVkIGEgY29tcHJlaGVuc2l2ZSBzb2x1dGlvbiBmb3JtYXREYXRlKGRhdGUsIHBhdHRlcm5TdHIpIHdoZXJlIHRoZSBjb2RlIGlzIGVhc3kgdG8gcmVhZCBhbmQgbW9kaWZ5LlxuICogICAgICBZb3UgY2FuIGRpc3BsYXkgZGF0ZSwgdGltZSwgQU0vUE0sIGV0Yy5cbiAqXG4gKiAgICAgIERhdGUgYW5kIFRpbWUgUGF0dGVybnNcbiAqICAgICAgeXkgPSAyLWRpZ2l0IHllYXI7IHl5eXkgPSBmdWxsIHllYXJcbiAqICAgICAgTSA9IGRpZ2l0IG1vbnRoOyBNTSA9IDItZGlnaXQgbW9udGg7IE1NTSA9IHNob3J0IG1vbnRoIG5hbWU7IE1NTU0gPSBmdWxsIG1vbnRoIG5hbWVcbiAqICAgICAgRUVFRSA9IGZ1bGwgd2Vla2RheSBuYW1lOyBFRUUgPSBzaG9ydCB3ZWVrZGF5IG5hbWVcbiAqICAgICAgZCA9IGRpZ2l0IGRheTsgZGQgPSAyLWRpZ2l0IGRheVxuICogICAgICBoID0gaG91cnMgYW0vcG07IGhoID0gMi1kaWdpdCBob3VycyBhbS9wbTsgSCA9IGhvdXJzOyBISCA9IDItZGlnaXQgaG91cnNcbiAqICAgICAgbSA9IG1pbnV0ZXM7IG1tID0gMi1kaWdpdCBtaW51dGVzOyBhYWEgPSBBTS9QTVxuICogICAgICBzID0gc2Vjb25kczsgc3MgPSAyLWRpZ2l0IHNlY29uZHNcbiAqICAgICAgUyA9IG1pbGlzZWNvbmRzXG4gKiA8L3ByZT5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBvcGVyYXRpb24gVGhlIHtAbGluayBEQk9wZXJhdGlvbnN9IHRvIGFjdCBvbi4gRGVmYXVsdHMgdG8ge0BsaW5rIERCT3BlcmF0aW9ucy5DUkVBVEVfVVBEQVRFfVxuICogQHBhcmFtIHtzdHJpbmd9IFtmb3JtYXRdIFRoZSBUaW1lU3RhbXAgZm9ybWF0LiBkZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9USU1FU1RBTVBfRk9STUFUfVxuICogQHBhcmFtIHt7bmV3OiBVcGRhdGVWYWxpZGF0b3J9fSBbdmFsaWRhdG9yXSBkZWZhdWx0cyB0byB7QGxpbmsgVGltZXN0YW1wVmFsaWRhdG9yfVxuICpcbiAqIEBkZWNvcmF0b3IgdGltZXN0YW1wXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbWVzdGFtcChcbiAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzW10gPSBEQk9wZXJhdGlvbnMuQ1JFQVRFX1VQREFURSBhcyB1bmtub3duIGFzIE9wZXJhdGlvbktleXNbXSxcbiAgZm9ybWF0OiBzdHJpbmcgPSBERUZBVUxUX1RJTUVTVEFNUF9GT1JNQVRcbikge1xuICBjb25zdCBrZXkgPSBWYWxpZGF0aW9uLnVwZGF0ZUtleShEQktleXMuVElNRVNUQU1QKTtcblxuICBjb25zdCBkZWNvcmF0b3JzOiBhbnlbXSA9IFtcbiAgICBkYXRlKGZvcm1hdCwgREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuREFURSksXG4gICAgcmVxdWlyZWQoREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuUkVRVUlSRUQpLFxuICAgIG9uKG9wZXJhdGlvbiwgdGltZXN0YW1wSGFuZGxlciksXG4gIF07XG5cbiAgaWYgKG9wZXJhdGlvbi5pbmRleE9mKE9wZXJhdGlvbktleXMuVVBEQVRFKSAhPT0gLTEpXG4gICAgZGVjb3JhdG9ycy5wdXNoKFxuICAgICAgcHJvcE1ldGFkYXRhKFZhbGlkYXRpb24udXBkYXRlS2V5KERCS2V5cy5USU1FU1RBTVApLCB7XG4gICAgICAgIG1lc3NhZ2U6IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuVElNRVNUQU1QLklOVkFMSUQsXG4gICAgICB9KVxuICAgICk7XG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihrZXkpXG4gICAgLmRlZmluZSguLi5kZWNvcmF0b3JzKVxuICAgIC5hcHBseSgpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VyaWFsaXplT25DcmVhdGVVcGRhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICBWLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFtb2RlbFtrZXldKSByZXR1cm47XG4gIHRyeSB7XG4gICAgbW9kZWxba2V5XSA9IEpTT04uc3RyaW5naWZ5KG1vZGVsW2tleV0pIGFzIE1ba2V5b2YgTV07XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgIGBGYWlsZWQgdG8gc2VyaWFsaXplICR7a2V5LnRvU3RyaW5nKCl9IHByb3BlcnR5IG9mIG1vZGVsICR7bW9kZWwuY29uc3RydWN0b3IubmFtZX06IGVgXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VyaWFsaXplQWZ0ZXJBbGw8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICBWLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFtb2RlbFtrZXldKSByZXR1cm47XG4gIGlmICh0eXBlb2YgbW9kZWxba2V5XSAhPT0gXCJzdHJpbmdcIikgcmV0dXJuO1xuXG4gIHRyeSB7XG4gICAgbW9kZWxba2V5XSA9IEpTT04ucGFyc2UobW9kZWxba2V5XSk7XG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgYEZhaWxlZCB0byBkZXNlcmlhbGl6ZSAke2tleS50b1N0cmluZygpfSBwcm9wZXJ0eSBvZiBtb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9OiAke2V9YFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBTZXJpYWxpemUgRGVjb3JhdG9yXG4gKiBAZGVzY3JpcHRpb24gcHJvcGVydGllcyBkZWNvcmF0ZWQgd2lsbCB0aGUgc2VyaWFsaXplZCBiZWZvcmUgc3RvcmVkIGluIHRoZSBkYlxuICpcbiAqIEBmdW5jdGlvbiBzZXJpYWxpemVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOndhbGxldC1kYi5EZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXJpYWxpemUoKSB7XG4gIHJldHVybiBhcHBseShcbiAgICBvbkNyZWF0ZVVwZGF0ZShzZXJpYWxpemVPbkNyZWF0ZVVwZGF0ZSksXG4gICAgYWZ0ZXIoREJPcGVyYXRpb25zLkFMTCwgc2VyaWFsaXplQWZ0ZXJBbGwpLFxuICAgIHR5cGUoW1N0cmluZy5uYW1lLCBPYmplY3QubmFtZV0pLFxuICAgIG1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5TRVJJQUxJWkUpLCB7fSlcbiAgKTtcbn1cbiIsImltcG9ydCB7IHByb3BNZXRhZGF0YSwgcmVxdWlyZWQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyByZWFkb25seSB9IGZyb20gXCIuLi92YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBEQktleXMgfSBmcm9tIFwiLi4vbW9kZWwvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IGFwcGx5IH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBpZCgpIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgIHJlcXVpcmVkKCksXG4gICAgcmVhZG9ubHkoKSxcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLklEKSwge30pXG4gICk7XG59XG4iLCJpbXBvcnQge1xuICBNb2RlbCxcbiAgTW9kZWxFcnJvckRlZmluaXRpb24sXG4gIE1vZGVsRXJyb3JzLFxuICBNb2RlbEtleXMsXG4gIFJlc2VydmVkTW9kZWxzLFxuICBzZixcbiAgVmFsaWRhdGFibGUsXG4gIFZhbGlkYXRpb24sXG4gIFZhbGlkYXRpb25LZXlzLFxuICBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBEZWNvcmF0b3JNZXRhZGF0YSwgUmVmbGVjdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgVXBkYXRlVmFsaWRhdGlvbktleXMsIFVwZGF0ZVZhbGlkYXRvciB9IGZyb20gXCIuLi92YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBmaW5kTW9kZWxJZCB9IGZyb20gXCIuLi9pZGVudGl0eVwiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFZhbGlkYXRlcyB0aGUgdXBkYXRlIG9mIGEgbW9kZWxcbiAqXG4gKiBAcGFyYW0ge1R9IG9sZE1vZGVsXG4gKiBAcGFyYW0ge1R9IG5ld01vZGVsXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbZXhjZXB0aW9uc11cbiAqXG4gKiBAZnVuY3Rpb24gdmFsaWRhdGVDb21wYXJlXG4gKiBAcmV0dXJuIHtNb2RlbEVycm9yRGVmaW5pdGlvbiB8IHVuZGVmaW5lZH1cbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuTW9kZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQ29tcGFyZTxNIGV4dGVuZHMgTW9kZWw+KFxuICBvbGRNb2RlbDogTSxcbiAgbmV3TW9kZWw6IE0sXG4gIC4uLmV4Y2VwdGlvbnM6IHN0cmluZ1tdXG4pOiBNb2RlbEVycm9yRGVmaW5pdGlvbiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGRlY29yYXRlZFByb3BlcnRpZXM6IFZhbGlkYXRpb25Qcm9wZXJ0eURlY29yYXRvckRlZmluaXRpb25bXSA9IFtdO1xuICBmb3IgKGNvbnN0IHByb3AgaW4gbmV3TW9kZWwpXG4gICAgaWYgKFxuICAgICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG5ld01vZGVsLCBwcm9wKSAmJlxuICAgICAgZXhjZXB0aW9ucy5pbmRleE9mKHByb3ApID09PSAtMVxuICAgIClcbiAgICAgIGRlY29yYXRlZFByb3BlcnRpZXMucHVzaChcbiAgICAgICAgUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgICAgVXBkYXRlVmFsaWRhdGlvbktleXMuUkVGTEVDVCxcbiAgICAgICAgICBuZXdNb2RlbCxcbiAgICAgICAgICBwcm9wXG4gICAgICAgICkgYXMgVmFsaWRhdGlvblByb3BlcnR5RGVjb3JhdG9yRGVmaW5pdGlvblxuICAgICAgKTtcblxuICBsZXQgcmVzdWx0OiBNb2RlbEVycm9ycyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICBmb3IgKGNvbnN0IGRlY29yYXRlZFByb3BlcnR5IG9mIGRlY29yYXRlZFByb3BlcnRpZXMpIHtcbiAgICBjb25zdCB7IHByb3AsIGRlY29yYXRvcnMgfSA9IGRlY29yYXRlZFByb3BlcnR5O1xuXG4gICAgZGVjb3JhdG9ycy5zaGlmdCgpOyAvLyByZW1vdmUgdGhlIGRlc2lnbjp0eXBlIGRlY29yYXRvciwgc2luY2UgdGhlIHR5cGUgd2lsbCBhbHJlYWR5IGJlIGNoZWNrZWRcblxuICAgIGlmICghZGVjb3JhdG9ycyB8fCAhZGVjb3JhdG9ycy5sZW5ndGgpIGNvbnRpbnVlO1xuICAgIGxldCBlcnJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gICAgZm9yIChjb25zdCBkZWNvcmF0b3Igb2YgZGVjb3JhdG9ycykge1xuICAgICAgY29uc3QgdmFsaWRhdG9yOiBVcGRhdGVWYWxpZGF0b3IgPSBWYWxpZGF0aW9uLmdldChcbiAgICAgICAgZGVjb3JhdG9yLmtleVxuICAgICAgKSBhcyBVcGRhdGVWYWxpZGF0b3I7XG4gICAgICBpZiAoIXZhbGlkYXRvcikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgIGBDb3VsZCBub3QgZmluZCBNYXRjaGluZyB2YWxpZGF0b3IgZm9yICR7ZGVjb3JhdG9yLmtleX0gZm9yIHByb3BlcnR5ICR7U3RyaW5nKGRlY29yYXRlZFByb3BlcnR5LnByb3ApfWBcbiAgICAgICAgKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVycjogc3RyaW5nIHwgdW5kZWZpbmVkID0gdmFsaWRhdG9yLnVwZGF0ZUhhc0Vycm9ycyhcbiAgICAgICAgKG5ld01vZGVsIGFzIGFueSlbcHJvcC50b1N0cmluZygpXSxcbiAgICAgICAgKG9sZE1vZGVsIGFzIGFueSlbcHJvcC50b1N0cmluZygpXSxcbiAgICAgICAgLi4uT2JqZWN0LnZhbHVlcyhkZWNvcmF0b3IucHJvcHMpXG4gICAgICApO1xuXG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIGVycnMgPSBlcnJzIHx8IHt9O1xuICAgICAgICBlcnJzW2RlY29yYXRvci5rZXldID0gZXJyO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlcnJzKSB7XG4gICAgICByZXN1bHQgPSByZXN1bHQgfHwge307XG4gICAgICByZXN1bHRbZGVjb3JhdGVkUHJvcGVydHkucHJvcC50b1N0cmluZygpXSA9IGVycnM7XG4gICAgfVxuICB9XG4gIC8vIHRlc3RzIG5lc3RlZCBjbGFzc2VzXG4gIGZvciAoY29uc3QgcHJvcCBvZiBPYmplY3Qua2V5cyhuZXdNb2RlbCkuZmlsdGVyKChrKSA9PiB7XG4gICAgaWYgKGV4Y2VwdGlvbnMuaW5jbHVkZXMoaykpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gIXJlc3VsdCB8fCAhcmVzdWx0W2tdO1xuICB9KSkge1xuICAgIGxldCBlcnI6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAvLyBpZiBhIG5lc3RlZCBNb2RlbFxuICAgIGNvbnN0IGFsbERlY29yYXRvcnMgPSBSZWZsZWN0aW9uLmdldFByb3BlcnR5RGVjb3JhdG9ycyhcbiAgICAgIFZhbGlkYXRpb25LZXlzLlJFRkxFQ1QsXG4gICAgICBuZXdNb2RlbCxcbiAgICAgIHByb3BcbiAgICApLmRlY29yYXRvcnM7XG4gICAgY29uc3QgZGVjb3JhdG9ycyA9IFJlZmxlY3Rpb24uZ2V0UHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgVmFsaWRhdGlvbktleXMuUkVGTEVDVCxcbiAgICAgIG5ld01vZGVsLFxuICAgICAgcHJvcFxuICAgICkuZGVjb3JhdG9ycy5maWx0ZXIoXG4gICAgICAoZCkgPT4gW01vZGVsS2V5cy5UWVBFLCBWYWxpZGF0aW9uS2V5cy5UWVBFXS5pbmRleE9mKGQua2V5IGFzIGFueSkgIT09IC0xXG4gICAgKTtcbiAgICBpZiAoIWRlY29yYXRvcnMgfHwgIWRlY29yYXRvcnMubGVuZ3RoKSBjb250aW51ZTtcbiAgICBjb25zdCBkZWMgPSBkZWNvcmF0b3JzLnBvcCgpIGFzIERlY29yYXRvck1ldGFkYXRhO1xuICAgIGNvbnN0IGNsYXp6ID0gZGVjLnByb3BzLm5hbWVcbiAgICAgID8gW2RlYy5wcm9wcy5uYW1lXVxuICAgICAgOiBBcnJheS5pc0FycmF5KGRlYy5wcm9wcy5jdXN0b21UeXBlcylcbiAgICAgICAgPyBkZWMucHJvcHMuY3VzdG9tVHlwZXNcbiAgICAgICAgOiBbZGVjLnByb3BzLmN1c3RvbVR5cGVzXTtcbiAgICBjb25zdCByZXNlcnZlZCA9IE9iamVjdC52YWx1ZXMoUmVzZXJ2ZWRNb2RlbHMpLm1hcCgodikgPT5cbiAgICAgIHYudG9Mb3dlckNhc2UoKVxuICAgICkgYXMgc3RyaW5nW107XG5cbiAgICBmb3IgKGNvbnN0IGMgb2YgY2xhenopIHtcbiAgICAgIGlmIChyZXNlcnZlZC5pbmRleE9mKGMudG9Mb3dlckNhc2UoKSkgPT09IC0xKSB7XG4gICAgICAgIHN3aXRjaCAoYykge1xuICAgICAgICAgIGNhc2UgQXJyYXkubmFtZTpcbiAgICAgICAgICBjYXNlIFNldC5uYW1lOlxuICAgICAgICAgICAgaWYgKGFsbERlY29yYXRvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGxpc3REZWMgPSBhbGxEZWNvcmF0b3JzLmZpbmQoXG4gICAgICAgICAgICAgICAgKGQpID0+IGQua2V5ID09PSBWYWxpZGF0aW9uS2V5cy5MSVNUXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGlmIChsaXN0RGVjKSB7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRMaXN0LCBvbGRMaXN0O1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoIChjKSB7XG4gICAgICAgICAgICAgICAgICBjYXNlIEFycmF5Lm5hbWU6XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRMaXN0ID0gKG5ld01vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdO1xuICAgICAgICAgICAgICAgICAgICBvbGRMaXN0ID0gKG9sZE1vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGNhc2UgU2V0Lm5hbWU6XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRMaXN0ID0gKG5ld01vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW1xuICAgICAgICAgICAgICAgICAgICAgIHByb3BcbiAgICAgICAgICAgICAgICAgICAgXS52YWx1ZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgb2xkTGlzdCA9IChvbGRNb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXS52YWx1ZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgYXR0cmlidXRlIHR5cGUgJHtjfWApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGVyciA9IGN1cnJlbnRMaXN0XG4gICAgICAgICAgICAgICAgICAubWFwKCh2OiBWYWxpZGF0YWJsZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpZCA9IGZpbmRNb2RlbElkKHYgYXMgYW55LCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpZCkgcmV0dXJuIFwiRmFpbGVkIHRvIGZpbmQgbW9kZWwgaWRcIjtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkTW9kZWwgPSBvbGRMaXN0LmZpbmQoXG4gICAgICAgICAgICAgICAgICAgICAgKGVsOiBhbnkpID0+IGlkID09PSBmaW5kTW9kZWxJZChlbCwgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIW9sZE1vZGVsKSByZXR1cm47IC8vIG5vdGhpbmcgdG8gY29tcGFyZSB3aXRoXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2Lmhhc0Vycm9ycyhvbGRNb2RlbCk7XG4gICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgLmZpbHRlcigoZTogYW55KSA9PiAhIWUpIGFzIGFueTtcblxuICAgICAgICAgICAgICAgIGlmICghZXJyPy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZXN1bHQgaXMgYW4gZW1wdHkgbGlzdC4uLlxuICAgICAgICAgICAgICAgICAgZXJyID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAobmV3TW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF0gJiZcbiAgICAgICAgICAgICAgICAob2xkTW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF1cbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIGVyciA9IChuZXdNb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXS5oYXNFcnJvcnMoXG4gICAgICAgICAgICAgICAgICAob2xkTW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKHNmKFwiTW9kZWwgc2hvdWxkIGJlIHZhbGlkYXRhYmxlIGJ1dCBpdHMgbm90XCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGVycikge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQgfHwge307XG4gICAgICAgIHJlc3VsdFtwcm9wXSA9IGVyciBhcyBhbnk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQgPyBuZXcgTW9kZWxFcnJvckRlZmluaXRpb24ocmVzdWx0KSA6IHVuZGVmaW5lZDtcbn1cbiIsImltcG9ydCB7IERCS2V5cywgRGVmYXVsdFNlcGFyYXRvciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgYXBwbHkgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7XG4gIEhhc2hpbmcsXG4gIE1vZGVsLFxuICBwcm9wTWV0YWRhdGEsXG4gIHR5cGUsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IG9uQ3JlYXRlLCBvbkNyZWF0ZVVwZGF0ZSwgb25VcGRhdGUgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL0lSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvZXJyb3JzXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L0NvbnRleHRcIjtcbmltcG9ydCB7IENydWRPcGVyYXRpb25zLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4uL29wZXJhdGlvbnNcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L3R5cGVzXCI7XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7c3RyfSBzdHJcbiAqIEBtZW1iZXJPZiBkYi1kZWNvcmF0b3JzLm1vZGVsXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGhhc2hPbkNyZWF0ZVVwZGF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYgZXh0ZW5kcyBvYmplY3QsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSwgb2xkTW9kZWw/OiBNKTogdm9pZCB7XG4gIGlmICh0eXBlb2YgbW9kZWxba2V5XSA9PT0gXCJ1bmRlZmluZWRcIikgcmV0dXJuO1xuICBjb25zdCBoYXNoID0gSGFzaGluZy5oYXNoKChtb2RlbCBhcyBhbnkpW2tleV0pO1xuICBpZiAob2xkTW9kZWwgJiYgKG1vZGVsIGFzIGFueSlba2V5XSA9PT0gaGFzaCkgcmV0dXJuO1xuICBtb2RlbFtrZXldID0gaGFzaDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhc2goKSB7XG4gIHJldHVybiBhcHBseShcbiAgICBvbkNyZWF0ZVVwZGF0ZShoYXNoT25DcmVhdGVVcGRhdGUpLFxuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuSEFTSCksIHt9KVxuICApO1xufVxuXG5leHBvcnQgdHlwZSBDb21wb3NlZEZyb21NZXRhZGF0YSA9IHtcbiAgYXJnczogc3RyaW5nW107XG4gIHNlcGFyYXRvcjogc3RyaW5nO1xuICBoYXNoUmVzdWx0OiBib29sZWFuO1xuICB0eXBlOiBcImtleXNcIiB8IFwidmFsdWVzXCI7XG4gIHByZWZpeD86IHN0cmluZztcbiAgc3VmZml4Pzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvc2VkRnJvbUNyZWF0ZVVwZGF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYgZXh0ZW5kcyBDb21wb3NlZEZyb21NZXRhZGF0YSxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPih0aGlzOiBSLCBjb250ZXh0OiBDLCBkYXRhOiBWLCBrZXk6IGtleW9mIE0sIG1vZGVsOiBNKSB7XG4gIHRyeSB7XG4gICAgY29uc3QgeyBhcmdzLCB0eXBlLCBwcmVmaXgsIHN1ZmZpeCwgc2VwYXJhdG9yIH0gPSBkYXRhO1xuICAgIGNvbnN0IGNvbXBvc2VkID0gYXJncy5tYXAoKGFyZzogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoIShhcmcgaW4gbW9kZWwpKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgUHJvcGVydHkgJHthcmd9IG5vdCBmb3VuZCB0byBjb21wb3NlIGZyb21gKTtcbiAgICAgIGlmICh0eXBlID09PSBcImtleXNcIikgcmV0dXJuIGFyZztcbiAgICAgIGlmICh0eXBlb2YgKG1vZGVsIGFzIGFueSlbYXJnXSA9PT0gXCJ1bmRlZmluZWRcIilcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgYFByb3BlcnR5ICR7YXJnc30gZG9lcyBub3QgY29udGFpbiBhIHZhbHVlIHRvIGNvbXBvc2UgZnJvbWBcbiAgICAgICAgKTtcbiAgICAgIHJldHVybiAoKG1vZGVsIGFzIGFueSlbYXJnXSBhcyBhbnkpLnRvU3RyaW5nKCk7XG4gICAgfSk7XG5cbiAgICBpZiAocHJlZml4KSBjb21wb3NlZC51bnNoaWZ0KHByZWZpeCk7XG4gICAgaWYgKHN1ZmZpeCkgY29tcG9zZWQucHVzaChzdWZmaXgpO1xuXG4gICAgKG1vZGVsIGFzIGFueSlba2V5XSA9IGNvbXBvc2VkLmpvaW4oc2VwYXJhdG9yKTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYEZhaWxlZCB0byBjb21wb3NlIHZhbHVlOiAke2V9YCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29tcG9zZWRGcm9tKFxuICBhcmdzOiBzdHJpbmdbXSxcbiAgaGFzaFJlc3VsdDogYm9vbGVhbiA9IGZhbHNlLFxuICBzZXBhcmF0b3I6IHN0cmluZyA9IERlZmF1bHRTZXBhcmF0b3IsXG4gIHR5cGU6IFwia2V5c1wiIHwgXCJ2YWx1ZXNcIiA9IFwidmFsdWVzXCIsXG4gIHByZWZpeCA9IFwiXCIsXG4gIHN1ZmZpeCA9IFwiXCJcbikge1xuICBjb25zdCBkYXRhOiBDb21wb3NlZEZyb21NZXRhZGF0YSA9IHtcbiAgICBhcmdzOiBhcmdzLFxuICAgIGhhc2hSZXN1bHQ6IGhhc2hSZXN1bHQsXG4gICAgc2VwYXJhdG9yOiBzZXBhcmF0b3IsXG4gICAgdHlwZTogdHlwZSxcbiAgICBwcmVmaXg6IHByZWZpeCxcbiAgICBzdWZmaXg6IHN1ZmZpeCxcbiAgfTtcblxuICBjb25zdCBkZWNvcmF0b3JzID0gW1xuICAgIG9uQ3JlYXRlVXBkYXRlKGNvbXBvc2VkRnJvbUNyZWF0ZVVwZGF0ZSwgZGF0YSksXG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5DT01QT1NFRCksIGRhdGEpLFxuICBdO1xuICBpZiAoaGFzaFJlc3VsdCkgZGVjb3JhdG9ycy5wdXNoKGhhc2goKSk7XG4gIHJldHVybiBhcHBseSguLi5kZWNvcmF0b3JzKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvc2VkRnJvbUtleXMoXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBzZXBhcmF0b3I6IHN0cmluZyA9IERlZmF1bHRTZXBhcmF0b3IsXG4gIGhhc2g6IGJvb2xlYW4gPSBmYWxzZSxcbiAgcHJlZml4ID0gXCJcIixcbiAgc3VmZml4ID0gXCJcIlxuKSB7XG4gIHJldHVybiBjb21wb3NlZEZyb20oYXJncywgaGFzaCwgc2VwYXJhdG9yLCBcImtleXNcIiwgcHJlZml4LCBzdWZmaXgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcG9zZWQoXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBzZXBhcmF0b3I6IHN0cmluZyA9IERlZmF1bHRTZXBhcmF0b3IsXG4gIGhhc2g6IGJvb2xlYW4gPSBmYWxzZSxcbiAgcHJlZml4ID0gXCJcIixcbiAgc3VmZml4ID0gXCJcIlxuKSB7XG4gIHJldHVybiBjb21wb3NlZEZyb20oYXJncywgaGFzaCwgc2VwYXJhdG9yLCBcInZhbHVlc1wiLCBwcmVmaXgsIHN1ZmZpeCk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlY29yYXRvciBmdW5jdGlvbiB0aGF0IHVwZGF0ZXMgdGhlIHZlcnNpb24gb2YgYSBtb2RlbCBkdXJpbmcgY3JlYXRlIG9yIHVwZGF0ZSBvcGVyYXRpb25zLlxuICpcbiAqIEBwYXJhbSB7Q3J1ZE9wZXJhdGlvbnN9IG9wZXJhdGlvbiAtIFRoZSB0eXBlIG9mIG9wZXJhdGlvbiBiZWluZyBwZXJmb3JtZWQgKENSRUFURSBvciBVUERBVEUpLlxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRoYXQgdXBkYXRlcyB0aGUgdmVyc2lvbiBvZiB0aGUgbW9kZWwgYmFzZWQgb24gdGhlIG9wZXJhdGlvbiB0eXBlLlxuICpcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgSVJlcG9zaXRvcnk8TT5cbiAqXG4gKiBAdGhpcyB7Vn0gLSBUaGUgcmVwb3NpdG9yeSBpbnN0YW5jZVxuICogQHBhcmFtIHtDb250ZXh0PE0+fSBjb250ZXh0IC0gVGhlIGNvbnRleHQgb2YgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHt1bmtub3dufSBkYXRhIC0gQWRkaXRpb25hbCBkYXRhIGZvciB0aGUgb3BlcmF0aW9uIChub3QgdXNlZCBpbiB0aGlzIGZ1bmN0aW9uKVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBrZXkgb2YgdGhlIHZlcnNpb24gcHJvcGVydHkgaW4gdGhlIG1vZGVsXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGJlaW5nIHVwZGF0ZWRcbiAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIGFuIGludmFsaWQgb3BlcmF0aW9uIGlzIHByb3ZpZGVkIG9yIGlmIHZlcnNpb24gdXBkYXRlIGZhaWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2ZXJzaW9uQ3JlYXRlVXBkYXRlKG9wZXJhdGlvbjogQ3J1ZE9wZXJhdGlvbnMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHZlcnNpb25DcmVhdGVVcGRhdGU8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgICBWIGV4dGVuZHMgb2JqZWN0LFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuICA+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0pIHtcbiAgICB0cnkge1xuICAgICAgc3dpdGNoIChvcGVyYXRpb24pIHtcbiAgICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLkNSRUFURTpcbiAgICAgICAgICAobW9kZWwgYXMgYW55KVtrZXldID0gMTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLlVQREFURTpcbiAgICAgICAgICAobW9kZWwgYXMgYW55KVtrZXldKys7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYEludmFsaWQgb3BlcmF0aW9uOiAke29wZXJhdGlvbn1gKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgRmFpbGVkIHRvIHVwZGF0ZSB2ZXJzaW9uOiAke2V9YCk7XG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgZGVjb3JhdG9yIGZvciB2ZXJzaW9uaW5nIGEgcHJvcGVydHkgaW4gYSBtb2RlbC5cbiAqIEBzdW1tYXJ5IFRoaXMgZGVjb3JhdG9yIGFwcGxpZXMgbXVsdGlwbGUgc3ViLWRlY29yYXRvcnMgdG8gaGFuZGxlIHZlcnNpb24gbWFuYWdlbWVudCBkdXJpbmcgY3JlYXRlIGFuZCB1cGRhdGUgb3BlcmF0aW9ucy5cbiAqXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IEEgY29tcG9zaXRlIGRlY29yYXRvciB0aGF0OlxuICogICAtIFNldHMgdGhlIHR5cGUgb2YgdGhlIHByb3BlcnR5IHRvIE51bWJlclxuICogICAtIEFwcGxpZXMgYSB2ZXJzaW9uIHVwZGF0ZSBvbiBjcmVhdGUgb3BlcmF0aW9uc1xuICogICAtIEFwcGxpZXMgYSB2ZXJzaW9uIHVwZGF0ZSBvbiB1cGRhdGUgb3BlcmF0aW9uc1xuICogICAtIEFkZHMgbWV0YWRhdGEgaW5kaWNhdGluZyB0aGlzIHByb3BlcnR5IGlzIHVzZWQgZm9yIHZlcnNpb25pbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcnNpb24oKSB7XG4gIHJldHVybiBhcHBseShcbiAgICB0eXBlKE51bWJlci5uYW1lKSxcbiAgICBvbkNyZWF0ZSh2ZXJzaW9uQ3JlYXRlVXBkYXRlKE9wZXJhdGlvbktleXMuQ1JFQVRFKSksXG4gICAgb25VcGRhdGUodmVyc2lvbkNyZWF0ZVVwZGF0ZShPcGVyYXRpb25LZXlzLlVQREFURSkpLFxuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuVkVSU0lPTiksIHRydWUpXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2llbnQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiB0cmFuc2llbnQobW9kZWw6IGFueSwgYXR0cmlidXRlOiBzdHJpbmcpIHtcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLlRSQU5TSUVOVCksIHRydWUpKG1vZGVsLCBhdHRyaWJ1dGUpO1xuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuVFJBTlNJRU5UKSwgdHJ1ZSkobW9kZWwuY29uc3RydWN0b3IpO1xuICB9O1xufVxuIiwiaW1wb3J0IHtcbiAgQ29tcGFyYWJsZSxcbiAgSGFzaGFibGUsXG4gIE1vZGVsQXJnLFxuICBNb2RlbEVycm9yRGVmaW5pdGlvbixcbiAgU2VyaWFsaXphYmxlLFxuICBWYWxpZGF0YWJsZSxcbiAgTW9kZWwsXG4gIHZhbGlkYXRlLFxuICBDb25zdHJ1Y3RvcixcbiAgTW9kZWxCdWlsZGVyRnVuY3Rpb24sXG4gIEJ1aWxkZXJSZWdpc3RyeSxcbiAgTW9kZWxDb25zdHJ1Y3Rvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgdmFsaWRhdGVDb21wYXJlIH0gZnJvbSBcIi4vdmFsaWRhdGlvblwiO1xuXG5Nb2RlbC5wcm90b3R5cGUuaGFzRXJyb3JzID0gZnVuY3Rpb24gPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIHRoaXM6IE0sXG4gIHByZXZpb3VzVmVyc2lvbj86IE0gfCBhbnksXG4gIC4uLmV4Y2x1c2lvbnM6IGFueVtdXG4pOiBNb2RlbEVycm9yRGVmaW5pdGlvbiB8IHVuZGVmaW5lZCB7XG4gIGlmIChwcmV2aW91c1ZlcnNpb24gJiYgIShwcmV2aW91c1ZlcnNpb24gaW5zdGFuY2VvZiBNb2RlbCkpIHtcbiAgICBleGNsdXNpb25zLnVuc2hpZnQocHJldmlvdXNWZXJzaW9uKTtcbiAgICBwcmV2aW91c1ZlcnNpb24gPSB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBlcnJzID0gdmFsaWRhdGUodGhpcywgLi4uZXhjbHVzaW9ucyk7XG4gIGlmIChlcnJzIHx8ICFwcmV2aW91c1ZlcnNpb24pIHJldHVybiBlcnJzO1xuXG4gIHJldHVybiB2YWxpZGF0ZUNvbXBhcmUocHJldmlvdXNWZXJzaW9uLCB0aGlzLCAuLi5leGNsdXNpb25zKTtcbn07XG5cbmRlY2xhcmUgbW9kdWxlIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCIge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgZGVjbGFyZSBhYnN0cmFjdCBjbGFzcyBNb2RlbFxuICAgIGltcGxlbWVudHMgVmFsaWRhdGFibGUsIFNlcmlhbGl6YWJsZSwgSGFzaGFibGUsIENvbXBhcmFibGU8TW9kZWw+XG4gIHtcbiAgICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoYXJnPzogTW9kZWxBcmc8TW9kZWw+KTtcblxuICAgIGhhc0Vycm9ycyguLi5leGNsdXNpb25zOiBhbnlbXSk6IE1vZGVsRXJyb3JEZWZpbml0aW9uIHwgdW5kZWZpbmVkO1xuICAgIGhhc0Vycm9ycyhcbiAgICAgIHByZXZpb3VzVmVyc2lvbj86IE1vZGVsIHwgYW55LFxuICAgICAgLi4uZXhjbHVzaW9uczogYW55W11cbiAgICApOiBNb2RlbEVycm9yRGVmaW5pdGlvbiB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IENvbXBhcmUgb2JqZWN0IGVxdWFsaXR5IHJlY3Vyc2l2ZWx5XG4gICAgICogQHBhcmFtIHthbnl9IG9iaiBvYmplY3QgdG8gY29tcGFyZSB0b1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbZXhjZXB0aW9uc10gcHJvcGVydHkgbmFtZXMgdG8gYmUgZXhjbHVkZWQgZnJvbSB0aGUgY29tcGFyaXNvblxuICAgICAqL1xuICAgIGVxdWFscyhvYmo6IGFueSwgLi4uZXhjZXB0aW9uczogc3RyaW5nW10pOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgUmV0dXJucyB0aGUgc2VyaWFsaXplZCBtb2RlbCBhY2NvcmRpbmcgdG8gdGhlIGN1cnJlbnRseSBkZWZpbmVkIHtAbGluayBTZXJpYWxpemVyfVxuICAgICAqL1xuICAgIHNlcmlhbGl6ZSgpOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBPdmVycmlkZSB0aGUgaW1wbGVtZW50YXRpb24gZm9yIGpzJ3MgJ3RvU3RyaW5nKCknIHdoaWNoIHN1Y2tzLi4uXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdG9TdHJpbmcoKTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgRGVmaW5lcyBhIGRlZmF1bHQgaW1wbGVtZW50YXRpb24gZm9yIG9iamVjdCBoYXNoLiBSZWxpZXMgb24gYSB2ZXJ5IGJhc2ljIGltcGxlbWVudGF0aW9uIGJhc2VkIG9uIEphdmEncyBzdHJpbmcgaGFzaDtcbiAgICAgKi9cbiAgICBoYXNoKCk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IERlc2VyaWFsaXplcyBhIE1vZGVsXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgICAqXG4gICAgICogQHRocm93cyB7RXJyb3J9IElmIGl0IGZhaWxzIHRvIHBhcnNlIHRoZSBzdHJpbmcsIG9yIGlmIGl0IGZhaWxzIHRvIGJ1aWxkIHRoZSBtb2RlbFxuICAgICAqL1xuICAgIHN0YXRpYyBkZXNlcmlhbGl6ZShzdHI6IHN0cmluZyk6IGFueTtcblxuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IFJlcG9wdWxhdGVzIHRoZSBPYmplY3QgcHJvcGVydGllcyB3aXRoIHRoZSBvbmVzIGZyb20gdGhlIG5ldyBvYmplY3RcbiAgICAgKiBAZGVzY3JpcHRpb24gSXRlcmF0ZXMgYWxsIGNvbW1vbiBwcm9wZXJ0aWVzIG9mIG9iaiAoaWYgZXhpc3RpbmcpIGFuZCBzZWxmLCBhbmQgY29waWVzIHRoZW0gb250byBzZWxmXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1R9IHNlbGZcbiAgICAgKiBAcGFyYW0ge1QgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbb2JqXVxuICAgICAqXG4gICAgICovXG4gICAgc3RhdGljIGZyb21PYmplY3Q8VCBleHRlbmRzIE1vZGVsPihcbiAgICAgIHNlbGY6IFQsXG4gICAgICBvYmo/OiBUIHwgUmVjb3JkPHN0cmluZywgYW55PlxuICAgICk6IFQ7XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBSZXBvcHVsYXRlcyB0aGUgaW5zdGFuY2Ugd2l0aCB0aGUgb25lcyBmcm9tIHRoZSBuZXcgTW9kZWwgT2JqZWN0XG4gICAgICogQGRlc2NyaXB0aW9uIEl0ZXJhdGVzIGFsbCBjb21tb24gcHJvcGVydGllcyBvZiBvYmogKGlmIGV4aXN0aW5nKSBhbmQgc2VsZiwgYW5kIGNvcGllcyB0aGVtIG9udG8gc2VsZi5cbiAgICAgKiBJcyBhd2FyZSBvZiBuZXN0ZWQgTW9kZWwgT2JqZWN0cyBhbmQgcmVidWlsZHMgdGhlbSBhbHNvLlxuICAgICAqIFdoZW4gTGlzdCBwcm9wZXJ0aWVzIGFyZSBkZWNvcmF0ZWQgd2l0aCB7QGxpbmsgbGlzdH0sIHRoZXkgbGlzdCBpdGVtcyB3aWxsIGFsc28gYmUgcmVidWlsdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtUfSBzZWxmXG4gICAgICogQHBhcmFtIHtUIHwgUmVjb3JkPHN0cmluZywgYW55Pn0gW29ial1cbiAgICAgKlxuICAgICAqL1xuICAgIHN0YXRpYyBmcm9tTW9kZWw8VCBleHRlbmRzIE1vZGVsPihcbiAgICAgIHNlbGY6IFQsXG4gICAgICBvYmo/OiBUIHwgUmVjb3JkPHN0cmluZywgYW55PlxuICAgICk6IFQ7XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBTZXRzIHRoZSBHbG9iYWwge0BsaW5rIE1vZGVsQnVpbGRlckZ1bmN0aW9ufVxuICAgICAqIEBwYXJhbSB7TW9kZWxCdWlsZGVyRnVuY3Rpb259IFtidWlsZGVyXVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRCdWlsZGVyKGJ1aWxkZXI/OiBNb2RlbEJ1aWxkZXJGdW5jdGlvbik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIGN1cnJlbnQgZ2xvYmFsIHtAbGluayBNb2RlbEJ1aWxkZXJGdW5jdGlvbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0QnVpbGRlcigpOiBNb2RlbEJ1aWxkZXJGdW5jdGlvbiB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQge0BsaW5rIE1vZGVsUmVnaXN0cnlNYW5hZ2VyfVxuICAgICAqXG4gICAgICogQHJldHVybiBNb2RlbFJlZ2lzdHJ5LCBkZWZhdWx0cyB0byB7QGxpbmsgTW9kZWxSZWdpc3RyeU1hbmFnZXJ9XG4gICAgICovXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0UmVnaXN0cnk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IGFjdGluZ01vZGVsUmVnaXN0cnlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QnVpbGRlclJlZ2lzdHJ5fSBtb2RlbFJlZ2lzdHJ5IHRoZSBuZXcgaW1wbGVtZW50YXRpb24gb2YgUmVnaXN0cnlcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0UmVnaXN0cnkobW9kZWxSZWdpc3RyeTogQnVpbGRlclJlZ2lzdHJ5PGFueT4pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgcmVnaXN0ZXIgbmV3IE1vZGVsc1xuICAgICAqIEBwYXJhbSB7YW55fSBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZV0gd2hlbiBub3QgZGVmaW5lZCwgdGhlIG5hbWUgb2YgdGhlIGNvbnN0cnVjdG9yIHdpbGwgYmUgdXNlZFxuICAgICAqXG4gICAgICogQHNlZSBNb2RlbFJlZ2lzdHJ5XG4gICAgICovXG4gICAgc3RhdGljIHJlZ2lzdGVyPFQgZXh0ZW5kcyBNb2RlbD4oXG4gICAgICBjb25zdHJ1Y3RvcjogTW9kZWxDb25zdHJ1Y3RvcjxUPixcbiAgICAgIG5hbWU/OiBzdHJpbmdcbiAgICApOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgR2V0cyBhIHJlZ2lzdGVyZWQgTW9kZWwge0BsaW5rIE1vZGVsQ29uc3RydWN0b3J9XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKlxuICAgICAqIEBzZWUgTW9kZWxSZWdpc3RyeVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXQ8VCBleHRlbmRzIE1vZGVsPihuYW1lOiBzdHJpbmcpOiBNb2RlbENvbnN0cnVjdG9yPFQ+IHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NsYXp6XSB3aGVuIHByb3ZpZGVkLCBpdCB3aWxsIGF0dGVtcHQgdG8gZmluZCB0aGUgbWF0Y2hpbmcgY29uc3RydWN0b3JcbiAgICAgKlxuICAgICAqIEB0aHJvd3MgRXJyb3IgSWYgY2xhenogaXMgbm90IGZvdW5kLCBvciBvYmogaXMgbm90IGEge0BsaW5rIE1vZGVsfSBtZWFuaW5nIGl0IGhhcyBubyB7QGxpbmsgTW9kZWxLZXlzLkFOQ0hPUn0gcHJvcGVydHlcbiAgICAgKlxuICAgICAqIEBzZWUgTW9kZWxSZWdpc3RyeVxuICAgICAqL1xuICAgIHN0YXRpYyBidWlsZDxUIGV4dGVuZHMgTW9kZWw+KG9iaj86IFJlY29yZDxzdHJpbmcsIGFueT4sIGNsYXp6Pzogc3RyaW5nKTogVDtcblxuICAgIHN0YXRpYyBnZXRNZXRhZGF0YTxWIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBWKTogYW55O1xuXG4gICAgc3RhdGljIGdldEF0dHJpYnV0ZXM8ViBleHRlbmRzIE1vZGVsPihtb2RlbDogQ29uc3RydWN0b3I8Vj4gfCBWKTogc3RyaW5nW107XG5cbiAgICBzdGF0aWMgZXF1YWxzPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgICBvYmoxOiBNLFxuICAgICAgb2JqMjogTSxcbiAgICAgIC4uLmV4Y2VwdGlvbnM6IGFueVtdXG4gICAgKTogYm9vbGVhbjtcblxuICAgIHN0YXRpYyBoYXNFcnJvcnM8TSBleHRlbmRzIE1vZGVsPihcbiAgICAgIG1vZGVsOiBNLFxuICAgICAgLi4ucHJvcHNUb0lnbm9yZTogc3RyaW5nW11cbiAgICApOiBNb2RlbEVycm9yRGVmaW5pdGlvbiB8IHVuZGVmaW5lZDtcblxuICAgIHN0YXRpYyBzZXJpYWxpemU8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSk6IGFueTtcblxuICAgIHN0YXRpYyBoYXNoPE0gZXh0ZW5kcyBNb2RlbD4obW9kZWw6IE0pOiBhbnk7XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBCdWlsZHMgdGhlIGtleSB0byBzdG9yZSBhcyBNZXRhZGF0YSB1bmRlciBSZWZsZWN0aW9uc1xuICAgICAqIEBkZXNjcmlwdGlvbiBjb25jYXRlbmF0ZXMge0BsaW5rIE1vZGVsS2V5cyNSRUZMRUNUfSB3aXRoIHRoZSBwcm92aWRlZCBrZXlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gICAgICovXG4gICAgc3RhdGljIGtleShzdHI6IHN0cmluZyk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBEZXRlcm1pbmVzIGlmIGFuIG9iamVjdCBpcyBhIG1vZGVsIGluc3RhbmNlIG9yIGhhcyBtb2RlbCBtZXRhZGF0YVxuICAgICAqIEBzdW1tYXJ5IENoZWNrcyB3aGV0aGVyIGEgZ2l2ZW4gb2JqZWN0IGlzIGVpdGhlciBhbiBpbnN0YW5jZSBvZiB0aGUgTW9kZWwgY2xhc3Mgb3JcbiAgICAgKiBoYXMgbW9kZWwgbWV0YWRhdGEgYXR0YWNoZWQgdG8gaXQuIFRoaXMgZnVuY3Rpb24gaXMgZXNzZW50aWFsIGZvciBzZXJpYWxpemF0aW9uIGFuZFxuICAgICAqIGRlc2VyaWFsaXphdGlvbiBwcm9jZXNzZXMsIGFzIGl0IGhlbHBzIGlkZW50aWZ5IG1vZGVsIG9iamVjdHMgdGhhdCBuZWVkIHNwZWNpYWwgaGFuZGxpbmcuXG4gICAgICogSXQgc2FmZWx5IGhhbmRsZXMgcG90ZW50aWFsIGVycm9ycyBkdXJpbmcgbWV0YWRhdGEgcmV0cmlldmFsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSB0YXJnZXQgLSBUaGUgb2JqZWN0IHRvIGNoZWNrXG4gICAgICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgb2JqZWN0IGlzIGEgbW9kZWwgaW5zdGFuY2Ugb3IgaGFzIG1vZGVsIG1ldGFkYXRhLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIC8vIENoZWNrIGlmIGFuIG9iamVjdCBpcyBhIG1vZGVsXG4gICAgICogY29uc3QgdXNlciA9IG5ldyBVc2VyKHsgbmFtZTogXCJKb2huXCIgfSk7XG4gICAgICogY29uc3QgaXNVc2VyTW9kZWwgPSBpc01vZGVsKHVzZXIpOyAvLyB0cnVlXG4gICAgICpcbiAgICAgKiAvLyBDaGVjayBhIHBsYWluIG9iamVjdFxuICAgICAqIGNvbnN0IHBsYWluT2JqZWN0ID0geyBuYW1lOiBcIkpvaG5cIiB9O1xuICAgICAqIGNvbnN0IGlzUGxhaW5PYmplY3RNb2RlbCA9IGlzTW9kZWwocGxhaW5PYmplY3QpOyAvLyBmYWxzZVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHN0YXRpYyBpc01vZGVsKHRhcmdldDogUmVjb3JkPHN0cmluZywgYW55Pik6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQ2hlY2tzIGlmIGEgcHJvcGVydHkgb2YgYSBtb2RlbCBpcyBpdHNlbGYgYSBtb2RlbCBvciBoYXMgYSBtb2RlbCB0eXBlXG4gICAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB3aGV0aGVyIGEgc3BlY2lmaWMgcHJvcGVydHkgb2YgYSBtb2RlbCBpbnN0YW5jZSBpcyBlaXRoZXIgYSBtb2RlbCBpbnN0YW5jZVxuICAgICAqIG9yIGhhcyBhIHR5cGUgdGhhdCBpcyByZWdpc3RlcmVkIGFzIGEgbW9kZWwuIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCBmb3IgbW9kZWwgc2VyaWFsaXphdGlvblxuICAgICAqIGFuZCBkZXNlcmlhbGl6YXRpb24gdG8gcHJvcGVybHkgaGFuZGxlIG5lc3RlZCBtb2RlbHMuXG4gICAgICogQHRlbXBsYXRlIE0gZXh0ZW5kcyB7QGxpbmsgTW9kZWx9XG4gICAgICogQHBhcmFtIHtNfSB0YXJnZXQgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gY2hlY2tcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gYXR0cmlidXRlIC0gVGhlIHByb3BlcnR5IG5hbWUgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJuIHtib29sZWFuIHwgc3RyaW5nIHwgdW5kZWZpbmVkfSBSZXR1cm5zIHRydWUgaWYgdGhlIHByb3BlcnR5IGlzIGEgbW9kZWwgaW5zdGFuY2UsXG4gICAgICogdGhlIG1vZGVsIG5hbWUgaWYgdGhlIHByb3BlcnR5IGhhcyBhIG1vZGVsIHR5cGUsIG9yIHVuZGVmaW5lZCBpZiBub3QgYSBtb2RlbFxuICAgICAqL1xuICAgIHN0YXRpYyBpc1Byb3BlcnR5TW9kZWw8TSBleHRlbmRzIE1vZGVsPihcbiAgICAgIHRhcmdldDogTSxcbiAgICAgIGF0dHJpYnV0ZTogc3RyaW5nXG4gICAgKTogYm9vbGVhbiB8IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlLFxuICBSZXBvc2l0b3J5LFxuICBTZXJpYWxpemF0aW9uRXJyb3IsXG59IGZyb20gXCIuLi9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERCS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gaXNUcmFuc2llbnQ8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSkge1xuICByZXR1cm4gISEoXG4gICAgUmVmbGVjdC5nZXRNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuVFJBTlNJRU5UKSwgbW9kZWwuY29uc3RydWN0b3IpIHx8XG4gICAgUmVmbGVjdC5nZXRNZXRhZGF0YShcbiAgICAgIFJlcG9zaXRvcnkua2V5KERCS2V5cy5UUkFOU0lFTlQpLFxuICAgICAgTW9kZWwuZ2V0KG1vZGVsLmNvbnN0cnVjdG9yLm5hbWUpIGFzIGFueVxuICAgIClcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1vZGVsVG9UcmFuc2llbnQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE1cbik6IHsgbW9kZWw6IE07IHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT4gfSB7XG4gIGlmICghaXNUcmFuc2llbnQobW9kZWwpKSByZXR1cm4geyBtb2RlbDogbW9kZWwgfTtcbiAgY29uc3QgZGVjczogUmVjb3JkPHN0cmluZywgYW55W10+ID0gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlKFxuICAgIG1vZGVsLFxuICAgIHVuZGVmaW5lZCxcbiAgICBSZXBvc2l0b3J5LmtleShEQktleXMuVFJBTlNJRU5UKVxuICApIGFzIFJlY29yZDxzdHJpbmcsIGFueVtdPjtcblxuICBjb25zdCByZXN1bHQgPSBPYmplY3QuZW50cmllcyhkZWNzKS5yZWR1Y2UoXG4gICAgKFxuICAgICAgYWNjdW06IHsgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT47IHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT4gfSxcbiAgICAgIFtrLCB2YWxdXG4gICAgKSA9PiB7XG4gICAgICBjb25zdCB0cmFuc2llbnQgPSB2YWwuZmluZCgoZWwpID0+IGVsLmtleSA9PT0gXCJcIik7XG4gICAgICBpZiAodHJhbnNpZW50KSB7XG4gICAgICAgIGFjY3VtLnRyYW5zaWVudCA9IGFjY3VtLnRyYW5zaWVudCB8fCB7fTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhY2N1bS50cmFuc2llbnRba10gPSBtb2RlbFtrIGFzIGtleW9mIE1dO1xuICAgICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgICAgIGBGYWlsZWQgdG8gc2VyaWFsaXplIHRyYW5zaWVudCBwcm9wZXJ0eSAke2t9OiAke2V9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFjY3VtLm1vZGVsID0gYWNjdW0ubW9kZWwgfHwge307XG4gICAgICAgIGFjY3VtLm1vZGVsW2tdID0gKG1vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2tdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sXG4gICAge30gYXMgeyBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PjsgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PiB9XG4gICk7XG4gIHJlc3VsdC5tb2RlbCA9IE1vZGVsLmJ1aWxkKHJlc3VsdC5tb2RlbCwgbW9kZWwuY29uc3RydWN0b3IubmFtZSk7XG4gIHJldHVybiByZXN1bHQgYXMgeyBtb2RlbDogTTsgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PiB9O1xufVxuIl0sIm5hbWVzIjpbIkRlY29yYXRvck1lc3NhZ2VzIl0sIm1hcHBpbmdzIjoiOzs7OztBQUVBOzs7OztBQUtHO0FBQ1UsTUFBQSxNQUFNLEdBQUc7QUFDcEIsSUFBQSxPQUFPLEVBQUUsQ0FBQSxFQUFHLFNBQVMsQ0FBQyxPQUFPLENBQWMsWUFBQSxDQUFBO0FBQzNDLElBQUEsVUFBVSxFQUFFLFlBQVk7QUFDeEIsSUFBQSxLQUFLLEVBQUUsUUFBUTtBQUNmLElBQUEsRUFBRSxFQUFFLElBQUk7QUFDUixJQUFBLEtBQUssRUFBRSxPQUFPO0FBQ2QsSUFBQSxNQUFNLEVBQUUsUUFBUTtBQUNoQixJQUFBLFNBQVMsRUFBRSxXQUFXO0FBQ3RCLElBQUEsUUFBUSxFQUFFLFVBQVU7QUFDcEIsSUFBQSxTQUFTLEVBQUUsV0FBVztBQUN0QixJQUFBLFNBQVMsRUFBRSxXQUFXO0FBQ3RCLElBQUEsSUFBSSxFQUFFLE1BQU07QUFDWixJQUFBLFFBQVEsRUFBRSxVQUFVO0FBQ3BCLElBQUEsT0FBTyxFQUFFLFNBQVM7QUFDbEIsSUFBQSxRQUFRLEVBQUUsZUFBZTs7QUFHM0I7Ozs7Ozs7QUFPRztBQUNJLE1BQU0sZ0JBQWdCLEdBQUc7QUFFaEM7Ozs7O0FBS0c7QUFDSSxNQUFNLHdCQUF3QixHQUFHOztBQ3ZDeEM7Ozs7O0FBS0c7QUFDVSxNQUFB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
|
|
2818
|
+
/**
|
|
2819
|
+
* @description Database decorators for TypeScript applications
|
|
2820
|
+
* @summary A comprehensive library providing decorators and utilities for database operations, model definitions, validation, and repository patterns in TypeScript applications
|
|
2821
|
+
* @module db-decorators
|
|
2822
|
+
*/
|
|
2823
|
+
/**
|
|
2824
|
+
* @description Current version of the reflection package
|
|
2825
|
+
* @summary Stores the semantic version number of the package
|
|
2826
|
+
* @const VERSION
|
|
2827
|
+
* @memberOf module:db-decorators
|
|
2828
|
+
*/
|
|
2829
|
+
const VERSION = "0.6.3";
|
|
2830
|
+
|
|
2831
|
+
export { BaseError, BaseRepository, BulkCrudOperationKeys, ConflictError, Context, DBKeys, DBOperations, DEFAULT_ERROR_MESSAGES, DEFAULT_TIMESTAMP_FORMAT, DefaultContextFactory, DefaultRepositoryFlags, DefaultSeparator, InternalError, NotFoundError, OperationKeys, Operations, OperationsRegistry, ReadOnlyValidator, Repository, SerializationError, TimestampValidator, UpdateValidationKeys, UpdateValidator, VERSION, ValidationError, after, afterAny, afterCreate, afterCreateUpdate, afterDelete, afterRead, afterUpdate, composed, composedFromCreateUpdate, composedFromKeys, enforceDBDecorators, findModelId, findPrimaryKey, getAllPropertyDecoratorsRecursive, getDbDecorators, getHandlerArgs, getValidatableUpdateProps, hash, hashOnCreateUpdate, id, isTransient, modelToTransient, on, onAny, onCreate, onCreateUpdate, onDelete, onRead, onUpdate, operation, prefixMethod, readonly, serialize, serializeAfterAll, serializeOnCreateUpdate, suffixMethod, timestamp, timestampHandler, transient, validateCompare, validateDecorator, validateDecorators, version, versionCreateUpdate, wrapMethodWithContext };
|
|
2832
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGItZGVjb3JhdG9ycy5lc20uY2pzIiwic291cmNlcyI6WyIuLi9zcmMvbW9kZWwvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vY29uc3RhbnRzLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vdmFsaWRhdG9ycy9SZWFkT25seVZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL3ZhbGlkYXRvcnMvVGltZXN0YW1wVmFsaWRhdG9yLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vdmFsaWRhdG9ycy9VcGRhdGVWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi92YWxpZGF0aW9uLnRzIiwiLi4vc3JjL29wZXJhdGlvbnMvY29uc3RhbnRzLnRzIiwiLi4vc3JjL29wZXJhdGlvbnMvT3BlcmF0aW9uc1JlZ2lzdHJ5LnRzIiwiLi4vc3JjL29wZXJhdGlvbnMvT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9vcGVyYXRpb25zL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvcmVwb3NpdG9yeS9lcnJvcnMudHMiLCIuLi9zcmMvcmVwb3NpdG9yeS91dGlscy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L2NvbnN0YW50cy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L0NvbnRleHQudHMiLCIuLi9zcmMvcmVwb3NpdG9yeS93cmFwcGVycy50cyIsIi4uL3NyYy9pZGVudGl0eS91dGlscy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L0Jhc2VSZXBvc2l0b3J5LnRzIiwiLi4vc3JjL3JlcG9zaXRvcnkvUmVwb3NpdG9yeS50cyIsIi4uL3NyYy92YWxpZGF0aW9uL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvaWRlbnRpdHkvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9tb2RlbC92YWxpZGF0aW9uLnRzIiwiLi4vc3JjL21vZGVsL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvbW9kZWwvb3ZlcnJpZGVzLnRzIiwiLi4vc3JjL21vZGVsL3V0aWxzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1vZGVsS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGF0YWJhc2UgcmVmbGVjdGlvbiBrZXlzXG4gKiBAc3VtbWFyeSBDb2xsZWN0aW9uIG9mIGtleXMgdXNlZCBmb3IgcmVmbGVjdGlvbiBtZXRhZGF0YSBpbiBkYXRhYmFzZSBvcGVyYXRpb25zXG4gKiBAY29uc3QgREJLZXlzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IERCS2V5cyA9IHtcbiAgUkVGTEVDVDogYCR7TW9kZWxLZXlzLlJFRkxFQ1R9cGVyc2lzdGVuY2UuYCxcbiAgUkVQT1NJVE9SWTogXCJyZXBvc2l0b3J5XCIsXG4gIENMQVNTOiBcIl9jbGFzc1wiLFxuICBJRDogXCJpZFwiLFxuICBJTkRFWDogXCJpbmRleFwiLFxuICBVTklRVUU6IFwidW5pcXVlXCIsXG4gIFNFUklBTElaRTogXCJzZXJpYWxpemVcIixcbiAgUkVBRE9OTFk6IFwicmVhZG9ubHlcIixcbiAgVElNRVNUQU1QOiBcInRpbWVzdGFtcFwiLFxuICBUUkFOU0lFTlQ6IFwidHJhbnNpZW50XCIsXG4gIEhBU0g6IFwiaGFzaFwiLFxuICBDT01QT1NFRDogXCJjb21wb3NlZFwiLFxuICBWRVJTSU9OOiBcInZlcnNpb25cIixcbiAgT1JJR0lOQUw6IFwiX19vcmlnaW5hbE9ialwiLFxufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBzZXBhcmF0b3IgY2hhcmFjdGVyIGZvciBjb21wb3NpdGUgaW5kZXhlc1xuICogQHN1bW1hcnkgVGhlIGRlZmF1bHQgc2VwYXJhdG9yIGNoYXJhY3RlciB1c2VkIHdoZW4gY29uY2F0ZW5hdGluZyBtdWx0aXBsZSBmaWVsZHMgaW50byBhIHNpbmdsZSBpbmRleFxuICogQGNvbnN0IERlZmF1bHRTZXBhcmF0b3JcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdFNlcGFyYXRvciA9IFwiX1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGZvcm1hdCBmb3IgdGltZXN0YW1wIGZpZWxkc1xuICogQHN1bW1hcnkgU3RhbmRhcmQgZGF0ZSBmb3JtYXQgc3RyaW5nIHVzZWQgZm9yIHRpbWVzdGFtcCBmaWVsZHMgaW4gZGF0YWJhc2UgbW9kZWxzXG4gKiBAY29uc3QgREVGQVVMVF9USU1FU1RBTVBfRk9STUFUXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfVElNRVNUQU1QX0ZPUk1BVCA9IFwiZGQvTU0veXl5eSBISDptbTpzczpTXCI7XG4iLCJpbXBvcnQgeyBEQktleXMgfSBmcm9tIFwiLi4vbW9kZWwvY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbGxlY3Rpb24gb2YgZGVmYXVsdCBlcnJvciBtZXNzYWdlcyB1c2VkIGJ5IHZhbGlkYXRvcnMuXG4gKiBAc3VtbWFyeSBIb2xkcyB0aGUgZGVmYXVsdCBlcnJvciBtZXNzYWdlcyBmb3IgdmFyaW91cyB2YWxpZGF0aW9uIHNjZW5hcmlvcyBpbmNsdWRpbmcgSUQgdmFsaWRhdGlvbiwgcmVhZG9ubHkgcHJvcGVydGllcywgYW5kIHRpbWVzdGFtcHMuXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBFcnJvck1lc3NhZ2VzXG4gKiBAcHJvcGVydHkge09iamVjdH0gSUQgLSBFcnJvciBtZXNzYWdlcyBmb3IgSUQgdmFsaWRhdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IElELklOVkFMSUQgLSBFcnJvciBtZXNzYWdlIHdoZW4gYW4gSUQgaXMgaW52YWxpZFxuICogQHByb3BlcnR5IHtzdHJpbmd9IElELlJFUVVJUkVEIC0gRXJyb3IgbWVzc2FnZSB3aGVuIGFuIElEIGlzIG1pc3NpbmdcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBSRUFET05MWSAtIEVycm9yIG1lc3NhZ2VzIGZvciByZWFkb25seSBwcm9wZXJ0aWVzXG4gKiBAcHJvcGVydHkge3N0cmluZ30gUkVBRE9OTFkuSU5WQUxJRCAtIEVycm9yIG1lc3NhZ2Ugd2hlbiBhdHRlbXB0aW5nIHRvIHVwZGF0ZSBhIHJlYWRvbmx5IHByb3BlcnR5XG4gKiBAcHJvcGVydHkge09iamVjdH0gVElNRVNUQU1QIC0gRXJyb3IgbWVzc2FnZXMgZm9yIHRpbWVzdGFtcCB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gVElNRVNUQU1QLlJFUVVJUkVEIC0gRXJyb3IgbWVzc2FnZSB3aGVuIGEgdGltZXN0YW1wIGlzIG1pc3NpbmdcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUSU1FU1RBTVAuREFURSAtIEVycm9yIG1lc3NhZ2Ugd2hlbiBhIHRpbWVzdGFtcCBpcyBub3QgYSB2YWxpZCBkYXRlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gVElNRVNUQU1QLklOVkFMSUQgLSBFcnJvciBtZXNzYWdlIHdoZW4gYSB0aW1lc3RhbXAgaXMgbm90IGluY3JlYXNpbmdcbiAqIEBjb25zdCBERUZBVUxUX0VSUk9SX01FU1NBR0VTXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnZhbGlkYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRVJST1JfTUVTU0FHRVMgPSB7XG4gIElEOiB7XG4gICAgSU5WQUxJRDogXCJUaGlzIElkIGlzIGludmFsaWRcIixcbiAgICBSRVFVSVJFRDogXCJUaGUgSWQgaXMgbWFuZGF0b3J5XCIsXG4gIH0sXG4gIFJFQURPTkxZOiB7XG4gICAgSU5WQUxJRDogXCJUaGlzIGNhbm5vdCBiZSB1cGRhdGVkXCIsXG4gIH0sXG4gIFRJTUVTVEFNUDoge1xuICAgIFJFUVVJUkVEOiBcIlRpbWVzdGFtcCBpcyBNYW5kYXRvcnlcIixcbiAgICBEQVRFOiBcIlRoZSBUaW1lc3RhbXAgbXVzdCB0aGUgYSB2YWxpZCBkYXRlXCIsXG4gICAgSU5WQUxJRDogXCJUaGlzIHZhbHVlIG11c3QgYWx3YXlzIGluY3JlYXNlXCIsXG4gIH0sXG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb25zdGFudHMgdXNlZCBmb3IgcmVmbGVjdGlvbi1iYXNlZCB2YWxpZGF0aW9uIGR1cmluZyB1cGRhdGUgb3BlcmF0aW9ucy5cbiAqIEBzdW1tYXJ5IEtleXMgdXNlZCBmb3Igc3RvcmluZyBhbmQgcmV0cmlldmluZyB2YWxpZGF0aW9uIG1ldGFkYXRhIG9uIG1vZGVsIHByb3BlcnRpZXMgZHVyaW5nIHVwZGF0ZSBvcGVyYXRpb25zLlxuICogQHR5cGVkZWYge09iamVjdH0gVmFsaWRhdGlvbktleXNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBSRUZMRUNUIC0gQmFzZSByZWZsZWN0aW9uIGtleSBwcmVmaXggZm9yIHVwZGF0ZSB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gVElNRVNUQU1QIC0gS2V5IGZvciB0aW1lc3RhbXAgdmFsaWRhdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IFJFQURPTkxZIC0gS2V5IGZvciByZWFkb25seSBwcm9wZXJ0eSB2YWxpZGF0aW9uXG4gKiBAY29uc3QgVXBkYXRlVmFsaWRhdGlvbktleXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dmFsaWRhdGlvblxuICovXG5leHBvcnQgY29uc3QgVXBkYXRlVmFsaWRhdGlvbktleXMgPSB7XG4gIFJFRkxFQ1Q6IFwiZGIudXBkYXRlLnZhbGlkYXRpb24uXCIsXG4gIFRJTUVTVEFNUDogREJLZXlzLlRJTUVTVEFNUCxcbiAgUkVBRE9OTFk6IERCS2V5cy5SRUFET05MWSxcbn07XG4iLCJpbXBvcnQgeyB2YWxpZGF0b3IsIFZhbGlkYXRvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMsIFVwZGF0ZVZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgaXNFcXVhbCB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBIHZhbGlkYXRvciB0aGF0IGVuc3VyZXMgcHJvcGVydGllcyBtYXJrZWQgYXMgcmVhZG9ubHkgY2Fubm90IGJlIG1vZGlmaWVkIGR1cmluZyB1cGRhdGVzLlxuICogQHN1bW1hcnkgVmFsaWRhdG9yIGZvciB0aGUge0BsaW5rIHJlYWRvbmx5fSBkZWNvcmF0b3IgdGhhdCBjaGVja3MgaWYgYSB2YWx1ZSBoYXMgYmVlbiBjaGFuZ2VkIGR1cmluZyBhbiB1cGRhdGUgb3BlcmF0aW9uLiBJdCBjb21wYXJlcyB0aGUgbmV3IHZhbHVlIHdpdGggdGhlIG9sZCB2YWx1ZSBhbmQgcmV0dXJucyBhbiBlcnJvciBtZXNzYWdlIGlmIHRoZXkgYXJlIG5vdCBlcXVhbC5cbiAqIEBwYXJhbSB7YW55fSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBiZSB2YWxpZGF0ZWRcbiAqIEBwYXJhbSB7YW55fSBvbGRWYWx1ZSAtIFRoZSBwcmV2aW91cyB2YWx1ZSB0byBjb21wYXJlIGFnYWluc3RcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gLSBPcHRpb25hbCBjdXN0b20gZXJyb3IgbWVzc2FnZVxuICogQGNsYXNzIFJlYWRPbmx5VmFsaWRhdG9yXG4gKiBAZXhhbXBsZVxuICogLy8gVXNpbmcgUmVhZE9ubHlWYWxpZGF0b3Igd2l0aCBhIHJlYWRvbmx5IHByb3BlcnR5XG4gKiBjbGFzcyBVc2VyIHtcbiAqICAgQHJlYWRvbmx5KClcbiAqICAgaWQ6IHN0cmluZztcbiAqICAgXG4gKiAgIG5hbWU6IHN0cmluZztcbiAqICAgXG4gKiAgIGNvbnN0cnVjdG9yKGlkOiBzdHJpbmcsIG5hbWU6IHN0cmluZykge1xuICogICAgIHRoaXMuaWQgPSBpZDtcbiAqICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICogICB9XG4gKiB9XG4gKiBcbiAqIC8vIFRoaXMgd2lsbCB0cmlnZ2VyIHZhbGlkYXRpb24gZXJyb3Igd2hlbiB0cnlpbmcgdG8gdXBkYXRlXG4gKiBjb25zdCB1c2VyID0gbmV3IFVzZXIoJzEyMycsICdKb2huJyk7XG4gKiB1c2VyLmlkID0gJzQ1Nic7IC8vIFdpbGwgYmUgcHJldmVudGVkIGJ5IFJlYWRPbmx5VmFsaWRhdG9yXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdG9yc1xuICovXG5AdmFsaWRhdG9yKFVwZGF0ZVZhbGlkYXRpb25LZXlzLlJFQURPTkxZKVxuZXhwb3J0IGNsYXNzIFJlYWRPbmx5VmFsaWRhdG9yIGV4dGVuZHMgVmFsaWRhdG9yIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5SRUFET05MWS5JTlZBTElEKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW1wbGVtZW50YXRpb24gb2YgdGhlIGJhc2UgdmFsaWRhdG9yJ3MgaGFzRXJyb3JzIG1ldGhvZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaXMgcmVxdWlyZWQgYnkgdGhlIFZhbGlkYXRvciBpbnRlcmZhY2UgYnV0IG5vdCB1c2VkIGluIHRoaXMgdmFsaWRhdG9yIGFzIHZhbGlkYXRpb24gb25seSBoYXBwZW5zIGR1cmluZyB1cGRhdGVzLlxuICAgKiBAcGFyYW0ge2FueX0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gdmFsaWRhdGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH0gQWx3YXlzIHJldHVybnMgdW5kZWZpbmVkIGFzIHRoaXMgdmFsaWRhdG9yIG9ubHkgd29ya3MgZHVyaW5nIHVwZGF0ZXNcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgaGFzRXJyb3JzKHZhbHVlOiBhbnksIC4uLmFyZ3M6IGFueVtdKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDaGVja3MgaWYgYSB2YWx1ZSBoYXMgYmVlbiBtb2RpZmllZCBkdXJpbmcgYW4gdXBkYXRlIG9wZXJhdGlvbi5cbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIGEgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkIGJ5IGNvbXBhcmluZyBpdCB3aXRoIHRoZSBwcmV2aW91cyB2YWx1ZSB1c2luZyBkZWVwIGVxdWFsaXR5LlxuICAgKiBAcGFyYW0ge2FueX0gdmFsdWUgLSBUaGUgbmV3IHZhbHVlIHRvIHZhbGlkYXRlXG4gICAqIEBwYXJhbSB7YW55fSBvbGRWYWx1ZSAtIFRoZSBvcmlnaW5hbCB2YWx1ZSB0byBjb21wYXJlIGFnYWluc3RcbiAgICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSAtIE9wdGlvbmFsIGN1c3RvbSBlcnJvciBtZXNzYWdlIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0XG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH0gQW4gZXJyb3IgbWVzc2FnZSBpZiB2YWxpZGF0aW9uIGZhaWxzLCB1bmRlZmluZWQgb3RoZXJ3aXNlXG4gICAqL1xuICBwdWJsaWMgdXBkYXRlSGFzRXJyb3JzKFxuICAgIHZhbHVlOiBhbnksXG4gICAgb2xkVmFsdWU6IGFueSxcbiAgICBtZXNzYWdlPzogc3RyaW5nLFxuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICByZXR1cm4gaXNFcXVhbCh2YWx1ZSwgb2xkVmFsdWUpXG4gICAgICA/IHVuZGVmaW5lZFxuICAgICAgOiB0aGlzLmdldE1lc3NhZ2UobWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UpO1xuICB9XG59XG4iLCJpbXBvcnQgeyB2YWxpZGF0b3IsIFZhbGlkYXRvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMsIFVwZGF0ZVZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBIHZhbGlkYXRvciB0aGF0IGVuc3VyZXMgdGltZXN0YW1wIHZhbHVlcyBhcmUgb25seSB1cGRhdGVkIHdpdGggbmV3ZXIgdGltZXN0YW1wcy5cbiAqIEBzdW1tYXJ5IFZhbGlkYXRlcyB0aGUgdXBkYXRlIG9mIGEgdGltZXN0YW1wIGJ5IGNvbXBhcmluZyB0aGUgbmV3IHRpbWVzdGFtcCB3aXRoIHRoZSBvbGQgb25lLCBlbnN1cmluZyB0aGUgbmV3IHRpbWVzdGFtcCBpcyBtb3JlIHJlY2VudC5cbiAqIEBwYXJhbSB7RGF0ZXxzdHJpbmd8bnVtYmVyfSB2YWx1ZSAtIFRoZSB0aW1lc3RhbXAgdmFsdWUgdG8gdmFsaWRhdGVcbiAqIEBwYXJhbSB7RGF0ZXxzdHJpbmd8bnVtYmVyfSBvbGRWYWx1ZSAtIFRoZSBwcmV2aW91cyB0aW1lc3RhbXAgdG8gY29tcGFyZSBhZ2FpbnN0XG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIC0gT3B0aW9uYWwgY3VzdG9tIGVycm9yIG1lc3NhZ2VcbiAqIEBjbGFzcyBUaW1lc3RhbXBWYWxpZGF0b3JcbiAqIEBleGFtcGxlXG4gKiAvLyBVc2luZyBUaW1lc3RhbXBWYWxpZGF0b3Igd2l0aCBhIHRpbWVzdGFtcCBwcm9wZXJ0eVxuICogY2xhc3MgRG9jdW1lbnQge1xuICogICBAdGltZXN0YW1wKClcbiAqICAgdXBkYXRlZEF0OiBEYXRlO1xuICogICBcbiAqICAgdGl0bGU6IHN0cmluZztcbiAqICAgXG4gKiAgIGNvbnN0cnVjdG9yKHRpdGxlOiBzdHJpbmcpIHtcbiAqICAgICB0aGlzLnRpdGxlID0gdGl0bGU7XG4gKiAgICAgdGhpcy51cGRhdGVkQXQgPSBuZXcgRGF0ZSgpO1xuICogICB9XG4gKiB9XG4gKiBcbiAqIC8vIFRoaXMgd2lsbCB0cmlnZ2VyIHZhbGlkYXRpb24gZXJyb3Igd2hlbiB0cnlpbmcgdG8gdXBkYXRlIHdpdGggYW4gb2xkZXIgdGltZXN0YW1wXG4gKiBjb25zdCBkb2MgPSBuZXcgRG9jdW1lbnQoJ015IERvY3VtZW50Jyk7XG4gKiBjb25zdCBvbGREYXRlID0gbmV3IERhdGUoMjAyMCwgMCwgMSk7XG4gKiBkb2MudXBkYXRlZEF0ID0gb2xkRGF0ZTsgLy8gV2lsbCBiZSBwcmV2ZW50ZWQgYnkgVGltZXN0YW1wVmFsaWRhdG9yXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdG9yc1xuICovXG5AdmFsaWRhdG9yKFVwZGF0ZVZhbGlkYXRpb25LZXlzLlRJTUVTVEFNUClcbmV4cG9ydCBjbGFzcyBUaW1lc3RhbXBWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3Ige1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihERUZBVUxUX0VSUk9SX01FU1NBR0VTLlRJTUVTVEFNUC5JTlZBTElEKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW1wbGVtZW50YXRpb24gb2YgdGhlIGJhc2UgdmFsaWRhdG9yJ3MgaGFzRXJyb3JzIG1ldGhvZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaXMgcmVxdWlyZWQgYnkgdGhlIFZhbGlkYXRvciBpbnRlcmZhY2UgYnV0IG5vdCB1c2VkIGluIHRoaXMgdmFsaWRhdG9yIGFzIHZhbGlkYXRpb24gb25seSBoYXBwZW5zIGR1cmluZyB1cGRhdGVzLlxuICAgKiBAcGFyYW0ge2FueX0gdmFsdWUgLSBUaGUgdGltZXN0YW1wIHZhbHVlIHRvIHZhbGlkYXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtzdHJpbmcgfCB1bmRlZmluZWR9IEFsd2F5cyByZXR1cm5zIHVuZGVmaW5lZCBhcyB0aGlzIHZhbGlkYXRvciBvbmx5IHdvcmtzIGR1cmluZyB1cGRhdGVzXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGhhc0Vycm9ycyh2YWx1ZTogYW55LCAuLi5hcmdzOiBhbnlbXSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVmFsaWRhdGVzIHRoYXQgYSB0aW1lc3RhbXAgaXMgbmV3ZXIgdGhhbiBpdHMgcHJldmlvdXMgdmFsdWUuXG4gICAqIEBzdW1tYXJ5IENoZWNrcyBpZiBhIHRpbWVzdGFtcCBoYXMgYmVlbiB1cGRhdGVkIHdpdGggYSBtb3JlIHJlY2VudCB2YWx1ZSBieSBjb252ZXJ0aW5nIGJvdGggdmFsdWVzIHRvIERhdGUgb2JqZWN0cyBhbmQgY29tcGFyaW5nIHRoZW0uXG4gICAqIEBwYXJhbSB7RGF0ZXxzdHJpbmd8bnVtYmVyfSB2YWx1ZSAtIFRoZSBuZXcgdGltZXN0YW1wIHZhbHVlIHRvIHZhbGlkYXRlXG4gICAqIEBwYXJhbSB7RGF0ZXxzdHJpbmd8bnVtYmVyfSBvbGRWYWx1ZSAtIFRoZSBvcmlnaW5hbCB0aW1lc3RhbXAgdG8gY29tcGFyZSBhZ2FpbnN0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gLSBPcHRpb25hbCBjdXN0b20gZXJyb3IgbWVzc2FnZSB0byBvdmVycmlkZSB0aGUgZGVmYXVsdFxuICAgKiBAcmV0dXJuIHtzdHJpbmcgfCB1bmRlZmluZWR9IEFuIGVycm9yIG1lc3NhZ2UgaWYgdmFsaWRhdGlvbiBmYWlscyAobmV3IHRpbWVzdGFtcCBpcyBub3QgbmV3ZXIpLCB1bmRlZmluZWQgb3RoZXJ3aXNlXG4gICAqL1xuICBwdWJsaWMgdXBkYXRlSGFzRXJyb3JzKFxuICAgIHZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVtYmVyLFxuICAgIG9sZFZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1lc3NhZ2U/OiBzdHJpbmdcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgbWVzc2FnZSA9IG1lc3NhZ2UgfHwgdGhpcy5nZXRNZXNzYWdlKG1lc3NhZ2UgfHwgdGhpcy5tZXNzYWdlKTtcblxuICAgIHRyeSB7XG4gICAgICB2YWx1ZSA9IG5ldyBEYXRlKHZhbHVlKTtcbiAgICAgIG9sZFZhbHVlID0gbmV3IERhdGUob2xkVmFsdWUpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZSA8PSBvbGRWYWx1ZSA/IG1lc3NhZ2UgOiB1bmRlZmluZWQ7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIERFRkFVTFRfRVJST1JfTUVTU0FHRVMgYXMgRGVjb3JhdG9yTWVzc2FnZXMsXG4gIFZhbGlkYXRvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBYnN0cmFjdCBiYXNlIGNsYXNzIGZvciB2YWxpZGF0b3JzIHRoYXQgY29tcGFyZSBuZXcgdmFsdWVzIHdpdGggb2xkIHZhbHVlcyBkdXJpbmcgdXBkYXRlcy5cbiAqIEBzdW1tYXJ5IEJhc2UgY2xhc3MgZm9yIGFuIFVwZGF0ZSB2YWxpZGF0b3IgdGhhdCBwcm92aWRlcyBhIGZyYW1ld29yayBmb3IgaW1wbGVtZW50aW5nIHZhbGlkYXRpb24gbG9naWMgdGhhdCBjb21wYXJlcyBhIG5ldyB2YWx1ZSB3aXRoIGl0cyBwcmV2aW91cyBzdGF0ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gLSBFcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgRGVjb3JhdG9yTWVzc2FnZXMjREVGQVVMVH1cbiAqIEBwYXJhbSB7c3RyaW5nW119IFthY2NlcHRlZFR5cGVzXSAtIFRoZSBhY2NlcHRlZCB2YWx1ZSB0eXBlcyBieSB0aGUgZGVjb3JhdG9yXG4gKiBAY2xhc3MgVXBkYXRlVmFsaWRhdG9yXG4gKiBAZXhhbXBsZVxuICogLy8gRXh0ZW5kaW5nIFVwZGF0ZVZhbGlkYXRvciB0byBjcmVhdGUgYSBjdXN0b20gdmFsaWRhdG9yXG4gKiBjbGFzcyBNeUN1c3RvbVZhbGlkYXRvciBleHRlbmRzIFVwZGF0ZVZhbGlkYXRvciB7XG4gKiAgIGNvbnN0cnVjdG9yKCkge1xuICogICAgIHN1cGVyKFwiQ3VzdG9tIHZhbGlkYXRpb24gZmFpbGVkXCIpO1xuICogICB9XG4gKiAgIFxuICogICBwdWJsaWMgdXBkYXRlSGFzRXJyb3JzKHZhbHVlOiBhbnksIG9sZFZhbHVlOiBhbnkpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICogICAgIC8vIEN1c3RvbSB2YWxpZGF0aW9uIGxvZ2ljXG4gKiAgICAgaWYgKHZhbHVlID09PSBvbGRWYWx1ZSkge1xuICogICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZTtcbiAqICAgICB9XG4gKiAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAqICAgfVxuICogICBcbiAqICAgaGFzRXJyb3JzKHZhbHVlOiBhbnkpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICogICAgIHJldHVybiB1bmRlZmluZWQ7IC8vIE5vdCB1c2VkIGZvciB1cGRhdGUgdmFsaWRhdG9yc1xuICogICB9XG4gKiB9XG4gKiBAY2F0ZWdvcnkgVmFsaWRhdG9yc1xuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVXBkYXRlVmFsaWRhdG9yIGV4dGVuZHMgVmFsaWRhdG9yIHtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyA9IERlY29yYXRvck1lc3NhZ2VzLkRFRkFVTFQsXG4gICAgLi4uYWNjZXB0ZWRUeXBlczogc3RyaW5nW11cbiAgKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgLi4uYWNjZXB0ZWRUeXBlcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgc3ViY2xhc3NlcyB0byBwZXJmb3JtIHVwZGF0ZSB2YWxpZGF0aW9uLlxuICAgKiBAc3VtbWFyeSBWYWxpZGF0ZXMgYSB2YWx1ZSBieSBjb21wYXJpbmcgaXQgdG8gaXRzIG9sZCB2ZXJzaW9uIHRvIGRldGVybWluZSBpZiB0aGUgdXBkYXRlIGlzIHZhbGlkLlxuICAgKiBAcGFyYW0ge2FueX0gdmFsdWUgLSBUaGUgbmV3IHZhbHVlIHRvIHZhbGlkYXRlXG4gICAqIEBwYXJhbSB7YW55fSBvbGRWYWx1ZSAtIFRoZSBwcmV2aW91cyB2YWx1ZSB0byBjb21wYXJlIGFnYWluc3RcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRoYXQgbWF5IGJlIG5lZWRlZCBmb3IgdmFsaWRhdGlvblxuICAgKiBAcmV0dXJuIHtzdHJpbmcgfCB1bmRlZmluZWR9IEFuIGVycm9yIG1lc3NhZ2UgaWYgdmFsaWRhdGlvbiBmYWlscywgdW5kZWZpbmVkIGlmIHZhbGlkYXRpb24gcGFzc2VzXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgdXBkYXRlSGFzRXJyb3JzKFxuICAgIHZhbHVlOiBhbnksXG4gICAgb2xkVmFsdWU6IGFueSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG59XG4iLCJpbXBvcnQge1xuICBWYWxpZGF0b3IsXG4gIFZhbGlkYXRpb24sXG4gIFZhbGlkYXRvckRlZmluaXRpb24sXG4gIElWYWxpZGF0b3JSZWdpc3RyeSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgVXBkYXRlVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEga2V5IGZvciB1cGRhdGUgdmFsaWRhdGlvbiBtZXRhZGF0YS5cbiAqIEBzdW1tYXJ5IEJ1aWxkcyB0aGUga2V5IHRvIHN0b3JlIGFzIG1ldGFkYXRhIHVuZGVyIFJlZmxlY3Rpb25zIGZvciB1cGRhdGUgdmFsaWRhdGlvbiBieSBwcmVmaXhpbmcgdGhlIHByb3ZpZGVkIGtleSB3aXRoIHRoZSB1cGRhdGUgdmFsaWRhdGlvbiBwcmVmaXguXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGJhc2Uga2V5IHRvIGJlIHByZWZpeGVkXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBjb21wbGV0ZSBtZXRhZGF0YSBrZXkgZm9yIHVwZGF0ZSB2YWxpZGF0aW9uXG4gKiBAZnVuY3Rpb24gdXBkYXRlS2V5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuVmFsaWRhdGlvbi51cGRhdGVLZXkgPSBmdW5jdGlvbiAoa2V5OiBzdHJpbmcpIHtcbiAgcmV0dXJuIFVwZGF0ZVZhbGlkYXRpb25LZXlzLlJFRkxFQ1QgKyBrZXk7XG59O1xuXG5kZWNsYXJlIG1vZHVsZSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gIGRlY2xhcmUgY2xhc3MgVmFsaWRhdGlvbiB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgYWN0aW5nVmFsaWRhdG9yUmVnaXN0cnk/O1xuICAgIHByaXZhdGUgY29uc3RydWN0b3IoKTtcbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBhY3RpbmcgVmFsaWRhdG9yUmVnaXN0cnlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SVZhbGlkYXRvclJlZ2lzdHJ5fSB2YWxpZGF0b3JSZWdpc3RyeSB0aGUgbmV3IGltcGxlbWVudGF0aW9uIG9mIHRoZSB2YWxpZGF0b3IgUmVnaXN0cnlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9uKFZhbGlkYXRvcik6IFZhbGlkYXRvcn0gW21pZ3JhdGlvbkhhbmRsZXJdIHRoZSBtZXRob2QgdG8gbWFwIHRoZSB2YWxpZGF0b3IgaWYgcmVxdWlyZWQ7XG4gICAgICovXG4gICAgc3RhdGljIHNldFJlZ2lzdHJ5KFxuICAgICAgdmFsaWRhdG9yUmVnaXN0cnk6IElWYWxpZGF0b3JSZWdpc3RyeTxWYWxpZGF0b3I+LFxuICAgICAgbWlncmF0aW9uSGFuZGxlcj86ICh2YWxpZGF0b3I6IFZhbGlkYXRvcikgPT4gVmFsaWRhdG9yXG4gICAgKTogdm9pZDtcbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBjdXJyZW50IFZhbGlkYXRvclJlZ2lzdHJ5XG4gICAgICpcbiAgICAgKiBAcmV0dXJuIElWYWxpZGF0b3JSZWdpc3RyeSwgZGVmYXVsdHMgdG8ge0BsaW5rIFZhbGlkYXRvclJlZ2lzdHJ5fVxuICAgICAqL1xuICAgIHByaXZhdGUgc3RhdGljIGdldFJlZ2lzdHJ5O1xuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhIHZhbGlkYXRvclxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbGlkYXRvcktleSBvbmUgb2YgdGhlIHtAbGluayBWYWxpZGF0aW9uS2V5c31cbiAgICAgKiBAcmV0dXJuIHtWYWxpZGF0b3IgfCB1bmRlZmluZWR9IHRoZSByZWdpc3RlcmVkIFZhbGlkYXRvciBvciB1bmRlZmluZWQgaWYgdGhlcmUgaXMgbm9ubyBtYXRjaGluZyB0aGUgcHJvdmlkZWQga2V5XG4gICAgICovXG4gICAgc3RhdGljIGdldDxUIGV4dGVuZHMgVmFsaWRhdG9yPih2YWxpZGF0b3JLZXk6IHN0cmluZyk6IFQgfCB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgUmVnaXN0ZXJzIHRoZSBwcm92aWRlZCB2YWxpZGF0b3JzIG9udG8gdGhlIHJlZ2lzdHJ5XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1RbXSB8IFZhbGlkYXRvckRlZmluaXRpb25bXX0gdmFsaWRhdG9yXG4gICAgICovXG4gICAgc3RhdGljIHJlZ2lzdGVyPFQgZXh0ZW5kcyBWYWxpZGF0b3I+KFxuICAgICAgLi4udmFsaWRhdG9yOiAoVmFsaWRhdG9yRGVmaW5pdGlvbiB8IFQpW11cbiAgICApOiB2b2lkO1xuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IEJ1aWxkcyB0aGUga2V5IHRvIHN0b3JlIGFzIE1ldGFkYXRhIHVuZGVyIFJlZmxlY3Rpb25zXG4gICAgICogQGRlc2NyaXB0aW9uIGNvbmNhdGVuYXRlcyB7QGxpbmsgVmFsaWRhdGlvbktleXMjUkVGTEVDVH0gd2l0aCB0aGUgcHJvdmlkZWQga2V5XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5XG4gICAgICovXG4gICAgc3RhdGljIGtleShrZXk6IHN0cmluZyk6IHN0cmluZztcblxuICAgIHN0YXRpYyB1cGRhdGVLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmc7XG4gIH1cbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIERhdGFiYXNlIG9wZXJhdGlvbiBrZXkgY29uc3RhbnRzXG4gKiBAc3VtbWFyeSBFbnVtIGRlZmluaW5nIENSVUQgb3BlcmF0aW9ucyBhbmQgdGhlaXIgbGlmZWN5Y2xlIHBoYXNlc1xuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBlbnVtIE9wZXJhdGlvbktleXMge1xuICBSRUZMRUNUID0gXCJkZWNhZi5tb2RlbC5kYi5vcGVyYXRpb25zLlwiLFxuICBDUkVBVEUgPSBcImNyZWF0ZVwiLFxuICBSRUFEID0gXCJyZWFkXCIsXG4gIFVQREFURSA9IFwidXBkYXRlXCIsXG4gIERFTEVURSA9IFwiZGVsZXRlXCIsXG4gIE9OID0gXCJvbi5cIixcbiAgQUZURVIgPSBcImFmdGVyLlwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUeXBlIGZvciBiYXNpYyBDUlVEIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IFVuaW9uIHR5cGUgb2YgdGhlIGZvdXIgYmFzaWMgZGF0YWJhc2Ugb3BlcmF0aW9uczogY3JlYXRlLCByZWFkLCB1cGRhdGUsIGRlbGV0ZVxuICogQHR5cGVkZWYge3N0cmluZ30gQ3J1ZE9wZXJhdGlvbnNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgdHlwZSBDcnVkT3BlcmF0aW9ucyA9XG4gIHwgT3BlcmF0aW9uS2V5cy5DUkVBVEVcbiAgfCBPcGVyYXRpb25LZXlzLlJFQURcbiAgfCBPcGVyYXRpb25LZXlzLlVQREFURVxuICB8IE9wZXJhdGlvbktleXMuREVMRVRFO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCdWxrIGRhdGFiYXNlIG9wZXJhdGlvbiBrZXkgY29uc3RhbnRzXG4gKiBAc3VtbWFyeSBFbnVtIGRlZmluaW5nIGJ1bGsgQ1JVRCBvcGVyYXRpb25zIGZvciBoYW5kbGluZyBtdWx0aXBsZSByZWNvcmRzIGF0IG9uY2VcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZW51bSBCdWxrQ3J1ZE9wZXJhdGlvbktleXMge1xuICBDUkVBVEVfQUxMID0gXCJjcmVhdGVBbGxcIixcbiAgUkVBRF9BTEwgPSBcInJlYWRBbGxcIixcbiAgVVBEQVRFX0FMTCA9IFwidXBkYXRlQWxsXCIsXG4gIERFTEVURV9BTEwgPSBcImRlbGV0ZUFsbFwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUeXBlIGZvciBidWxrIENSVUQgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgVW5pb24gdHlwZSBvZiB0aGUgZm91ciBidWxrIGRhdGFiYXNlIG9wZXJhdGlvbnMgZm9yIGhhbmRsaW5nIG11bHRpcGxlIHJlY29yZHMgYXQgb25jZVxuICogQHR5cGVkZWYge3N0cmluZ30gQnVsa0NydWRPcGVyYXRpb25zXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IHR5cGUgQnVsa0NydWRPcGVyYXRpb25zID1cbiAgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuQ1JFQVRFX0FMTFxuICB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5SRUFEX0FMTFxuICB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5VUERBVEVfQUxMXG4gIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEw7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdyb3VwZWQgQ1JVRCBvcGVyYXRpb25zIGZvciBkZWNvcmF0b3IgbWFwcGluZ1xuICogQHN1bW1hcnkgTWFwcyBvdXQgZ3JvdXBzIG9mIENSVUQgb3BlcmF0aW9ucyBmb3IgZWFzaWVyIG1hcHBpbmcgb2YgZGVjb3JhdG9yc1xuICogQGNvbnN0IERCT3BlcmF0aW9uc1xuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBEQk9wZXJhdGlvbnM6IFJlY29yZDxzdHJpbmcsIENydWRPcGVyYXRpb25zW10+ID0ge1xuICBDUkVBVEU6IFtPcGVyYXRpb25LZXlzLkNSRUFURV0sXG4gIFJFQUQ6IFtPcGVyYXRpb25LZXlzLlJFQURdLFxuICBVUERBVEU6IFtPcGVyYXRpb25LZXlzLlVQREFURV0sXG4gIERFTEVURTogW09wZXJhdGlvbktleXMuREVMRVRFXSxcbiAgQ1JFQVRFX1VQREFURTogW09wZXJhdGlvbktleXMuQ1JFQVRFLCBPcGVyYXRpb25LZXlzLlVQREFURV0sXG4gIFJFQURfQ1JFQVRFOiBbT3BlcmF0aW9uS2V5cy5SRUFELCBPcGVyYXRpb25LZXlzLkNSRUFURV0sXG4gIEFMTDogW1xuICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgXSxcbn07XG4iLCJpbXBvcnQgeyBPcGVyYXRpb25IYW5kbGVyIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IE9wZXJhdGlvbnMgfSBmcm9tIFwiLi9PcGVyYXRpb25zXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVnaXN0cnkgZm9yIGRhdGFiYXNlIG9wZXJhdGlvbiBoYW5kbGVyc1xuICogQHN1bW1hcnkgTWFuYWdlcyBhbmQgc3RvcmVzIG9wZXJhdGlvbiBoYW5kbGVycyBmb3IgZGlmZmVyZW50IG1vZGVsIHByb3BlcnRpZXMgYW5kIG9wZXJhdGlvbnNcbiAqIEBjbGFzcyBPcGVyYXRpb25zUmVnaXN0cnlcbiAqIEB0ZW1wbGF0ZSBNIC0gTW9kZWwgdHlwZVxuICogQHRlbXBsYXRlIFIgLSBSZXBvc2l0b3J5IHR5cGVcbiAqIEB0ZW1wbGF0ZSBWIC0gTWV0YWRhdGEgdHlwZVxuICogQHRlbXBsYXRlIEYgLSBSZXBvc2l0b3J5IGZsYWdzXG4gKiBAdGVtcGxhdGUgQyAtIENvbnRleHQgdHlwZVxuICogQGV4YW1wbGVcbiAqIC8vIENyZWF0ZSBhIHJlZ2lzdHJ5IGFuZCByZWdpc3RlciBhIGhhbmRsZXJcbiAqIGNvbnN0IHJlZ2lzdHJ5ID0gbmV3IE9wZXJhdGlvbnNSZWdpc3RyeSgpO1xuICogcmVnaXN0cnkucmVnaXN0ZXIobXlIYW5kbGVyLCBPcGVyYXRpb25LZXlzLkNSRUFURSwgdGFyZ2V0TW9kZWwsICdwcm9wZXJ0eU5hbWUnKTtcbiAqXG4gKiAvLyBHZXQgaGFuZGxlcnMgZm9yIGEgc3BlY2lmaWMgb3BlcmF0aW9uXG4gKiBjb25zdCBoYW5kbGVycyA9IHJlZ2lzdHJ5LmdldCh0YXJnZXRNb2RlbC5jb25zdHJ1Y3Rvci5uYW1lLCAncHJvcGVydHlOYW1lJywgJ29uQ3JlYXRlJyk7XG4gKlxuICogQG1lcm1haWRcbiAqIGNsYXNzRGlhZ3JhbVxuICogICBjbGFzcyBPcGVyYXRpb25zUmVnaXN0cnkge1xuICogICAgIC1jYWNoZTogUmVjb3JkfnN0cmluZywgUmVjb3JkfnN0cmluZ3xzeW1ib2wsIFJlY29yZH5zdHJpbmcsIFJlY29yZH5zdHJpbmcsIE9wZXJhdGlvbkhhbmRsZXJ+fn5+XG4gKiAgICAgK2dldCh0YXJnZXQsIHByb3BLZXksIG9wZXJhdGlvbiwgYWNjdW0pXG4gKiAgICAgK3JlZ2lzdGVyKGhhbmRsZXIsIG9wZXJhdGlvbiwgdGFyZ2V0LCBwcm9wS2V5KVxuICogICB9XG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVyYXRpb25zUmVnaXN0cnkge1xuICBwcml2YXRlIHJlYWRvbmx5IGNhY2hlOiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIFJlY29yZDxcbiAgICAgIHN0cmluZyB8IHN5bWJvbCxcbiAgICAgIFJlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIGFueSwgYW55LCBhbnk+Pj5cbiAgICA+XG4gID4gPSB7fTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBvcGVyYXRpb24gaGFuZGxlcnMgZm9yIGEgc3BlY2lmaWMgdGFyZ2V0IGFuZCBvcGVyYXRpb25cbiAgICogQHN1bW1hcnkgRmluZHMgYWxsIHJlZ2lzdGVyZWQgaGFuZGxlcnMgZm9yIGEgZ2l2ZW4gdGFyZ2V0LCBwcm9wZXJ0eSwgYW5kIG9wZXJhdGlvbiwgaW5jbHVkaW5nIGZyb20gcGFyZW50IGNsYXNzZXNcbiAgICogQHRlbXBsYXRlIE0gLSBNb2RlbCB0eXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAdGVtcGxhdGUgUiAtIFJlcG9zaXRvcnkgdHlwZSBleHRlbmRpbmcgSVJlcG9zaXRvcnlcbiAgICogQHRlbXBsYXRlIFYgLSBNZXRhZGF0YSB0eXBlXG4gICAqIEB0ZW1wbGF0ZSBGIC0gUmVwb3NpdG9yeSBmbGFncyBleHRlbmRpbmcgUmVwb3NpdG9yeUZsYWdzXG4gICAqIEB0ZW1wbGF0ZSBDIC0gQ29udGV4dCB0eXBlIGV4dGVuZGluZyBDb250ZXh0PEY+XG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgUmVjb3JkPHN0cmluZywgYW55Pn0gdGFyZ2V0IC0gVGhlIHRhcmdldCBjbGFzcyBuYW1lIG9yIG9iamVjdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcEtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gZ2V0IGhhbmRsZXJzIGZvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiBrZXkgdG8gZ2V0IGhhbmRsZXJzIGZvclxuICAgKiBAcGFyYW0ge09wZXJhdGlvbkhhbmRsZXJbXX0gW2FjY3VtXSAtIEFjY3VtdWxhdG9yIGZvciByZWN1cnNpdmUgY2FsbHNcbiAgICogQHJldHVybiB7T3BlcmF0aW9uSGFuZGxlcltdIHwgdW5kZWZpbmVkfSBBcnJheSBvZiBoYW5kbGVycyBvciB1bmRlZmluZWQgaWYgbm9uZSBmb3VuZFxuICAgKi9cbiAgZ2V0PFxuICAgIE0gZXh0ZW5kcyBNb2RlbCxcbiAgICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gICAgVixcbiAgICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICAgIEMgZXh0ZW5kcyBDb250ZXh0PEY+LFxuICA+KFxuICAgIHRhcmdldDogc3RyaW5nIHwgUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBwcm9wS2V5OiBzdHJpbmcsXG4gICAgb3BlcmF0aW9uOiBzdHJpbmcsXG4gICAgYWNjdW0/OiBPcGVyYXRpb25IYW5kbGVyPE0sIFIsIFYsIEYsIEM+W11cbiAgKTogT3BlcmF0aW9uSGFuZGxlcjxNLCBSLCBWLCBGLCBDPltdIHwgdW5kZWZpbmVkIHtcbiAgICBhY2N1bSA9IGFjY3VtIHx8IFtdO1xuICAgIGxldCBuYW1lO1xuICAgIHRyeSB7XG4gICAgICBuYW1lID0gdHlwZW9mIHRhcmdldCA9PT0gXCJzdHJpbmdcIiA/IHRhcmdldCA6IHRhcmdldC5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgYWNjdW0udW5zaGlmdChcbiAgICAgICAgLi4uT2JqZWN0LnZhbHVlcyh0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldW29wZXJhdGlvbl0gfHwgW10pXG4gICAgICApO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmIChcbiAgICAgICAgdHlwZW9mIHRhcmdldCA9PT0gXCJzdHJpbmdcIiB8fFxuICAgICAgICB0YXJnZXQgPT09IE9iamVjdC5wcm90b3R5cGUgfHxcbiAgICAgICAgT2JqZWN0LmdldFByb3RvdHlwZU9mKHRhcmdldCkgPT09IE9iamVjdC5wcm90b3R5cGVcbiAgICAgIClcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH1cblxuICAgIGxldCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih0YXJnZXQpO1xuICAgIGlmIChwcm90by5jb25zdHJ1Y3Rvci5uYW1lID09PSBuYW1lKSBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihwcm90byk7XG5cbiAgICByZXR1cm4gdGhpcy5nZXQ8TSwgUiwgViwgRiwgQz4ocHJvdG8sIHByb3BLZXksIG9wZXJhdGlvbiwgYWNjdW0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlcnMgYW4gb3BlcmF0aW9uIGhhbmRsZXIgZm9yIGEgc3BlY2lmaWMgdGFyZ2V0IGFuZCBvcGVyYXRpb25cbiAgICogQHN1bW1hcnkgU3RvcmVzIGEgaGFuZGxlciBpbiB0aGUgcmVnaXN0cnkgZm9yIGEgZ2l2ZW4gdGFyZ2V0LCBwcm9wZXJ0eSwgYW5kIG9wZXJhdGlvblxuICAgKiBAdGVtcGxhdGUgTSAtIE1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEB0ZW1wbGF0ZSBSIC0gUmVwb3NpdG9yeSB0eXBlIGV4dGVuZGluZyBJUmVwb3NpdG9yeVxuICAgKiBAdGVtcGxhdGUgViAtIE1ldGFkYXRhIHR5cGVcbiAgICogQHRlbXBsYXRlIEYgLSBSZXBvc2l0b3J5IGZsYWdzIGV4dGVuZGluZyBSZXBvc2l0b3J5RmxhZ3NcbiAgICogQHRlbXBsYXRlIEMgLSBDb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAgICogQHBhcmFtIHtPcGVyYXRpb25IYW5kbGVyfSBoYW5kbGVyIC0gVGhlIGhhbmRsZXIgZnVuY3Rpb24gdG8gcmVnaXN0ZXJcbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIGtleSB0byByZWdpc3RlciB0aGUgaGFuZGxlciBmb3JcbiAgICogQHBhcmFtIHtNfSB0YXJnZXQgLSBUaGUgdGFyZ2V0IG1vZGVsIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgc3ltYm9sfSBwcm9wS2V5IC0gVGhlIHByb3BlcnR5IGtleSB0byByZWdpc3RlciB0aGUgaGFuZGxlciBmb3JcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHJlZ2lzdGVyPFxuICAgIE0gZXh0ZW5kcyBNb2RlbCxcbiAgICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gICAgVixcbiAgICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICAgIEMgZXh0ZW5kcyBDb250ZXh0PEY+LFxuICA+KFxuICAgIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz4sXG4gICAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzLFxuICAgIHRhcmdldDogTSxcbiAgICBwcm9wS2V5OiBzdHJpbmcgfCBzeW1ib2xcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgbmFtZSA9IHRhcmdldC5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgIGNvbnN0IGhhbmRsZXJOYW1lID0gT3BlcmF0aW9ucy5nZXRIYW5kbGVyTmFtZShoYW5kbGVyKTtcblxuICAgIGlmICghdGhpcy5jYWNoZVtuYW1lXSkgdGhpcy5jYWNoZVtuYW1lXSA9IHt9O1xuICAgIGlmICghdGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XSkgdGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XSA9IHt9O1xuICAgIGlmICghdGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XVtvcGVyYXRpb25dKVxuICAgICAgdGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XVtvcGVyYXRpb25dID0ge307XG4gICAgaWYgKHRoaXMuY2FjaGVbbmFtZV1bcHJvcEtleV1bb3BlcmF0aW9uXVtoYW5kbGVyTmFtZV0pIHJldHVybjtcbiAgICB0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldW29wZXJhdGlvbl1baGFuZGxlck5hbWVdID0gaGFuZGxlcjtcbiAgfVxufVxuIiwiaW1wb3J0IHsgSGFzaGluZywgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25IYW5kbGVyIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IE9wZXJhdGlvbnNSZWdpc3RyeSB9IGZyb20gXCIuL09wZXJhdGlvbnNSZWdpc3RyeVwiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlc1wiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuLi9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdGF0aWMgdXRpbGl0eSBjbGFzcyBmb3IgZGF0YWJhc2Ugb3BlcmF0aW9uIG1hbmFnZW1lbnRcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGZ1bmN0aW9uYWxpdHkgZm9yIHJlZ2lzdGVyaW5nLCByZXRyaWV2aW5nLCBhbmQgbWFuYWdpbmcgZGF0YWJhc2Ugb3BlcmF0aW9uIGhhbmRsZXJzXG4gKiBAY2xhc3MgT3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIE0gLSBNb2RlbCB0eXBlXG4gKiBAdGVtcGxhdGUgUiAtIFJlcG9zaXRvcnkgdHlwZVxuICogQHRlbXBsYXRlIFYgLSBNZXRhZGF0YSB0eXBlXG4gKiBAdGVtcGxhdGUgRiAtIFJlcG9zaXRvcnkgZmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gQ29udGV4dCB0eXBlXG4gKiBAZXhhbXBsZVxuICogLy8gUmVnaXN0ZXIgYSBoYW5kbGVyIGZvciBhIGNyZWF0ZSBvcGVyYXRpb25cbiAqIE9wZXJhdGlvbnMucmVnaXN0ZXIobXlIYW5kbGVyLCBPcGVyYXRpb25LZXlzLkNSRUFURSwgdGFyZ2V0TW9kZWwsICdwcm9wZXJ0eU5hbWUnKTtcbiAqIFxuICogLy8gR2V0IGhhbmRsZXJzIGZvciBhIHNwZWNpZmljIG9wZXJhdGlvblxuICogY29uc3QgaGFuZGxlcnMgPSBPcGVyYXRpb25zLmdldCh0YXJnZXRNb2RlbC5jb25zdHJ1Y3Rvci5uYW1lLCAncHJvcGVydHlOYW1lJywgJ29uQ3JlYXRlJyk7XG4gKiBcbiAqIEBtZXJtYWlkXG4gKiBjbGFzc0RpYWdyYW1cbiAqICAgY2xhc3MgT3BlcmF0aW9ucyB7XG4gKiAgICAgLXJlZ2lzdHJ5OiBPcGVyYXRpb25zUmVnaXN0cnlcbiAqICAgICArZ2V0SGFuZGxlck5hbWUoaGFuZGxlcilcbiAqICAgICAra2V5KHN0cilcbiAqICAgICArZ2V0KHRhcmdldE5hbWUsIHByb3BLZXksIG9wZXJhdGlvbilcbiAqICAgICAtZ2V0T3BSZWdpc3RyeSgpXG4gKiAgICAgK3JlZ2lzdGVyKGhhbmRsZXIsIG9wZXJhdGlvbiwgdGFyZ2V0LCBwcm9wS2V5KVxuICogICB9XG4gKiAgIE9wZXJhdGlvbnMgLS0+IE9wZXJhdGlvbnNSZWdpc3RyeSA6IHVzZXNcbiAqL1xuZXhwb3J0IGNsYXNzIE9wZXJhdGlvbnMge1xuICBwcml2YXRlIHN0YXRpYyByZWdpc3RyeTogT3BlcmF0aW9uc1JlZ2lzdHJ5O1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBhIHVuaXF1ZSBuYW1lIGZvciBhbiBvcGVyYXRpb24gaGFuZGxlclxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSBoYW5kbGVyIGZ1bmN0aW9uIG9yIGdlbmVyYXRlcyBhIGhhc2ggaWYgbmFtZSBpcyBub3QgYXZhaWxhYmxlXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgYW55LCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgaGFuZGxlciBmdW5jdGlvbiB0byBnZXQgdGhlIG5hbWUgZm9yXG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIGhhbmRsZXIgb3IgYSBnZW5lcmF0ZWQgaGFzaFxuICAgKi9cbiAgc3RhdGljIGdldEhhbmRsZXJOYW1lKGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIGFueSwgYW55LCBhbnk+KSB7XG4gICAgaWYgKGhhbmRsZXIubmFtZSkgcmV0dXJuIGhhbmRsZXIubmFtZTtcblxuICAgIGNvbnNvbGUud2FybihcbiAgICAgIFwiSGFuZGxlciBuYW1lIG5vdCBkZWZpbmVkLiBBIG5hbWUgd2lsbCBiZSBnZW5lcmF0ZWQsIGJ1dCB0aGlzIGlzIG5vdCBkZXNpcmFibGUuIHBsZWFzZSBhdm9pZCB1c2luZyBhbm9ueW1vdXMgZnVuY3Rpb25zXCJcbiAgICApO1xuICAgIHJldHVybiBIYXNoaW5nLmhhc2goaGFuZGxlci50b1N0cmluZygpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgcmVmbGVjdGlvbiBtZXRhZGF0YSBrZXlcbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBhIGZ1bGx5IHF1YWxpZmllZCBtZXRhZGF0YSBrZXkgYnkgcHJlZml4aW5nIHdpdGggdGhlIHJlZmxlY3Rpb24gbmFtZXNwYWNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBUaGUgb3BlcmF0aW9uIGtleSBzdHJpbmcgdG8gcHJlZml4XG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGZ1bGx5IHF1YWxpZmllZCBtZXRhZGF0YSBrZXlcbiAgICovXG4gIHN0YXRpYyBrZXkoc3RyOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gT3BlcmF0aW9uS2V5cy5SRUZMRUNUICsgc3RyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgb3BlcmF0aW9uIGhhbmRsZXJzIGZvciBhIHNwZWNpZmljIHRhcmdldCBhbmQgb3BlcmF0aW9uXG4gICAqIEBzdW1tYXJ5IEdldHMgcmVnaXN0ZXJlZCBoYW5kbGVycyBmcm9tIHRoZSBvcGVyYXRpb25zIHJlZ2lzdHJ5IGZvciBhIGdpdmVuIHRhcmdldCwgcHJvcGVydHksIGFuZCBvcGVyYXRpb25cbiAgICogQHRlbXBsYXRlIE0gLSBNb2RlbCB0eXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAdGVtcGxhdGUgUiAtIFJlcG9zaXRvcnkgdHlwZSBleHRlbmRpbmcgSVJlcG9zaXRvcnlcbiAgICogQHRlbXBsYXRlIFYgLSBNZXRhZGF0YSB0eXBlLCBkZWZhdWx0cyB0byBvYmplY3RcbiAgICogQHRlbXBsYXRlIEYgLSBSZXBvc2l0b3J5IGZsYWdzIGV4dGVuZGluZyBSZXBvc2l0b3J5RmxhZ3NcbiAgICogQHRlbXBsYXRlIEMgLSBDb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+fSB0YXJnZXROYW1lIC0gVGhlIHRhcmdldCBjbGFzcyBuYW1lIG9yIG9iamVjdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcEtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gZ2V0IGhhbmRsZXJzIGZvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiBrZXkgdG8gZ2V0IGhhbmRsZXJzIGZvclxuICAgKiBAcmV0dXJuIHthbnl9IFRoZSByZWdpc3RlcmVkIGhhbmRsZXJzIGZvciB0aGUgc3BlY2lmaWVkIHRhcmdldCwgcHJvcGVydHksIGFuZCBvcGVyYXRpb25cbiAgICovXG4gIHN0YXRpYyBnZXQ8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgICBWID0gb2JqZWN0LFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuICA+KFxuICAgIHRhcmdldE5hbWU6IHN0cmluZyB8IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgcHJvcEtleTogc3RyaW5nLFxuICAgIG9wZXJhdGlvbjogc3RyaW5nXG4gICkge1xuICAgIHJldHVybiBPcGVyYXRpb25zLnJlZ2lzdHJ5LmdldDxNLCBSLCBWLCBGLCBDPihcbiAgICAgIHRhcmdldE5hbWUsXG4gICAgICBwcm9wS2V5LFxuICAgICAgb3BlcmF0aW9uXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBvciBpbml0aWFsaXplcyB0aGUgb3BlcmF0aW9ucyByZWdpc3RyeVxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBleGlzdGluZyByZWdpc3RyeSBvciBjcmVhdGVzIGEgbmV3IG9uZSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAqIEByZXR1cm4ge09wZXJhdGlvbnNSZWdpc3RyeX0gVGhlIG9wZXJhdGlvbnMgcmVnaXN0cnkgaW5zdGFuY2VcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldE9wUmVnaXN0cnkoKSB7XG4gICAgaWYgKCFPcGVyYXRpb25zLnJlZ2lzdHJ5KSBPcGVyYXRpb25zLnJlZ2lzdHJ5ID0gbmV3IE9wZXJhdGlvbnNSZWdpc3RyeSgpO1xuICAgIHJldHVybiBPcGVyYXRpb25zLnJlZ2lzdHJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlcnMgYW4gb3BlcmF0aW9uIGhhbmRsZXIgZm9yIGEgc3BlY2lmaWMgdGFyZ2V0IGFuZCBvcGVyYXRpb25cbiAgICogQHN1bW1hcnkgQWRkcyBhIGhhbmRsZXIgdG8gdGhlIG9wZXJhdGlvbnMgcmVnaXN0cnkgZm9yIGEgZ2l2ZW4gdGFyZ2V0LCBwcm9wZXJ0eSwgYW5kIG9wZXJhdGlvblxuICAgKiBAdGVtcGxhdGUgViAtIE1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcjxWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgaGFuZGxlciBmdW5jdGlvbiB0byByZWdpc3RlclxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXN9IG9wZXJhdGlvbiAtIFRoZSBvcGVyYXRpb24ga2V5IHRvIHJlZ2lzdGVyIHRoZSBoYW5kbGVyIGZvclxuICAgKiBAcGFyYW0ge1Z9IHRhcmdldCAtIFRoZSB0YXJnZXQgbW9kZWwgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBzeW1ib2x9IHByb3BLZXkgLSBUaGUgcHJvcGVydHkga2V5IHRvIHJlZ2lzdGVyIHRoZSBoYW5kbGVyIGZvclxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgc3RhdGljIHJlZ2lzdGVyPFYgZXh0ZW5kcyBNb2RlbD4oXG4gICAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxWLCBhbnksIGFueT4sXG4gICAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzLFxuICAgIHRhcmdldDogVixcbiAgICBwcm9wS2V5OiBzdHJpbmcgfCBzeW1ib2xcbiAgKSB7XG4gICAgT3BlcmF0aW9ucy5nZXRPcFJlZ2lzdHJ5KCkucmVnaXN0ZXIoXG4gICAgICBoYW5kbGVyIGFzIGFueSxcbiAgICAgIG9wZXJhdGlvbixcbiAgICAgIHRhcmdldCxcbiAgICAgIHByb3BLZXlcbiAgICApO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBJZE9wZXJhdGlvbkhhbmRsZXIsXG4gIE9wZXJhdGlvbkhhbmRsZXIsXG4gIFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcixcbiAgVXBkYXRlT3BlcmF0aW9uSGFuZGxlcixcbn0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERCT3BlcmF0aW9ucywgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9ucyB9IGZyb20gXCIuL09wZXJhdGlvbnNcIjtcbmltcG9ydCB7IGFwcGx5IH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBwcm9wTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEludGVybmFsIGZ1bmN0aW9uIHRvIHJlZ2lzdGVyIG9wZXJhdGlvbiBoYW5kbGVyc1xuICogQHN1bW1hcnkgUmVnaXN0ZXJzIGFuIG9wZXJhdGlvbiBoYW5kbGVyIGZvciBhIHNwZWNpZmljIG9wZXJhdGlvbiBrZXkgb24gYSB0YXJnZXQgcHJvcGVydHlcbiAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c30gb3AgLSBUaGUgb3BlcmF0aW9uIGtleSB0byBoYW5kbGVcbiAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgYW55LCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgaGFuZGxlciBmdW5jdGlvbiB0byByZWdpc3RlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgcmVnaXN0ZXJzIHRoZSBoYW5kbGVyXG4gKiBAZnVuY3Rpb24gaGFuZGxlXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5mdW5jdGlvbiBoYW5kbGUoXG4gIG9wOiBPcGVyYXRpb25LZXlzLFxuICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBhbnksIGFueSwgYW55PlxuKSB7XG4gIHJldHVybiAodGFyZ2V0OiBhbnksIHByb3BlcnR5S2V5OiBzdHJpbmcpID0+IHtcbiAgICBPcGVyYXRpb25zLnJlZ2lzdGVyKGhhbmRsZXIsIG9wLCB0YXJnZXQsIHByb3BlcnR5S2V5KTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIGZvciBoYW5kbGluZyBjcmVhdGUgYW5kIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3IgdG8gZXhlY3V0ZSBkdXJpbmcgYm90aCBjcmVhdGUgYW5kIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7U3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4gfCBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIG9uQ3JlYXRlVXBkYXRlXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25DcmVhdGVVcGRhdGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6XG4gICAgfCBTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PlxuICAgIHwgVXBkYXRlT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBvbihEQk9wZXJhdGlvbnMuQ1JFQVRFX1VQREFURSwgaGFuZGxlciwgZGF0YSk7XG59XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZm9yIGhhbmRsaW5nIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3IgdG8gZXhlY3V0ZSBkdXJpbmcgdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnk+fSBoYW5kbGVyIC0gVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBvblVwZGF0ZVxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uVXBkYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBvbihEQk9wZXJhdGlvbnMuVVBEQVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgY3JlYXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGR1cmluZyBjcmVhdGUgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YSwgZGVmYXVsdHMgdG8gb2JqZWN0XG4gKiBAcGFyYW0ge1N0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+fSBoYW5kbGVyIC0gVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBvbkNyZWF0ZVxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uQ3JlYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gb24oREJPcGVyYXRpb25zLkNSRUFURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgcmVhZCBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3IgdG8gZXhlY3V0ZSBkdXJpbmcgcmVhZCBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7SWRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIG9uUmVhZFxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uUmVhZDxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogSWRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gb24oREJPcGVyYXRpb25zLlJFQUQsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZm9yIGhhbmRsaW5nIGRlbGV0ZSBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3IgdG8gZXhlY3V0ZSBkdXJpbmcgZGVsZXRlIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIG9uRGVsZXRlXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25EZWxldGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YTogVlxuKSB7XG4gIHJldHVybiBvbihEQk9wZXJhdGlvbnMuREVMRVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIGZvciBoYW5kbGluZyBhbGwgb3BlcmF0aW9uIHR5cGVzXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3IgdG8gZXhlY3V0ZSBkdXJpbmcgYW55IGRhdGFiYXNlIG9wZXJhdGlvblxuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YSwgZGVmYXVsdHMgdG8gb2JqZWN0XG4gKiBAcGFyYW0ge09wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gb25BbnlcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbkFueTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIG9uKERCT3BlcmF0aW9ucy5BTEwsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIGRlY29yYXRvciBmb3IgaGFuZGxpbmcgZGF0YWJhc2Ugb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgZHVyaW5nIHNwZWNpZmllZCBkYXRhYmFzZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c1tdIHwgREJPcGVyYXRpb25zfSBbb3A9REJPcGVyYXRpb25zLkFMTF0gLSBPbmUgb3IgbW9yZSBvcGVyYXRpb24gdHlwZXMgdG8gaGFuZGxlXG4gKiBAcGFyYW0ge09wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gb25cbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSB1c2FnZTpcbiAqIGNsYXNzIE15TW9kZWwge1xuICogICBAb24oREJPcGVyYXRpb25zLkNSRUFURSwgbXlIYW5kbGVyKVxuICogICBteVByb3BlcnR5OiBzdHJpbmc7XG4gKiB9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbjxWID0gb2JqZWN0PihcbiAgb3A6IE9wZXJhdGlvbktleXNbXSA9IERCT3BlcmF0aW9ucy5BTEwsXG4gIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gb3BlcmF0aW9uKE9wZXJhdGlvbktleXMuT04sIG9wLCBoYW5kbGVyLCBkYXRhKTtcbn1cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgcG9zdC1jcmVhdGUgYW5kIHBvc3QtdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGFmdGVyIGJvdGggY3JlYXRlIGFuZCB1cGRhdGUgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YSwgZGVmYXVsdHMgdG8gb2JqZWN0XG4gKiBAcGFyYW0ge1N0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+IHwgVXBkYXRlT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+fSBoYW5kbGVyIC0gVGhlIG1ldGhvZCBjYWxsZWQgYWZ0ZXIgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gYWZ0ZXJDcmVhdGVVcGRhdGVcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlckNyZWF0ZVVwZGF0ZTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjpcbiAgICB8IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+XG4gICAgfCBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gYWZ0ZXIoREJPcGVyYXRpb25zLkNSRUFURV9VUERBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZm9yIGhhbmRsaW5nIHBvc3QtdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGFmdGVyIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7VXBkYXRlT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+fSBoYW5kbGVyIC0gVGhlIG1ldGhvZCBjYWxsZWQgYWZ0ZXIgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gYWZ0ZXJVcGRhdGVcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlclVwZGF0ZTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogVXBkYXRlT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5VUERBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZm9yIGhhbmRsaW5nIHBvc3QtY3JlYXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGFmdGVyIGNyZWF0ZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7U3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCBhZnRlciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBhZnRlckNyZWF0ZVxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyQ3JlYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YTogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuQ1JFQVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIGZvciBoYW5kbGluZyBwb3N0LXJlYWQgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgYWZ0ZXIgcmVhZCBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7U3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCBhZnRlciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBhZnRlclJlYWRcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlclJlYWQ8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuUkVBRCwgaGFuZGxlciwgZGF0YSk7XG59XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZm9yIGhhbmRsaW5nIHBvc3QtZGVsZXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGFmdGVyIGRlbGV0ZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7U3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCBhZnRlciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBhZnRlckRlbGV0ZVxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyRGVsZXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gYWZ0ZXIoREJPcGVyYXRpb25zLkRFTEVURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgcG9zdC1vcGVyYXRpb24gZm9yIGFsbCBvcGVyYXRpb24gdHlwZXNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGFmdGVyIGFueSBkYXRhYmFzZSBvcGVyYXRpb25cbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIGFmdGVyIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIGFmdGVyQW55XG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYWZ0ZXJBbnk8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuQUxMLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQmFzZSBkZWNvcmF0b3IgZm9yIGhhbmRsaW5nIHBvc3Qtb3BlcmF0aW9uIGJlaGF2aW9yc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgYWZ0ZXIgc3BlY2lmaWVkIGRhdGFiYXNlIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtPcGVyYXRpb25LZXlzW10gfCBEQk9wZXJhdGlvbnN9IFtvcD1EQk9wZXJhdGlvbnMuQUxMXSAtIE9uZSBvciBtb3JlIG9wZXJhdGlvbiB0eXBlcyB0byBoYW5kbGVcbiAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+fSBoYW5kbGVyIC0gVGhlIG1ldGhvZCBjYWxsZWQgYWZ0ZXIgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gYWZ0ZXJcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSB1c2FnZTpcbiAqIGNsYXNzIE15TW9kZWwge1xuICogICBAYWZ0ZXIoREJPcGVyYXRpb25zLkNSRUFURSwgbXlIYW5kbGVyKVxuICogICBteVByb3BlcnR5OiBzdHJpbmc7XG4gKiB9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlcjxWID0gb2JqZWN0PihcbiAgb3A6IE9wZXJhdGlvbktleXNbXSA9IERCT3BlcmF0aW9ucy5BTEwsXG4gIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gb3BlcmF0aW9uKE9wZXJhdGlvbktleXMuQUZURVIsIG9wLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29yZSBkZWNvcmF0b3IgZmFjdG9yeSBmb3Igb3BlcmF0aW9uIGhhbmRsZXJzXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGRlY29yYXRvcnMgdGhhdCByZWdpc3RlciBoYW5kbGVycyBmb3IgZGF0YWJhc2Ugb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YSwgZGVmYXVsdHMgdG8gb2JqZWN0XG4gKiBAcGFyYW0ge09wZXJhdGlvbktleXMuT04gfCBPcGVyYXRpb25LZXlzLkFGVEVSfSBiYXNlT3AgLSBXaGV0aGVyIHRoZSBoYW5kbGVyIHJ1bnMgZHVyaW5nIG9yIGFmdGVyIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c1tdfSBbb3BlcmF0aW9uPURCT3BlcmF0aW9ucy5BTExdIC0gVGhlIHNwZWNpZmljIG9wZXJhdGlvbnMgdG8gaGFuZGxlXG4gKiBAcGFyYW0ge09wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBoYW5kbGVyIGZ1bmN0aW9uIHRvIGV4ZWN1dGVcbiAqIEBwYXJhbSB7Vn0gW2RhdGFUb0FkZF0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gb3BlcmF0aW9uXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgRGVjb3JhdG9yIGFzIEBvcGVyYXRpb25cbiAqICAgcGFydGljaXBhbnQgT3BlcmF0aW9ucyBhcyBPcGVyYXRpb25zIFJlZ2lzdHJ5XG4gKiAgIHBhcnRpY2lwYW50IEhhbmRsZXJcbiAqXG4gKiAgIENsaWVudC0+PkRlY29yYXRvcjogQXBwbHkgdG8gcHJvcGVydHlcbiAqICAgRGVjb3JhdG9yLT4+T3BlcmF0aW9uczogUmVnaXN0ZXIgaGFuZGxlclxuICogICBEZWNvcmF0b3ItPj5EZWNvcmF0b3I6IFN0b3JlIG1ldGFkYXRhXG4gKlxuICogICBOb3RlIG92ZXIgQ2xpZW50LEhhbmRsZXI6IExhdGVyLCBkdXJpbmcgb3BlcmF0aW9uIGV4ZWN1dGlvblxuICogICBDbGllbnQtPj5PcGVyYXRpb25zOiBFeGVjdXRlIG9wZXJhdGlvblxuICogICBPcGVyYXRpb25zLT4+SGFuZGxlcjogQ2FsbCByZWdpc3RlcmVkIGhhbmRsZXJcbiAqICAgSGFuZGxlci0tPj5PcGVyYXRpb25zOiBSZXR1cm4gcmVzdWx0XG4gKiAgIE9wZXJhdGlvbnMtLT4+Q2xpZW50OiBSZXR1cm4gZmluYWwgcmVzdWx0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvcGVyYXRpb248ViA9IG9iamVjdD4oXG4gIGJhc2VPcDogT3BlcmF0aW9uS2V5cy5PTiB8IE9wZXJhdGlvbktleXMuQUZURVIsXG4gIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5c1tdID0gREJPcGVyYXRpb25zLkFMTCxcbiAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhVG9BZGQ/OiBWXG4pIHtcbiAgcmV0dXJuICh0YXJnZXQ6IG9iamVjdCwgcHJvcGVydHlLZXk/OiBhbnkpID0+IHtcbiAgICBjb25zdCBuYW1lID0gdGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgY29uc3QgZGVjb3JhdG9ycyA9IG9wZXJhdGlvbi5yZWR1Y2UoKGFjY3VtOiBhbnlbXSwgb3ApID0+IHtcbiAgICAgIGNvbnN0IGNvbXBvdW5kS2V5ID0gYmFzZU9wICsgb3A7XG4gICAgICBsZXQgZGF0YSA9IFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICAgIE9wZXJhdGlvbnMua2V5KGNvbXBvdW5kS2V5KSxcbiAgICAgICAgdGFyZ2V0LFxuICAgICAgICBwcm9wZXJ0eUtleVxuICAgICAgKTtcbiAgICAgIGlmICghZGF0YSlcbiAgICAgICAgZGF0YSA9IHtcbiAgICAgICAgICBvcGVyYXRpb246IG9wLFxuICAgICAgICAgIGhhbmRsZXJzOiB7fSxcbiAgICAgICAgfTtcblxuICAgICAgY29uc3QgaGFuZGxlcktleSA9IE9wZXJhdGlvbnMuZ2V0SGFuZGxlck5hbWUoaGFuZGxlcik7XG5cbiAgICAgIGlmIChcbiAgICAgICAgIWRhdGEuaGFuZGxlcnNbbmFtZV0gfHxcbiAgICAgICAgIWRhdGEuaGFuZGxlcnNbbmFtZV1bcHJvcGVydHlLZXldIHx8XG4gICAgICAgICEoaGFuZGxlcktleSBpbiBkYXRhLmhhbmRsZXJzW25hbWVdW3Byb3BlcnR5S2V5XSlcbiAgICAgICkge1xuICAgICAgICBkYXRhLmhhbmRsZXJzW25hbWVdID0gZGF0YS5oYW5kbGVyc1tuYW1lXSB8fCB7fTtcbiAgICAgICAgZGF0YS5oYW5kbGVyc1tuYW1lXVtwcm9wZXJ0eUtleV0gPVxuICAgICAgICAgIGRhdGEuaGFuZGxlcnNbbmFtZV1bcHJvcGVydHlLZXldIHx8IHt9O1xuICAgICAgICBkYXRhLmhhbmRsZXJzW25hbWVdW3Byb3BlcnR5S2V5XVtoYW5kbGVyS2V5XSA9IHtcbiAgICAgICAgICBkYXRhOiBkYXRhVG9BZGQsXG4gICAgICAgIH07XG5cbiAgICAgICAgYWNjdW0ucHVzaChcbiAgICAgICAgICBoYW5kbGUoY29tcG91bmRLZXkgYXMgT3BlcmF0aW9uS2V5cywgaGFuZGxlciksXG4gICAgICAgICAgcHJvcE1ldGFkYXRhKE9wZXJhdGlvbnMua2V5KGNvbXBvdW5kS2V5KSwgZGF0YSlcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LCBbXSk7XG4gICAgcmV0dXJuIGFwcGx5KC4uLmRlY29yYXRvcnMpKHRhcmdldCwgcHJvcGVydHlLZXkpO1xuICB9O1xufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gQmFzZSBlcnJvciBjbGFzcyBmb3IgdGhlIHJlcG9zaXRvcnkgbW9kdWxlXG4gKiBAc3VtbWFyeSBBYnN0cmFjdCBiYXNlIGVycm9yIGNsYXNzIHRoYXQgYWxsIG90aGVyIGVycm9yIHR5cGVzIGV4dGVuZCBmcm9tLiBQcm92aWRlcyBjb21tb24gZXJyb3IgaGFuZGxpbmcgZnVuY3Rpb25hbGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGVycm9yXG4gKiBAcGFyYW0ge3N0cmluZ3xFcnJvcn0gbXNnIC0gVGhlIGVycm9yIG1lc3NhZ2Ugb3IgRXJyb3Igb2JqZWN0XG4gKiBAcGFyYW0ge251bWJlcn0gY29kZSAtIFRoZSBIVFRQIHN0YXR1cyBjb2RlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGVycm9yXG4gKiBAY2xhc3MgQmFzZUVycm9yXG4gKiBAZXhhbXBsZVxuICogLy8gVGhpcyBpcyBhbiBhYnN0cmFjdCBjbGFzcyBhbmQgc2hvdWxkIG5vdCBiZSBpbnN0YW50aWF0ZWQgZGlyZWN0bHlcbiAqIC8vIEluc3RlYWQsIHVzZSBvbmUgb2YgdGhlIGNvbmNyZXRlIGVycm9yIGNsYXNzZXM6XG4gKiB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdJbnZhbGlkIGRhdGEgcHJvdmlkZWQnKTtcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgcmVhZG9ubHkgY29kZSE6IG51bWJlcjtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgbXNnOiBzdHJpbmcgfCBFcnJvciwgY29kZTogbnVtYmVyID0gNTAwKSB7XG4gICAgaWYgKG1zZyBpbnN0YW5jZW9mIEJhc2VFcnJvcikgcmV0dXJuIG1zZztcbiAgICBjb25zdCBtZXNzYWdlID0gYFske25hbWV9XSAke21zZyBpbnN0YW5jZW9mIEVycm9yID8gbXNnLm1lc3NhZ2UgOiBtc2d9YDtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLmNvZGUgPSBjb2RlO1xuICAgIGlmIChtc2cgaW5zdGFuY2VvZiBFcnJvcikgdGhpcy5zdGFjayA9IG1zZy5zdGFjaztcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFcnJvciB0aHJvd24gd2hlbiB2YWxpZGF0aW9uIGZhaWxzXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSBpbiB0aGUgTW9kZWwgZGV0YWlscywgdHlwaWNhbGx5IHRocm93biB3aGVuIGRhdGEgdmFsaWRhdGlvbiBmYWlsc1xuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIEVycm9yIG9iamVjdFxuICogQHJldHVybiB7VmFsaWRhdGlvbkVycm9yfSBBIG5ldyBWYWxpZGF0aW9uRXJyb3IgaW5zdGFuY2VcbiAqIEBjbGFzcyBWYWxpZGF0aW9uRXJyb3JcbiAqIEBleGFtcGxlXG4gKiAvLyBUaHJvdyBhIHZhbGlkYXRpb24gZXJyb3Igd2hlbiBkYXRhIGlzIGludmFsaWRcbiAqIGlmICghaXNWYWxpZChkYXRhKSkge1xuICogICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdJbnZhbGlkIGRhdGEgZm9ybWF0Jyk7XG4gKiB9XG4gKi9cbmV4cG9ydCBjbGFzcyBWYWxpZGF0aW9uRXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoVmFsaWRhdGlvbkVycm9yLm5hbWUsIG1zZywgNDIyKTtcbiAgfVxufVxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXJyb3IgdGhyb3duIGZvciBpbnRlcm5hbCBzeXN0ZW0gZmFpbHVyZXNcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW4gaW50ZXJuYWwgZmFpbHVyZSAoc2hvdWxkIG1lYW4gYW4gZXJyb3IgaW4gY29kZSkgd2l0aCBIVFRQIDUwMCBzdGF0dXMgY29kZVxuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIEVycm9yIG9iamVjdFxuICogQHJldHVybiB7SW50ZXJuYWxFcnJvcn0gQSBuZXcgSW50ZXJuYWxFcnJvciBpbnN0YW5jZVxuICogQGNsYXNzIEludGVybmFsRXJyb3JcbiAqIEBleGFtcGxlXG4gKiAvLyBUaHJvdyBhbiBpbnRlcm5hbCBlcnJvciB3aGVuIGFuIHVuZXhwZWN0ZWQgY29uZGl0aW9uIG9jY3Vyc1xuICogdHJ5IHtcbiAqICAgLy8gU29tZSBvcGVyYXRpb25cbiAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKCdVbmV4cGVjdGVkIGludGVybmFsIGVycm9yIG9jY3VycmVkJyk7XG4gKiB9XG4gKi9cbmV4cG9ydCBjbGFzcyBJbnRlcm5hbEVycm9yIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKEludGVybmFsRXJyb3IubmFtZSwgbXNnLCA1MDApO1xuICB9XG59XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFcnJvciB0aHJvd24gd2hlbiBzZXJpYWxpemF0aW9uIG9yIGRlc2VyaWFsaXphdGlvbiBmYWlsc1xuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZhaWx1cmUgaW4gdGhlIE1vZGVsIGRlL3NlcmlhbGl6YXRpb24sIHR5cGljYWxseSB3aGVuIGNvbnZlcnRpbmcgYmV0d2VlbiBkYXRhIGZvcm1hdHNcbiAqIEBwYXJhbSB7c3RyaW5nfEVycm9yfSBtc2cgLSBUaGUgZXJyb3IgbWVzc2FnZSBvciBFcnJvciBvYmplY3RcbiAqIEByZXR1cm4ge1NlcmlhbGl6YXRpb25FcnJvcn0gQSBuZXcgU2VyaWFsaXphdGlvbkVycm9yIGluc3RhbmNlXG4gKiBAY2xhc3MgU2VyaWFsaXphdGlvbkVycm9yXG4gKiBAZXhhbXBsZVxuICogLy8gVGhyb3cgYSBzZXJpYWxpemF0aW9uIGVycm9yIHdoZW4gSlNPTiBwYXJzaW5nIGZhaWxzXG4gKiB0cnkge1xuICogICBjb25zdCBkYXRhID0gSlNPTi5wYXJzZShpbnZhbGlkSnNvbik7XG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKCdGYWlsZWQgdG8gcGFyc2UgSlNPTiBkYXRhJyk7XG4gKiB9XG4gKi9cbmV4cG9ydCBjbGFzcyBTZXJpYWxpemF0aW9uRXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoU2VyaWFsaXphdGlvbkVycm9yLm5hbWUsIG1zZywgNDIyKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFcnJvciB0aHJvd24gd2hlbiBhIHJlcXVlc3RlZCByZXNvdXJjZSBpcyBub3QgZm91bmRcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIGZpbmRpbmcgYSBtb2RlbCwgcmVzdWx0aW5nIGluIGEgNDA0IEhUVFAgc3RhdHVzIGNvZGVcbiAqIEBwYXJhbSB7c3RyaW5nfEVycm9yfSBtc2cgLSBUaGUgZXJyb3IgbWVzc2FnZSBvciBFcnJvciBvYmplY3RcbiAqIEByZXR1cm4ge05vdEZvdW5kRXJyb3J9IEEgbmV3IE5vdEZvdW5kRXJyb3IgaW5zdGFuY2VcbiAqIEBjbGFzcyBOb3RGb3VuZEVycm9yXG4gKiBAZXhhbXBsZVxuICogLy8gVGhyb3cgYSBub3QgZm91bmQgZXJyb3Igd2hlbiBhIHJlY29yZCBkb2Vzbid0IGV4aXN0XG4gKiBjb25zdCB1c2VyID0gYXdhaXQgcmVwb3NpdG9yeS5maW5kQnlJZChpZCk7XG4gKiBpZiAoIXVzZXIpIHtcbiAqICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoYFVzZXIgd2l0aCBJRCAke2lkfSBub3QgZm91bmRgKTtcbiAqIH1cbiAqL1xuZXhwb3J0IGNsYXNzIE5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoTm90Rm91bmRFcnJvci5uYW1lLCBtc2csIDQwNCk7XG4gIH1cbn1cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVycm9yIHRocm93biB3aGVuIGEgY29uZmxpY3Qgb2NjdXJzIGluIHRoZSBzdG9yYWdlXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgY29uZmxpY3QgaW4gdGhlIHN0b3JhZ2UsIHR5cGljYWxseSB3aGVuIHRyeWluZyB0byBjcmVhdGUgYSBkdXBsaWNhdGUgcmVzb3VyY2VcbiAqIEBwYXJhbSB7c3RyaW5nfEVycm9yfSBtc2cgLSBUaGUgZXJyb3IgbWVzc2FnZSBvciBFcnJvciBvYmplY3RcbiAqIEByZXR1cm4ge0NvbmZsaWN0RXJyb3J9IEEgbmV3IENvbmZsaWN0RXJyb3IgaW5zdGFuY2VcbiAqIEBjbGFzcyBDb25mbGljdEVycm9yXG4gKiBAZXhhbXBsZVxuICogLy8gVGhyb3cgYSBjb25mbGljdCBlcnJvciB3aGVuIHRyeWluZyB0byBjcmVhdGUgYSBkdXBsaWNhdGUgcmVjb3JkXG4gKiBjb25zdCBleGlzdGluZ1VzZXIgPSBhd2FpdCByZXBvc2l0b3J5LmZpbmRCeUVtYWlsKGVtYWlsKTtcbiAqIGlmIChleGlzdGluZ1VzZXIpIHtcbiAqICAgdGhyb3cgbmV3IENvbmZsaWN0RXJyb3IoYFVzZXIgd2l0aCBlbWFpbCAke2VtYWlsfSBhbHJlYWR5IGV4aXN0c2ApO1xuICogfVxuICovXG5leHBvcnQgY2xhc3MgQ29uZmxpY3RFcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihDb25mbGljdEVycm9yLm5hbWUsIG1zZywgNDA5KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgT3BlcmF0aW9ucyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL09wZXJhdGlvbnNcIjtcbmltcG9ydCB7IE9wZXJhdGlvbkhhbmRsZXIsIFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXIgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy90eXBlc1wiO1xuaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9JUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgRGVjb3JhdG9yTWV0YWRhdGEsIFJlZmxlY3Rpb24gfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCwgTW9kZWxLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuL0NvbnRleHRcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbnRleHQgYXJndW1lbnRzIGZvciByZXBvc2l0b3J5IG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIHRoZSBjb250ZXh0IGFuZCBhcmd1bWVudHMgZm9yIHJlcG9zaXRvcnkgb3BlcmF0aW9ucy5cbiAqIFRoaXMgdHlwZSBpcyB1c2VkIHRvIHBhc3MgY29udGV4dCBhbmQgYXJndW1lbnRzIGJldHdlZW4gcmVwb3NpdG9yeSBtZXRob2RzLlxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlLCBkZWZhdWx0cyB0byBSZXBvc2l0b3J5RmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSwgZGVmYXVsdHMgdG8gQ29udGV4dDxGPlxuICogQHR5cGVkZWYge09iamVjdH0gQ29udGV4dEFyZ3NcbiAqIEBwcm9wZXJ0eSB7Q30gY29udGV4dCAtIFRoZSBvcGVyYXRpb24gY29udGV4dFxuICogQHByb3BlcnR5IHthbnlbXX0gYXJncyAtIFRoZSBvcGVyYXRpb24gYXJndW1lbnRzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IHR5cGUgQ29udGV4dEFyZ3M8XG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4gPSB7XG4gIGNvbnRleHQ6IEM7XG4gIGFyZ3M6IGFueVtdO1xufTtcblxuLyoqXG4gKiBAc3VtbWFyeSByZXRyaWV2ZXMgdGhlIGFyZ3VtZW50cyBmb3IgdGhlIGhhbmRsZXJcbiAqIEBwYXJhbSB7YW55fSBkZWMgdGhlIGRlY29yYXRvclxuICogQHBhcmFtIHtzdHJpbmd9IHByb3AgdGhlIHByb3BlcnR5IG5hbWVcbiAqIEBwYXJhbSB7e319IG0gdGhlIG1vZGVsXG4gKiBAcGFyYW0ge3t9fSBbYWNjdW1dIGFjY3VtdWxhdG9yIHVzZWQgZm9yIGludGVybmFsIHJlY3Vyc2l2ZW5lc3NcbiAqXG4gKiBAZnVuY3Rpb24gZ2V0SGFuZGxlckFyZ3NcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5SZXBvc2l0b3J5XG4gKi9cbmV4cG9ydCBjb25zdCBnZXRIYW5kbGVyQXJncyA9IGZ1bmN0aW9uIChcbiAgZGVjOiBhbnksXG4gIHByb3A6IHN0cmluZyxcbiAgbTogQ29uc3RydWN0b3I8YW55PixcbiAgYWNjdW0/OiBSZWNvcmQ8c3RyaW5nLCB7IGFyZ3M6IHN0cmluZ1tdIH0+XG4pOiBSZWNvcmQ8c3RyaW5nLCB7IGFyZ3M6IHN0cmluZ1tdIH0+IHwgdm9pZCB7XG4gIGNvbnN0IG5hbWUgPSBtLmNvbnN0cnVjdG9yLm5hbWU7XG4gIGlmICghbmFtZSkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJDb3VsZCBub3QgZGV0ZXJtaW5lIG1vZGVsIGNsYXNzXCIpO1xuICBhY2N1bSA9IGFjY3VtIHx8IHt9O1xuXG4gIGlmIChkZWMucHJvcHMuaGFuZGxlcnNbbmFtZV0gJiYgZGVjLnByb3BzLmhhbmRsZXJzW25hbWVdW3Byb3BdKVxuICAgIGFjY3VtID0geyAuLi5kZWMucHJvcHMuaGFuZGxlcnNbbmFtZV1bcHJvcF0sIC4uLmFjY3VtIH07XG5cbiAgbGV0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG0pO1xuICBpZiAocHJvdG8gPT09IE9iamVjdC5wcm90b3R5cGUpIHJldHVybiBhY2N1bTtcbiAgaWYgKHByb3RvLmNvbnN0cnVjdG9yLm5hbWUgPT09IG5hbWUpIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvKTtcblxuICByZXR1cm4gZ2V0SGFuZGxlckFyZ3MoZGVjLCBwcm9wLCBwcm90bywgYWNjdW0pO1xufTtcblxuLyoqXG4gKlxuICogQHBhcmFtIHtJUmVwb3NpdG9yeTxUPn0gcmVwb1xuICogQHBhcmFtIGNvbnRleHRcbiAqIEBwYXJhbSB7VH0gbW9kZWxcbiAqIEBwYXJhbSBvcGVyYXRpb25cbiAqIEBwYXJhbSBwcmVmaXhcbiAqXG4gKiBAcGFyYW0gb2xkTW9kZWxcbiAqIEBmdW5jdGlvbiBlbmZvcmNlREJQcm9wZXJ0eURlY29yYXRvcnNBc3luY1xuICpcbiAqIEBtZW1iZXJPZiBkYi1kZWNvcmF0b3JzLnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbmZvcmNlREJEZWNvcmF0b3JzPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgViBleHRlbmRzIG9iamVjdCA9IG9iamVjdCxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPihcbiAgcmVwbzogUixcbiAgY29udGV4dDogQyxcbiAgbW9kZWw6IE0sXG4gIG9wZXJhdGlvbjogc3RyaW5nLFxuICBwcmVmaXg6IHN0cmluZyxcbiAgb2xkTW9kZWw/OiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZGVjb3JhdG9yczogUmVjb3JkPHN0cmluZywgRGVjb3JhdG9yTWV0YWRhdGFbXT4gfCB1bmRlZmluZWQgPVxuICAgIGdldERiRGVjb3JhdG9ycyhtb2RlbCwgb3BlcmF0aW9uLCBwcmVmaXgpO1xuXG4gIGlmICghZGVjb3JhdG9ycykgcmV0dXJuO1xuXG4gIGZvciAoY29uc3QgcHJvcCBpbiBkZWNvcmF0b3JzKSB7XG4gICAgY29uc3QgZGVjczogRGVjb3JhdG9yTWV0YWRhdGFbXSA9IGRlY29yYXRvcnNbcHJvcF07XG4gICAgZm9yIChjb25zdCBkZWMgb2YgZGVjcykge1xuICAgICAgY29uc3QgeyBrZXkgfSA9IGRlYztcbiAgICAgIGNvbnN0IGhhbmRsZXJzOiBPcGVyYXRpb25IYW5kbGVyPE0sIFIsIFYsIEYsIEM+W10gfCB1bmRlZmluZWQgPVxuICAgICAgICBPcGVyYXRpb25zLmdldDxNLCBSLCBWLCBGLCBDPihtb2RlbCwgcHJvcCwgcHJlZml4ICsga2V5KTtcbiAgICAgIGlmICghaGFuZGxlcnMgfHwgIWhhbmRsZXJzLmxlbmd0aClcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgYENvdWxkIG5vdCBmaW5kIHJlZ2lzdGVyZWQgaGFuZGxlciBmb3IgdGhlIG9wZXJhdGlvbiAke3ByZWZpeCArIGtleX0gdW5kZXIgcHJvcGVydHkgJHtwcm9wfWBcbiAgICAgICAgKTtcblxuICAgICAgY29uc3QgaGFuZGxlckFyZ3MgPSBnZXRIYW5kbGVyQXJncyhkZWMsIHByb3AsIG1vZGVsIGFzIGFueSk7XG5cbiAgICAgIGlmICghaGFuZGxlckFyZ3MgfHwgT2JqZWN0LnZhbHVlcyhoYW5kbGVyQXJncykubGVuZ3RoICE9PSBoYW5kbGVycy5sZW5ndGgpXG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiQXJncyBhbmQgaGFuZGxlcnMgbGVuZ3RoIGRvIG5vdCBtYXRjaFwiKTtcblxuICAgICAgbGV0IGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz47XG4gICAgICBsZXQgZGF0YTogYW55O1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoYW5kbGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICBoYW5kbGVyID0gaGFuZGxlcnNbaV07XG4gICAgICAgIGRhdGEgPSBPYmplY3QudmFsdWVzKGhhbmRsZXJBcmdzKVtpXTtcblxuICAgICAgICBjb25zdCBhcmdzOiBhbnlbXSA9IFtjb250ZXh0LCBkYXRhLmRhdGEsIHByb3AsIG1vZGVsXTtcblxuICAgICAgICBpZiAob3BlcmF0aW9uID09PSBPcGVyYXRpb25LZXlzLlVQREFURSAmJiBwcmVmaXggPT09IE9wZXJhdGlvbktleXMuT04pIHtcbiAgICAgICAgICBpZiAoIW9sZE1vZGVsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJNaXNzaW5nIG9sZCBtb2RlbCBmb3IgdXBkYXRlIG9wZXJhdGlvblwiKTtcbiAgICAgICAgICBhcmdzLnB1c2gob2xkTW9kZWwpO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgKGhhbmRsZXIgYXMgVXBkYXRlT3BlcmF0aW9uSGFuZGxlcjxNLCBSLCBWLCBGLCBDPikuYXBwbHkoXG4gICAgICAgICAgICByZXBvLFxuICAgICAgICAgICAgYXJncyBhcyBbQywgViwga2V5b2YgTSwgTSwgTV1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgICAgY29uc3QgbXNnID0gYEZhaWxlZCB0byBleGVjdXRlIGhhbmRsZXIgJHtoYW5kbGVyLm5hbWV9IGZvciAke3Byb3B9IG9uICR7bW9kZWwuY29uc3RydWN0b3IubmFtZX0gZHVlIHRvIGVycm9yOiAke2V9YDtcbiAgICAgICAgICBpZiAoY29udGV4dC5nZXQoXCJicmVha09uSGFuZGxlckVycm9yXCIpKSB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihtc2cpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKG1zZyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBTcGVjaWZpYyBmb3IgREIgRGVjb3JhdG9yc1xuICogQHBhcmFtIHtUfSBtb2RlbFxuICogQHBhcmFtIHtzdHJpbmd9IG9wZXJhdGlvbiBDUlVEIHtAbGluayBPcGVyYXRpb25LZXlzfVxuICogQHBhcmFtIHtzdHJpbmd9IFtleHRyYVByZWZpeF1cbiAqXG4gKiBAZnVuY3Rpb24gZ2V0RGJQcm9wZXJ0eURlY29yYXRvcnNcbiAqXG4gKiBAbWVtYmVyT2YgZGItZGVjb3JhdG9ycy51dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGJEZWNvcmF0b3JzPFQgZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBULFxuICBvcGVyYXRpb246IHN0cmluZyxcbiAgZXh0cmFQcmVmaXg/OiBzdHJpbmdcbik6IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhW10+IHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZGVjb3JhdG9yczogUmVjb3JkPHN0cmluZywgRGVjb3JhdG9yTWV0YWRhdGFbXT4gfCB1bmRlZmluZWQgPVxuICAgIFJlZmxlY3Rpb24uZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgbW9kZWwsXG4gICAgICAvLyB1bmRlZmluZWQsXG4gICAgICBPcGVyYXRpb25LZXlzLlJFRkxFQ1QgKyAoZXh0cmFQcmVmaXggPyBleHRyYVByZWZpeCA6IFwiXCIpXG4gICAgKTtcbiAgaWYgKCFkZWNvcmF0b3JzKSByZXR1cm47XG4gIHJldHVybiBPYmplY3Qua2V5cyhkZWNvcmF0b3JzKS5yZWR1Y2UoXG4gICAgKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBEZWNvcmF0b3JNZXRhZGF0YVtdPiB8IHVuZGVmaW5lZCwgZGVjb3JhdG9yKSA9PiB7XG4gICAgICBjb25zdCBkZWMgPSBkZWNvcmF0b3JzW2RlY29yYXRvcl0uZmlsdGVyKChkKSA9PiBkLmtleSA9PT0gb3BlcmF0aW9uKTtcbiAgICAgIGlmIChkZWMgJiYgZGVjLmxlbmd0aCkge1xuICAgICAgICBpZiAoIWFjY3VtKSBhY2N1bSA9IHt9O1xuICAgICAgICBhY2N1bVtkZWNvcmF0b3JdID0gZGVjO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sXG4gICAgdW5kZWZpbmVkXG4gICk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBkZWNvcmF0b3JzIGZvciBhbiBvYmplY3QncyBwcm9wZXJ0aWVzIHByZWZpeGVkIGJ5IHtAcGFyYW0gcHJlZml4ZXN9IHJlY3Vyc2l2ZWx5XG4gKiBAcGFyYW0gbW9kZWxcbiAqIEBwYXJhbSBhY2N1bVxuICogQHBhcmFtIHByZWZpeGVzXG4gKlxuICogQGZ1bmN0aW9uIGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLlJlcG9zaXRvcnlcbiAqL1xuZXhwb3J0IGNvbnN0IGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZSA9IGZ1bmN0aW9uIDxUIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogVCxcbiAgYWNjdW06IHsgW2luZGV4ZXI6IHN0cmluZ106IGFueVtdIH0gfCB1bmRlZmluZWQsXG4gIC4uLnByZWZpeGVzOiBzdHJpbmdbXVxuKTogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGFjY3VtdWxhdG9yID0gYWNjdW0gfHwge307XG4gIGNvbnN0IG1lcmdlRGVjb3JhdG9ycyA9IGZ1bmN0aW9uIChkZWNzOiB7IFtpbmRleGVyOiBzdHJpbmddOiBhbnlbXSB9KSB7XG4gICAgY29uc3QgcHVzaE9yU3F1YXNoID0gKGtleTogc3RyaW5nLCAuLi52YWx1ZXM6IGFueVtdKSA9PiB7XG4gICAgICB2YWx1ZXMuZm9yRWFjaCgodmFsKSA9PiB7XG4gICAgICAgIGxldCBtYXRjaDogYW55O1xuICAgICAgICBpZiAoXG4gICAgICAgICAgIShtYXRjaCA9IGFjY3VtdWxhdG9yW2tleV0uZmluZCgoZSkgPT4gZS5rZXkgPT09IHZhbC5rZXkpKSB8fFxuICAgICAgICAgIG1hdGNoLnByb3BzLm9wZXJhdGlvbiAhPT0gdmFsLnByb3BzLm9wZXJhdGlvblxuICAgICAgICApIHtcbiAgICAgICAgICBhY2N1bXVsYXRvcltrZXldLnB1c2godmFsKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsLmtleSA9PT0gTW9kZWxLZXlzLlRZUEUpIHJldHVybjtcblxuICAgICAgICBjb25zdCB7IGhhbmRsZXJzLCBvcGVyYXRpb24gfSA9IHZhbC5wcm9wcztcblxuICAgICAgICBpZiAoXG4gICAgICAgICAgIW9wZXJhdGlvbiB8fFxuICAgICAgICAgICFvcGVyYXRpb24ubWF0Y2goXG4gICAgICAgICAgICBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgICBgXig6PyR7T3BlcmF0aW9uS2V5cy5PTn18JHtPcGVyYXRpb25LZXlzLkFGVEVSfSkoOj8ke09wZXJhdGlvbktleXMuQ1JFQVRFfXwke09wZXJhdGlvbktleXMuUkVBRH18JHtPcGVyYXRpb25LZXlzLlVQREFURX18JHtPcGVyYXRpb25LZXlzLkRFTEVURX0pJGBcbiAgICAgICAgICAgIClcbiAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgIGFjY3VtdWxhdG9yW2tleV0ucHVzaCh2YWwpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFjY3VtSGFuZGxlcnMgPSBtYXRjaC5wcm9wcy5oYW5kbGVycztcblxuICAgICAgICBPYmplY3QuZW50cmllcyhoYW5kbGVycykuZm9yRWFjaCgoW2NsYXp6LCBoYW5kbGVyRGVmXSkgPT4ge1xuICAgICAgICAgIGlmICghKGNsYXp6IGluIGFjY3VtSGFuZGxlcnMpKSB7XG4gICAgICAgICAgICBhY2N1bUhhbmRsZXJzW2NsYXp6XSA9IGhhbmRsZXJEZWY7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgT2JqZWN0LmVudHJpZXMoaGFuZGxlckRlZiBhcyBvYmplY3QpLmZvckVhY2goXG4gICAgICAgICAgICAoW2hhbmRsZXJQcm9wLCBoYW5kbGVyXSkgPT4ge1xuICAgICAgICAgICAgICBpZiAoIShoYW5kbGVyUHJvcCBpbiBhY2N1bUhhbmRsZXJzW2NsYXp6XSkpIHtcbiAgICAgICAgICAgICAgICBhY2N1bUhhbmRsZXJzW2NsYXp6XVtoYW5kbGVyUHJvcF0gPSBoYW5kbGVyO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGhhbmRsZXIgYXMgb2JqZWN0KS5mb3JFYWNoKFxuICAgICAgICAgICAgICAgIChbaGFuZGxlcktleSwgYXJnc09ial0pID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghKGhhbmRsZXJLZXkgaW4gYWNjdW1IYW5kbGVyc1tjbGF6el1baGFuZGxlclByb3BdKSkge1xuICAgICAgICAgICAgICAgICAgICBhY2N1bUhhbmRsZXJzW2NsYXp6XVtoYW5kbGVyUHJvcF1baGFuZGxlcktleV0gPSBhcmdzT2JqO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgICAgIGBTa2lwcGluZyBoYW5kbGVyIHJlZ2lzdHJhdGlvbiBmb3IgJHtjbGF6en0gdW5kZXIgcHJvcCAke2hhbmRsZXJQcm9wfSBiZWNhdXNlIGhhbmRsZXIgaXMgdGhlIHNhbWVgXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBPYmplY3QuZW50cmllcyhkZWNzKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW2tleV0gPSBhY2N1bXVsYXRvcltrZXldIHx8IFtdO1xuICAgICAgcHVzaE9yU3F1YXNoKGtleSwgLi4udmFsdWUpO1xuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IGRlY3M6IHsgW2luZGV4ZXI6IHN0cmluZ106IGFueVtdIH0gfCB1bmRlZmluZWQgPVxuICAgIFJlZmxlY3Rpb24uZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzKG1vZGVsLCAuLi5wcmVmaXhlcyk7XG4gIGlmIChkZWNzKSBtZXJnZURlY29yYXRvcnMoZGVjcyk7XG5cbiAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZihtb2RlbCkgPT09IE9iamVjdC5wcm90b3R5cGUpIHJldHVybiBhY2N1bXVsYXRvcjtcblxuICAvLyBjb25zdCBuYW1lID0gbW9kZWwuY29uc3RydWN0b3IubmFtZTtcbiAgY29uc3QgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YobW9kZWwpO1xuICBpZiAoIXByb3RvKSByZXR1cm4gYWNjdW11bGF0b3I7XG4gIC8vIGlmIChwcm90by5jb25zdHJ1Y3RvciAmJiBwcm90by5jb25zdHJ1Y3Rvci5uYW1lID09PSBuYW1lKVxuICAvLyAgICAgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pXG4gIHJldHVybiBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUocHJvdG8sIGFjY3VtdWxhdG9yLCAuLi5wcmVmaXhlcyk7XG59O1xuIiwiaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBjb25maWd1cmF0aW9uIGZsYWdzIGZvciByZXBvc2l0b3J5IG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBkZWZhdWx0IHZhbHVlcyBmb3IgcmVwb3NpdG9yeSBvcGVyYXRpb24gZmxhZ3MsIGV4Y2x1ZGluZyB0aGUgdGltZXN0YW1wIHByb3BlcnR5LlxuICogVGhlc2UgZmxhZ3MgY29udHJvbCBiZWhhdmlvciBzdWNoIGFzIGNvbnRleHQgaGFuZGxpbmcsIHZhbGlkYXRpb24sIGVycm9yIGhhbmRsaW5nLCBhbmQgbW9yZS5cbiAqIEBjb25zdCBEZWZhdWx0UmVwb3NpdG9yeUZsYWdzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRSZXBvc2l0b3J5RmxhZ3M6IE9taXQ8UmVwb3NpdG9yeUZsYWdzLCBcInRpbWVzdGFtcFwiPiA9IHtcbiAgcGFyZW50Q29udGV4dDogdW5kZWZpbmVkLFxuICBjaGlsZENvbnRleHRzOiBbXSxcbiAgaWdub3JlZFZhbGlkYXRpb25Qcm9wZXJ0aWVzOiBbXSxcbiAgY2FsbEFyZ3M6IFtdLFxuICB3cml0ZU9wZXJhdGlvbjogZmFsc2UsXG4gIGFmZmVjdGVkVGFibGVzOiBbXSxcbiAgb3BlcmF0aW9uOiB1bmRlZmluZWQsXG4gIGJyZWFrT25IYW5kbGVyRXJyb3I6IHRydWUsXG4gIHJlYnVpbGRXaXRoVHJhbnNpZW50OiB0cnVlLFxufTtcbiIsImltcG9ydCB7IENvbnRleHRBcmdzIH0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCB7IENvbnRleHR1YWwgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9Db250ZXh0dWFsXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBEZWZhdWx0UmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBPYmplY3RBY2N1bXVsYXRvciB9IGZyb20gXCJ0eXBlZC1vYmplY3QtYWNjdW11bGF0b3JcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEZhY3RvcnkgdHlwZSBmb3IgY3JlYXRpbmcgY29udGV4dCBpbnN0YW5jZXMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgZnVuY3Rpb24gdHlwZSB0aGF0IGNyZWF0ZXMgY29udGV4dCBpbnN0YW5jZXMgd2l0aCBzcGVjaWZpYyByZXBvc2l0b3J5IGZsYWdzLlxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlIGV4dGVuZGluZyBSZXBvc2l0b3J5RmxhZ3NcbiAqIEB0eXBlZGVmIHtGdW5jdGlvbn0gQ29udGV4dEZhY3RvcnlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgdHlwZSBDb250ZXh0RmFjdG9yeTxGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzPiA9IDxDIGV4dGVuZHMgQ29udGV4dDxGPj4oXG4gIGFyZzogT21pdDxGLCBcInRpbWVzdGFtcFwiPlxuKSA9PiBDO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGZhY3RvcnkgZm9yIGNyZWF0aW5nIGNvbnRleHQgaW5zdGFuY2VzLlxuICogQHN1bW1hcnkgQSBmYWN0b3J5IGZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBuZXcgQ29udGV4dCBpbnN0YW5jZXMgd2l0aCB0aGUgcHJvdmlkZWQgcmVwb3NpdG9yeSBmbGFncy5cbiAqIEl0IGF1dG9tYXRpY2FsbHkgYWRkcyBhIHRpbWVzdGFtcCB0byB0aGUgY29udGV4dCBhbmQgcmV0dXJucyBhIHByb3Blcmx5IHR5cGVkIGNvbnRleHQgaW5zdGFuY2UuXG4gKiBAY29uc3QgRGVmYXVsdENvbnRleHRGYWN0b3J5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRDb250ZXh0RmFjdG9yeTogQ29udGV4dEZhY3Rvcnk8YW55PiA9IDxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4+KFxuICBhcmc6IE9taXQ8RiwgXCJ0aW1lc3RhbXBcIj5cbikgPT4ge1xuICByZXR1cm4gbmV3IENvbnRleHQ8Rj4oKS5hY2N1bXVsYXRlKFxuICAgIE9iamVjdC5hc3NpZ24oe30sIGFyZywgeyB0aW1lc3RhbXA6IG5ldyBEYXRlKCkgfSkgYXMgRlxuICApIGFzIEM7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBIGNvbnRleHQgbWFuYWdlbWVudCBjbGFzcyBmb3IgaGFuZGxpbmcgcmVwb3NpdG9yeSBvcGVyYXRpb25zLlxuICogQHN1bW1hcnkgVGhlIENvbnRleHQgY2xhc3MgcHJvdmlkZXMgYSBtZWNoYW5pc20gZm9yIG1hbmFnaW5nIHJlcG9zaXRvcnkgb3BlcmF0aW9ucyB3aXRoIGZsYWdzLFxuICogcGFyZW50LWNoaWxkIHJlbGF0aW9uc2hpcHMsIGFuZCBzdGF0ZSBhY2N1bXVsYXRpb24uIEl0IGFsbG93cyBmb3IgaGllcmFyY2hpY2FsIGNvbnRleHQgY2hhaW5zXG4gKiBhbmQgbWFpbnRhaW5zIG9wZXJhdGlvbi1zcGVjaWZpYyBjb25maWd1cmF0aW9ucyB3aGlsZSBzdXBwb3J0aW5nIHR5cGUgc2FmZXR5IHRocm91Z2ggZ2VuZXJpY3MuXG4gKlxuICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyBSZXBvc2l0b3J5RmxhZ3MgdGhhdCBkZWZpbmVzIHRoZSBjb250ZXh0IGNvbmZpZ3VyYXRpb25cbiAqXG4gKiBAcGFyYW0ge09iamVjdEFjY3VtdWxhdG9yPEY+fSBjYWNoZSAtIFRoZSBpbnRlcm5hbCBjYWNoZSBzdG9yaW5nIGFjY3VtdWxhdGVkIHZhbHVlc1xuICpcbiAqIEBjbGFzc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGluZyBhIG5ldyBjb250ZXh0IHdpdGggcmVwb3NpdG9yeSBmbGFnc1xuICogY29uc3QgY29udGV4dCA9IG5ldyBDb250ZXh0PFJlcG9zaXRvcnlGbGFncz4oKTtcbiAqXG4gKiAvLyBBY2N1bXVsYXRpbmcgdmFsdWVzXG4gKiBjb25zdCBlbnJpY2hlZENvbnRleHQgPSBjb250ZXh0LmFjY3VtdWxhdGUoe1xuICogICB3cml0ZU9wZXJhdGlvbjogdHJ1ZSxcbiAqICAgYWZmZWN0ZWRUYWJsZXM6IFsndXNlcnMnXSxcbiAqICAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzLkNSRUFURVxuICogfSk7XG4gKlxuICogLy8gQWNjZXNzaW5nIHZhbHVlc1xuICogY29uc3QgaXNXcml0ZSA9IGVucmljaGVkQ29udGV4dC5nZXQoJ3dyaXRlT3BlcmF0aW9uJyk7IC8vIHRydWVcbiAqIGNvbnN0IHRhYmxlcyA9IGVucmljaGVkQ29udGV4dC5nZXQoJ2FmZmVjdGVkVGFibGVzJyk7IC8vIFsndXNlcnMnXVxuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudFxuICogICBwYXJ0aWNpcGFudCBDdHggYXMgQ29udGV4dFxuICogICBwYXJ0aWNpcGFudCBDYWNoZSBhcyBPYmplY3RBY2N1bXVsYXRvclxuICpcbiAqICAgQy0+PkN0eDogbmV3IENvbnRleHQoKVxuICogICBDdHgtPj5DYWNoZTogY3JlYXRlIGNhY2hlXG4gKlxuICogICBDLT4+Q3R4OiBhY2N1bXVsYXRlKHZhbHVlKVxuICogICBDdHgtPj5DYWNoZTogYWNjdW11bGF0ZSh2YWx1ZSlcbiAqICAgQ2FjaGUtLT4+Q3R4OiB1cGRhdGVkIGNhY2hlXG4gKiAgIEN0eC0tPj5DOiB1cGRhdGVkIGNvbnRleHRcbiAqXG4gKiAgIEMtPj5DdHg6IGdldChrZXkpXG4gKiAgIEN0eC0+PkNhY2hlOiBnZXQoa2V5KVxuICogICBhbHQgS2V5IGV4aXN0cyBpbiBjYWNoZVxuICogICAgIENhY2hlLS0+PkN0eDogdmFsdWVcbiAqICAgZWxzZSBLZXkgbm90IGZvdW5kXG4gKiAgICAgQ3R4LT4+Q3R4OiBjaGVjayBwYXJlbnQgY29udGV4dFxuICogICAgIGFsdCBQYXJlbnQgZXhpc3RzXG4gKiAgICAgICBDdHgtPj5QYXJlbnQ6IGdldChrZXkpXG4gKiAgICAgICBQYXJlbnQtLT4+Q3R4OiB2YWx1ZVxuICogICAgIGVsc2UgTm8gcGFyZW50XG4gKiAgICAgICBDdHgtLT4+QzogdGhyb3cgZXJyb3JcbiAqICAgICBlbmRcbiAqICAgZW5kXG4gKiAgIEN0eC0tPj5DOiByZXF1ZXN0ZWQgdmFsdWVcbiAqL1xuZXhwb3J0IGNsYXNzIENvbnRleHQ8RiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncz4ge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgXCJjYWNoZVwiLCB7XG4gICAgICB2YWx1ZTogbmV3IE9iamVjdEFjY3VtdWxhdG9yPEY+KCksXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmYWN0b3J5OiBDb250ZXh0RmFjdG9yeTxhbnk+ID0gRGVmYXVsdENvbnRleHRGYWN0b3J5O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGU6IEYgJiBPYmplY3RBY2N1bXVsYXRvcjxGPiA9XG4gICAgbmV3IE9iamVjdEFjY3VtdWxhdG9yKCkgYXMgRiAmIE9iamVjdEFjY3VtdWxhdG9yPEY+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWNjdW11bGF0ZXMgbmV3IHZhbHVlcyBpbnRvIHRoZSBjb250ZXh0LlxuICAgKiBAc3VtbWFyeSBNZXJnZXMgdGhlIHByb3ZpZGVkIHZhbHVlIG9iamVjdCB3aXRoIHRoZSBleGlzdGluZyBjb250ZXh0IHN0YXRlLFxuICAgKiBjcmVhdGluZyBhIG5ldyBpbW11dGFibGUgY2FjaGUgc3RhdGUuXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBGIC0gY3VycmVudCBhY2N1bXVsYXRvciB0eXBlXG4gICAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgb2JqZWN0IGZvciB0aGUgdmFsdWVzIHRvIGFjY3VtdWxhdGVcbiAgICogQHBhcmFtIHtWfSB2YWx1ZSAtIFRoZSBvYmplY3QgY29udGFpbmluZyB2YWx1ZXMgdG8gYWNjdW11bGF0ZVxuICAgKiBAcmV0dXJucyBBIG5ldyBjb250ZXh0IGluc3RhbmNlIHdpdGggYWNjdW11bGF0ZWQgdmFsdWVzXG4gICAqL1xuICBhY2N1bXVsYXRlPFYgZXh0ZW5kcyBvYmplY3Q+KHZhbHVlOiBWKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIFwiY2FjaGVcIiwge1xuICAgICAgdmFsdWU6IHRoaXMuY2FjaGUuYWNjdW11bGF0ZSh2YWx1ZSksXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcyBhcyB1bmtub3duIGFzIENvbnRleHQ8RiAmIFY+O1xuICB9XG5cbiAgZ2V0IHRpbWVzdGFtcCgpIHtcbiAgICByZXR1cm4gdGhpcy5jYWNoZS50aW1lc3RhbXA7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHZhbHVlIGZyb20gdGhlIGNvbnRleHQgYnkga2V5LlxuICAgKiBAc3VtbWFyeSBBdHRlbXB0cyB0byBnZXQgYSB2YWx1ZSBmcm9tIHRoZSBjdXJyZW50IGNvbnRleHQncyBjYWNoZS5cbiAgICogSWYgbm90IGZvdW5kLCB0cmF2ZXJzZXMgdXAgdGhlIHBhcmVudCBjb250ZXh0IGNoYWluLlxuICAgKlxuICAgKiBAdGVtcGxhdGUgSyAtIFR5cGUgZXh0ZW5kaW5nIGtleW9mIEYgZm9yIHRoZSBrZXkgdG8gcmV0cmlldmVcbiAgICogQHRlbXBsYXRlIEYgLSBBY2N1bXVsYXRvciB0eXBlXG4gICAqIEBwYXJhbSB7S30ga2V5IC0gVGhlIGtleSB0byByZXRyaWV2ZSBmcm9tIHRoZSBjb250ZXh0XG4gICAqIEByZXR1cm5zIFRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGtleVxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIGtleSBpcyBub3QgZm91bmQgaW4gdGhlIGNvbnRleHQgY2hhaW5cbiAgICovXG4gIGdldDxLIGV4dGVuZHMga2V5b2YgRj4oa2V5OiBLKTogRltLXSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldChrZXkpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmICh0aGlzLmNhY2hlLnBhcmVudENvbnRleHQpIHJldHVybiB0aGlzLmNhY2hlLnBhcmVudENvbnRleHQuZ2V0KGtleSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGNoaWxkIGNvbnRleHRcbiAgICogQHN1bW1hcnkgR2VuZXJhdGVzIGEgbmV3IGNvbnRleHQgaW5zdGFuY2Ugd2l0aCBjdXJyZW50IGNvbnRleHQgYXMgcGFyZW50XG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIHR5cGVcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gW21vZGVsXSAtIE9wdGlvbmFsIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqIEByZXR1cm5zIHtDfSBOZXcgY2hpbGQgY29udGV4dCBpbnN0YW5jZVxuICAgKi9cbiAgY2hpbGQ8TSBleHRlbmRzIE1vZGVsLCBDIGV4dGVuZHMgQ29udGV4dDxGPj4oXG4gICAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzLFxuICAgIG1vZGVsPzogQ29uc3RydWN0b3I8TT5cbiAgKTogQyB7XG4gICAgcmV0dXJuIENvbnRleHQuY2hpbGRGcm9tPEYsIEM+KFxuICAgICAgdGhpcyBhcyB1bmtub3duIGFzIEMsXG4gICAgICB7XG4gICAgICAgIG9wZXJhdGlvbjogb3BlcmF0aW9uLFxuICAgICAgICBhZmZlY3RlZFRhYmxlczogbW9kZWwgPyBbbW9kZWxdIDogW10sXG4gICAgICB9IGFzIHVua25vd24gYXMgUGFydGlhbDxGPlxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBjaGlsZCBjb250ZXh0IGZyb20gYW5vdGhlciBjb250ZXh0XG4gICAqIEBzdW1tYXJ5IEdlbmVyYXRlcyBhIG5ldyBjb250ZXh0IGluc3RhbmNlIHdpdGggcGFyZW50IHJlZmVyZW5jZVxuICAgKlxuICAgKiBAdGVtcGxhdGUgRiAtIFR5cGUgZXh0ZW5kaW5nIFJlcG9zaXRvcnkgRmxhZ3NcbiAgICogQHRlbXBsYXRlIEMgLSBUeXBlIGV4dGVuZGluZyBDb250ZXh0PEY+XG4gICAqIEBwYXJhbSB7Q30gY29udGV4dCAtIFRoZSBwYXJlbnQgY29udGV4dFxuICAgKiBAcGFyYW0ge1BhcnRpYWw8Rj59IFtvdmVycmlkZXNdIC0gT3B0aW9uYWwgZmxhZyBvdmVycmlkZXNcbiAgICogQHJldHVybnMge0N9IE5ldyBjaGlsZCBjb250ZXh0IGluc3RhbmNlXG4gICAqL1xuICBzdGF0aWMgY2hpbGRGcm9tPEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsIEMgZXh0ZW5kcyBDb250ZXh0PEY+PihcbiAgICBjb250ZXh0OiBDLFxuICAgIG92ZXJyaWRlcz86IFBhcnRpYWw8Rj5cbiAgKTogQyB7XG4gICAgcmV0dXJuIENvbnRleHQuZmFjdG9yeShcbiAgICAgIE9iamVjdC5hc3NpZ24oe30sIGNvbnRleHQuY2FjaGUsIG92ZXJyaWRlcyB8fCB7fSlcbiAgICApIGFzIHVua25vd24gYXMgQztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBjb250ZXh0IGZyb20gb3BlcmF0aW9uIHBhcmFtZXRlcnNcbiAgICogQHN1bW1hcnkgR2VuZXJhdGVzIGEgY29udGV4dCBpbnN0YW5jZSBmb3Igc3BlY2lmaWMgb3BlcmF0aW9uXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBGIC0gVHlwZSBleHRlbmRpbmcgUmVwb3NpdG9yeSBGbGFnc1xuICAgKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cy5ERUxFVEV9IG9wZXJhdGlvbiAtIFRoZSBvcGVyYXRpb24gdHlwZVxuICAgKiBAcGFyYW0ge1BhcnRpYWw8Rj59IG92ZXJyaWRlcyAtIEZsYWcgb3ZlcnJpZGVzXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7YW55fSBhcmdzIC0gT3BlcmF0aW9uIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxDPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gbmV3IGNvbnRleHRcbiAgICovXG4gIHN0YXRpYyBhc3luYyBmcm9tPFxuICAgIE0gZXh0ZW5kcyBNb2RlbCxcbiAgICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICAgIEMgZXh0ZW5kcyBDb250ZXh0PEY+LFxuICA+KFxuICAgIG9wZXJhdGlvbjpcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5DUkVBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5SRUFEXG4gICAgICB8IE9wZXJhdGlvbktleXMuVVBEQVRFXG4gICAgICB8IE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgIG92ZXJyaWRlczogUGFydGlhbDxGPixcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8Qz4ge1xuICAgIHJldHVybiBDb250ZXh0LmZhY3RvcnkoXG4gICAgICBPYmplY3QuYXNzaWduKHt9LCBEZWZhdWx0UmVwb3NpdG9yeUZsYWdzLCBvdmVycmlkZXMsIHtcbiAgICAgICAgb3BlcmF0aW9uOiBvcGVyYXRpb24sXG4gICAgICAgIG1vZGVsOiBtb2RlbCxcbiAgICAgIH0pXG4gICAgKSBhcyBDO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBhcmd1bWVudHMgZm9yIGNvbnRleHQgb3BlcmF0aW9uc1xuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgY29udGV4dCBhcmdzIG9iamVjdCB3aXRoIHRoZSBzcGVjaWZpZWQgb3BlcmF0aW9uIHBhcmFtZXRlcnNcbiAgICpcbiAgICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyB7QGxpbmsgUmVwb3NpdG9yeUZsYWdzfVxuICAgKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIHtAbGluayBNb2RlbH1cbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzLkRFTEVURX0gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiB0eXBlXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBPcGVyYXRpb24gYXJndW1lbnRzXG4gICAqIEBwYXJhbSB7Q29udGV4dHVhbDxGPn0gW2NvbnRleHR1YWxdIC0gT3B0aW9uYWwgY29udGV4dHVhbCBvYmplY3RcbiAgICogQHBhcmFtIHtQYXJ0aWFsPEY+fSBbb3ZlcnJpZGVzXSAtIE9wdGlvbmFsIGZsYWcgb3ZlcnJpZGVzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPENvbnRleHRBcmdzPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gY29udGV4dCBhcmd1bWVudHNcbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQyBhcyBDb250ZXh0XG4gICAqICAgcGFydGljaXBhbnQgTSBhcyBNb2RlbFxuICAgKiAgIHBhcnRpY2lwYW50IEEgYXMgQXJnc1xuICAgKlxuICAgKiAgIEMtPj5DOiBSZWNlaXZlIG9wZXJhdGlvbiByZXF1ZXN0XG4gICAqICAgQy0+Pk06IFZhbGlkYXRlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqICAgQy0+PkM6IENyZWF0ZSBjaGlsZCBjb250ZXh0XG4gICAqICAgQy0+PkE6IFByb2Nlc3Mgb3BlcmF0aW9uIGFyZ3NcbiAgICogICBBLT4+QzogUmV0dXJuIGNvbnRleHQgYXJnc1xuICAgKiAgIEMtPj5DOiBBcHBseSBvdmVycmlkZXNcbiAgICogICBDLT4+QzogUmV0dXJuIGZpbmFsIGNvbnRleHRcbiAgICovXG4gIHN0YXRpYyBhc3luYyBhcmdzPFxuICAgIE0gZXh0ZW5kcyBNb2RlbCxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbiAgICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICA+KFxuICAgIG9wZXJhdGlvbjpcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5DUkVBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5SRUFEXG4gICAgICB8IE9wZXJhdGlvbktleXMuVVBEQVRFXG4gICAgICB8IE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBhcmdzOiBhbnlbXSxcbiAgICBjb250ZXh0dWFsPzogQ29udGV4dHVhbDxGPixcbiAgICBvdmVycmlkZXM/OiBQYXJ0aWFsPEY+XG4gICk6IFByb21pc2U8Q29udGV4dEFyZ3M8RiwgQz4+IHtcbiAgICBjb25zdCBsYXN0ID0gYXJncy5wb3AoKTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGdldENvbnRleHQoKSB7XG4gICAgICBpZiAoY29udGV4dHVhbClcbiAgICAgICAgcmV0dXJuIGNvbnRleHR1YWwuY29udGV4dChvcGVyYXRpb24sIG92ZXJyaWRlcyB8fCB7fSwgbW9kZWwsIC4uLmFyZ3MpO1xuICAgICAgcmV0dXJuIENvbnRleHQuZnJvbShvcGVyYXRpb24sIG92ZXJyaWRlcyB8fCB7fSwgbW9kZWwsIC4uLmFyZ3MpO1xuICAgIH1cblxuICAgIGxldCBjOiBDO1xuICAgIGlmIChsYXN0KSB7XG4gICAgICBpZiAobGFzdCBpbnN0YW5jZW9mIENvbnRleHQpIHtcbiAgICAgICAgYyA9IGxhc3QgYXMgQztcbiAgICAgICAgYXJncy5wdXNoKGxhc3QpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYyA9IChhd2FpdCBnZXRDb250ZXh0KCkpIGFzIEM7XG4gICAgICAgIGFyZ3MucHVzaChsYXN0LCBjKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYyA9IChhd2FpdCBnZXRDb250ZXh0KCkpIGFzIEM7XG4gICAgICBhcmdzLnB1c2goYyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgY29udGV4dDogYywgYXJnczogYXJncyB9O1xuICB9XG59XG4iLCJpbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4vQ29udGV4dFwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFV0aWwgbWV0aG9kIHRvIGNoYW5nZSBhIG1ldGhvZCBvZiBhbiBvYmplY3QgcHJlZml4aW5nIGl0IHdpdGggYW5vdGhlclxuICogQHBhcmFtIHthbnl9IG9iaiBUaGUgQmFzZSBPYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGFmdGVyIFRoZSBvcmlnaW5hbCBtZXRob2RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWZpeCBUaGUgUHJlZml4IG1ldGhvZC4gVGhlIG91dHB1dCB3aWxsIGJlIHVzZWQgYXMgYXJndW1lbnRzIGluIHRoZSBvcmlnaW5hbCBtZXRob2RcbiAqIEBwYXJhbSB7c3RyaW5nfSBbYWZ0ZXJOYW1lXSBXaGVuIHRoZSBhZnRlciBmdW5jdGlvbiBhbm1lIGNhbm5vdCBiZSBleHRyYWN0ZWQsIHBhc3MgaXQgaGVyZVxuICpcbiAqIEBmdW5jdGlvbiBwcmVmaXhNZXRob2RcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZWZpeE1ldGhvZChcbiAgb2JqOiBhbnksXG4gIGFmdGVyOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgcHJlZml4OiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgYWZ0ZXJOYW1lPzogc3RyaW5nXG4pIHtcbiAgYXN5bmMgZnVuY3Rpb24gd3JhcHBlcih0aGlzOiBhbnksIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShwcmVmaXguY2FsbCh0aGlzLCAuLi5hcmdzKSk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShhZnRlci5hcHBseSh0aGlzLCByZXN1bHRzKSk7XG4gIH1cbiAgY29uc3Qgd3JhcHBlZCA9IHdyYXBwZXIuYmluZChvYmopO1xuICBjb25zdCBuYW1lID0gYWZ0ZXJOYW1lID8gYWZ0ZXJOYW1lIDogYWZ0ZXIubmFtZTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdyYXBwZWQsIFwibmFtZVwiLCB7XG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgd3JpdGFibGU6IGZhbHNlLFxuICAgIHZhbHVlOiBuYW1lLFxuICB9KTtcbiAgb2JqW25hbWVdID0gd3JhcHBlZDtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBVdGlsIG1ldGhvZCB0byBjaGFuZ2UgYSBtZXRob2Qgb2YgYW4gb2JqZWN0IHN1ZmZpeGluZyBpdCB3aXRoIGFub3RoZXJcbiAqIEBwYXJhbSB7YW55fSBvYmogVGhlIEJhc2UgT2JqZWN0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBiZWZvcmUgVGhlIG9yaWdpbmFsIG1ldGhvZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gc3VmZml4IFRoZSBQcmVmaXggbWV0aG9kLiBUaGUgb3V0cHV0IHdpbGwgYmUgdXNlZCBhcyBhcmd1bWVudHMgaW4gdGhlIG9yaWdpbmFsIG1ldGhvZFxuICogQHBhcmFtIHtzdHJpbmd9IFtiZWZvcmVOYW1lXSBXaGVuIHRoZSBhZnRlciBmdW5jdGlvbiBhbm1lIGNhbm5vdCBiZSBleHRyYWN0ZWQsIHBhc3MgaXQgaGVyZVxuICpcbiAqIEBmdW5jdGlvbiBzdWZmaXhNZXRob2RcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuUmVwb3NpdG9yeVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3VmZml4TWV0aG9kKFxuICBvYmo6IGFueSxcbiAgYmVmb3JlOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgc3VmZml4OiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgYmVmb3JlTmFtZT86IHN0cmluZ1xuKSB7XG4gIGFzeW5jIGZ1bmN0aW9uIHdyYXBwZXIodGhpczogYW55LCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLnJlc29sdmUoYmVmb3JlLmNhbGwodGhpcywgLi4uYXJncykpO1xuICAgIHJldHVybiBzdWZmaXguY2FsbCh0aGlzLCAuLi5yZXN1bHRzKTtcbiAgfVxuICBjb25zdCB3cmFwcGVkID0gd3JhcHBlci5iaW5kKG9iaik7XG4gIGNvbnN0IG5hbWUgPSBiZWZvcmVOYW1lID8gYmVmb3JlTmFtZSA6IGJlZm9yZS5uYW1lO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkod3JhcHBlZCwgXCJuYW1lXCIsIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IG5hbWUsXG4gIH0pO1xuICBvYmpbbmFtZV0gPSB3cmFwcGVkO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFV0aWwgbWV0aG9kIHRvIHdyYXAgYSBtZXRob2Qgb2YgYW4gb2JqZWN0IHdpdGggYWRkaXRpb25hbCBsb2dpY1xuICpcbiAqIEBwYXJhbSB7YW55fSBvYmogVGhlIEJhc2UgT2JqZWN0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBiZWZvcmUgdGhlIG1ldGhvZCB0byBiZSBwcmVmaXhlZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gbWV0aG9kIHRoZSBtZXRob2QgdG8gYmUgd3JhcHBlZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gYWZ0ZXIgVGhlIG1ldGhvZCB0byBiZSBzdWZmaXhlZFxuICogQHBhcmFtIHtzdHJpbmd9IFttZXRob2ROYW1lXSBXaGVuIHRoZSBhZnRlciBmdW5jdGlvbiBhbm1lIGNhbm5vdCBiZSBleHRyYWN0ZWQsIHBhc3MgaXQgaGVyZVxuICpcbiAqIEBmdW5jdGlvbiB3cmFwTWV0aG9kV2l0aENvbnRleHRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyYXBNZXRob2RXaXRoQ29udGV4dChcbiAgb2JqOiBhbnksXG4gIGJlZm9yZTogKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnksXG4gIG1ldGhvZDogKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnksXG4gIGFmdGVyOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgbWV0aG9kTmFtZT86IHN0cmluZ1xuKSB7XG4gIGNvbnN0IG5hbWUgPSBtZXRob2ROYW1lID8gbWV0aG9kTmFtZSA6IG1ldGhvZC5uYW1lO1xuICBvYmpbbmFtZV0gPSBuZXcgUHJveHkob2JqW25hbWVdLCB7XG4gICAgYXBwbHk6IGFzeW5jICh0YXJnZXQsIHRoaXNBcmcsIGFyZ0FycmF5KSA9PiB7XG4gICAgICBsZXQgdHJhbnNmb3JtZWRBcmdzID0gYmVmb3JlLmNhbGwodGhpc0FyZywgLi4uYXJnQXJyYXkpO1xuICAgICAgaWYgKHRyYW5zZm9ybWVkQXJncyBpbnN0YW5jZW9mIFByb21pc2UpXG4gICAgICAgIHRyYW5zZm9ybWVkQXJncyA9IGF3YWl0IHRyYW5zZm9ybWVkQXJncztcbiAgICAgIGNvbnN0IGNvbnRleHQgPSB0cmFuc2Zvcm1lZEFyZ3NbdHJhbnNmb3JtZWRBcmdzLmxlbmd0aCAtIDFdIGFzIGFueTtcbiAgICAgIGlmICghKGNvbnRleHQgaW5zdGFuY2VvZiBDb250ZXh0KSlcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJNaXNzaW5nIGEgY29udGV4dFwiKTtcbiAgICAgIGxldCByZXN1bHRzID0gYXdhaXQgdGFyZ2V0LmNhbGwodGhpc0FyZywgLi4udHJhbnNmb3JtZWRBcmdzKTtcbiAgICAgIGlmIChyZXN1bHRzIGluc3RhbmNlb2YgUHJvbWlzZSkgcmVzdWx0cyA9IGF3YWl0IHJlc3VsdHM7XG4gICAgICByZXN1bHRzID0gYWZ0ZXIuY2FsbCh0aGlzQXJnLCByZXN1bHRzLCBjb250ZXh0KTtcbiAgICAgIGlmIChyZXN1bHRzIGluc3RhbmNlb2YgUHJvbWlzZSkgcmVzdWx0cyA9IGF3YWl0IHJlc3VsdHM7XG4gICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9LFxuICB9KTtcbn1cbiIsImltcG9ydCB7IERCS2V5cyB9IGZyb20gXCIuLi9tb2RlbC9jb25zdGFudHNcIjtcbmltcG9ydCB7IGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZSB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L3V0aWxzXCI7XG5pbXBvcnQgeyBNb2RlbCwgTW9kZWxLZXlzLCBzZiB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9lcnJvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRmluZHMgdGhlIHByaW1hcnkga2V5IGF0dHJpYnV0ZSBmb3IgYSBtb2RlbFxuICogQHN1bW1hcnkgU2VhcmNoZXMgaW4gYWxsIHRoZSBwcm9wZXJ0aWVzIGluIHRoZSBvYmplY3QgZm9yIGFuIHtAbGluayBpZH0gZGVjb3JhdGVkIHByb3BlcnR5IGFuZCByZXR1cm5zIHRoZSBwcm9wZXJ0eSBrZXkgYW5kIG1ldGFkYXRhXG4gKiBAcGFyYW0ge01vZGVsfSBtb2RlbCAtIFRoZSBtb2RlbCBvYmplY3QgdG8gc2VhcmNoIGZvciBwcmltYXJ5IGtleVxuICogQHJldHVybiB7T2JqZWN0fSBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgaWQgcHJvcGVydHkgbmFtZSBhbmQgaXRzIG1ldGFkYXRhXG4gKiBAZnVuY3Rpb24gZmluZFByaW1hcnlLZXlcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IGZpbmRQcmltYXJ5S2V5XG4gKiAgIHBhcnRpY2lwYW50IGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZVxuICpcbiAqICAgQ2FsbGVyLT4+ZmluZFByaW1hcnlLZXk6IG1vZGVsXG4gKiAgIGZpbmRQcmltYXJ5S2V5LT4+Z2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlOiBnZXQgZGVjb3JhdG9yc1xuICogICBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUtLT4+ZmluZFByaW1hcnlLZXk6IGRlY29yYXRvcnNcbiAqICAgZmluZFByaW1hcnlLZXktPj5maW5kUHJpbWFyeUtleTogZmlsdGVyIElEIGRlY29yYXRvcnNcbiAqICAgZmluZFByaW1hcnlLZXktPj5maW5kUHJpbWFyeUtleTogdmFsaWRhdGUgc2luZ2xlIElEIHByb3BlcnR5XG4gKiAgIGZpbmRQcmltYXJ5S2V5LS0+PkNhbGxlcjoge2lkLCBwcm9wc31cbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFByaW1hcnlLZXk8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSkge1xuICBjb25zdCBkZWNvcmF0b3JzID0gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlKFxuICAgIG1vZGVsLFxuICAgIHVuZGVmaW5lZCxcbiAgICBEQktleXMuUkVGTEVDVCArIERCS2V5cy5JRFxuICApO1xuICBjb25zdCBpZERlY29yYXRvcnMgPSBPYmplY3QuZW50cmllcyhkZWNvcmF0b3JzIGFzIG9iamVjdCkucmVkdWNlKFxuICAgIChhY2N1bTogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSwgW3Byb3AsIGRlY3NdKSA9PiB7XG4gICAgICBjb25zdCBmaWx0ZXJlZCA9IChkZWNzIGFzIHsga2V5OiBzdHJpbmcgfVtdKS5maWx0ZXIoXG4gICAgICAgIChkKSA9PiBkLmtleSAhPT0gTW9kZWxLZXlzLlRZUEVcbiAgICAgICk7XG4gICAgICBpZiAoZmlsdGVyZWQgJiYgZmlsdGVyZWQubGVuZ3RoKSB7XG4gICAgICAgIGFjY3VtW3Byb3BdID0gYWNjdW1bcHJvcF0gfHwgW107XG4gICAgICAgIGFjY3VtW3Byb3BdLnB1c2goLi4uZmlsdGVyZWQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sXG4gICAge31cbiAgKTtcblxuICBpZiAoIWlkRGVjb3JhdG9ycyB8fCAhT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJDb3VsZCBub3QgZmluZCBJRCBkZWNvcmF0ZWQgUHJvcGVydHlcIik7XG4gIGlmIChPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpLmxlbmd0aCA+IDEpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3Ioc2YoT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKS5qb2luKFwiLCBcIikpKTtcbiAgY29uc3QgaWRQcm9wID0gT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKVswXTtcbiAgaWYgKCFpZFByb3ApIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiQ291bGQgbm90IGZpbmQgSUQgZGVjb3JhdGVkIFByb3BlcnR5XCIpO1xuICByZXR1cm4ge1xuICAgIGlkOiBpZFByb3AgYXMga2V5b2YgTSxcbiAgICBwcm9wczogaWREZWNvcmF0b3JzW2lkUHJvcF1bMF0ucHJvcHMsXG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcHJpbWFyeSBrZXkgdmFsdWUgZnJvbSBhIG1vZGVsXG4gKiBAc3VtbWFyeSBTZWFyY2hlcyBmb3IgdGhlIElELWRlY29yYXRlZCBwcm9wZXJ0eSBpbiB0aGUgbW9kZWwgYW5kIHJldHVybnMgaXRzIHZhbHVlXG4gKiBAcGFyYW0ge01vZGVsfSBtb2RlbCAtIFRoZSBtb2RlbCBvYmplY3QgdG8gZXh0cmFjdCB0aGUgSUQgZnJvbVxuICogQHBhcmFtIHtib29sZWFufSBbcmV0dXJuRW1wdHk9ZmFsc2VdIC0gV2hldGhlciB0byByZXR1cm4gdW5kZWZpbmVkIGlmIG5vIElEIHZhbHVlIGlzIGZvdW5kXG4gKiBAcmV0dXJuIHtzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnR9IFRoZSBwcmltYXJ5IGtleSB2YWx1ZVxuICogQGZ1bmN0aW9uIGZpbmRNb2RlbElkXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBmaW5kTW9kZWxJZFxuICogICBwYXJ0aWNpcGFudCBmaW5kUHJpbWFyeUtleVxuICpcbiAqICAgQ2FsbGVyLT4+ZmluZE1vZGVsSWQ6IG1vZGVsLCByZXR1cm5FbXB0eVxuICogICBmaW5kTW9kZWxJZC0+PmZpbmRQcmltYXJ5S2V5OiBtb2RlbFxuICogICBmaW5kUHJpbWFyeUtleS0tPj5maW5kTW9kZWxJZDoge2lkLCBwcm9wc31cbiAqICAgZmluZE1vZGVsSWQtPj5maW5kTW9kZWxJZDogZXh0cmFjdCBtb2RlbFtpZF1cbiAqICAgZmluZE1vZGVsSWQtPj5maW5kTW9kZWxJZDogdmFsaWRhdGUgSUQgZXhpc3RzIGlmIHJlcXVpcmVkXG4gKiAgIGZpbmRNb2RlbElkLS0+PkNhbGxlcjogSUQgdmFsdWVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZE1vZGVsSWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0sXG4gIHJldHVybkVtcHR5ID0gZmFsc2Vcbik6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCB7XG4gIGNvbnN0IGlkUHJvcCA9IGZpbmRQcmltYXJ5S2V5KG1vZGVsKS5pZDtcbiAgY29uc3QgbW9kZWxJZCA9IG1vZGVsW2lkUHJvcF07XG4gIGlmICh0eXBlb2YgbW9kZWxJZCA9PT0gXCJ1bmRlZmluZWRcIiAmJiAhcmV0dXJuRW1wdHkpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgTm8gdmFsdWUgZm9yIHRoZSBJZCBpcyBkZWZpbmVkIHVuZGVyIHRoZSBwcm9wZXJ0eSAke2lkUHJvcCBhcyBzdHJpbmd9YFxuICAgICk7XG4gIHJldHVybiBtb2RlbElkIGFzIHN0cmluZyB8IG51bWJlciB8IGJpZ2ludDtcbn1cbiIsImltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGVuZm9yY2VEQkRlY29yYXRvcnMgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgd3JhcE1ldGhvZFdpdGhDb250ZXh0IH0gZnJvbSBcIi4vd3JhcHBlcnNcIjtcbmltcG9ydCB7IGZpbmRQcmltYXJ5S2V5IH0gZnJvbSBcIi4uL2lkZW50aXR5L3V0aWxzXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4vQ29udGV4dFwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQmFzZSByZXBvc2l0b3J5IGltcGxlbWVudGF0aW9uIHByb3ZpZGluZyBDUlVEIG9wZXJhdGlvbnMgZm9yIG1vZGVscy5cbiAqIEBzdW1tYXJ5IFRoZSBCYXNlUmVwb3NpdG9yeSBjbGFzcyBzZXJ2ZXMgYXMgYSBmb3VuZGF0aW9uIGZvciByZXBvc2l0b3J5IGltcGxlbWVudGF0aW9ucywgcHJvdmlkaW5nXG4gKiBhYnN0cmFjdCBhbmQgY29uY3JldGUgbWV0aG9kcyBmb3IgY3JlYXRpbmcsIHJlYWRpbmcsIHVwZGF0aW5nLCBhbmQgZGVsZXRpbmcgbW9kZWwgaW5zdGFuY2VzLlxuICogSXQgaGFuZGxlcyBvcGVyYXRpb24gbGlmZWN5Y2xlcyBpbmNsdWRpbmcgcHJlZml4IGFuZCBzdWZmaXggb3BlcmF0aW9ucywgYW5kIGVuZm9yY2VzIGRlY29yYXRvcnMuXG4gKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlLCBkZWZhdWx0cyB0byBSZXBvc2l0b3J5RmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSwgZGVmYXVsdHMgdG8gQ29udGV4dDxGPlxuICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogLSBUaGUgY29uc3RydWN0b3IgZm9yIHRoZSBtb2RlbCBjbGFzc1xuICogQGNsYXNzIEJhc2VSZXBvc2l0b3J5XG4gKiBAZXhhbXBsZVxuICogY2xhc3MgVXNlck1vZGVsIGV4dGVuZHMgTW9kZWwge1xuICogICBAaWQoKVxuICogICBpZDogc3RyaW5nO1xuICpcbiAqICAgQHJlcXVpcmVkKClcbiAqICAgbmFtZTogc3RyaW5nO1xuICogfVxuICpcbiAqIGNsYXNzIFVzZXJSZXBvc2l0b3J5IGV4dGVuZHMgQmFzZVJlcG9zaXRvcnk8VXNlck1vZGVsPiB7XG4gKiAgIGNvbnN0cnVjdG9yKCkge1xuICogICAgIHN1cGVyKFVzZXJNb2RlbCk7XG4gKiAgIH1cbiAqXG4gKiAgIGFzeW5jIGNyZWF0ZShtb2RlbDogVXNlck1vZGVsKTogUHJvbWlzZTxVc2VyTW9kZWw+IHtcbiAqICAgICAvLyBJbXBsZW1lbnRhdGlvblxuICogICAgIHJldHVybiBtb2RlbDtcbiAqICAgfVxuICpcbiAqICAgYXN5bmMgcmVhZChrZXk6IHN0cmluZyk6IFByb21pc2U8VXNlck1vZGVsPiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb25cbiAqICAgICByZXR1cm4gbmV3IFVzZXJNb2RlbCh7IGlkOiBrZXksIG5hbWU6ICdVc2VyJyB9KTtcbiAqICAgfVxuICpcbiAqICAgYXN5bmMgdXBkYXRlKG1vZGVsOiBVc2VyTW9kZWwpOiBQcm9taXNlPFVzZXJNb2RlbD4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uXG4gKiAgICAgcmV0dXJuIG1vZGVsO1xuICogICB9XG4gKlxuICogICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPFVzZXJNb2RlbD4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uXG4gKiAgICAgY29uc3QgbW9kZWwgPSBhd2FpdCB0aGlzLnJlYWQoa2V5KTtcbiAqICAgICByZXR1cm4gbW9kZWw7XG4gKiAgIH1cbiAqIH1cbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IFIgYXMgUmVwb3NpdG9yeVxuICogICBwYXJ0aWNpcGFudCBQIGFzIFByZWZpeCBNZXRob2RzXG4gKiAgIHBhcnRpY2lwYW50IEQgYXMgRGF0YWJhc2VcbiAqICAgcGFydGljaXBhbnQgUyBhcyBTdWZmaXggTWV0aG9kc1xuICogICBwYXJ0aWNpcGFudCBWIGFzIFZhbGlkYXRvcnMvRGVjb3JhdG9yc1xuICpcbiAqICAgTm90ZSBvdmVyIEMsVjogQ3JlYXRlIE9wZXJhdGlvblxuICogICBDLT4+UjogY3JlYXRlKG1vZGVsKVxuICogICBSLT4+UDogY3JlYXRlUHJlZml4KG1vZGVsKVxuICogICBQLT4+VjogZW5mb3JjZURCRGVjb3JhdG9ycyhPTilcbiAqICAgUC0+PkQ6IERhdGFiYXNlIG9wZXJhdGlvblxuICogICBELT4+UzogY3JlYXRlU3VmZml4KG1vZGVsKVxuICogICBTLT4+VjogZW5mb3JjZURCRGVjb3JhdG9ycyhBRlRFUilcbiAqICAgUy0+PkM6IFJldHVybiBtb2RlbFxuICpcbiAqICAgTm90ZSBvdmVyIEMsVjogUmVhZCBPcGVyYXRpb25cbiAqICAgQy0+PlI6IHJlYWQoa2V5KVxuICogICBSLT4+UDogcmVhZFByZWZpeChrZXkpXG4gKiAgIFAtPj5WOiBlbmZvcmNlREJEZWNvcmF0b3JzKE9OKVxuICogICBQLT4+RDogRGF0YWJhc2Ugb3BlcmF0aW9uXG4gKiAgIEQtPj5TOiByZWFkU3VmZml4KG1vZGVsKVxuICogICBTLT4+VjogZW5mb3JjZURCRGVjb3JhdG9ycyhBRlRFUilcbiAqICAgUy0+PkM6IFJldHVybiBtb2RlbFxuICpcbiAqICAgTm90ZSBvdmVyIEMsVjogVXBkYXRlIE9wZXJhdGlvblxuICogICBDLT4+UjogdXBkYXRlKG1vZGVsKVxuICogICBSLT4+UDogdXBkYXRlUHJlZml4KG1vZGVsKVxuICogICBQLT4+VjogZW5mb3JjZURCRGVjb3JhdG9ycyhPTilcbiAqICAgUC0+PkQ6IERhdGFiYXNlIG9wZXJhdGlvblxuICogICBELT4+UzogdXBkYXRlU3VmZml4KG1vZGVsKVxuICogICBTLT4+VjogZW5mb3JjZURCRGVjb3JhdG9ycyhBRlRFUilcbiAqICAgUy0+PkM6IFJldHVybiBtb2RlbFxuICpcbiAqICAgTm90ZSBvdmVyIEMsVjogRGVsZXRlIE9wZXJhdGlvblxuICogICBDLT4+UjogZGVsZXRlKGtleSlcbiAqICAgUi0+PlA6IGRlbGV0ZVByZWZpeChrZXkpXG4gKiAgIFAtPj5WOiBlbmZvcmNlREJEZWNvcmF0b3JzKE9OKVxuICogICBQLT4+RDogRGF0YWJhc2Ugb3BlcmF0aW9uXG4gKiAgIEQtPj5TOiBkZWxldGVTdWZmaXgobW9kZWwpXG4gKiAgIFMtPj5WOiBlbmZvcmNlREJEZWNvcmF0b3JzKEFGVEVSKVxuICogICBTLT4+QzogUmV0dXJuIG1vZGVsXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlUmVwb3NpdG9yeTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+IGltcGxlbWVudHMgSVJlcG9zaXRvcnk8TSwgRiwgQz5cbntcbiAgcHJpdmF0ZSByZWFkb25seSBfY2xhc3MhOiBDb25zdHJ1Y3RvcjxNPjtcbiAgcHJpdmF0ZSBfcGshOiBrZXlvZiBNO1xuICBwcml2YXRlIF9wa1Byb3BzITogYW55O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgbW9kZWwgY2xhc3MgY29uc3RydWN0b3IuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgY29uc3RydWN0b3IgZm9yIHRoZSBtb2RlbCBjbGFzcyBhc3NvY2lhdGVkIHdpdGggdGhpcyByZXBvc2l0b3J5LlxuICAgKiBUaHJvd3MgYW4gZXJyb3IgaWYgbm8gY2xhc3MgZGVmaW5pdGlvbiBpcyBmb3VuZC5cbiAgICogQHJldHVybiB7Q29uc3RydWN0b3I8TT59IFRoZSBjb25zdHJ1Y3RvciBmb3IgdGhlIG1vZGVsIGNsYXNzXG4gICAqL1xuICBnZXQgY2xhc3MoKSB7XG4gICAgaWYgKCF0aGlzLl9jbGFzcylcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBObyBjbGFzcyBkZWZpbml0aW9uIGZvdW5kIGZvciB0aGlzIHJlcG9zaXRvcnlgKTtcbiAgICByZXR1cm4gdGhpcy5fY2xhc3M7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHByaW1hcnkga2V5IHByb3BlcnR5IG5hbWUgb2YgdGhlIG1vZGVsLlxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRoYXQgc2VydmVzIGFzIHRoZSBwcmltYXJ5IGtleSBmb3IgdGhlIG1vZGVsLlxuICAgKiBJZiBub3QgYWxyZWFkeSBkZXRlcm1pbmVkLCBpdCBmaW5kcyB0aGUgcHJpbWFyeSBrZXkgdXNpbmcgdGhlIG1vZGVsJ3MgZGVjb3JhdG9ycy5cbiAgICogQHJldHVybiBUaGUgbmFtZSBvZiB0aGUgcHJpbWFyeSBrZXkgcHJvcGVydHlcbiAgICovXG4gIGdldCBwaygpOiBrZXlvZiBNIHtcbiAgICBpZiAoIXRoaXMuX3BrKSB7XG4gICAgICBjb25zdCB7IGlkLCBwcm9wcyB9ID0gZmluZFByaW1hcnlLZXkobmV3IHRoaXMuY2xhc3MoKSk7XG4gICAgICB0aGlzLl9wayA9IGlkO1xuICAgICAgdGhpcy5fcGtQcm9wcyA9IHByb3BzO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fcGs7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHByaW1hcnkga2V5IHByb3BlcnRpZXMuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgcHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhlIHByaW1hcnkga2V5IG9mIHRoZSBtb2RlbC5cbiAgICogSWYgbm90IGFscmVhZHkgZGV0ZXJtaW5lZCwgaXQgdHJpZ2dlcnMgdGhlIHBrIGdldHRlciB0byBmaW5kIHRoZSBwcmltYXJ5IGtleSBwcm9wZXJ0aWVzLlxuICAgKiBAcmV0dXJuIHthbnl9IFRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBwcmltYXJ5IGtleVxuICAgKi9cbiAgcHJvdGVjdGVkIGdldCBwa1Byb3BzKCk6IGFueSB7XG4gICAgaWYgKCF0aGlzLl9wa1Byb3BzKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICBjb25zdCBwayA9IHRoaXMucGs7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9wa1Byb3BzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGNsYXp6PzogQ29uc3RydWN0b3I8TT4pIHtcbiAgICBpZiAoY2xhenopIHRoaXMuX2NsYXNzID0gY2xheno7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby10aGlzLWFsaWFzXG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgW3RoaXMuY3JlYXRlLCB0aGlzLnJlYWQsIHRoaXMudXBkYXRlLCB0aGlzLmRlbGV0ZV0uZm9yRWFjaCgobSkgPT4ge1xuICAgICAgY29uc3QgbmFtZSA9IG0ubmFtZTtcbiAgICAgIHdyYXBNZXRob2RXaXRoQ29udGV4dChcbiAgICAgICAgc2VsZixcbiAgICAgICAgKHNlbGYgYXMgYW55KVtuYW1lICsgXCJQcmVmaXhcIl0sXG4gICAgICAgIG0sXG4gICAgICAgIChzZWxmIGFzIGFueSlbbmFtZSArIFwiU3VmZml4XCJdXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IG1vZGVsIGluc3RhbmNlIGluIHRoZSByZXBvc2l0b3J5LlxuICAgKiBAc3VtbWFyeSBQZXJzaXN0cyBhIG5ldyBtb2RlbCBpbnN0YW5jZSB0byB0aGUgdW5kZXJseWluZyBkYXRhIHN0b3JlLlxuICAgKiBUaGlzIG1ldGhvZCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IGNvbmNyZXRlIHJlcG9zaXRvcnkgY2xhc3Nlcy5cbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBjcmVhdGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgY3JlYXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgY3JlYXRlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgYWJzdHJhY3QgY3JlYXRlKG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIG11bHRpcGxlIG1vZGVsIGluc3RhbmNlcyBpbiB0aGUgcmVwb3NpdG9yeS5cbiAgICogQHN1bW1hcnkgUGVyc2lzdHMgbXVsdGlwbGUgbW9kZWwgaW5zdGFuY2VzIHRvIHRoZSB1bmRlcmx5aW5nIGRhdGEgc3RvcmUgYnkgY2FsbGluZ1xuICAgKiB0aGUgY3JlYXRlIG1ldGhvZCBmb3IgZWFjaCBtb2RlbCBpbiB0aGUgYXJyYXkuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgYXJyYXkgb2YgbW9kZWwgaW5zdGFuY2VzIHRvIGNyZWF0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSBjcmVhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgY3JlYXRlZCBtb2RlbCBpbnN0YW5jZXNcbiAgICovXG4gIGFzeW5jIGNyZWF0ZUFsbChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIHJldHVybiBQcm9taXNlLmFsbChtb2RlbHMubWFwKChtKSA9PiB0aGlzLmNyZWF0ZShtLCAuLi5hcmdzKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBhIG1vZGVsIGZvciBjcmVhdGlvbiBhbmQgZXhlY3V0ZXMgcHJlLWNyZWF0aW9uIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBhIG1vZGVsIGJlZm9yZSBpdCBpcyBjcmVhdGVkIGluIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGNyZWF0aW5nIGEgY29udGV4dCwgaW5zdGFudGlhdGluZyBhIG5ldyBtb2RlbCBpbnN0YW5jZSwgYW5kIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9yc1xuICAgKiB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGJlZm9yZSBjcmVhdGlvbi5cbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBwcmVwYXJlIGZvciBjcmVhdGlvblxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSBjcmVhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgcHJlcGFyZWQgbW9kZWwgYW5kIGNvbnRleHQgYXJndW1lbnRzXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlUHJlZml4KG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgbW9kZWwgPSBuZXcgdGhpcy5jbGFzcyhtb2RlbCk7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICApO1xuICAgIHJldHVybiBbbW9kZWwsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgYSBtb2RlbCBhZnRlciBjcmVhdGlvbiBhbmQgZXhlY3V0ZXMgcG9zdC1jcmVhdGlvbiBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBGaW5hbGl6ZXMgYSBtb2RlbCBhZnRlciBpdCBoYXMgYmVlbiBjcmVhdGVkIGluIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9ycyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGFmdGVyIGNyZWF0aW9uLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRoYXQgd2FzIGNyZWF0ZWRcbiAgICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHByb2Nlc3NlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZVN1ZmZpeChtb2RlbDogTSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIG11bHRpcGxlIG1vZGVscyBmb3IgY3JlYXRpb24gYW5kIGV4ZWN1dGVzIHByZS1jcmVhdGlvbiBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgbXVsdGlwbGUgbW9kZWxzIGJlZm9yZSB0aGV5IGFyZSBjcmVhdGVkIGluIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGNyZWF0aW5nIGEgY29udGV4dCwgaW5zdGFudGlhdGluZyBuZXcgbW9kZWwgaW5zdGFuY2VzLCBhbmQgZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzXG4gICAqIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYmVmb3JlIGNyZWF0aW9uIGZvciBlYWNoIG1vZGVsLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIGFycmF5IG9mIG1vZGVsIGluc3RhbmNlcyB0byBwcmVwYXJlIGZvciBjcmVhdGlvblxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSBjcmVhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4gIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHByZXBhcmVkIG1vZGVscyBhbmQgY29udGV4dCBhcmd1bWVudHNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBjcmVhdGVBbGxQcmVmaXgobW9kZWxzOiBNW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoYXN5bmMgKG0pID0+IHtcbiAgICAgICAgbSA9IG5ldyB0aGlzLmNsYXNzKG0pO1xuICAgICAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgICB9KVxuICAgICk7XG4gICAgcmV0dXJuIFttb2RlbHMsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgbXVsdGlwbGUgbW9kZWxzIGFmdGVyIGNyZWF0aW9uIGFuZCBleGVjdXRlcyBwb3N0LWNyZWF0aW9uIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IEZpbmFsaXplcyBtdWx0aXBsZSBtb2RlbHMgYWZ0ZXIgdGhleSBoYXZlIGJlZW4gY3JlYXRlZCBpbiB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnMgdGhhdCBzaG91bGQgYmUgYXBwbGllZCBhZnRlciBjcmVhdGlvbiBmb3IgZWFjaCBtb2RlbC5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBhcnJheSBvZiBtb2RlbCBpbnN0YW5jZXMgdGhhdCB3ZXJlIGNyZWF0ZWRcbiAgICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgYXJyYXkgb2YgcHJvY2Vzc2VkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZUFsbFN1ZmZpeChtb2RlbHM6IE1bXSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcCgobSkgPT5cbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuICAgIHJldHVybiBtb2RlbHM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIG1vZGVsIGluc3RhbmNlIGZyb20gdGhlIHJlcG9zaXRvcnkgYnkgaXRzIHByaW1hcnkga2V5LlxuICAgKiBAc3VtbWFyeSBGZXRjaGVzIGEgbW9kZWwgaW5zdGFuY2UgZnJvbSB0aGUgdW5kZXJseWluZyBkYXRhIHN0b3JlIHVzaW5nIGl0cyBwcmltYXJ5IGtleS5cbiAgICogVGhpcyBtZXRob2QgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBjb25jcmV0ZSByZXBvc2l0b3J5IGNsYXNzZXMuXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSBrZXkgLSBUaGUgcHJpbWFyeSBrZXkgb2YgdGhlIG1vZGVsIHRvIHJldHJpZXZlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHJlYWQgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSByZXRyaWV2ZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIGFic3RyYWN0IHJlYWQoa2V5OiBzdHJpbmcgfCBudW1iZXIsIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBtdWx0aXBsZSBtb2RlbCBpbnN0YW5jZXMgZnJvbSB0aGUgcmVwb3NpdG9yeSBieSB0aGVpciBwcmltYXJ5IGtleXMuXG4gICAqIEBzdW1tYXJ5IEZldGNoZXMgbXVsdGlwbGUgbW9kZWwgaW5zdGFuY2VzIGZyb20gdGhlIHVuZGVybHlpbmcgZGF0YSBzdG9yZSB1c2luZyB0aGVpciBwcmltYXJ5IGtleXNcbiAgICogYnkgY2FsbGluZyB0aGUgcmVhZCBtZXRob2QgZm9yIGVhY2gga2V5IGluIHRoZSBhcnJheS5cbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBrZXlzIC0gVGhlIGFycmF5IG9mIHByaW1hcnkga2V5cyBvZiB0aGUgbW9kZWxzIHRvIHJldHJpZXZlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHJlYWQgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgcmV0cmlldmVkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgYXN5bmMgcmVhZEFsbChrZXlzOiBzdHJpbmdbXSB8IG51bWJlcltdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgcmV0dXJuIGF3YWl0IFByb21pc2UuYWxsKGtleXMubWFwKChpZCkgPT4gdGhpcy5yZWFkKGlkLCAuLi5hcmdzKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgYSBtb2RlbCBhZnRlciByZXRyaWV2YWwgYW5kIGV4ZWN1dGVzIHBvc3QtcmVhZCBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBGaW5hbGl6ZXMgYSBtb2RlbCBhZnRlciBpdCBoYXMgYmVlbiByZXRyaWV2ZWQgZnJvbSB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnMgdGhhdCBzaG91bGQgYmUgYXBwbGllZCBhZnRlciByZWFkaW5nLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRoYXQgd2FzIHJldHJpZXZlZFxuICAgKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcHJvY2Vzc2VkIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgcmVhZFN1ZmZpeChtb2RlbDogTSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBmb3IgcmVhZGluZyBhIG1vZGVsIGFuZCBleGVjdXRlcyBwcmUtcmVhZCBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgYSBrZXkgYmVmb3JlIGEgbW9kZWwgaXMgcmVhZCBmcm9tIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGNyZWF0aW5nIGEgY29udGV4dCwgaW5zdGFudGlhdGluZyBhIG5ldyBtb2RlbCBpbnN0YW5jZSB3aXRoIHRoZSBrZXksIGFuZCBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnNcbiAgICogdGhhdCBzaG91bGQgYmUgYXBwbGllZCBiZWZvcmUgcmVhZGluZy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBwcmltYXJ5IGtleSBvZiB0aGUgbW9kZWwgdG8gcmVhZFxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSByZWFkIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIGtleSBhbmQgY29udGV4dCBhcmd1bWVudHNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZWFkUHJlZml4KGtleTogc3RyaW5nLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIGNvbnN0IG1vZGVsOiBNID0gbmV3IHRoaXMuY2xhc3MoKTtcbiAgICBtb2RlbFt0aGlzLnBrXSA9IGtleSBhcyBhbnk7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgKTtcbiAgICByZXR1cm4gW2tleSwgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGZvciByZWFkaW5nIG11bHRpcGxlIG1vZGVscyBhbmQgZXhlY3V0ZXMgcHJlLXJlYWQgb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgUHJvY2Vzc2VzIG11bHRpcGxlIGtleXMgYmVmb3JlIG1vZGVscyBhcmUgcmVhZCBmcm9tIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGNyZWF0aW5nIGEgY29udGV4dCwgaW5zdGFudGlhdGluZyBuZXcgbW9kZWwgaW5zdGFuY2VzIHdpdGggdGhlIGtleXMsIGFuZCBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnNcbiAgICogdGhhdCBzaG91bGQgYmUgYXBwbGllZCBiZWZvcmUgcmVhZGluZyBmb3IgZWFjaCBrZXkuXG4gICAqIEBwYXJhbSB7c3RyaW5nW10gfCBudW1iZXJbXX0ga2V5cyAtIFRoZSBhcnJheSBvZiBwcmltYXJ5IGtleXMgb2YgdGhlIG1vZGVscyB0byByZWFkXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHJlYWQgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgY29udGFpbmluZyB0aGUga2V5cyBhbmQgY29udGV4dCBhcmd1bWVudHNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZWFkQWxsUHJlZml4KGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBrZXlzLm1hcChhc3luYyAoaykgPT4ge1xuICAgICAgICBjb25zdCBtID0gbmV3IHRoaXMuY2xhc3MoKTtcbiAgICAgICAgbVt0aGlzLnBrXSA9IGsgYXMgYW55O1xuICAgICAgICByZXR1cm4gZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICAgICApO1xuICAgICAgfSlcbiAgICApO1xuICAgIHJldHVybiBba2V5cywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBtdWx0aXBsZSBtb2RlbHMgYWZ0ZXIgcmV0cmlldmFsIGFuZCBleGVjdXRlcyBwb3N0LXJlYWQgb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgRmluYWxpemVzIG11bHRpcGxlIG1vZGVscyBhZnRlciB0aGV5IGhhdmUgYmVlbiByZXRyaWV2ZWQgZnJvbSB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnMgdGhhdCBzaG91bGQgYmUgYXBwbGllZCBhZnRlciByZWFkaW5nIGZvciBlYWNoIG1vZGVsLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIGFycmF5IG9mIG1vZGVsIGluc3RhbmNlcyB0aGF0IHdlcmUgcmV0cmlldmVkXG4gICAqIEBwYXJhbSB7Q30gY29udGV4dCAtIFRoZSBjb250ZXh0IGZvciB0aGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGFycmF5IG9mIHByb2Nlc3NlZCBtb2RlbCBpbnN0YW5jZXNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZWFkQWxsU3VmZml4KG1vZGVsczogTVtdLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PlxuICAgICAgICBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuICAgIHJldHVybiBtb2RlbHM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgYW4gZXhpc3RpbmcgbW9kZWwgaW5zdGFuY2UgaW4gdGhlIHJlcG9zaXRvcnkuXG4gICAqIEBzdW1tYXJ5IFVwZGF0ZXMgYW4gZXhpc3RpbmcgbW9kZWwgaW5zdGFuY2UgaW4gdGhlIHVuZGVybHlpbmcgZGF0YSBzdG9yZS5cbiAgICogVGhpcyBtZXRob2QgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBjb25jcmV0ZSByZXBvc2l0b3J5IGNsYXNzZXMuXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gdXBkYXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHVwZGF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHVwZGF0ZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIGFic3RyYWN0IHVwZGF0ZShtb2RlbDogTSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBtdWx0aXBsZSBtb2RlbCBpbnN0YW5jZXMgaW4gdGhlIHJlcG9zaXRvcnkuXG4gICAqIEBzdW1tYXJ5IFVwZGF0ZXMgbXVsdGlwbGUgbW9kZWwgaW5zdGFuY2VzIGluIHRoZSB1bmRlcmx5aW5nIGRhdGEgc3RvcmUgYnkgY2FsbGluZ1xuICAgKiB0aGUgdXBkYXRlIG1ldGhvZCBmb3IgZWFjaCBtb2RlbCBpbiB0aGUgYXJyYXkuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgYXJyYXkgb2YgbW9kZWwgaW5zdGFuY2VzIHRvIHVwZGF0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSB1cGRhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgdXBkYXRlZCBtb2RlbCBpbnN0YW5jZXNcbiAgICovXG4gIGFzeW5jIHVwZGF0ZUFsbChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55KTogUHJvbWlzZTxNW10+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwobW9kZWxzLm1hcCgobSkgPT4gdGhpcy51cGRhdGUobSwgLi4uYXJncykpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIGEgbW9kZWwgYWZ0ZXIgdXBkYXRlIGFuZCBleGVjdXRlcyBwb3N0LXVwZGF0ZSBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBGaW5hbGl6ZXMgYSBtb2RlbCBhZnRlciBpdCBoYXMgYmVlbiB1cGRhdGVkIGluIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9ycyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGFmdGVyIHVwZGF0aW5nLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRoYXQgd2FzIHVwZGF0ZWRcbiAgICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHByb2Nlc3NlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHVwZGF0ZVN1ZmZpeChtb2RlbDogTSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgbW9kZWwgZm9yIHVwZGF0ZSBhbmQgZXhlY3V0ZXMgcHJlLXVwZGF0ZSBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgYSBtb2RlbCBiZWZvcmUgaXQgaXMgdXBkYXRlZCBpbiB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBjcmVhdGluZyBhIGNvbnRleHQsIHZhbGlkYXRpbmcgdGhlIHByaW1hcnkga2V5LCByZXRyaWV2aW5nIHRoZSBleGlzdGluZyBtb2RlbCxcbiAgICogYW5kIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9ycyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGJlZm9yZSB1cGRhdGluZy5cbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBwcmVwYXJlIGZvciB1cGRhdGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgdXBkYXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHByZXBhcmVkIG1vZGVsIGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHVwZGF0ZVByZWZpeChtb2RlbDogTSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJnczxNLCBDLCBGPihcbiAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIGNvbnN0IGlkID0gbW9kZWxbdGhpcy5wa107XG4gICAgaWYgKCFpZClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgTm8gdmFsdWUgZm9yIHRoZSBJZCBpcyBkZWZpbmVkIHVuZGVyIHRoZSBwcm9wZXJ0eSAke3RoaXMucGsgYXMgc3RyaW5nfWBcbiAgICAgICk7XG4gICAgY29uc3Qgb2xkTW9kZWwgPSBhd2FpdCB0aGlzLnJlYWQoaWQgYXMgc3RyaW5nKTtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5PTixcbiAgICAgIG9sZE1vZGVsXG4gICAgKTtcbiAgICByZXR1cm4gW21vZGVsLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgbXVsdGlwbGUgbW9kZWxzIGZvciB1cGRhdGUgYW5kIGV4ZWN1dGVzIHByZS11cGRhdGUgb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgUHJvY2Vzc2VzIG11bHRpcGxlIG1vZGVscyBiZWZvcmUgdGhleSBhcmUgdXBkYXRlZCBpbiB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBjcmVhdGluZyBhIGNvbnRleHQsIGluc3RhbnRpYXRpbmcgbmV3IG1vZGVsIGluc3RhbmNlcywgYW5kIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9yc1xuICAgKiB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGJlZm9yZSB1cGRhdGluZyBmb3IgZWFjaCBtb2RlbC5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBhcnJheSBvZiBtb2RlbCBpbnN0YW5jZXMgdG8gcHJlcGFyZSBmb3IgdXBkYXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHVwZGF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBjb250YWluaW5nIHRoZSBwcmVwYXJlZCBtb2RlbHMgYW5kIGNvbnRleHQgYXJndW1lbnRzXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgdXBkYXRlQWxsUHJlZml4KG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PiB7XG4gICAgICAgIG0gPSBuZXcgdGhpcy5jbGFzcyhtKTtcbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfSlcbiAgICApO1xuICAgIHJldHVybiBbbW9kZWxzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIG11bHRpcGxlIG1vZGVscyBhZnRlciB1cGRhdGUgYW5kIGV4ZWN1dGVzIHBvc3QtdXBkYXRlIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IEZpbmFsaXplcyBtdWx0aXBsZSBtb2RlbHMgYWZ0ZXIgdGhleSBoYXZlIGJlZW4gdXBkYXRlZCBpbiB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnMgdGhhdCBzaG91bGQgYmUgYXBwbGllZCBhZnRlciB1cGRhdGluZyBmb3IgZWFjaCBtb2RlbC5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBhcnJheSBvZiBtb2RlbCBpbnN0YW5jZXMgdGhhdCB3ZXJlIHVwZGF0ZWRcbiAgICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgYXJyYXkgb2YgcHJvY2Vzc2VkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHVwZGF0ZUFsbFN1ZmZpeChtb2RlbHM6IE1bXSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcCgobSkgPT5cbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuICAgIHJldHVybiBtb2RlbHM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgYSBtb2RlbCBpbnN0YW5jZSBmcm9tIHRoZSByZXBvc2l0b3J5IGJ5IGl0cyBwcmltYXJ5IGtleS5cbiAgICogQHN1bW1hcnkgUmVtb3ZlcyBhIG1vZGVsIGluc3RhbmNlIGZyb20gdGhlIHVuZGVybHlpbmcgZGF0YSBzdG9yZSB1c2luZyBpdHMgcHJpbWFyeSBrZXkuXG4gICAqIFRoaXMgbWV0aG9kIG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgY29uY3JldGUgcmVwb3NpdG9yeSBjbGFzc2VzLlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0ga2V5IC0gVGhlIHByaW1hcnkga2V5IG9mIHRoZSBtb2RlbCB0byBkZWxldGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgZGVsZXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgZGVsZXRlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgYWJzdHJhY3QgZGVsZXRlKGtleTogc3RyaW5nIHwgbnVtYmVyLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIG11bHRpcGxlIG1vZGVsIGluc3RhbmNlcyBmcm9tIHRoZSByZXBvc2l0b3J5IGJ5IHRoZWlyIHByaW1hcnkga2V5cy5cbiAgICogQHN1bW1hcnkgUmVtb3ZlcyBtdWx0aXBsZSBtb2RlbCBpbnN0YW5jZXMgZnJvbSB0aGUgdW5kZXJseWluZyBkYXRhIHN0b3JlIHVzaW5nIHRoZWlyIHByaW1hcnkga2V5c1xuICAgKiBieSBjYWxsaW5nIHRoZSBkZWxldGUgbWV0aG9kIGZvciBlYWNoIGtleSBpbiB0aGUgYXJyYXkuXG4gICAqIEBwYXJhbSB7c3RyaW5nW10gfCBudW1iZXJbXX0ga2V5cyAtIFRoZSBhcnJheSBvZiBwcmltYXJ5IGtleXMgb2YgdGhlIG1vZGVscyB0byBkZWxldGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgZGVsZXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIGRlbGV0ZWQgbW9kZWwgaW5zdGFuY2VzXG4gICAqL1xuICBhc3luYyBkZWxldGVBbGwoa2V5czogc3RyaW5nW10gfCBudW1iZXJbXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIHJldHVybiBQcm9taXNlLmFsbChrZXlzLm1hcCgoaykgPT4gdGhpcy5kZWxldGUoaywgLi4uYXJncykpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIGEgbW9kZWwgYWZ0ZXIgZGVsZXRpb24gYW5kIGV4ZWN1dGVzIHBvc3QtZGVsZXRlIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IEZpbmFsaXplcyBhIG1vZGVsIGFmdGVyIGl0IGhhcyBiZWVuIGRlbGV0ZWQgZnJvbSB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnMgdGhhdCBzaG91bGQgYmUgYXBwbGllZCBhZnRlciBkZWxldGlvbi5cbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0aGF0IHdhcyBkZWxldGVkXG4gICAqIEBwYXJhbSB7Q30gY29udGV4dCAtIFRoZSBjb250ZXh0IGZvciB0aGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcm9jZXNzZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVTdWZmaXgobW9kZWw6IE0sIGNvbnRleHQ6IEMpIHtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBmb3IgZGVsZXRpbmcgYSBtb2RlbCBhbmQgZXhlY3V0ZXMgcHJlLWRlbGV0ZSBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgYSBrZXkgYmVmb3JlIGEgbW9kZWwgaXMgZGVsZXRlZCBmcm9tIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGNyZWF0aW5nIGEgY29udGV4dCwgcmV0cmlldmluZyB0aGUgbW9kZWwgdG8gYmUgZGVsZXRlZCwgYW5kIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9yc1xuICAgKiB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGJlZm9yZSBkZWxldGlvbi5cbiAgICogQHBhcmFtIHthbnl9IGtleSAtIFRoZSBwcmltYXJ5IGtleSBvZiB0aGUgbW9kZWwgdG8gZGVsZXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIGRlbGV0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBjb250YWluaW5nIHRoZSBrZXkgYW5kIGNvbnRleHQgYXJndW1lbnRzXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgZGVsZXRlUHJlZml4KGtleTogYW55LCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgbW9kZWwgPSBhd2FpdCB0aGlzLnJlYWQoa2V5LCAuLi5jb250ZXh0QXJncy5hcmdzKTtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICk7XG4gICAgcmV0dXJuIFtrZXksIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBmb3IgZGVsZXRpbmcgbXVsdGlwbGUgbW9kZWxzIGFuZCBleGVjdXRlcyBwcmUtZGVsZXRlIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBtdWx0aXBsZSBrZXlzIGJlZm9yZSBtb2RlbHMgYXJlIGRlbGV0ZWQgZnJvbSB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBjcmVhdGluZyBhIGNvbnRleHQsIHJldHJpZXZpbmcgdGhlIG1vZGVscyB0byBiZSBkZWxldGVkLCBhbmQgZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzXG4gICAqIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYmVmb3JlIGRlbGV0aW9uIGZvciBlYWNoIG1vZGVsLlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdIHwgbnVtYmVyW119IGtleXMgLSBUaGUgYXJyYXkgb2YgcHJpbWFyeSBrZXlzIG9mIHRoZSBtb2RlbHMgdG8gZGVsZXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIGRlbGV0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBjb250YWluaW5nIHRoZSBrZXlzIGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGRlbGV0ZUFsbFByZWZpeChrZXlzOiBzdHJpbmdbXSB8IG51bWJlcltdLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgbW9kZWxzID0gYXdhaXQgdGhpcy5yZWFkQWxsKGtleXMsIC4uLmNvbnRleHRBcmdzLmFyZ3MpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcChhc3luYyAobSkgPT4ge1xuICAgICAgICByZXR1cm4gZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICk7XG4gICAgcmV0dXJuIFtrZXlzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIG11bHRpcGxlIG1vZGVscyBhZnRlciBkZWxldGlvbiBhbmQgZXhlY3V0ZXMgcG9zdC1kZWxldGUgb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgRmluYWxpemVzIG11bHRpcGxlIG1vZGVscyBhZnRlciB0aGV5IGhhdmUgYmVlbiBkZWxldGVkIGZyb20gdGhlIGRhdGEgc3RvcmUuIFRoaXMgaW5jbHVkZXNcbiAgICogZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYWZ0ZXIgZGVsZXRpb24gZm9yIGVhY2ggbW9kZWwuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgYXJyYXkgb2YgbW9kZWwgaW5zdGFuY2VzIHRoYXQgd2VyZSBkZWxldGVkXG4gICAqIEBwYXJhbSB7Q30gY29udGV4dCAtIFRoZSBjb250ZXh0IGZvciB0aGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGFycmF5IG9mIHByb2Nlc3NlZCBtb2RlbCBpbnN0YW5jZXNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVBbGxTdWZmaXgobW9kZWxzOiBNW10sIGNvbnRleHQ6IEMpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0pID0+XG4gICAgICAgIGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWxzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBNZXJnZXMgdHdvIG1vZGVsIGluc3RhbmNlcyBpbnRvIGEgbmV3IGluc3RhbmNlLlxuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgbmV3IG1vZGVsIGluc3RhbmNlIGJ5IGNvbWJpbmluZyBwcm9wZXJ0aWVzIGZyb20gYW4gb2xkIG1vZGVsIGFuZCBhIG5ldyBtb2RlbC5cbiAgICogUHJvcGVydGllcyBmcm9tIHRoZSBuZXcgbW9kZWwgb3ZlcnJpZGUgcHJvcGVydGllcyBmcm9tIHRoZSBvbGQgbW9kZWwgaWYgdGhleSBhcmUgZGVmaW5lZC5cbiAgICogQHBhcmFtIHtNfSBvbGRNb2RlbCAtIFRoZSBvcmlnaW5hbCBtb2RlbCBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG5ldyBtb2RlbCBpbnN0YW5jZSB3aXRoIHVwZGF0ZWQgcHJvcGVydGllc1xuICAgKiBAcmV0dXJuIHtNfSBBIG5ldyBtb2RlbCBpbnN0YW5jZSB3aXRoIG1lcmdlZCBwcm9wZXJ0aWVzXG4gICAqL1xuICBwcm90ZWN0ZWQgbWVyZ2Uob2xkTW9kZWw6IE0sIG1vZGVsOiBNKTogTSB7XG4gICAgY29uc3QgZXh0cmFjdCA9IChtb2RlbDogTSkgPT5cbiAgICAgIE9iamVjdC5lbnRyaWVzKG1vZGVsKS5yZWR1Y2UoKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsICE9PSBcInVuZGVmaW5lZFwiKSBhY2N1bVtrZXldID0gdmFsO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LCB7fSk7XG5cbiAgICByZXR1cm4gbmV3IHRoaXMuY2xhc3MoT2JqZWN0LmFzc2lnbih7fSwgZXh0cmFjdChvbGRNb2RlbCksIGV4dHJhY3QobW9kZWwpKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHJlcG9zaXRvcnkuXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgcmVwb3NpdG9yeSBieSB0aGUgbmFtZSBvZiBpdHMgbW9kZWwgY2xhc3MuXG4gICAqIEByZXR1cm4ge3N0cmluZ30gQSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHJlcG9zaXRvcnlcbiAgICovXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBgJHt0aGlzLmNsYXNzLm5hbWV9IFJlcG9zaXRvcnlgO1xuICB9XG59XG4iLCJpbXBvcnQgeyBlbmZvcmNlREJEZWNvcmF0b3JzIH0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCB7IE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9jb25zdGFudHNcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IsIFZhbGlkYXRpb25FcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgQmFzZVJlcG9zaXRvcnkgfSBmcm9tIFwiLi9CYXNlUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIi4uL21vZGVsL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuL0NvbnRleHRcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbmNyZXRlIHJlcG9zaXRvcnkgaW1wbGVtZW50YXRpb24gd2l0aCB2YWxpZGF0aW9uIHN1cHBvcnQuXG4gKiBAc3VtbWFyeSBUaGUgUmVwb3NpdG9yeSBjbGFzcyBleHRlbmRzIEJhc2VSZXBvc2l0b3J5IHRvIHByb3ZpZGUgYWRkaXRpb25hbCB2YWxpZGF0aW9uXG4gKiBmdW5jdGlvbmFsaXR5LiBJdCBvdmVycmlkZXMgcHJlZml4IG1ldGhvZHMgdG8gcGVyZm9ybSBtb2RlbCB2YWxpZGF0aW9uIGJlZm9yZSBkYXRhYmFzZVxuICogb3BlcmF0aW9ucyBhbmQgdGhyb3dzIFZhbGlkYXRpb25FcnJvciB3aGVuIHZhbGlkYXRpb24gZmFpbHMuXG4gKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlLCBkZWZhdWx0cyB0byBSZXBvc2l0b3J5RmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSwgZGVmYXVsdHMgdG8gQ29udGV4dDxGPlxuICogQGNsYXNzIFJlcG9zaXRvcnlcbiAqIEBleGFtcGxlXG4gKiBjbGFzcyBVc2VyTW9kZWwgZXh0ZW5kcyBNb2RlbCB7XG4gKiAgIEBpZCgpXG4gKiAgIGlkOiBzdHJpbmc7XG4gKlxuICogICBAcmVxdWlyZWQoKVxuICogICBAbWluTGVuZ3RoKDMpXG4gKiAgIG5hbWU6IHN0cmluZztcbiAqIH1cbiAqXG4gKiBjbGFzcyBVc2VyUmVwb3NpdG9yeSBleHRlbmRzIFJlcG9zaXRvcnk8VXNlck1vZGVsPiB7XG4gKiAgIGNvbnN0cnVjdG9yKCkge1xuICogICAgIHN1cGVyKFVzZXJNb2RlbCk7XG4gKiAgIH1cbiAqXG4gKiAgIGFzeW5jIGNyZWF0ZShtb2RlbDogVXNlck1vZGVsKTogUHJvbWlzZTxVc2VyTW9kZWw+IHtcbiAqICAgICAvLyBJbXBsZW1lbnRhdGlvbiB3aXRoIGF1dG9tYXRpYyB2YWxpZGF0aW9uXG4gKiAgICAgcmV0dXJuIG1vZGVsO1xuICogICB9XG4gKiB9XG4gKlxuICogLy8gVXNpbmcgdGhlIHJlcG9zaXRvcnlcbiAqIGNvbnN0IHJlcG8gPSBuZXcgVXNlclJlcG9zaXRvcnkoKTtcbiAqIHRyeSB7XG4gKiAgIGNvbnN0IHVzZXIgPSBhd2FpdCByZXBvLmNyZWF0ZSh7IG5hbWU6ICdKbycgfSk7IC8vIFdpbGwgdGhyb3cgVmFsaWRhdGlvbkVycm9yXG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICBjb25zb2xlLmVycm9yKGVycm9yKTsgLy8gVmFsaWRhdGlvbkVycm9yOiBuYW1lIG11c3QgYmUgYXQgbGVhc3QgMyBjaGFyYWN0ZXJzXG4gKiB9XG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZXBvc2l0b3J5PFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4gZXh0ZW5kcyBCYXNlUmVwb3NpdG9yeTxNLCBGLCBDPiB7XG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihjbGF6ej86IENvbnN0cnVjdG9yPE0+KSB7XG4gICAgc3VwZXIoY2xhenopO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBhIG1vZGVsIGZvciBjcmVhdGlvbiB3aXRoIHZhbGlkYXRpb24uXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcyB0aGUgYmFzZSBjcmVhdGVQcmVmaXggbWV0aG9kIHRvIGFkZCB2YWxpZGF0aW9uIGNoZWNrcy5cbiAgICogQ3JlYXRlcyBhIGNvbnRleHQsIGluc3RhbnRpYXRlcyBhIG5ldyBtb2RlbCwgZW5mb3JjZXMgZGVjb3JhdG9ycywgYW5kIHZhbGlkYXRlc1xuICAgKiB0aGUgbW9kZWwgYmVmb3JlIGFsbG93aW5nIGNyZWF0aW9uIHRvIHByb2NlZWQuXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gcHJlcGFyZSBmb3IgY3JlYXRpb25cbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgY3JlYXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHZhbGlkYXRlZCBtb2RlbCBhbmQgY29udGV4dCBhcmd1bWVudHNcbiAgICogQHRocm93cyB7VmFsaWRhdGlvbkVycm9yfSBJZiB0aGUgbW9kZWwgZmFpbHMgdmFsaWRhdGlvblxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZVByZWZpeChcbiAgICBtb2RlbDogTSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFtNLCAuLi5hbnlbXV0+IHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIG1vZGVsID0gbmV3IHRoaXMuY2xhc3MobW9kZWwpO1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnMoXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgKTtcblxuICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShtb2RlbC5oYXNFcnJvcnMoKSk7XG4gICAgaWYgKGVycm9ycykgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihlcnJvcnMudG9TdHJpbmcoKSk7XG5cbiAgICByZXR1cm4gW21vZGVsLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgbXVsdGlwbGUgbW9kZWxzIGZvciBjcmVhdGlvbiB3aXRoIHZhbGlkYXRpb24uXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcyB0aGUgYmFzZSBjcmVhdGVBbGxQcmVmaXggbWV0aG9kIHRvIGFkZCB2YWxpZGF0aW9uIGNoZWNrcyBmb3IgbXVsdGlwbGUgbW9kZWxzLlxuICAgKiBDcmVhdGVzIGEgY29udGV4dCwgaW5zdGFudGlhdGVzIG5ldyBtb2RlbHMsIGVuZm9yY2VzIGRlY29yYXRvcnMsIGFuZCB2YWxpZGF0ZXNcbiAgICogZWFjaCBtb2RlbCBiZWZvcmUgYWxsb3dpbmcgY3JlYXRpb24gdG8gcHJvY2VlZC4gQ29sbGVjdHMgdmFsaWRhdGlvbiBlcnJvcnMgZnJvbSBhbGwgbW9kZWxzLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIGFycmF5IG9mIG1vZGVsIGluc3RhbmNlcyB0byBwcmVwYXJlIGZvciBjcmVhdGlvblxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSBjcmVhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8YW55W10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBjb250YWluaW5nIHRoZSB2YWxpZGF0ZWQgbW9kZWxzIGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKiBAdGhyb3dzIHtWYWxpZGF0aW9uRXJyb3J9IElmIGFueSBtb2RlbCBmYWlscyB2YWxpZGF0aW9uLCB3aXRoIGRldGFpbHMgYWJvdXQgd2hpY2ggbW9kZWxzIGZhaWxlZFxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbFByZWZpeChcbiAgICBtb2RlbHM6IE1bXSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPGFueVtdPiB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoYXN5bmMgKG0pID0+IHtcbiAgICAgICAgbSA9IG5ldyB0aGlzLmNsYXNzKG0pO1xuICAgICAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgICB9KVxuICAgICk7XG5cbiAgICBjb25zdCBtb2RlbHNWYWxpZGF0aW9uID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PiBQcm9taXNlLnJlc29sdmUobS5oYXNFcnJvcnMoKSkpXG4gICAgKTtcblxuICAgIGNvbnN0IGVycm9ycyA9IG1vZGVsc1ZhbGlkYXRpb24ucmVkdWNlKFxuICAgICAgKGFjY3VtOiBzdHJpbmcgfCB1bmRlZmluZWQsIGUsIGkpID0+IHtcbiAgICAgICAgaWYgKGUpXG4gICAgICAgICAgYWNjdW0gPVxuICAgICAgICAgICAgdHlwZW9mIGFjY3VtID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgID8gYWNjdW0gKyBgXFxuIC0gJHtpfTogJHtlLnRvU3RyaW5nKCl9YFxuICAgICAgICAgICAgICA6IGAgLSAke2l9OiAke2UudG9TdHJpbmcoKX1gO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LFxuICAgICAgdW5kZWZpbmVkXG4gICAgKTtcblxuICAgIGlmIChlcnJvcnMpIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoZXJyb3JzKTtcbiAgICByZXR1cm4gW21vZGVscywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgbW9kZWwgZm9yIHVwZGF0ZSB3aXRoIHZhbGlkYXRpb24uXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcyB0aGUgYmFzZSB1cGRhdGVQcmVmaXggbWV0aG9kIHRvIGFkZCB2YWxpZGF0aW9uIGNoZWNrcy5cbiAgICogQ3JlYXRlcyBhIGNvbnRleHQsIHZhbGlkYXRlcyB0aGUgcHJpbWFyeSBrZXksIHJldHJpZXZlcyB0aGUgZXhpc3RpbmcgbW9kZWwsXG4gICAqIG1lcmdlcyB0aGUgb2xkIGFuZCBuZXcgbW9kZWxzLCBlbmZvcmNlcyBkZWNvcmF0b3JzLCBhbmQgdmFsaWRhdGVzIHRoZSBtb2RlbFxuICAgKiBiZWZvcmUgYWxsb3dpbmcgdGhlIHVwZGF0ZSB0byBwcm9jZWVkLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHByZXBhcmUgZm9yIHVwZGF0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSB1cGRhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgdmFsaWRhdGVkIG1vZGVsIGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiB0aGUgbW9kZWwgZG9lc24ndCBoYXZlIGEgcHJpbWFyeSBrZXkgdmFsdWVcbiAgICogQHRocm93cyB7VmFsaWRhdGlvbkVycm9yfSBJZiB0aGUgbW9kZWwgZmFpbHMgdmFsaWRhdGlvblxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZVByZWZpeChcbiAgICBtb2RlbDogTSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFtNLCAuLi5hcmdzOiBhbnlbXV0+IHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIGNvbnN0IHBrID0gKG1vZGVsIGFzIGFueSlbdGhpcy5wa107XG4gICAgaWYgKCFwaylcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgTm8gdmFsdWUgZm9yIHRoZSBJZCBpcyBkZWZpbmVkIHVuZGVyIHRoZSBwcm9wZXJ0eSAke3RoaXMucGsgYXMgc3RyaW5nfWBcbiAgICAgICk7XG5cbiAgICBjb25zdCBvbGRNb2RlbDogTSA9IGF3YWl0IHRoaXMucmVhZChwayk7XG5cbiAgICBtb2RlbCA9IHRoaXMubWVyZ2Uob2xkTW9kZWwsIG1vZGVsKTtcblxuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnMoXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLk9OLFxuICAgICAgb2xkTW9kZWxcbiAgICApO1xuXG4gICAgY29uc3QgZXJyb3JzID0gYXdhaXQgUHJvbWlzZS5yZXNvbHZlKG1vZGVsLmhhc0Vycm9ycyhvbGRNb2RlbCBhcyBhbnkpKTtcbiAgICBpZiAoZXJyb3JzKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGVycm9ycy50b1N0cmluZygpKTtcbiAgICByZXR1cm4gW21vZGVsLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgbXVsdGlwbGUgbW9kZWxzIGZvciB1cGRhdGUgd2l0aCB2YWxpZGF0aW9uLlxuICAgKiBAc3VtbWFyeSBPdmVycmlkZXMgdGhlIGJhc2UgdXBkYXRlQWxsUHJlZml4IG1ldGhvZCB0byBhZGQgdmFsaWRhdGlvbiBjaGVja3MgZm9yIG11bHRpcGxlIG1vZGVscy5cbiAgICogQ3JlYXRlcyBhIGNvbnRleHQsIHZhbGlkYXRlcyBwcmltYXJ5IGtleXMsIHJldHJpZXZlcyBleGlzdGluZyBtb2RlbHMsIG1lcmdlcyBvbGQgYW5kIG5ldyBtb2RlbHMsXG4gICAqIGVuZm9yY2VzIGRlY29yYXRvcnMsIGFuZCB2YWxpZGF0ZXMgZWFjaCBtb2RlbCBiZWZvcmUgYWxsb3dpbmcgdXBkYXRlcyB0byBwcm9jZWVkLlxuICAgKiBDb2xsZWN0cyB2YWxpZGF0aW9uIGVycm9ycyBmcm9tIGFsbCBtb2RlbHMuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgYXJyYXkgb2YgbW9kZWwgaW5zdGFuY2VzIHRvIHByZXBhcmUgZm9yIHVwZGF0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSB1cGRhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgdmFsaWRhdGVkIG1vZGVscyBhbmQgY29udGV4dCBhcmd1bWVudHNcbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgYW55IG1vZGVsIGRvZXNuJ3QgaGF2ZSBhIHByaW1hcnkga2V5IHZhbHVlXG4gICAqIEB0aHJvd3Mge1ZhbGlkYXRpb25FcnJvcn0gSWYgYW55IG1vZGVsIGZhaWxzIHZhbGlkYXRpb24sIHdpdGggZGV0YWlscyBhYm91dCB3aGljaCBtb2RlbHMgZmFpbGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlQWxsUHJlZml4KG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgaWRzID0gbW9kZWxzLm1hcCgobSkgPT4ge1xuICAgICAgY29uc3QgaWQgPSBtW3RoaXMucGtdO1xuICAgICAgaWYgKHR5cGVvZiBpZCA9PT0gXCJ1bmRlZmluZWRcIilcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgYE5vIHZhbHVlIGZvciB0aGUgSWQgaXMgZGVmaW5lZCB1bmRlciB0aGUgcHJvcGVydHkgJHt0aGlzLnBrIGFzIHN0cmluZ31gXG4gICAgICAgICk7XG4gICAgICByZXR1cm4gaWQgYXMgc3RyaW5nO1xuICAgIH0pO1xuICAgIGNvbnN0IG9sZE1vZGVsczogTVtdID0gYXdhaXQgdGhpcy5yZWFkQWxsKGlkcywgLi4uY29udGV4dEFyZ3MuYXJncyk7XG4gICAgbW9kZWxzID0gbW9kZWxzLm1hcCgobSwgaSkgPT4gdGhpcy5tZXJnZShvbGRNb2RlbHNbaV0sIG0pKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0sIGkpID0+XG4gICAgICAgIGVuZm9yY2VEQkRlY29yYXRvcnMoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5PTixcbiAgICAgICAgICBvbGRNb2RlbHNbaV1cbiAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG5cbiAgICBjb25zdCBtb2RlbHNWYWxpZGF0aW9uID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtLCBpKSA9PiBQcm9taXNlLnJlc29sdmUobS5oYXNFcnJvcnMob2xkTW9kZWxzW2ldIGFzIGFueSkpKVxuICAgICk7XG5cbiAgICBjb25zdCBlcnJvcnMgPSBtb2RlbHNWYWxpZGF0aW9uLnJlZHVjZShcbiAgICAgIChhY2N1bTogc3RyaW5nIHwgdW5kZWZpbmVkLCBlLCBpKSA9PiB7XG4gICAgICAgIGlmIChlKVxuICAgICAgICAgIGFjY3VtID1cbiAgICAgICAgICAgIHR5cGVvZiBhY2N1bSA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICA/IGFjY3VtICsgYFxcbiAtICR7aX06ICR7ZS50b1N0cmluZygpfWBcbiAgICAgICAgICAgICAgOiBgIC0gJHtpfTogJHtlLnRvU3RyaW5nKCl9YDtcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSxcbiAgICAgIHVuZGVmaW5lZFxuICAgICk7XG5cbiAgICBpZiAoZXJyb3JzKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGVycm9ycyk7XG4gICAgcmV0dXJuIFttb2RlbHMsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgcmVmbGVjdGlvbiBrZXkgZm9yIGRhdGFiYXNlIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IEdlbmVyYXRlcyBhIGtleSBmb3Igc3RvcmluZyBtZXRhZGF0YSBpbiB0aGUgcmVmbGVjdGlvbiBzeXN0ZW0gYnkgcHJlZml4aW5nXG4gICAqIHRoZSBwcm92aWRlZCBrZXkgd2l0aCB0aGUgZGF0YWJhc2UgcmVmbGVjdGlvbiBwcmVmaXguXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgYmFzZSBrZXkgdG8gcHJlZml4XG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHByZWZpeGVkIHJlZmxlY3Rpb24ga2V5XG4gICAqL1xuICBzdGF0aWMga2V5KGtleTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIERCS2V5cy5SRUZMRUNUICsga2V5O1xuICB9XG59XG4iLCJpbXBvcnQgXCIuL3ZhbGlkYXRpb25cIjtcbmltcG9ydCB7XG4gIGRhdGUsXG4gIERlY29yYXRpb24sXG4gIE1vZGVsLFxuICBwcm9wTWV0YWRhdGEsXG4gIHJlcXVpcmVkLFxuICB0eXBlLFxuICBWYWxpZGF0aW9uLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBEQktleXMsIERFRkFVTFRfVElNRVNUQU1QX0ZPUk1BVCB9IGZyb20gXCIuLi9tb2RlbC9jb25zdGFudHNcIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IERCT3BlcmF0aW9ucywgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgYWZ0ZXIsIG9uLCBvbkNyZWF0ZVVwZGF0ZSB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IFNlcmlhbGl6YXRpb25FcnJvciB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L2Vycm9yc1wiO1xuaW1wb3J0IHsgYXBwbHksIG1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9Db250ZXh0XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQcmV2ZW50cyBhIHByb3BlcnR5IGZyb20gYmVpbmcgbW9kaWZpZWQgYWZ0ZXIgaW5pdGlhbCBjcmVhdGlvbi5cbiAqIEBzdW1tYXJ5IE1hcmtzIHRoZSBwcm9wZXJ0eSBhcyByZWFkb25seSwgY2F1c2luZyB2YWxpZGF0aW9uIGVycm9ycyBpZiBhdHRlbXB0cyBhcmUgbWFkZSB0byBtb2RpZnkgaXQgZHVyaW5nIHVwZGF0ZXMuXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIC0gVGhlIGVycm9yIG1lc3NhZ2UgdG8gZGlzcGxheSB3aGVuIHZhbGlkYXRpb24gZmFpbHMuIERlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX0VSUk9SX01FU1NBR0VTLlJFQURPTkxZLklOVkFMSUR9XG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgZnVuY3Rpb24gdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gcmVhZG9ubHlcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkb25seShcbiAgbWVzc2FnZTogc3RyaW5nID0gREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5SRUFET05MWS5JTlZBTElEXG4pIHtcbiAgY29uc3Qga2V5ID0gVmFsaWRhdGlvbi51cGRhdGVLZXkoREJLZXlzLlJFQURPTkxZKTtcbiAgcmV0dXJuIERlY29yYXRpb24uZm9yKGtleSlcbiAgICAuZGVmaW5lKFxuICAgICAgcHJvcE1ldGFkYXRhKGtleSwge1xuICAgICAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgfSlcbiAgICApXG4gICAgLmFwcGx5KCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXIgZnVuY3Rpb24gdGhhdCBzZXRzIGEgdGltZXN0YW1wIHByb3BlcnR5IHRvIHRoZSBjdXJyZW50IHRpbWVzdGFtcC5cbiAqIEBzdW1tYXJ5IFVwZGF0ZXMgYSBtb2RlbCBwcm9wZXJ0eSB3aXRoIHRoZSBjdXJyZW50IHRpbWVzdGFtcCBmcm9tIHRoZSByZXBvc2l0b3J5IGNvbnRleHQuXG4gKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFIgLSBUaGUgcmVwb3NpdG9yeSB0eXBlIGV4dGVuZGluZyBJUmVwb3NpdG9yeVxuICogQHRlbXBsYXRlIFYgLSBUaGUgZGF0YSB0eXBlIGZvciB0aGUgb3BlcmF0aW9uXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGVcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZVxuICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIHJlcG9zaXRvcnkgY29udGV4dCBjb250YWluaW5nIHRoZSBjdXJyZW50IHRpbWVzdGFtcFxuICogQHBhcmFtIHtWfSBkYXRhIC0gVGhlIGRhdGEgYmVpbmcgcHJvY2Vzc2VkXG4gKiBAcGFyYW0ga2V5IC0gVGhlIHByb3BlcnR5IGtleSB0byB1cGRhdGVcbiAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgYmVpbmcgdXBkYXRlZFxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgdGltZXN0YW1wIGhhcyBiZWVuIHNldFxuICogQGZ1bmN0aW9uIHRpbWVzdGFtcEhhbmRsZXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdGltZXN0YW1wSGFuZGxlcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSk6IFByb21pc2U8dm9pZD4ge1xuICAobW9kZWwgYXMgYW55KVtrZXldID0gY29udGV4dC50aW1lc3RhbXA7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEF1dG9tYXRpY2FsbHkgbWFuYWdlcyB0aW1lc3RhbXAgcHJvcGVydGllcyBmb3IgdHJhY2tpbmcgY3JlYXRpb24gYW5kIHVwZGF0ZSB0aW1lcy5cbiAqIEBzdW1tYXJ5IE1hcmtzIHRoZSBwcm9wZXJ0eSBhcyBhIHRpbWVzdGFtcCwgbWFraW5nIGl0IHJlcXVpcmVkIGFuZCBlbnN1cmluZyBpdCdzIGEgdmFsaWQgZGF0ZS4gVGhlIHByb3BlcnR5IHdpbGwgYmUgYXV0b21hdGljYWxseSB1cGRhdGVkIHdpdGggdGhlIGN1cnJlbnQgdGltZXN0YW1wIGR1cmluZyBzcGVjaWZpZWQgb3BlcmF0aW9ucy5cbiAqXG4gKiBEYXRlIEZvcm1hdDpcbiAqXG4gKiA8cHJlPlxuICogICAgICBVc2luZyBzaW1pbGFyIGZvcm1hdHRpbmcgYXMgTW9tZW50LmpzLCBDbGFzcyBEYXRlVGltZUZvcm1hdHRlciAoSmF2YSksIGFuZCBDbGFzcyBTaW1wbGVEYXRlRm9ybWF0IChKYXZhKSxcbiAqICAgICAgSSBpbXBsZW1lbnRlZCBhIGNvbXByZWhlbnNpdmUgc29sdXRpb24gZm9ybWF0RGF0ZShkYXRlLCBwYXR0ZXJuU3RyKSB3aGVyZSB0aGUgY29kZSBpcyBlYXN5IHRvIHJlYWQgYW5kIG1vZGlmeS5cbiAqICAgICAgWW91IGNhbiBkaXNwbGF5IGRhdGUsIHRpbWUsIEFNL1BNLCBldGMuXG4gKlxuICogICAgICBEYXRlIGFuZCBUaW1lIFBhdHRlcm5zXG4gKiAgICAgIHl5ID0gMi1kaWdpdCB5ZWFyOyB5eXl5ID0gZnVsbCB5ZWFyXG4gKiAgICAgIE0gPSBkaWdpdCBtb250aDsgTU0gPSAyLWRpZ2l0IG1vbnRoOyBNTU0gPSBzaG9ydCBtb250aCBuYW1lOyBNTU1NID0gZnVsbCBtb250aCBuYW1lXG4gKiAgICAgIEVFRUUgPSBmdWxsIHdlZWtkYXkgbmFtZTsgRUVFID0gc2hvcnQgd2Vla2RheSBuYW1lXG4gKiAgICAgIGQgPSBkaWdpdCBkYXk7IGRkID0gMi1kaWdpdCBkYXlcbiAqICAgICAgaCA9IGhvdXJzIGFtL3BtOyBoaCA9IDItZGlnaXQgaG91cnMgYW0vcG07IEggPSBob3VyczsgSEggPSAyLWRpZ2l0IGhvdXJzXG4gKiAgICAgIG0gPSBtaW51dGVzOyBtbSA9IDItZGlnaXQgbWludXRlczsgYWFhID0gQU0vUE1cbiAqICAgICAgcyA9IHNlY29uZHM7IHNzID0gMi1kaWdpdCBzZWNvbmRzXG4gKiAgICAgIFMgPSBtaWxpc2Vjb25kc1xuICogPC9wcmU+XG4gKlxuICogQHBhcmFtIHtPcGVyYXRpb25LZXlzW119IG9wZXJhdGlvbiAtIFRoZSBvcGVyYXRpb25zIHRvIGFjdCBvbi4gRGVmYXVsdHMgdG8ge0BsaW5rIERCT3BlcmF0aW9ucy5DUkVBVEVfVVBEQVRFfVxuICogQHBhcmFtIHtzdHJpbmd9IFtmb3JtYXRdIC0gVGhlIHRpbWVzdGFtcCBmb3JtYXQuIERlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX1RJTUVTVEFNUF9GT1JNQVR9XG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgZnVuY3Rpb24gdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gdGltZXN0YW1wXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudFxuICogICBwYXJ0aWNpcGFudCBNIGFzIE1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IFQgYXMgVGltZXN0YW1wRGVjb3JhdG9yXG4gKiAgIHBhcnRpY2lwYW50IFYgYXMgVmFsaWRhdG9yXG4gKlxuICogICBDLT4+TTogQ3JlYXRlL1VwZGF0ZSBtb2RlbFxuICogICBNLT4+VDogUHJvY2VzcyB0aW1lc3RhbXAgcHJvcGVydHlcbiAqICAgVC0+Pk06IEFwcGx5IHJlcXVpcmVkIHZhbGlkYXRpb25cbiAqICAgVC0+Pk06IEFwcGx5IGRhdGUgZm9ybWF0IHZhbGlkYXRpb25cbiAqXG4gKiAgIGFsdCBVcGRhdGUgb3BlcmF0aW9uXG4gKiAgICAgVC0+PlY6IFJlZ2lzdGVyIHRpbWVzdGFtcCB2YWxpZGF0b3JcbiAqICAgICBWLT4+TTogVmFsaWRhdGUgdGltZXN0YW1wIGlzIG5ld2VyXG4gKiAgIGVuZFxuICpcbiAqICAgVC0+Pk06IFNldCBjdXJyZW50IHRpbWVzdGFtcFxuICogICBNLT4+QzogUmV0dXJuIHVwZGF0ZWQgbW9kZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbWVzdGFtcChcbiAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzW10gPSBEQk9wZXJhdGlvbnMuQ1JFQVRFX1VQREFURSBhcyB1bmtub3duIGFzIE9wZXJhdGlvbktleXNbXSxcbiAgZm9ybWF0OiBzdHJpbmcgPSBERUZBVUxUX1RJTUVTVEFNUF9GT1JNQVRcbikge1xuICBjb25zdCBrZXkgPSBWYWxpZGF0aW9uLnVwZGF0ZUtleShEQktleXMuVElNRVNUQU1QKTtcblxuICBjb25zdCBkZWNvcmF0b3JzOiBhbnlbXSA9IFtcbiAgICBkYXRlKGZvcm1hdCwgREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuREFURSksXG4gICAgcmVxdWlyZWQoREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuUkVRVUlSRUQpLFxuICAgIG9uKG9wZXJhdGlvbiwgdGltZXN0YW1wSGFuZGxlciksXG4gIF07XG5cbiAgaWYgKG9wZXJhdGlvbi5pbmRleE9mKE9wZXJhdGlvbktleXMuVVBEQVRFKSAhPT0gLTEpXG4gICAgZGVjb3JhdG9ycy5wdXNoKFxuICAgICAgcHJvcE1ldGFkYXRhKFZhbGlkYXRpb24udXBkYXRlS2V5KERCS2V5cy5USU1FU1RBTVApLCB7XG4gICAgICAgIG1lc3NhZ2U6IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuVElNRVNUQU1QLklOVkFMSUQsXG4gICAgICB9KVxuICAgICk7XG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihrZXkpXG4gICAgLmRlZmluZSguLi5kZWNvcmF0b3JzKVxuICAgIC5hcHBseSgpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBIYW5kbGVyIGZ1bmN0aW9uIHRoYXQgc2VyaWFsaXplcyBhIHByb3BlcnR5IHRvIEpTT04gc3RyaW5nIGR1cmluZyBjcmVhdGUgYW5kIHVwZGF0ZSBvcGVyYXRpb25zLlxuICogQHN1bW1hcnkgQ29udmVydHMgYSBjb21wbGV4IG9iamVjdCBwcm9wZXJ0eSB0byBhIEpTT04gc3RyaW5nIGJlZm9yZSBzdG9yaW5nIGl0IGluIHRoZSBkYXRhYmFzZS5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIElSZXBvc2l0b3J5XG4gKiBAdGVtcGxhdGUgViAtIFRoZSBkYXRhIHR5cGUgZm9yIHRoZSBvcGVyYXRpb25cbiAqIEB0ZW1wbGF0ZSBGIC0gVGhlIHJlcG9zaXRvcnkgZmxhZ3MgdHlwZVxuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlXG4gKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgcmVwb3NpdG9yeSBjb250ZXh0XG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBUaGUgZGF0YSBiZWluZyBwcm9jZXNzZWRcbiAqIEBwYXJhbSBrZXkgLSBUaGUgcHJvcGVydHkga2V5IHRvIHNlcmlhbGl6ZVxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSBiZWluZyBwcm9jZXNzZWRcbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHByb3BlcnR5IGhhcyBiZWVuIHNlcmlhbGl6ZWRcbiAqIEBmdW5jdGlvbiBzZXJpYWxpemVPbkNyZWF0ZVVwZGF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXJpYWxpemVPbkNyZWF0ZVVwZGF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoIW1vZGVsW2tleV0pIHJldHVybjtcbiAgdHJ5IHtcbiAgICBtb2RlbFtrZXldID0gSlNPTi5zdHJpbmdpZnkobW9kZWxba2V5XSkgYXMgTVtrZXlvZiBNXTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgYEZhaWxlZCB0byBzZXJpYWxpemUgJHtrZXkudG9TdHJpbmcoKX0gcHJvcGVydHkgb2YgbW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfTogZWBcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXIgZnVuY3Rpb24gdGhhdCBkZXNlcmlhbGl6ZXMgYSBwcm9wZXJ0eSBmcm9tIEpTT04gc3RyaW5nIGFmdGVyIGRhdGFiYXNlIG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBDb252ZXJ0cyBhIEpTT04gc3RyaW5nIHByb3BlcnR5IGJhY2sgdG8gaXRzIG9yaWdpbmFsIGNvbXBsZXggb2JqZWN0IGZvcm0gYWZ0ZXIgcmV0cmlldmluZyBpdCBmcm9tIHRoZSBkYXRhYmFzZS5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIElSZXBvc2l0b3J5XG4gKiBAdGVtcGxhdGUgViAtIFRoZSBkYXRhIHR5cGUgZm9yIHRoZSBvcGVyYXRpb25cbiAqIEB0ZW1wbGF0ZSBGIC0gVGhlIHJlcG9zaXRvcnkgZmxhZ3MgdHlwZVxuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlXG4gKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgcmVwb3NpdG9yeSBjb250ZXh0XG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBUaGUgZGF0YSBiZWluZyBwcm9jZXNzZWRcbiAqIEBwYXJhbSBrZXkgLSBUaGUgcHJvcGVydHkga2V5IHRvIGRlc2VyaWFsaXplXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIGJlaW5nIHByb2Nlc3NlZFxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgcHJvcGVydHkgaGFzIGJlZW4gZGVzZXJpYWxpemVkXG4gKiBAZnVuY3Rpb24gc2VyaWFsaXplQWZ0ZXJBbGxcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VyaWFsaXplQWZ0ZXJBbGw8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICBWLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFtb2RlbFtrZXldKSByZXR1cm47XG4gIGlmICh0eXBlb2YgbW9kZWxba2V5XSAhPT0gXCJzdHJpbmdcIikgcmV0dXJuO1xuXG4gIHRyeSB7XG4gICAgbW9kZWxba2V5XSA9IEpTT04ucGFyc2UobW9kZWxba2V5XSk7XG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgYEZhaWxlZCB0byBkZXNlcmlhbGl6ZSAke2tleS50b1N0cmluZygpfSBwcm9wZXJ0eSBvZiBtb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9OiAke2V9YFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRW5hYmxlcyBhdXRvbWF0aWMgSlNPTiBzZXJpYWxpemF0aW9uIGFuZCBkZXNlcmlhbGl6YXRpb24gZm9yIGNvbXBsZXggb2JqZWN0IHByb3BlcnRpZXMuXG4gKiBAc3VtbWFyeSBEZWNvcmF0b3IgdGhhdCBhdXRvbWF0aWNhbGx5IGNvbnZlcnRzIGNvbXBsZXggb2JqZWN0cyB0byBKU09OIHN0cmluZ3MgYmVmb3JlIHN0b3JpbmcgaW4gdGhlIGRhdGFiYXNlIGFuZCBiYWNrIHRvIG9iamVjdHMgd2hlbiByZXRyaWV2aW5nIHRoZW0uXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgZnVuY3Rpb24gdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gc2VyaWFsaXplXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudFxuICogICBwYXJ0aWNpcGFudCBNIGFzIE1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IFMgYXMgU2VyaWFsaXplRGVjb3JhdG9yXG4gKiAgIHBhcnRpY2lwYW50IERCIGFzIERhdGFiYXNlXG4gKlxuICogICBOb3RlIG92ZXIgQyxEQjogQ3JlYXRlL1VwZGF0ZSBGbG93XG4gKiAgIEMtPj5NOiBTZXQgY29tcGxleCBvYmplY3QgcHJvcGVydHlcbiAqICAgTS0+PlM6IFByb2Nlc3MgcHJvcGVydHkgKGNyZWF0ZS91cGRhdGUpXG4gKiAgIFMtPj5NOiBDb252ZXJ0IHRvIEpTT04gc3RyaW5nXG4gKiAgIE0tPj5EQjogU3RvcmUgc2VyaWFsaXplZCBkYXRhXG4gKlxuICogICBOb3RlIG92ZXIgQyxEQjogUmV0cmlldmFsIEZsb3dcbiAqICAgQy0+Pk06IFJlcXVlc3QgbW9kZWxcbiAqICAgTS0+PkRCOiBGZXRjaCBkYXRhXG4gKiAgIERCLT4+TTogUmV0dXJuIHdpdGggc2VyaWFsaXplZCBwcm9wZXJ0eVxuICogICBNLT4+UzogUHJvY2VzcyBwcm9wZXJ0eSAoYWZ0ZXIgYWxsIG9wcylcbiAqICAgUy0+Pk06IFBhcnNlIEpTT04gYmFjayB0byBvYmplY3RcbiAqICAgTS0+PkM6IFJldHVybiBtb2RlbCB3aXRoIGRlc2VyaWFsaXplZCBwcm9wZXJ0eVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplKCkge1xuICByZXR1cm4gYXBwbHkoXG4gICAgb25DcmVhdGVVcGRhdGUoc2VyaWFsaXplT25DcmVhdGVVcGRhdGUpLFxuICAgIGFmdGVyKERCT3BlcmF0aW9ucy5BTEwsIHNlcmlhbGl6ZUFmdGVyQWxsKSxcbiAgICB0eXBlKFtTdHJpbmcubmFtZSwgT2JqZWN0Lm5hbWVdKSxcbiAgICBtZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuU0VSSUFMSVpFKSwge30pXG4gICk7XG59XG4iLCJpbXBvcnQgeyBwcm9wTWV0YWRhdGEsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgcmVhZG9ubHkgfSBmcm9tIFwiLi4vdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIi4uL21vZGVsL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBhcHBseSB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgdGhhdCBtYXJrcyBhIHByb3BlcnR5IGFzIGFuIElEIGZpZWxkXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY29tcG9zaXRlIGRlY29yYXRvciB0aGF0IG1hcmtzIGEgcHJvcGVydHkgYXMgcmVxdWlyZWQsIHJlYWRvbmx5LCBhbmQgYXMgdGhlIElEIGZpZWxkIGZvciBkYXRhYmFzZSBvcGVyYXRpb25zXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gaWRcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpZCgpIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgIHJlcXVpcmVkKCksXG4gICAgcmVhZG9ubHkoKSxcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLklEKSwge30pXG4gICk7XG59XG4iLCJpbXBvcnQge1xuICBDb25kaXRpb25hbEFzeW5jLFxuICBEZWNvcmF0b3JNZXRhZGF0YUFzeW5jLFxuICBnZXRWYWxpZGF0aW9uRGVjb3JhdG9ycyxcbiAgTW9kZWwsXG4gIE1vZGVsQ29uZGl0aW9uYWxBc3luYyxcbiAgTW9kZWxFcnJvckRlZmluaXRpb24sXG4gIE1vZGVsRXJyb3JzLFxuICBNb2RlbEtleXMsXG4gIHRvQ29uZGl0aW9uYWxQcm9taXNlLFxuICBWYWxpZGF0aW9uLFxuICBWYWxpZGF0aW9uS2V5cyxcbiAgVmFsaWRhdGlvblByb3BlcnR5RGVjb3JhdG9yRGVmaW5pdGlvbixcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgUmVmbGVjdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgVXBkYXRlVmFsaWRhdGlvbktleXMsIFVwZGF0ZVZhbGlkYXRvciB9IGZyb20gXCIuLi92YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBmaW5kTW9kZWxJZCB9IGZyb20gXCIuLi9pZGVudGl0eVwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvblxuICogUmV0cmlldmVzIHZhbGlkYXRpb24gZGVjb3JhdG9yIGRlZmluaXRpb25zIGZyb20gYSBtb2RlbCBmb3IgdXBkYXRlIG9wZXJhdGlvbnMsIGluY2x1ZGluZ1xuICogc3VwcG9ydCBmb3Igc3BlY2lhbCBoYW5kbGluZyBvZiBsaXN0IGRlY29yYXRvcnMuXG4gKlxuICogQHN1bW1hcnlcbiAqIEl0ZXJhdGVzIG92ZXIgdGhlIG1vZGVsJ3Mgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBhbmQgZmlsdGVycyBvdXQgdGhvc2Ugc3BlY2lmaWVkIGluIHRoZVxuICogYHByb3BzVG9JZ25vcmVgIGFycmF5LiBGb3IgZWFjaCByZW1haW5pbmcgcHJvcGVydHksIHJldHJpZXZlcyB2YWxpZGF0aW9uIGRlY29yYXRvcnMgc3BlY2lmaWNcbiAqIHRvIHVwZGF0ZSBvcGVyYXRpb25zIHVzaW5nIHRoZSBgVXBkYXRlVmFsaWRhdGlvbktleXMuUkVGTEVDVGAga2V5LiBBZGRpdGlvbmFsbHksIGl0IGV4cGxpY2l0bHlcbiAqIGNoZWNrcyBmb3IgYW5kIGFwcGVuZHMgYW55IGBMSVNUYCB0eXBlIGRlY29yYXRvcnMgdG8gZW5zdXJlIHByb3BlciB2YWxpZGF0aW9uIG9mIGNvbGxlY3Rpb24gdHlwZXMuXG4gKlxuICogQHRlbXBsYXRlIE0gLSBBIGdlbmVyaWMgcGFyYW1ldGVyIGV4dGVuZGluZyB0aGUgYE1vZGVsYCBjbGFzcywgcmVwcmVzZW50aW5nIHRoZSBtb2RlbCB0eXBlIGJlaW5nIGluc3BlY3RlZC5cbiAqXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHdob3NlIHByb3BlcnRpZXMgYXJlIGJlaW5nIGluc3BlY3RlZCBmb3IgdXBkYXRlLXJlbGF0ZWQgdmFsaWRhdGlvbnMuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBwcm9wc1RvSWdub3JlIC0gQSBsaXN0IG9mIHByb3BlcnR5IG5hbWVzIHRvIGV4Y2x1ZGUgZnJvbSB0aGUgdmFsaWRhdGlvbiBkZWNvcmF0b3IgcmV0cmlldmFsIHByb2Nlc3MuXG4gKlxuICogQHJldHVybiB7VmFsaWRhdGlvblByb3BlcnR5RGVjb3JhdG9yRGVmaW5pdGlvbltdfSBBbiBhcnJheSBvZiB2YWxpZGF0aW9uIGRlY29yYXRvciBkZWZpbml0aW9ucywgaW5jbHVkaW5nIGJvdGhcbiAqIHVwZGF0ZS1zcGVjaWZpYyBhbmQgbGlzdC10eXBlIGRlY29yYXRvcnMsIGV4Y2x1ZGluZyB0aG9zZSBmb3IgaWdub3JlZCBwcm9wZXJ0aWVzLlxuICpcbiAqIEBmdW5jdGlvbiBnZXRWYWxpZGF0YWJsZVVwZGF0ZVByb3BzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRWYWxpZGF0YWJsZVVwZGF0ZVByb3BzPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNLFxuICBwcm9wc1RvSWdub3JlOiBzdHJpbmdbXVxuKTogVmFsaWRhdGlvblByb3BlcnR5RGVjb3JhdG9yRGVmaW5pdGlvbltdIHtcbiAgY29uc3QgZGVjb3JhdGVkUHJvcGVydGllczogVmFsaWRhdGlvblByb3BlcnR5RGVjb3JhdG9yRGVmaW5pdGlvbltdID0gW107XG4gIGZvciAoY29uc3QgcHJvcCBpbiBtb2RlbCkge1xuICAgIGlmIChcbiAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbCwgcHJvcCkgJiZcbiAgICAgICFwcm9wc1RvSWdub3JlLmluY2x1ZGVzKHByb3ApXG4gICAgKSB7XG4gICAgICBjb25zdCB2YWxpZGF0aW9uUHJvcGVydHlEZWZpbml0aW9uID0gZ2V0VmFsaWRhdGlvbkRlY29yYXRvcnMoXG4gICAgICAgIG1vZGVsLFxuICAgICAgICBwcm9wLFxuICAgICAgICBVcGRhdGVWYWxpZGF0aW9uS2V5cy5SRUZMRUNUXG4gICAgICApO1xuXG4gICAgICBjb25zdCBsaXN0RGVjb3JhdG9yID0gZ2V0VmFsaWRhdGlvbkRlY29yYXRvcnMoXG4gICAgICAgIG1vZGVsLFxuICAgICAgICBwcm9wXG4gICAgICApLmRlY29yYXRvcnMuZmluZCgoeyBrZXkgfSkgPT4ga2V5ID09PSBWYWxpZGF0aW9uS2V5cy5MSVNUKTtcblxuICAgICAgaWYgKGxpc3REZWNvcmF0b3IpXG4gICAgICAgIHZhbGlkYXRpb25Qcm9wZXJ0eURlZmluaXRpb24uZGVjb3JhdG9ycy5wdXNoKGxpc3REZWNvcmF0b3IpO1xuXG4gICAgICBkZWNvcmF0ZWRQcm9wZXJ0aWVzLnB1c2godmFsaWRhdGlvblByb3BlcnR5RGVmaW5pdGlvbik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRlY29yYXRlZFByb3BlcnRpZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZURlY29yYXRvcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBBc3luYyBleHRlbmRzIGJvb2xlYW4gPSBmYWxzZSxcbj4oXG4gIG5ld01vZGVsOiBNLFxuICBvbGRNb2RlbDogTSxcbiAgcHJvcDogc3RyaW5nLFxuICBkZWNvcmF0b3I6IERlY29yYXRvck1ldGFkYXRhQXN5bmMsXG4gIGFzeW5jPzogQXN5bmNcbik6IENvbmRpdGlvbmFsQXN5bmM8QXN5bmMsIHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCB2YWxpZGF0b3I6IFVwZGF0ZVZhbGlkYXRvciA9IFZhbGlkYXRpb24uZ2V0KFxuICAgIGRlY29yYXRvci5rZXlcbiAgKSBhcyBVcGRhdGVWYWxpZGF0b3I7XG5cbiAgaWYgKCF2YWxpZGF0b3IpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYE1pc3NpbmcgdmFsaWRhdG9yIGZvciAke2RlY29yYXRvci5rZXl9YCk7XG4gIH1cblxuICAvLyBTa2lwIHZhbGlkYXRvcnMgdGhhdCBhcmVuJ3QgVXBkYXRlVmFsaWRhdG9yc1xuICBpZiAoIXZhbGlkYXRvci51cGRhdGVIYXNFcnJvcnMpIHJldHVybiB0b0NvbmRpdGlvbmFsUHJvbWlzZSh1bmRlZmluZWQsIGFzeW5jKTtcblxuICAvLyBza2lwIGFzeW5jIGRlY29yYXRvcnMgaWYgdmFsaWRhdGVEZWNvcmF0b3JzIGlzIGNhbGxlZCBzeW5jaHJvbm91c2x5IChhc3luYyA9IGZhbHNlKVxuICBpZiAoIWFzeW5jICYmIGRlY29yYXRvci5wcm9wcy5hc3luYylcbiAgICByZXR1cm4gdG9Db25kaXRpb25hbFByb21pc2UodW5kZWZpbmVkLCBhc3luYyk7XG5cbiAgY29uc3QgZGVjb3JhdG9yUHJvcHMgPSBPYmplY3QudmFsdWVzKGRlY29yYXRvci5wcm9wcykgfHwge307XG5cbiAgLy8gY29uc3QgY29udGV4dCA9IFBhdGhQcm94eUVuZ2luZS5jcmVhdGUob2JqLCB7XG4gIC8vICAgaWdub3JlVW5kZWZpbmVkOiB0cnVlLFxuICAvLyAgIGlnbm9yZU51bGw6IHRydWUsXG4gIC8vIH0pO1xuXG4gIGNvbnN0IG1heWJlRXJyb3IgPSB2YWxpZGF0b3IudXBkYXRlSGFzRXJyb3JzKFxuICAgIChuZXdNb2RlbCBhcyBhbnkpW3Byb3BdLFxuICAgIChvbGRNb2RlbCBhcyBhbnkpW3Byb3BdLFxuICAgIC4uLmRlY29yYXRvclByb3BzXG4gICk7XG5cbiAgcmV0dXJuIHRvQ29uZGl0aW9uYWxQcm9taXNlKG1heWJlRXJyb3IsIGFzeW5jKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlRGVjb3JhdG9yczxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBBc3luYyBleHRlbmRzIGJvb2xlYW4gPSBmYWxzZSxcbj4oXG4gIG5ld01vZGVsOiBNLFxuICBvbGRNb2RlbDogTSxcbiAgcHJvcDogc3RyaW5nLFxuICBkZWNvcmF0b3JzOiBEZWNvcmF0b3JNZXRhZGF0YUFzeW5jW10sXG4gIGFzeW5jPzogQXN5bmNcbik6IENvbmRpdGlvbmFsQXN5bmM8QXN5bmMsIFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBQcm9taXNlPHN0cmluZz4+ID0ge307XG5cbiAgZm9yIChjb25zdCBkZWNvcmF0b3Igb2YgZGVjb3JhdG9ycykge1xuICAgIC8vIHNraXAgYXN5bmMgZGVjb3JhdG9ycyBpZiB2YWxpZGF0ZURlY29yYXRvcnMgaXMgY2FsbGVkIHN5bmNocm9ub3VzbHkgKGFzeW5jID0gZmFsc2UpXG4gICAgaWYgKCFhc3luYyAmJiBkZWNvcmF0b3IucHJvcHMuYXN5bmMpIGNvbnRpbnVlO1xuXG4gICAgbGV0IHZhbGlkYXRpb25FcnJvcnMgPSB2YWxpZGF0ZURlY29yYXRvcihcbiAgICAgIG5ld01vZGVsLFxuICAgICAgb2xkTW9kZWwsXG4gICAgICBwcm9wLFxuICAgICAgZGVjb3JhdG9yLFxuICAgICAgYXN5bmNcbiAgICApO1xuXG4gICAgLypcbiAgICBJZiB0aGUgZGVjb3JhdG9yIGlzIGEgbGlzdCwgZWFjaCBlbGVtZW50IG11c3QgYmUgY2hlY2tlZC5cbiAgICBXaGVuICdhc3luYycgaXMgdHJ1ZSwgdGhlICdlcnInIHdpbGwgYWx3YXlzIGJlIGEgcGVuZGluZyBwcm9taXNlIGluaXRpYWxseSxcbiAgICBzbyB0aGUgJyFlcnInIGNoZWNrIHdpbGwgZXZhbHVhdGUgdG8gZmFsc2UgKGV2ZW4gaWYgdGhlIHByb21pc2UgbGF0ZXIgcmVzb2x2ZXMgd2l0aCBubyBlcnJvcnMpXG4gICAgKi9cbiAgICBpZiAoZGVjb3JhdG9yLmtleSA9PT0gVmFsaWRhdGlvbktleXMuTElTVCAmJiAoIXZhbGlkYXRpb25FcnJvcnMgfHwgYXN5bmMpKSB7XG4gICAgICBjb25zdCBuZXdQcm9wVmFsdWUgPSAobmV3TW9kZWwgYXMgYW55KVtwcm9wXTtcbiAgICAgIGNvbnN0IG9sZFByb3BWYWx1ZSA9IChvbGRNb2RlbCBhcyBhbnkpW3Byb3BdO1xuXG4gICAgICBjb25zdCBuZXdWYWx1ZXMgPVxuICAgICAgICBuZXdQcm9wVmFsdWUgaW5zdGFuY2VvZiBTZXQgPyBbLi4ubmV3UHJvcFZhbHVlXSA6IG5ld1Byb3BWYWx1ZTtcbiAgICAgIGNvbnN0IG9sZFZhbHVlcyA9XG4gICAgICAgIG9sZFByb3BWYWx1ZSBpbnN0YW5jZW9mIFNldCA/IFsuLi5vbGRQcm9wVmFsdWVdIDogb2xkUHJvcFZhbHVlO1xuXG4gICAgICBpZiAobmV3VmFsdWVzICYmIG5ld1ZhbHVlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IHR5cGVzID1cbiAgICAgICAgICBkZWNvcmF0b3IucHJvcHMuY2xhc3MgfHxcbiAgICAgICAgICBkZWNvcmF0b3IucHJvcHMuY2xhenogfHxcbiAgICAgICAgICBkZWNvcmF0b3IucHJvcHMuY3VzdG9tVHlwZXM7XG5cbiAgICAgICAgY29uc3QgYWxsb3dlZFR5cGVzID0gW3R5cGVzXS5mbGF0KCkubWFwKCh0KSA9PiBTdHJpbmcodCkudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgIGNvbnN0IGVycnMgPSBuZXdWYWx1ZXMubWFwKChjaGlsZFZhbHVlOiBhbnkpID0+IHtcbiAgICAgICAgICAvLyBmaW5kIGJ5IGlkIHNvIHRoZSBsaXN0IGVsZW1lbnRzIG9yZGVyIGRvZXNuJ3QgbWF0dGVyXG4gICAgICAgICAgY29uc3QgaWQgPSBmaW5kTW9kZWxJZChjaGlsZFZhbHVlIGFzIGFueSwgdHJ1ZSk7XG4gICAgICAgICAgaWYgKCFpZCkgcmV0dXJuIFwiRmFpbGVkIHRvIGZpbmQgbW9kZWwgaWRcIjtcblxuICAgICAgICAgIGNvbnN0IG9sZE1vZGVsID0gb2xkVmFsdWVzLmZpbmQoXG4gICAgICAgICAgICAoZWw6IGFueSkgPT4gaWQgPT09IGZpbmRNb2RlbElkKGVsLCB0cnVlKVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBpZiAoTW9kZWwuaXNNb2RlbChjaGlsZFZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNoaWxkVmFsdWUuaGFzRXJyb3JzKG9sZE1vZGVsKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gYWxsb3dlZFR5cGVzLmluY2x1ZGVzKHR5cGVvZiBjaGlsZFZhbHVlKVxuICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgIDogXCJWYWx1ZSBoYXMgbm8gdmFsaWRhdGFibGUgdHlwZVwiO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoYXN5bmMpIHtcbiAgICAgICAgICB2YWxpZGF0aW9uRXJyb3JzID0gUHJvbWlzZS5hbGwoZXJycykudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhbGxFbXB0eSA9IHJlc3VsdC5ldmVyeSgocikgPT4gIXIpO1xuICAgICAgICAgICAgcmV0dXJuIGFsbEVtcHR5ID8gdW5kZWZpbmVkIDogcmVzdWx0O1xuICAgICAgICAgIH0pIGFzIGFueTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBhbGxFbXB0eSA9IGVycnMuZXZlcnkoKHI6IHN0cmluZyB8IHVuZGVmaW5lZCkgPT4gIXIpO1xuICAgICAgICAgIHZhbGlkYXRpb25FcnJvcnMgPSBlcnJzLmxlbmd0aCA+IDAgJiYgIWFsbEVtcHR5ID8gZXJycyA6IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh2YWxpZGF0aW9uRXJyb3JzKSAocmVzdWx0IGFzIGFueSlbZGVjb3JhdG9yLmtleV0gPSB2YWxpZGF0aW9uRXJyb3JzO1xuICB9XG5cbiAgaWYgKCFhc3luYylcbiAgICByZXR1cm4gT2JqZWN0LmtleXMocmVzdWx0KS5sZW5ndGggPiAwID8gKHJlc3VsdCBhcyBhbnkpIDogdW5kZWZpbmVkO1xuXG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhyZXN1bHQpO1xuICBjb25zdCBwcm9taXNlcyA9IE9iamVjdC52YWx1ZXMocmVzdWx0KSBhcyBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD5bXTtcbiAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKChyZXNvbHZlZFZhbHVlcykgPT4ge1xuICAgIGNvbnN0IHJlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVzb2x2ZWRWYWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHZhbCA9IHJlc29sdmVkVmFsdWVzW2ldO1xuICAgICAgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlc1trZXlzW2ldXSA9IHZhbDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHJlcykubGVuZ3RoID4gMCA/IHJlcyA6IHVuZGVmaW5lZDtcbiAgfSkgYXMgYW55O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgY2hhbmdlcyBiZXR3ZWVuIHR3byBtb2RlbCB2ZXJzaW9uc1xuICogQHN1bW1hcnkgQ29tcGFyZXMgYW4gb2xkIGFuZCBuZXcgbW9kZWwgdmVyc2lvbiB0byB2YWxpZGF0ZSB1cGRhdGUgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHBhcmFtIHtNfSBvbGRNb2RlbCAtIFRoZSBvcmlnaW5hbCBtb2RlbCB2ZXJzaW9uXG4gKiBAcGFyYW0ge019IG5ld01vZGVsIC0gVGhlIHVwZGF0ZWQgbW9kZWwgdmVyc2lvblxuICogQHBhcmFtIHtib29sZWFufSBhc3luYyAtIEEgZmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgdmFsaWRhdGlvbiBzaG91bGQgYmUgYXN5bmNocm9ub3VzLlxuICogQHBhcmFtIHsuLi5zdHJpbmdbXX0gZXhjZXB0aW9ucyAtIFByb3BlcnRpZXMgdG8gZXhjbHVkZSBmcm9tIHZhbGlkYXRpb25cbiAqIEByZXR1cm4ge01vZGVsRXJyb3JEZWZpbml0aW9ufHVuZGVmaW5lZH0gRXJyb3IgZGVmaW5pdGlvbiBpZiB2YWxpZGF0aW9uIGZhaWxzLCB1bmRlZmluZWQgb3RoZXJ3aXNlXG4gKiBAZnVuY3Rpb24gdmFsaWRhdGVDb21wYXJlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IHZhbGlkYXRlQ29tcGFyZVxuICogICBwYXJ0aWNpcGFudCBSZWZsZWN0aW9uXG4gKiAgIHBhcnRpY2lwYW50IFZhbGlkYXRpb25cbiAqXG4gKiAgIENhbGxlci0+PnZhbGlkYXRlQ29tcGFyZTogb2xkTW9kZWwsIG5ld01vZGVsLCBleGNlcHRpb25zXG4gKiAgIHZhbGlkYXRlQ29tcGFyZS0+PlJlZmxlY3Rpb246IGdldCBkZWNvcmF0ZWQgcHJvcGVydGllc1xuICogICBSZWZsZWN0aW9uLS0+PnZhbGlkYXRlQ29tcGFyZTogcHJvcGVydHkgZGVjb3JhdG9yc1xuICogICBsb29wIEZvciBlYWNoIGRlY29yYXRlZCBwcm9wZXJ0eVxuICogICAgIHZhbGlkYXRlQ29tcGFyZS0+PlZhbGlkYXRpb246IGdldCB2YWxpZGF0b3JcbiAqICAgICBWYWxpZGF0aW9uLS0+PnZhbGlkYXRlQ29tcGFyZTogdmFsaWRhdG9yXG4gKiAgICAgdmFsaWRhdGVDb21wYXJlLT4+dmFsaWRhdGVDb21wYXJlOiB2YWxpZGF0ZSBwcm9wZXJ0eSB1cGRhdGVcbiAqICAgZW5kXG4gKiAgIGxvb3AgRm9yIG5lc3RlZCBtb2RlbHNcbiAqICAgICB2YWxpZGF0ZUNvbXBhcmUtPj52YWxpZGF0ZUNvbXBhcmU6IHZhbGlkYXRlIG5lc3RlZCBtb2RlbHNcbiAqICAgZW5kXG4gKiAgIHZhbGlkYXRlQ29tcGFyZS0tPj5DYWxsZXI6IHZhbGlkYXRpb24gZXJyb3JzIG9yIHVuZGVmaW5lZFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVDb21wYXJlPE0gZXh0ZW5kcyBNb2RlbDxhbnk+PihcbiAgb2xkTW9kZWw6IE0sXG4gIG5ld01vZGVsOiBNLFxuICBhc3luYzogYm9vbGVhbixcbiAgLi4uZXhjZXB0aW9uczogc3RyaW5nW11cbik6IE1vZGVsQ29uZGl0aW9uYWxBc3luYzxNPiB7XG4gIGNvbnN0IGRlY29yYXRlZFByb3BlcnRpZXM6IFZhbGlkYXRpb25Qcm9wZXJ0eURlY29yYXRvckRlZmluaXRpb25bXSA9XG4gICAgZ2V0VmFsaWRhdGFibGVVcGRhdGVQcm9wcyhuZXdNb2RlbCwgZXhjZXB0aW9ucyk7XG5cbiAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG5cbiAgY29uc3QgbmVzdGVkRXJyb3JzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gIGZvciAoY29uc3QgeyBwcm9wLCBkZWNvcmF0b3JzIH0gb2YgZGVjb3JhdGVkUHJvcGVydGllcykge1xuICAgIGNvbnN0IHByb3BLZXkgPSBTdHJpbmcocHJvcCk7XG4gICAgbGV0IHByb3BWYWx1ZSA9IChuZXdNb2RlbCBhcyBhbnkpW3Byb3BdO1xuXG4gICAgaWYgKCFkZWNvcmF0b3JzPy5sZW5ndGgpIGNvbnRpbnVlO1xuXG4gICAgLy8gR2V0IHRoZSBkZWZhdWx0IHR5cGUgdmFsaWRhdG9yXG4gICAgY29uc3QgZGVzaWduVHlwZURlYyA9IGRlY29yYXRvcnMuZmluZCgoZCkgPT5cbiAgICAgIFtNb2RlbEtleXMuVFlQRSwgVmFsaWRhdGlvbktleXMuVFlQRV0uaW5jbHVkZXMoZC5rZXkgYXMgYW55KVxuICAgICk7XG4gICAgaWYgKCFkZXNpZ25UeXBlRGVjKSBjb250aW51ZTtcblxuICAgIGNvbnN0IGRlc2lnblR5cGUgPSBkZXNpZ25UeXBlRGVjLnByb3BzLm5hbWU7XG5cbiAgICAvLyBIYW5kbGUgYXJyYXkgb3IgU2V0IHR5cGVzIGFuZCBlbmZvcmNlIHRoZSBwcmVzZW5jZSBvZiBAbGlzdCBkZWNvcmF0b3JcbiAgICBpZiAoW0FycmF5Lm5hbWUsIFNldC5uYW1lXS5pbmNsdWRlcyhkZXNpZ25UeXBlKSkge1xuICAgICAgY29uc3QgeyBkZWNvcmF0b3JzIH0gPSBSZWZsZWN0aW9uLmdldFByb3BlcnR5RGVjb3JhdG9ycyhcbiAgICAgICAgVmFsaWRhdGlvbktleXMuUkVGTEVDVCxcbiAgICAgICAgbmV3TW9kZWwsXG4gICAgICAgIHByb3BLZXlcbiAgICAgICkgYXMgdW5rbm93biBhcyBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uO1xuXG4gICAgICBpZiAoIWRlY29yYXRvcnMuc29tZSgoZCkgPT4gZC5rZXkgPT09IFZhbGlkYXRpb25LZXlzLkxJU1QpKSB7XG4gICAgICAgIHJlc3VsdFtwcm9wS2V5XSA9IHtcbiAgICAgICAgICBbVmFsaWRhdGlvbktleXMuVFlQRV06IGBBcnJheSBvciBTZXQgcHJvcGVydHkgJyR7cHJvcEtleX0nIHJlcXVpcmVzIGEgQGxpc3QgZGVjb3JhdG9yYCxcbiAgICAgICAgfTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgcHJvcFZhbHVlICYmXG4gICAgICAgICEoQXJyYXkuaXNBcnJheShwcm9wVmFsdWUpIHx8IHByb3BWYWx1ZSBpbnN0YW5jZW9mIFNldClcbiAgICAgICkge1xuICAgICAgICByZXN1bHRbcHJvcEtleV0gPSB7XG4gICAgICAgICAgW1ZhbGlkYXRpb25LZXlzLlRZUEVdOiBgUHJvcGVydHkgJyR7U3RyaW5nKHByb3ApfScgbXVzdCBiZSBlaXRoZXIgYW4gYXJyYXkgb3IgYSBTZXRgLFxuICAgICAgICB9O1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVtb3ZlIGRlc2lnbjp0eXBlIGRlY29yYXRvciwgc2luY2UgQGxpc3QgZGVjb3JhdG9yIGFscmVhZHkgZW5zdXJlcyB0eXBlXG4gICAgICBmb3IgKGxldCBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBpZiAoZGVjb3JhdG9yc1tpXS5rZXkgPT09IE1vZGVsS2V5cy5UWVBFKSB7XG4gICAgICAgICAgZGVjb3JhdG9ycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHByb3BWYWx1ZSA9IHByb3BWYWx1ZSBpbnN0YW5jZW9mIFNldCA/IFsuLi5wcm9wVmFsdWVdIDogcHJvcFZhbHVlO1xuICAgIH1cblxuICAgIGNvbnN0IHByb3BFcnJvcnM6IFJlY29yZDxzdHJpbmcsIGFueT4gPVxuICAgICAgdmFsaWRhdGVEZWNvcmF0b3JzKG5ld01vZGVsLCBvbGRNb2RlbCwgcHJvcEtleSwgZGVjb3JhdG9ycywgYXN5bmMpIHx8IHt9O1xuXG4gICAgLy8gQ2hlY2sgZm9yIG5lc3RlZCBwcm9wZXJ0aWVzLlxuICAgIC8vIFRvIHByZXZlbnQgdW5uZWNlc3NhcnkgcHJvY2Vzc2luZywgXCJwcm9wVmFsdWVcIiBtdXN0IGJlIGRlZmluZWQgYW5kIHZhbGlkYXRhYmxlXG4gICAgY29uc3QgaXNDb25zdHIgPSBNb2RlbC5pc1Byb3BlcnR5TW9kZWwobmV3TW9kZWwsIHByb3BLZXkpO1xuICAgIC8vIGlmIHByb3BWYWx1ZSAhPT0gdW5kZWZpbmVkLCBudWxsXG4gICAgaWYgKHByb3BWYWx1ZSAmJiBpc0NvbnN0cikge1xuICAgICAgY29uc3QgaW5zdGFuY2U6IE1vZGVsID0gcHJvcFZhbHVlO1xuICAgICAgY29uc3QgaXNJbnZhbGlkTW9kZWwgPVxuICAgICAgICB0eXBlb2YgaW5zdGFuY2UgIT09IFwib2JqZWN0XCIgfHxcbiAgICAgICAgIWluc3RhbmNlLmhhc0Vycm9ycyB8fFxuICAgICAgICB0eXBlb2YgaW5zdGFuY2UuaGFzRXJyb3JzICE9PSBcImZ1bmN0aW9uXCI7XG5cbiAgICAgIGlmIChpc0ludmFsaWRNb2RlbCkge1xuICAgICAgICAvLyBwcm9wRXJyb3JzW1ZhbGlkYXRpb25LZXlzLlRZUEVdID1cbiAgICAgICAgLy8gICBcIk1vZGVsIHNob3VsZCBiZSB2YWxpZGF0YWJsZSBidXQgaXQncyBub3QuXCI7XG4gICAgICAgIGNvbnNvbGUud2FybihcIk1vZGVsIHNob3VsZCBiZSB2YWxpZGF0YWJsZSBidXQgaXQncyBub3QuXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmVzdGVkRXJyb3JzW3Byb3BLZXldID0gaW5zdGFuY2UuaGFzRXJyb3JzKChvbGRNb2RlbCBhcyBhbnkpW3Byb3BdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBZGQgdG8gdGhlIHJlc3VsdCBpZiB3ZSBoYXZlIGFueSBlcnJvcnNcbiAgICAvLyBBc3luYyBtb2RlIHJldHVybnMgYSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdW5kZWZpbmVkIHdoZW4gbm8gZXJyb3JzIGV4aXN0XG4gICAgaWYgKE9iamVjdC5rZXlzKHByb3BFcnJvcnMpLmxlbmd0aCA+IDAgfHwgYXN5bmMpXG4gICAgICByZXN1bHRbcHJvcEtleV0gPSBwcm9wRXJyb3JzO1xuXG4gICAgLy8gVGhlbiBtZXJnZSBhbnkgbmVzdGVkIGVycm9yc1xuICAgIGlmICghYXN5bmMpIHtcbiAgICAgIE9iamVjdC5lbnRyaWVzKG5lc3RlZEVycm9yc1twcm9wS2V5XSB8fCB7fSkuZm9yRWFjaCgoW2tleSwgZXJyb3JdKSA9PiB7XG4gICAgICAgIGlmIChlcnJvciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmVzdWx0W2Ake3Byb3BLZXl9LiR7a2V5fWBdID0gZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIFN5bmNocm9ub3VzIHJldHVyblxuICBpZiAoIWFzeW5jKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIE9iamVjdC5rZXlzKHJlc3VsdCkubGVuZ3RoID4gMFxuICAgICAgICA/IG5ldyBNb2RlbEVycm9yRGVmaW5pdGlvbihyZXN1bHQpXG4gICAgICAgIDogdW5kZWZpbmVkXG4gICAgKSBhcyBhbnk7XG4gIH1cblxuICBjb25zdCBtZXJnZWQ6IGFueSA9IHJlc3VsdDsgLy8gVE9ETzogYXBwbHkgZmlsdGVyaW5nXG5cbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG1lcmdlZCk7XG4gIGNvbnN0IHByb21pc2VzID0gT2JqZWN0LnZhbHVlcyhtZXJnZWQpO1xuICByZXR1cm4gUHJvbWlzZS5hbGxTZXR0bGVkKHByb21pc2VzKS50aGVuKGFzeW5jIChyZXN1bHRzKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0OiBNb2RlbEVycm9ycyA9IHt9O1xuXG4gICAgZm9yIChjb25zdCBbcGFyZW50UHJvcCwgbmVzdGVkRXJyUHJvbWlzZV0gb2YgT2JqZWN0LmVudHJpZXMobmVzdGVkRXJyb3JzKSkge1xuICAgICAgY29uc3QgbmVzdGVkUHJvcERlY0Vycm9ycyA9IChhd2FpdCBuZXN0ZWRFcnJQcm9taXNlKSBhcyBSZWNvcmQ8XG4gICAgICAgIHN0cmluZyxcbiAgICAgICAgYW55XG4gICAgICA+O1xuXG4gICAgICBpZiAobmVzdGVkUHJvcERlY0Vycm9ycylcbiAgICAgICAgT2JqZWN0LmVudHJpZXMobmVzdGVkUHJvcERlY0Vycm9ycykuZm9yRWFjaChcbiAgICAgICAgICAoW25lc3RlZFByb3AsIG5lc3RlZFByb3BEZWNFcnJvcl0pID0+IHtcbiAgICAgICAgICAgIGlmIChuZXN0ZWRQcm9wRGVjRXJyb3IgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjb25zdCBuZXN0ZWRLZXkgPSBbcGFyZW50UHJvcCwgbmVzdGVkUHJvcF0uam9pbihcIi5cIik7XG4gICAgICAgICAgICAgIHJlc3VsdFtuZXN0ZWRLZXldID0gbmVzdGVkUHJvcERlY0Vycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNbaV07XG4gICAgICBjb25zdCByZXMgPSByZXN1bHRzW2ldO1xuXG4gICAgICBpZiAocmVzLnN0YXR1cyA9PT0gXCJmdWxmaWxsZWRcIiAmJiByZXMudmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAocmVzdWx0IGFzIGFueSlba2V5XSA9IHJlcy52YWx1ZTtcbiAgICAgIH0gZWxzZSBpZiAocmVzLnN0YXR1cyA9PT0gXCJyZWplY3RlZFwiKSB7XG4gICAgICAgIChyZXN1bHQgYXMgYW55KVtrZXldID1cbiAgICAgICAgICByZXMucmVhc29uIGluc3RhbmNlb2YgRXJyb3JcbiAgICAgICAgICAgID8gcmVzLnJlYXNvbi5tZXNzYWdlXG4gICAgICAgICAgICA6IFN0cmluZyhyZXMucmVhc29uIHx8IFwiVmFsaWRhdGlvbiBmYWlsZWRcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHJlc3VsdCkubGVuZ3RoID4gMFxuICAgICAgPyBuZXcgTW9kZWxFcnJvckRlZmluaXRpb24ocmVzdWx0KVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH0pIGFzIGFueTtcbn1cbiIsImltcG9ydCB7IERCS2V5cywgRGVmYXVsdFNlcGFyYXRvciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgYXBwbHkgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7XG4gIEhhc2hpbmcsXG4gIE1vZGVsLFxuICBwcm9wTWV0YWRhdGEsXG4gIHR5cGUsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IG9uQ3JlYXRlLCBvbkNyZWF0ZVVwZGF0ZSwgb25VcGRhdGUgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL0lSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvZXJyb3JzXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L0NvbnRleHRcIjtcbmltcG9ydCB7IENydWRPcGVyYXRpb25zLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4uL29wZXJhdGlvbnNcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhc2hlcyBhIHByb3BlcnR5IHZhbHVlIGR1cmluZyBjcmVhdGUgb3IgdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IENhbGxiYWNrIGZ1bmN0aW9uIHVzZWQgYnkgdGhlIGhhc2ggZGVjb3JhdG9yIHRvIGFwcGx5IGhhc2hpbmcgdG8gYSBwcm9wZXJ0eSB2YWx1ZVxuICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFIgLSBUeXBlIGV4dGVuZGluZyBJUmVwb3NpdG9yeVxuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YVxuICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyBSZXBvc2l0b3J5RmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVHlwZSBleHRlbmRpbmcgQ29udGV4dFxuICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIG9wZXJhdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBNZXRhZGF0YSBmb3IgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gaGFzaFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBiZWluZyBwcm9jZXNzZWRcbiAqIEBwYXJhbSB7TX0gW29sZE1vZGVsXSAtIFRoZSBwcmV2aW91cyBtb2RlbCBzdGF0ZSAoZm9yIHVwZGF0ZXMpXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGZ1bmN0aW9uIGhhc2hPbkNyZWF0ZVVwZGF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoT25DcmVhdGVVcGRhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICBWIGV4dGVuZHMgb2JqZWN0LFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0sIG9sZE1vZGVsPzogTSk6IHZvaWQge1xuICBpZiAodHlwZW9mIG1vZGVsW2tleV0gPT09IFwidW5kZWZpbmVkXCIpIHJldHVybjtcbiAgY29uc3QgaGFzaCA9IEhhc2hpbmcuaGFzaCgobW9kZWwgYXMgYW55KVtrZXldKTtcbiAgaWYgKG9sZE1vZGVsICYmIChtb2RlbCBhcyBhbnkpW2tleV0gPT09IGhhc2gpIHJldHVybjtcbiAgbW9kZWxba2V5XSA9IGhhc2g7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBkZWNvcmF0b3IgdGhhdCBoYXNoZXMgYSBwcm9wZXJ0eSB2YWx1ZVxuICogQHN1bW1hcnkgRGVjb3JhdG9yIHRoYXQgYXV0b21hdGljYWxseSBoYXNoZXMgYSBwcm9wZXJ0eSB2YWx1ZSBkdXJpbmcgY3JlYXRlIGFuZCB1cGRhdGUgb3BlcmF0aW9uc1xuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIGhhc2hcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoKCkge1xuICByZXR1cm4gYXBwbHkoXG4gICAgb25DcmVhdGVVcGRhdGUoaGFzaE9uQ3JlYXRlVXBkYXRlKSxcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLkhBU0gpLCB7fSlcbiAgKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWV0YWRhdGEgZm9yIGNvbXBvc2VkIHByb3BlcnR5IGRlY29yYXRvcnNcbiAqIEBzdW1tYXJ5IENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgcHJvcGVydHkgY29tcG9zaXRpb24gZnJvbSBvdGhlciBwcm9wZXJ0aWVzXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDb21wb3NlZEZyb21NZXRhZGF0YVxuICogQHByb3BlcnR5IHtzdHJpbmdbXX0gYXJncyAtIFByb3BlcnR5IG5hbWVzIHRvIGNvbXBvc2UgZnJvbVxuICogQHByb3BlcnR5IHtzdHJpbmd9IHNlcGFyYXRvciAtIENoYXJhY3RlciB1c2VkIHRvIGpvaW4gdGhlIGNvbXBvc2VkIHZhbHVlc1xuICogQHByb3BlcnR5IHtib29sZWFufSBoYXNoUmVzdWx0IC0gV2hldGhlciB0byBoYXNoIHRoZSBjb21wb3NlZCByZXN1bHRcbiAqIEBwcm9wZXJ0eSB7XCJrZXlzXCJ8XCJ2YWx1ZXNcIn0gdHlwZSAtIFdoZXRoZXIgdG8gdXNlIHByb3BlcnR5IGtleXMgb3IgdmFsdWVzXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW3ByZWZpeF0gLSBPcHRpb25hbCBwcmVmaXggdG8gYWRkIHRvIHRoZSBjb21wb3NlZCB2YWx1ZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtzdWZmaXhdIC0gT3B0aW9uYWwgc3VmZml4IHRvIGFkZCB0byB0aGUgY29tcG9zZWQgdmFsdWVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgdHlwZSBDb21wb3NlZEZyb21NZXRhZGF0YSA9IHtcbiAgYXJnczogc3RyaW5nW107XG4gIHNlcGFyYXRvcjogc3RyaW5nO1xuICBoYXNoUmVzdWx0OiBib29sZWFuO1xuICB0eXBlOiBcImtleXNcIiB8IFwidmFsdWVzXCI7XG4gIHByZWZpeD86IHN0cmluZztcbiAgc3VmZml4Pzogc3RyaW5nO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29tcG9zZXMgYSBwcm9wZXJ0eSB2YWx1ZSBmcm9tIG90aGVyIHByb3BlcnRpZXMgZHVyaW5nIGNyZWF0ZSBvciB1cGRhdGUgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgQ2FsbGJhY2sgZnVuY3Rpb24gdXNlZCBieSBjb21wb3NlZCBkZWNvcmF0b3JzIHRvIGdlbmVyYXRlIGEgcHJvcGVydHkgdmFsdWUgZnJvbSBvdGhlciBwcm9wZXJ0aWVzXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFR5cGUgZXh0ZW5kaW5nIElSZXBvc2l0b3J5XG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZXh0ZW5kaW5nIENvbXBvc2VkRnJvbU1ldGFkYXRhXG4gKiBAdGVtcGxhdGUgRiAtIFR5cGUgZXh0ZW5kaW5nIFJlcG9zaXRvcnlGbGFnc1xuICogQHRlbXBsYXRlIEMgLSBUeXBlIGV4dGVuZGluZyBDb250ZXh0XG4gKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgb3BlcmF0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIE1ldGFkYXRhIGZvciB0aGUgY29tcG9zaXRpb25cbiAqIEBwYXJhbSBrZXkgLSBUaGUgcHJvcGVydHkga2V5IHRvIHNldCB0aGUgY29tcG9zZWQgdmFsdWUgb25cbiAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgYmVpbmcgcHJvY2Vzc2VkXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGZ1bmN0aW9uIGNvbXBvc2VkRnJvbUNyZWF0ZVVwZGF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wb3NlZEZyb21DcmVhdGVVcGRhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICBWIGV4dGVuZHMgQ29tcG9zZWRGcm9tTWV0YWRhdGEsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSkge1xuICB0cnkge1xuICAgIGNvbnN0IHsgYXJncywgdHlwZSwgcHJlZml4LCBzdWZmaXgsIHNlcGFyYXRvciB9ID0gZGF0YTtcbiAgICBjb25zdCBjb21wb3NlZCA9IGFyZ3MubWFwKChhcmc6IHN0cmluZykgPT4ge1xuICAgICAgaWYgKCEoYXJnIGluIG1vZGVsKSlcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYFByb3BlcnR5ICR7YXJnfSBub3QgZm91bmQgdG8gY29tcG9zZSBmcm9tYCk7XG4gICAgICBpZiAodHlwZSA9PT0gXCJrZXlzXCIpIHJldHVybiBhcmc7XG4gICAgICBpZiAodHlwZW9mIChtb2RlbCBhcyBhbnkpW2FyZ10gPT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgIGBQcm9wZXJ0eSAke2FyZ3N9IGRvZXMgbm90IGNvbnRhaW4gYSB2YWx1ZSB0byBjb21wb3NlIGZyb21gXG4gICAgICAgICk7XG4gICAgICByZXR1cm4gKChtb2RlbCBhcyBhbnkpW2FyZ10gYXMgYW55KS50b1N0cmluZygpO1xuICAgIH0pO1xuXG4gICAgaWYgKHByZWZpeCkgY29tcG9zZWQudW5zaGlmdChwcmVmaXgpO1xuICAgIGlmIChzdWZmaXgpIGNvbXBvc2VkLnB1c2goc3VmZml4KTtcblxuICAgIChtb2RlbCBhcyBhbnkpW2tleV0gPSBjb21wb3NlZC5qb2luKHNlcGFyYXRvcik7XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBGYWlsZWQgdG8gY29tcG9zZSB2YWx1ZTogJHtlfWApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBkZWNvcmF0b3IgdGhhdCBjb21wb3NlcyBhIHByb3BlcnR5IHZhbHVlIGZyb20gb3RoZXIgcHJvcGVydGllc1xuICogQHN1bW1hcnkgQmFzZSBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgcHJvcGVydHkgY29tcG9zaXRpb24gZGVjb3JhdG9yc1xuICogQHBhcmFtIHtzdHJpbmdbXX0gYXJncyAtIFByb3BlcnR5IG5hbWVzIHRvIGNvbXBvc2UgZnJvbVxuICogQHBhcmFtIHtib29sZWFufSBbaGFzaFJlc3VsdD1mYWxzZV0gLSBXaGV0aGVyIHRvIGhhc2ggdGhlIGNvbXBvc2VkIHJlc3VsdFxuICogQHBhcmFtIHtzdHJpbmd9IFtzZXBhcmF0b3I9RGVmYXVsdFNlcGFyYXRvcl0gLSBDaGFyYWN0ZXIgdXNlZCB0byBqb2luIHRoZSBjb21wb3NlZCB2YWx1ZXNcbiAqIEBwYXJhbSB7XCJrZXlzXCJ8XCJ2YWx1ZXNcIn0gW3R5cGU9XCJ2YWx1ZXNcIl0gLSBXaGV0aGVyIHRvIHVzZSBwcm9wZXJ0eSBrZXlzIG9yIHZhbHVlc1xuICogQHBhcmFtIHtzdHJpbmd9IFtwcmVmaXg9XCJcIl0gLSBPcHRpb25hbCBwcmVmaXggdG8gYWRkIHRvIHRoZSBjb21wb3NlZCB2YWx1ZVxuICogQHBhcmFtIHtzdHJpbmd9IFtzdWZmaXg9XCJcIl0gLSBPcHRpb25hbCBzdWZmaXggdG8gYWRkIHRvIHRoZSBjb21wb3NlZCB2YWx1ZVxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIGNvbXBvc2VkRnJvbVxuICogQGNhdGVnb3J5IFByb3BlcnR5RGVjb3JhdG9yc1xuICovXG5mdW5jdGlvbiBjb21wb3NlZEZyb20oXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBoYXNoUmVzdWx0OiBib29sZWFuID0gZmFsc2UsXG4gIHNlcGFyYXRvcjogc3RyaW5nID0gRGVmYXVsdFNlcGFyYXRvcixcbiAgdHlwZTogXCJrZXlzXCIgfCBcInZhbHVlc1wiID0gXCJ2YWx1ZXNcIixcbiAgcHJlZml4ID0gXCJcIixcbiAgc3VmZml4ID0gXCJcIlxuKSB7XG4gIGNvbnN0IGRhdGE6IENvbXBvc2VkRnJvbU1ldGFkYXRhID0ge1xuICAgIGFyZ3M6IGFyZ3MsXG4gICAgaGFzaFJlc3VsdDogaGFzaFJlc3VsdCxcbiAgICBzZXBhcmF0b3I6IHNlcGFyYXRvcixcbiAgICB0eXBlOiB0eXBlLFxuICAgIHByZWZpeDogcHJlZml4LFxuICAgIHN1ZmZpeDogc3VmZml4LFxuICB9O1xuXG4gIGNvbnN0IGRlY29yYXRvcnMgPSBbXG4gICAgb25DcmVhdGVVcGRhdGUoY29tcG9zZWRGcm9tQ3JlYXRlVXBkYXRlLCBkYXRhKSxcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLkNPTVBPU0VEKSwgZGF0YSksXG4gIF07XG4gIGlmIChoYXNoUmVzdWx0KSBkZWNvcmF0b3JzLnB1c2goaGFzaCgpKTtcbiAgcmV0dXJuIGFwcGx5KC4uLmRlY29yYXRvcnMpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgZGVjb3JhdG9yIHRoYXQgY29tcG9zZXMgYSBwcm9wZXJ0eSB2YWx1ZSBmcm9tIHByb3BlcnR5IGtleXNcbiAqIEBzdW1tYXJ5IERlY29yYXRvciB0aGF0IGdlbmVyYXRlcyBhIHByb3BlcnR5IHZhbHVlIGJ5IGpvaW5pbmcgdGhlIG5hbWVzIG9mIG90aGVyIHByb3BlcnRpZXNcbiAqIEBwYXJhbSB7c3RyaW5nW119IGFyZ3MgLSBQcm9wZXJ0eSBuYW1lcyB0byBjb21wb3NlIGZyb21cbiAqIEBwYXJhbSB7c3RyaW5nfSBbc2VwYXJhdG9yPURlZmF1bHRTZXBhcmF0b3JdIC0gQ2hhcmFjdGVyIHVzZWQgdG8gam9pbiB0aGUgcHJvcGVydHkgbmFtZXNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2hhc2g9ZmFsc2VdIC0gV2hldGhlciB0byBoYXNoIHRoZSBjb21wb3NlZCByZXN1bHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBbcHJlZml4PVwiXCJdIC0gT3B0aW9uYWwgcHJlZml4IHRvIGFkZCB0byB0aGUgY29tcG9zZWQgdmFsdWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc3VmZml4PVwiXCJdIC0gT3B0aW9uYWwgc3VmZml4IHRvIGFkZCB0byB0aGUgY29tcG9zZWQgdmFsdWVcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBjb21wb3NlZEZyb21LZXlzXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHlEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wb3NlZEZyb21LZXlzKFxuICBhcmdzOiBzdHJpbmdbXSxcbiAgc2VwYXJhdG9yOiBzdHJpbmcgPSBEZWZhdWx0U2VwYXJhdG9yLFxuICBoYXNoOiBib29sZWFuID0gZmFsc2UsXG4gIHByZWZpeCA9IFwiXCIsXG4gIHN1ZmZpeCA9IFwiXCJcbikge1xuICByZXR1cm4gY29tcG9zZWRGcm9tKGFyZ3MsIGhhc2gsIHNlcGFyYXRvciwgXCJrZXlzXCIsIHByZWZpeCwgc3VmZml4KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGRlY29yYXRvciB0aGF0IGNvbXBvc2VzIGEgcHJvcGVydHkgdmFsdWUgZnJvbSBwcm9wZXJ0eSB2YWx1ZXNcbiAqIEBzdW1tYXJ5IERlY29yYXRvciB0aGF0IGdlbmVyYXRlcyBhIHByb3BlcnR5IHZhbHVlIGJ5IGpvaW5pbmcgdGhlIHZhbHVlcyBvZiBvdGhlciBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzIC0gUHJvcGVydHkgbmFtZXMgd2hvc2UgdmFsdWVzIHdpbGwgYmUgY29tcG9zZWRcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc2VwYXJhdG9yPURlZmF1bHRTZXBhcmF0b3JdIC0gQ2hhcmFjdGVyIHVzZWQgdG8gam9pbiB0aGUgcHJvcGVydHkgdmFsdWVzXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtoYXNoPWZhbHNlXSAtIFdoZXRoZXIgdG8gaGFzaCB0aGUgY29tcG9zZWQgcmVzdWx0XG4gKiBAcGFyYW0ge3N0cmluZ30gW3ByZWZpeD1cIlwiXSAtIE9wdGlvbmFsIHByZWZpeCB0byBhZGQgdG8gdGhlIGNvbXBvc2VkIHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gW3N1ZmZpeD1cIlwiXSAtIE9wdGlvbmFsIHN1ZmZpeCB0byBhZGQgdG8gdGhlIGNvbXBvc2VkIHZhbHVlXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gY29tcG9zZWRcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eURlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvc2VkKFxuICBhcmdzOiBzdHJpbmdbXSxcbiAgc2VwYXJhdG9yOiBzdHJpbmcgPSBEZWZhdWx0U2VwYXJhdG9yLFxuICBoYXNoOiBib29sZWFuID0gZmFsc2UsXG4gIHByZWZpeCA9IFwiXCIsXG4gIHN1ZmZpeCA9IFwiXCJcbikge1xuICByZXR1cm4gY29tcG9zZWRGcm9tKGFyZ3MsIGhhc2gsIHNlcGFyYXRvciwgXCJ2YWx1ZXNcIiwgcHJlZml4LCBzdWZmaXgpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCB1cGRhdGVzIGEgdmVyc2lvbiBwcm9wZXJ0eSBkdXJpbmcgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRmFjdG9yeSBmdW5jdGlvbiB0aGF0IGdlbmVyYXRlcyBhIGNhbGxiYWNrIGZvciBpbmNyZW1lbnRpbmcgdmVyc2lvbiBudW1iZXJzXG4gKiBAcGFyYW0ge0NydWRPcGVyYXRpb25zfSBvcGVyYXRpb24gLSBUaGUgdHlwZSBvZiBvcGVyYXRpb24gKENSRUFURSBvciBVUERBVEUpXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IHVwZGF0ZXMgdGhlIHZlcnNpb24gcHJvcGVydHlcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVHlwZSBleHRlbmRpbmcgSVJlcG9zaXRvcnlcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGFcbiAqIEB0ZW1wbGF0ZSBGIC0gVHlwZSBleHRlbmRpbmcgUmVwb3NpdG9yeUZsYWdzXG4gKiBAdGVtcGxhdGUgQyAtIFR5cGUgZXh0ZW5kaW5nIENvbnRleHRcbiAqIEBmdW5jdGlvbiB2ZXJzaW9uQ3JlYXRlVXBkYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IHZlcnNpb25DcmVhdGVVcGRhdGVcbiAqXG4gKiAgIENhbGxlci0+PnZlcnNpb25DcmVhdGVVcGRhdGU6IG9wZXJhdGlvblxuICogICB2ZXJzaW9uQ3JlYXRlVXBkYXRlLS0+PkNhbGxlcjogY2FsbGJhY2sgZnVuY3Rpb25cbiAqICAgTm90ZSBvdmVyIENhbGxlcix2ZXJzaW9uQ3JlYXRlVXBkYXRlOiBXaGVuIGNhbGxiYWNrIGlzIGV4ZWN1dGVkOlxuICogICBDYWxsZXItPj52ZXJzaW9uQ3JlYXRlVXBkYXRlOiBjb250ZXh0LCBkYXRhLCBrZXksIG1vZGVsXG4gKiAgIGFsdCBvcGVyYXRpb24gaXMgQ1JFQVRFXG4gKiAgICAgdmVyc2lvbkNyZWF0ZVVwZGF0ZS0+PnZlcnNpb25DcmVhdGVVcGRhdGU6IHNldCB2ZXJzaW9uIHRvIDFcbiAqICAgZWxzZSBvcGVyYXRpb24gaXMgVVBEQVRFXG4gKiAgICAgdmVyc2lvbkNyZWF0ZVVwZGF0ZS0+PnZlcnNpb25DcmVhdGVVcGRhdGU6IGluY3JlbWVudCB2ZXJzaW9uXG4gKiAgIGVsc2UgaW52YWxpZCBvcGVyYXRpb25cbiAqICAgICB2ZXJzaW9uQ3JlYXRlVXBkYXRlLT4+dmVyc2lvbkNyZWF0ZVVwZGF0ZTogdGhyb3cgZXJyb3JcbiAqICAgZW5kXG4gKiAgIHZlcnNpb25DcmVhdGVVcGRhdGUtLT4+Q2FsbGVyOiB2b2lkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2ZXJzaW9uQ3JlYXRlVXBkYXRlKG9wZXJhdGlvbjogQ3J1ZE9wZXJhdGlvbnMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHZlcnNpb25DcmVhdGVVcGRhdGU8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgICBWIGV4dGVuZHMgb2JqZWN0LFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuICA+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0pIHtcbiAgICB0cnkge1xuICAgICAgc3dpdGNoIChvcGVyYXRpb24pIHtcbiAgICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLkNSRUFURTpcbiAgICAgICAgICAobW9kZWwgYXMgYW55KVtrZXldID0gMTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLlVQREFURTpcbiAgICAgICAgICAobW9kZWwgYXMgYW55KVtrZXldKys7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYEludmFsaWQgb3BlcmF0aW9uOiAke29wZXJhdGlvbn1gKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgRmFpbGVkIHRvIHVwZGF0ZSB2ZXJzaW9uOiAke2V9YCk7XG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgZGVjb3JhdG9yIGZvciB2ZXJzaW9uaW5nIGEgcHJvcGVydHkgaW4gYSBtb2RlbFxuICogQHN1bW1hcnkgVGhpcyBkZWNvcmF0b3IgYXBwbGllcyBtdWx0aXBsZSBzdWItZGVjb3JhdG9ycyB0byBoYW5kbGUgdmVyc2lvbiBtYW5hZ2VtZW50IGR1cmluZyBjcmVhdGUgYW5kIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBjb21wb3NpdGUgZGVjb3JhdG9yIHRoYXQgc2V0cyB0aGUgdHlwZSB0byBOdW1iZXIsIG1hbmFnZXMgdmVyc2lvbiB1cGRhdGVzLCBhbmQgYWRkcyB2ZXJzaW9uaW5nIG1ldGFkYXRhXG4gKiBAZnVuY3Rpb24gdmVyc2lvblxuICogQGNhdGVnb3J5IFByb3BlcnR5RGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyc2lvbigpIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgIHR5cGUoTnVtYmVyLm5hbWUpLFxuICAgIG9uQ3JlYXRlKHZlcnNpb25DcmVhdGVVcGRhdGUoT3BlcmF0aW9uS2V5cy5DUkVBVEUpKSxcbiAgICBvblVwZGF0ZSh2ZXJzaW9uQ3JlYXRlVXBkYXRlKE9wZXJhdGlvbktleXMuVVBEQVRFKSksXG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5WRVJTSU9OKSwgdHJ1ZSlcbiAgKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGRlY29yYXRvciB0aGF0IG1hcmtzIGEgcHJvcGVydHkgYXMgdHJhbnNpZW50XG4gKiBAc3VtbWFyeSBEZWNvcmF0b3IgdGhhdCBpbmRpY2F0ZXMgYSBwcm9wZXJ0eSBzaG91bGQgbm90IGJlIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2VcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiB0cmFuc2llbnRcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eURlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zaWVudCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHRyYW5zaWVudChtb2RlbDogYW55LCBhdHRyaWJ1dGU6IHN0cmluZykge1xuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuVFJBTlNJRU5UKSwgdHJ1ZSkobW9kZWwsIGF0dHJpYnV0ZSk7XG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5UUkFOU0lFTlQpLCB0cnVlKShtb2RlbC5jb25zdHJ1Y3Rvcik7XG4gIH07XG59XG4iLCJpbXBvcnQge1xuICBNb2RlbCxcbiAgTW9kZWxDb25kaXRpb25hbEFzeW5jLFxuICB2YWxpZGF0ZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgdmFsaWRhdGVDb21wYXJlIH0gZnJvbSBcIi4vdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgdGhlIG1vZGVsIGFuZCBjaGVja3MgZm9yIGVycm9yc1xuICogQHN1bW1hcnkgVmFsaWRhdGVzIHRoZSBjdXJyZW50IG1vZGVsIHN0YXRlIGFuZCBvcHRpb25hbGx5IGNvbXBhcmVzIHdpdGggYSBwcmV2aW91cyB2ZXJzaW9uXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAcGFyYW0ge018YW55fSBbcHJldmlvdXNWZXJzaW9uXSAtIE9wdGlvbmFsIHByZXZpb3VzIHZlcnNpb24gb2YgdGhlIG1vZGVsIGZvciBjb21wYXJpc29uXG4gKiBAcGFyYW0gey4uLmFueVtdfSBleGNsdXNpb25zIC0gUHJvcGVydGllcyB0byBleGNsdWRlIGZyb20gdmFsaWRhdGlvblxuICogQHJldHVybiB7TW9kZWxFcnJvckRlZmluaXRpb258dW5kZWZpbmVkfSBFcnJvciBkZWZpbml0aW9uIGlmIHZhbGlkYXRpb24gZmFpbHMsIHVuZGVmaW5lZCBvdGhlcndpc2VcbiAqIEBmdW5jdGlvbiBoYXNFcnJvcnNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG4vLyBAdHMtZXhwZWN0LWVycm9yIE92ZXJyaWRpbmcgTW9kZWwgcHJvdG90eXBlIG1ldGhvZCB3aXRoIGR5bmFtaWMgY29uZGl0aW9uYWwgcmV0dXJuIHR5cGUuXG5Nb2RlbC5wcm90b3R5cGUuaGFzRXJyb3JzID0gZnVuY3Rpb24gPE0gZXh0ZW5kcyBNb2RlbDxib29sZWFuPj4oXG4gIHRoaXM6IE0sXG4gIHByZXZpb3VzVmVyc2lvbj86IE0gfCBhbnksXG4gIC4uLmV4Y2x1c2lvbnM6IGFueVtdXG4pOiBNb2RlbENvbmRpdGlvbmFsQXN5bmM8TT4ge1xuICBpZiAocHJldmlvdXNWZXJzaW9uICYmICEocHJldmlvdXNWZXJzaW9uIGluc3RhbmNlb2YgTW9kZWwpKSB7XG4gICAgZXhjbHVzaW9ucy51bnNoaWZ0KHByZXZpb3VzVmVyc2lvbik7XG4gICAgcHJldmlvdXNWZXJzaW9uID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgYXN5bmMgPSB0aGlzLmlzQXN5bmMoKTtcbiAgY29uc3QgZXJycyA9IHZhbGlkYXRlKHRoaXMsIGFzeW5jLCAuLi5leGNsdXNpb25zKTtcblxuICBpZiAoYXN5bmMpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGVycnMpLnRoZW4oKHJlc29sdmVkRXJycykgPT4ge1xuICAgICAgaWYgKHJlc29sdmVkRXJycyB8fCAhcHJldmlvdXNWZXJzaW9uKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlZEVycnM7XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsaWRhdGVDb21wYXJlKHByZXZpb3VzVmVyc2lvbiwgdGhpcywgYXN5bmMsIC4uLmV4Y2x1c2lvbnMpO1xuICAgIH0pIGFzIGFueTtcbiAgfVxuXG4gIGlmIChlcnJzIHx8ICFwcmV2aW91c1ZlcnNpb24pIHJldHVybiBlcnJzIGFzIGFueTtcblxuICAvLyBAdHMtZXhwZWN0LWVycm9yIE92ZXJyaWRpbmcgTW9kZWwgcHJvdG90eXBlIG1ldGhvZCB3aXRoIGR5bmFtaWMgY29uZGl0aW9uYWwgcmV0dXJuIHR5cGUuXG4gIHJldHVybiB2YWxpZGF0ZUNvbXBhcmUocHJldmlvdXNWZXJzaW9uLCB0aGlzLCBhc3luYywgLi4uZXhjbHVzaW9ucyk7XG59O1xuIiwiaW1wb3J0IHtcbiAgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlLFxuICBSZXBvc2l0b3J5LFxuICBTZXJpYWxpemF0aW9uRXJyb3IsXG59IGZyb20gXCIuLi9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERCS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDaGVja3MgaWYgYSBtb2RlbCBpcyBtYXJrZWQgYXMgdHJhbnNpZW50XG4gKiBAc3VtbWFyeSBEZXRlcm1pbmVzIHdoZXRoZXIgYSBtb2RlbCBjbGFzcyBoYXMgYmVlbiBkZWNvcmF0ZWQgd2l0aCB0aGUgdHJhbnNpZW50IGRlY29yYXRvclxuICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBjaGVja1xuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgbW9kZWwgaXMgdHJhbnNpZW50LCBmYWxzZSBvdGhlcndpc2VcbiAqIEBmdW5jdGlvbiBpc1RyYW5zaWVudFxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1RyYW5zaWVudDxNIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBNKSB7XG4gIHJldHVybiAhIShcbiAgICBSZWZsZWN0LmdldE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5UUkFOU0lFTlQpLCBtb2RlbC5jb25zdHJ1Y3RvcikgfHxcbiAgICBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgUmVwb3NpdG9yeS5rZXkoREJLZXlzLlRSQU5TSUVOVCksXG4gICAgICBNb2RlbC5nZXQobW9kZWwuY29uc3RydWN0b3IubmFtZSkgYXMgYW55XG4gICAgKVxuICApO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXBhcmF0ZXMgdHJhbnNpZW50IHByb3BlcnRpZXMgZnJvbSBhIG1vZGVsXG4gKiBAc3VtbWFyeSBFeHRyYWN0cyBwcm9wZXJ0aWVzIG1hcmtlZCBhcyB0cmFuc2llbnQgaW50byBhIHNlcGFyYXRlIG9iamVjdFxuICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBwcm9jZXNzXG4gKiBAcmV0dXJuIHtPYmplY3R9IE9iamVjdCBjb250YWluaW5nIHRoZSBtb2RlbCB3aXRob3V0IHRyYW5zaWVudCBwcm9wZXJ0aWVzIGFuZCBhIHNlcGFyYXRlIHRyYW5zaWVudCBvYmplY3RcbiAqIEBwcm9wZXJ0eSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgd2l0aCB0cmFuc2llbnQgcHJvcGVydGllcyByZW1vdmVkXG4gKiBAcHJvcGVydHkge1JlY29yZDxzdHJpbmcsIGFueT59IFt0cmFuc2llbnRdIC0gT2JqZWN0IGNvbnRhaW5pbmcgdGhlIHRyYW5zaWVudCBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gbW9kZWxUb1RyYW5zaWVudFxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBtb2RlbFRvVHJhbnNpZW50XG4gKiAgIHBhcnRpY2lwYW50IGlzVHJhbnNpZW50XG4gKiAgIHBhcnRpY2lwYW50IGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZVxuICpcbiAqICAgQ2FsbGVyLT4+bW9kZWxUb1RyYW5zaWVudDogbW9kZWxcbiAqICAgbW9kZWxUb1RyYW5zaWVudC0+PmlzVHJhbnNpZW50OiBjaGVjayBpZiBtb2RlbCBpcyB0cmFuc2llbnRcbiAqICAgaXNUcmFuc2llbnQtLT4+bW9kZWxUb1RyYW5zaWVudDogdHJhbnNpZW50IHN0YXR1c1xuICogICBhbHQgbW9kZWwgaXMgbm90IHRyYW5zaWVudFxuICogICAgIG1vZGVsVG9UcmFuc2llbnQtLT4+Q2FsbGVyOiB7bW9kZWx9XG4gKiAgIGVsc2UgbW9kZWwgaXMgdHJhbnNpZW50XG4gKiAgICAgbW9kZWxUb1RyYW5zaWVudC0+PmdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZTogZ2V0IHRyYW5zaWVudCBwcm9wZXJ0aWVzXG4gKiAgICAgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlLS0+Pm1vZGVsVG9UcmFuc2llbnQ6IHByb3BlcnR5IGRlY29yYXRvcnNcbiAqICAgICBtb2RlbFRvVHJhbnNpZW50LT4+bW9kZWxUb1RyYW5zaWVudDogc2VwYXJhdGUgcHJvcGVydGllc1xuICogICAgIG1vZGVsVG9UcmFuc2llbnQtPj5Nb2RlbC5idWlsZDogcmVidWlsZCBtb2RlbCB3aXRob3V0IHRyYW5zaWVudCBwcm9wc1xuICogICAgIG1vZGVsVG9UcmFuc2llbnQtLT4+Q2FsbGVyOiB7bW9kZWwsIHRyYW5zaWVudH1cbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb2RlbFRvVHJhbnNpZW50PE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNXG4pOiB7IG1vZGVsOiBNOyB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+IH0ge1xuICBpZiAoIWlzVHJhbnNpZW50KG1vZGVsKSkgcmV0dXJuIHsgbW9kZWw6IG1vZGVsIH07XG4gIGNvbnN0IGRlY3M6IFJlY29yZDxzdHJpbmcsIGFueVtdPiA9IGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZShcbiAgICBtb2RlbCxcbiAgICB1bmRlZmluZWQsXG4gICAgUmVwb3NpdG9yeS5rZXkoREJLZXlzLlRSQU5TSUVOVClcbiAgKSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnlbXT47XG5cbiAgY29uc3QgcmVzdWx0ID0gT2JqZWN0LmVudHJpZXMoZGVjcykucmVkdWNlKFxuICAgIChcbiAgICAgIGFjY3VtOiB7IG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+OyB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+IH0sXG4gICAgICBbaywgdmFsXVxuICAgICkgPT4ge1xuICAgICAgY29uc3QgdHJhbnNpZW50ID0gdmFsLmZpbmQoKGVsKSA9PiBlbC5rZXkgPT09IFwiXCIpO1xuICAgICAgaWYgKHRyYW5zaWVudCkge1xuICAgICAgICBhY2N1bS50cmFuc2llbnQgPSBhY2N1bS50cmFuc2llbnQgfHwge307XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYWNjdW0udHJhbnNpZW50W2tdID0gbW9kZWxbayBhcyBrZXlvZiBNXTtcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgICAgICBgRmFpbGVkIHRvIHNlcmlhbGl6ZSB0cmFuc2llbnQgcHJvcGVydHkgJHtrfTogJHtlfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY2N1bS5tb2RlbCA9IGFjY3VtLm1vZGVsIHx8IHt9O1xuICAgICAgICBhY2N1bS5tb2RlbFtrXSA9IChtb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtrXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LFxuICAgIHt9IGFzIHsgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT47IHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT4gfVxuICApO1xuICByZXN1bHQubW9kZWwgPSBNb2RlbC5idWlsZChyZXN1bHQubW9kZWwsIG1vZGVsLmNvbnN0cnVjdG9yLm5hbWUpO1xuICByZXR1cm4gcmVzdWx0IGFzIHsgbW9kZWw6IE07IHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT4gfTtcbn1cbiIsImV4cG9ydCAqIGZyb20gXCIuL2lkZW50aXR5XCI7XG5leHBvcnQgKiBmcm9tIFwiLi9pbnRlcmZhY2VzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9tb2RlbFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vb3BlcmF0aW9uc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vcmVwb3NpdG9yeVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEYXRhYmFzZSBkZWNvcmF0b3JzIGZvciBUeXBlU2NyaXB0IGFwcGxpY2F0aW9uc1xuICogQHN1bW1hcnkgQSBjb21wcmVoZW5zaXZlIGxpYnJhcnkgcHJvdmlkaW5nIGRlY29yYXRvcnMgYW5kIHV0aWxpdGllcyBmb3IgZGF0YWJhc2Ugb3BlcmF0aW9ucywgbW9kZWwgZGVmaW5pdGlvbnMsIHZhbGlkYXRpb24sIGFuZCByZXBvc2l0b3J5IHBhdHRlcm5zIGluIFR5cGVTY3JpcHQgYXBwbGljYXRpb25zXG4gKiBAbW9kdWxlIGRiLWRlY29yYXRvcnNcbiAqL1xuXG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgcmVmbGVjdGlvbiBwYWNrYWdlXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIHNlbWFudGljIHZlcnNpb24gbnVtYmVyIG9mIHRoZSBwYWNrYWdlXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuIl0sIm5hbWVzIjpbIkRlY29yYXRvck1lc3NhZ2VzIl0sIm1hcHBpbmdzIjoiOzs7OztBQUVBOzs7OztBQUtHO0FBQ1UsTUFBQSxNQUFNLEdBQUc7QUFDcEIsSUFBQSxPQUFPLEVBQUUsQ0FBQSxFQUFHLFNBQVMsQ0FBQyxPQUFPLENBQWMsWUFBQSxDQUFBO0FBQzNDLElBQUEsVUFBVSxFQUFFLFlBQVk7QUFDeEIsSUFBQSxLQUFLLEVBQUUsUUFBUTtBQUNmLElBQUEsRUFBRSxFQUFFLElBQUk7QUFDUixJQUFBLEtBQUssRUFBRSxPQUFPO0FBQ2QsSUFBQSxNQUFNLEVBQUUsUUFBUTtBQUNoQixJQUFBLFNBQVMsRUFBRSxXQUFXO0FBQ3RCLElBQUEsUUFBUSxFQUFFLFVBQVU7QUFDcEIsSUFBQSxTQUFTLEVBQUUsV0FBVztBQUN0QixJQUFBLFNBQVMsRUFBRSxXQUFXO0FBQ3RCLElBQUEsSUFBSSxFQUFFLE1BQU07QUFDWixJQUFBLFFBQVEsRUFBRSxVQUFVO0FBQ3BCLElBQUEsT0FBTyxFQUFFLFNBQVM7QUFDbEIsSUFBQSxRQUFRLEVBQUUsZUFBZTs7QUFHM0I7Ozs7O0FB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
|