@decaf-ts/decoration 0.0.7 → 0.0.8

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.
@@ -1,55 +1,55 @@
1
1
  import 'reflect-metadata';
2
2
 
3
3
  /**
4
- * @description Default flavour identifier for the decorator system
5
- * @summary Defines the default flavour used by the Decoration class when no specific flavour is provided.
6
- * This constant is used throughout the library as the fallback flavour for decorators.
4
+ * @description Default flavour identifier for the decorator system.
5
+ * @summary Defines the default flavour used by the Decoration class when no specific flavour is provided. This constant is used throughout the library as the fallback flavour for decorators.
7
6
  * @const DefaultFlavour
8
7
  * @memberOf module:decoration
9
8
  */
10
9
  const DefaultFlavour = "decaf";
11
10
  /**
12
- * @description Character used to split nested metadata keys
13
- * @summary The delimiter used by the metadata store to traverse nested object paths when reading/writing values.
11
+ * @description Character used to split nested metadata keys.
12
+ * @summary Defines the delimiter the metadata store uses to traverse nested object paths when reading or writing values.
14
13
  * @const ObjectKeySplitter
15
14
  * @memberOf module:decoration
16
15
  */
17
16
  const ObjectKeySplitter = ".";
18
17
  /**
19
- * @description Enum containing metadata keys used for reflection in the model system
20
- * @summary Defines the various Model keys used for reflection and metadata storage.
21
- * These keys are used throughout the library to store and retrieve metadata about models,
22
- * their properties, and their behavior.
23
- * @readonly
18
+ * @description Metadata token registry for the decoration system.
19
+ * @summary Enumerates the keys used during reflection and metadata storage for classes, properties, methods, descriptions, and registered libraries.
24
20
  * @enum {string}
25
21
  * @readonly
22
+ * @const DecorationKeys
26
23
  * @memberOf module:decoration
27
24
  */
28
25
  var DecorationKeys;
29
26
  (function (DecorationKeys) {
27
+ /** @description Storage bucket for decoration-aware library registrations. */
30
28
  DecorationKeys["LIBRARIES"] = "libraries";
31
- /** Storage key used on the constructor to mirror runtime metadata */
29
+ /** @description Storage key mirrored on constructors that holds runtime metadata. */
32
30
  DecorationKeys["REFLECT"] = "__decaf";
33
- /** Map of model property keys to their reflected design types */
31
+ /** @description Container of reflected property metadata for a model. */
34
32
  DecorationKeys["PROPERTIES"] = "properties";
35
- /** Map of model method keys to their reflected design params and return types */
33
+ /** @description Container of reflected method metadata for a model. */
36
34
  DecorationKeys["METHODS"] = "methods";
37
- /** Key under which the model's constructor is stored */
35
+ /** @description Key under which the model constructor reference is persisted. */
38
36
  DecorationKeys["CLASS"] = "class";
39
- /** Container of human-friendly descriptions per class and property */
37
+ /** @description Human-readable descriptions for classes and members. */
40
38
  DecorationKeys["DESCRIPTION"] = "description";
41
- /** Holds the original constructor - for constructor override**/
39
+ /** @description Storage slot tracking the original constructor when overridden. */
42
40
  DecorationKeys["CONSTRUCTOR"] = "constructor";
43
- /** Reflect metadata key for design time type of a property */
41
+ /** @description Collected parameter metadata for configured decorators. */
42
+ DecorationKeys["PARAMETERS"] = "parameters";
43
+ /** @description Reflect metadata key for a property's design type. */
44
44
  DecorationKeys["DESIGN_TYPE"] = "design:type";
45
- /** Reflect metadata key for constructor parameter types */
45
+ /** @description Reflect metadata key for recorded constructor parameter types. */
46
46
  DecorationKeys["DESIGN_PARAMS"] = "design:paramtypes";
47
- /** Reflect metadata key for method return type */
47
+ /** @description Reflect metadata key for a method's return type. */
48
48
  DecorationKeys["DESIGN_RETURN"] = "design:returntype";
49
49
  })(DecorationKeys || (DecorationKeys = {}));
50
50
  /**
51
- * @description Default metadata instance
52
- * @summary Concrete default metadata object used when initializing metadata for a model
51
+ * @description Default metadata instance.
52
+ * @summary Provides the default metadata shape used when initializing new metadata entries for a model.
53
53
  * @const DefaultMetadata
54
54
  * @memberOf module:decoration
55
55
  */
@@ -58,12 +58,12 @@ const DefaultMetadata = {
58
58
  };
59
59
 
60
60
  /**
61
- * @description Retrieves a nested value from an object given a path
62
- * @summary Walks an object structure using a splitter-delimited path and returns the value at that location or undefined if any key is missing.
63
- * @param {Record<string, any>} obj The object to traverse
64
- * @param {string} path The path to the desired value (e.g., "a.b.c")
65
- * @param {string} [splitter=ObjectKeySplitter] The delimiter used to split the path
66
- * @return {*} The resolved value at the given path or undefined if not found
61
+ * @description Retrieves a nested value from an object given a path.
62
+ * @summary Walks an object structure using a splitter-delimited path and returns the value at that location or `undefined` if any key is missing.
63
+ * @param {Record<string, any>} obj Object to traverse for the lookup.
64
+ * @param {string} path Splitter-delimited path to the desired value (e.g., "a.b.c").
65
+ * @param {string} [splitter=ObjectKeySplitter] Delimiter used to separate the path segments.
66
+ * @return {any|undefined} Value resolved at the given path or `undefined` when not found.
67
67
  * @function getValueBySplitter
68
68
  * @mermaid
69
69
  * sequenceDiagram
@@ -94,12 +94,12 @@ function getValueBySplitter(obj, path, splitter = ObjectKeySplitter) {
94
94
  return current;
95
95
  }
96
96
  /**
97
- * @description Sets a nested value on an object given a path
97
+ * @description Sets a nested value on an object given a path.
98
98
  * @summary Traverses or creates intermediate objects following a splitter-delimited path and assigns the provided value at the destination key.
99
- * @param {Record<string, any>} obj The object to mutate
100
- * @param {string} path The destination path (e.g., "a.b.c")
101
- * @param {*} value The value to set at the destination
102
- * @param {string} [splitter=ObjectKeySplitter] The delimiter used to split the path
99
+ * @param {Record<string, any>} obj Object to mutate while drilling into nested keys.
100
+ * @param {string} path Splitter-delimited destination path (e.g., "a.b.c").
101
+ * @param {any} value Value to set at the destination node.
102
+ * @param {string} [splitter=ObjectKeySplitter] Delimiter used to separate the path segments.
103
103
  * @return {void}
104
104
  * @function setValueBySplitter
105
105
  * @mermaid
@@ -137,10 +137,11 @@ function setValueBySplitter(obj, path, value, splitter = ObjectKeySplitter) {
137
137
  current[lastKey] = value;
138
138
  }
139
139
  /**
140
- * @description Centralized runtime metadata store bound to constructors
140
+ * @description Centralized runtime metadata store bound to constructors.
141
141
  * @summary Provides utilities to read and write structured metadata for classes and their members, with optional mirroring onto the constructor via a well-known symbol key. Supports nested key paths using a configurable splitter and offers both instance and static APIs.
142
- * @template M The model type the metadata belongs to
143
- * @template META Extends BasicMetadata<M> representing the metadata structure
142
+ * @template M The model type the metadata belongs to.
143
+ * @template META Extends BasicMetadata<M> representing the metadata structure.
144
+ * @param {string} [flavour=DefaultFlavour] Optional flavour identifier applied when instantiating helper builders.
144
145
  * @class
145
146
  * @example
146
147
  * // Define and read metadata for a class
@@ -180,10 +181,10 @@ class Metadata {
180
181
  static { this.mirror = true; }
181
182
  constructor() { }
182
183
  /**
183
- * @description Lists known property keys for a model
184
+ * @description Lists known property keys for a model.
184
185
  * @summary Reads the metadata entry and returns the names of properties that have recorded type information.
185
- * @param {Constructor} model The target constructor
186
- * @return {string[]|undefined} Array of property names or undefined if no metadata exists
186
+ * @param {Constructor} model Target constructor whose property metadata should be inspected.
187
+ * @return {string[]|undefined} Array of property names or `undefined` if no metadata exists.
187
188
  */
188
189
  static properties(model) {
189
190
  const meta = this.get(model);
@@ -192,10 +193,10 @@ class Metadata {
192
193
  return Object.keys(meta.properties);
193
194
  }
194
195
  /**
195
- * @description Lists known methods for a model
196
+ * @description Lists known methods for a model.
196
197
  * @summary Reads the metadata entry and returns the method names that have recorded signature metadata for the provided constructor.
197
- * @param {Constructor} model The target constructor
198
- * @return {string[]|undefined} Array of property names or undefined if no metadata exists
198
+ * @param {Constructor} model Target constructor whose method metadata should be inspected.
199
+ * @return {string[]|undefined} Array of method names or `undefined` if no metadata exists.
199
200
  */
200
201
  static methods(model) {
201
202
  const meta = this.get(model, DecorationKeys.METHODS);
@@ -204,65 +205,83 @@ class Metadata {
204
205
  return Object.keys(meta);
205
206
  }
206
207
  /**
207
- * @description Retrieves a human-readable description for a class or a property
208
+ * @description Retrieves a human-readable description for a class or a property.
208
209
  * @summary Looks up the description stored under the metadata "description" map. If a property key is provided, returns the property's description; otherwise returns the class description.
209
210
  * @template M
210
- * @param {Constructor<M>} model The target constructor whose description is being retrieved
211
- * @param {string} [prop] Optional property key for which to fetch the description
212
- * @return {string|undefined} The description text if present, otherwise undefined
211
+ * @param {Constructor<M>} model Target constructor whose description is being retrieved.
212
+ * @param {string} [prop] Optional property key (typed as `keyof M`) for which to fetch the description.
213
+ * @return {string|undefined} Description text if present, otherwise `undefined`.
213
214
  */
214
215
  static description(model, prop) {
215
216
  return this.get(model, [DecorationKeys.DESCRIPTION, prop ? prop : DecorationKeys.CLASS].join(this.splitter));
216
217
  }
217
218
  /**
218
- * @description Retrieves the recorded params for a method
219
- * @summary Reads the metadata entry under "methods.<prop>.design:params" to return the arguments for the iven method.
220
- * @param {Constructor} model The target constructor
221
- * @param {string} prop The method name
222
- * @return {any[] | undefined} The argument types of the method or undefined if not available
219
+ * @description Retrieves the recorded params for a method.
220
+ * @summary Reads the metadata entry under `methods.<prop>.design:paramtypes` to return the parameter constructors for the given method.
221
+ * @template M
222
+ * @param {Constructor<M>} model Target constructor owning the method metadata.
223
+ * @param {string} prop Method name whose parameters should be fetched.
224
+ * @return {any[]|undefined} Array of constructor references describing each parameter or `undefined` when not available.
223
225
  */
224
226
  static params(model, prop) {
225
227
  return this.get(model, [DecorationKeys.METHODS, prop, DecorationKeys.DESIGN_PARAMS].join(this.splitter));
226
228
  }
227
229
  /**
228
- * @description Retrieves the recorded return type for a method
229
- * @summary Reads the metadata entry under "methods.<prop>.design:return" to return the return type for the given method.
230
- * @param {Constructor} model The target constructor
231
- * @param {string} prop The method name
232
- * @return {any|undefined} The return type of the method or undefined if not available
230
+ * @description Retrieves a single recorded parameter type for a method.
231
+ * @summary Looks up the parameter metadata for the provided index, enforcing bounds and returning the constructor reference for that argument.
232
+ * @template M
233
+ * @param {Constructor<M>} model Target constructor owning the method metadata.
234
+ * @param {string} prop Method name whose parameter should be returned.
235
+ * @param {number} index Zero-based index of the desired parameter metadata.
236
+ * @return {any|undefined} Constructor reference for the parameter or `undefined` if not recorded.
237
+ */
238
+ static param(model, prop, index) {
239
+ const params = this.params(model, prop);
240
+ if (!params)
241
+ return undefined;
242
+ if (index > params.length - 1)
243
+ throw new Error(`Parameter index ${index} out of range for ${String(prop)}`);
244
+ return params[index];
245
+ }
246
+ /**
247
+ * @description Retrieves the recorded return type for a method.
248
+ * @summary Reads the metadata entry under `methods.<prop>.design:returntype` to return the return type for the given method.
249
+ * @template M
250
+ * @param {Constructor<M>} model Target constructor whose method metadata should be inspected.
251
+ * @param {string} prop Method name whose return type should be fetched.
252
+ * @return {any|undefined} Constructor reference for the return type or `undefined` when not available.
233
253
  */
234
254
  static return(model, prop) {
235
255
  return this.get(model, [DecorationKeys.METHODS, prop, DecorationKeys.DESIGN_RETURN].join(this.splitter));
236
256
  }
237
257
  /**
238
- * @description Retrieves the recorded design type for a property
239
- * @summary Reads the metadata entry under "properties.<prop>" to return the constructor recorded for the given property name.
240
- * @param {Constructor} model The target constructor
241
- * @param {string} prop The property name whose type should be returned
242
- * @return {Constructor|undefined} The constructor reference of the property type or undefined if not available
258
+ * @description Retrieves the recorded design type for a property.
259
+ * @summary Reads the metadata entry under `properties.<prop>` to return the constructor recorded for the given property name.
260
+ * @param {Constructor} model Target constructor whose property metadata should be inspected.
261
+ * @param {string} prop Property name whose type metadata should be returned.
262
+ * @return {Constructor|undefined} Constructor reference for the property type or `undefined` if not available.
243
263
  */
244
264
  static type(model, prop) {
245
265
  return this.get(model, [DecorationKeys.PROPERTIES, prop].join(this.splitter));
246
266
  }
247
267
  /**
248
- * @description Resolves the canonical constructor associated with the provided model handle
249
- * @summary Returns the stored constructor reference when the provided model is a proxy or reduced value. Falls back to the
250
- * original model when no constructor metadata has been recorded yet.
268
+ * @description Resolves the canonical constructor associated with the provided model handle.
269
+ * @summary Returns the stored constructor reference when the provided model is a proxy or reduced value. Falls back to the original model when no constructor metadata has been recorded yet.
251
270
  * @template M
252
- * @param {Constructor<M>} model The model used when recording metadata
253
- * @return {Constructor<M> | undefined} The canonical constructor if stored, otherwise undefined
271
+ * @param {Constructor<M>} model Model used when recording metadata.
272
+ * @return {Constructor<M>|undefined} Canonical constructor if stored, otherwise `undefined`.
254
273
  */
255
274
  static constr(model) {
256
275
  return this.get(model, DecorationKeys.CONSTRUCTOR);
257
276
  }
258
277
  /**
259
- * @description Retrieves metadata for a model or a specific key within it
278
+ * @description Retrieves metadata for a model or a specific key within it.
260
279
  * @summary When called with a constructor only, returns the entire metadata object associated with the model. When a key path is provided, returns the value stored at that nested key.
261
280
  * @template M
262
281
  * @template META
263
- * @param {Constructor<M> | string} model The target constructor used to locate the metadata record
264
- * @param {string} [key] Optional nested key path to fetch a specific value
265
- * @return {META|*|undefined} The metadata object, the value at the key path, or undefined if nothing exists
282
+ * @param {Constructor<M>|string} model Target constructor used to locate the metadata record or a pre-resolved symbol identifier.
283
+ * @param {string} [key] Optional nested key path to fetch a specific value.
284
+ * @return {META|*|undefined} Metadata object, the value at the key path, or `undefined` if nothing exists.
266
285
  */
267
286
  static get(model, key) {
268
287
  if (key !== DecorationKeys.CONSTRUCTOR)
@@ -270,25 +289,44 @@ class Metadata {
270
289
  const symbol = Symbol.for(model.toString());
271
290
  return this.innerGet(symbol, key);
272
291
  }
292
+ /**
293
+ * @description Retrieves metadata stored under a symbol key.
294
+ * @summary Internal helper that resolves and optionally drills into the in-memory metadata map for the provided symbol and key path.
295
+ * @param {symbol} symbol Symbol representing the metadata bucket.
296
+ * @param {string|symbol} [key] Optional nested key referencing a specific metadata entry.
297
+ * @return {any} Stored metadata object or value for the provided key, or `undefined` when absent.
298
+ */
273
299
  static innerGet(symbol, key) {
274
300
  if (!this._metadata[symbol])
275
301
  return undefined;
276
302
  if (!key)
277
303
  return this._metadata[symbol];
278
- return getValueBySplitter(this._metadata[symbol], key, this.splitter);
304
+ if (typeof key === "string")
305
+ return getValueBySplitter(this._metadata[symbol], key, this.splitter);
306
+ return this._metadata[symbol][key];
279
307
  }
308
+ /**
309
+ * @description Writes metadata under a symbol key.
310
+ * @summary Internal helper that ensures the metadata bucket exists for the provided symbol and persists the given value, drilling into nested structures when the key is a string path.
311
+ * @param {symbol} symbol Symbol representing the metadata bucket.
312
+ * @param {string|symbol} key Nested key path or direct symbol under which to store the metadata value.
313
+ * @param {any} value Value persisted in the metadata store.
314
+ * @return {void}
315
+ */
280
316
  static innerSet(symbol, key, value) {
281
317
  if (!this._metadata[symbol])
282
318
  this._metadata[symbol] = {};
283
- setValueBySplitter(this._metadata[symbol], key, value, this.splitter);
319
+ if (typeof key === "string")
320
+ return setValueBySplitter(this._metadata[symbol], key, value, this.splitter);
321
+ this._metadata[symbol][key] = value;
284
322
  }
285
323
  /**
286
- * @description Writes a metadata value at a given nested key path
324
+ * @description Writes a metadata value at a given nested key path.
287
325
  * @summary Ensures the metadata record exists for the constructor, mirrors it on the constructor when enabled, and sets the provided value on the nested key path using the configured splitter.
288
326
  * @template M
289
- * @param {Constructor<M> | string} model The target constructor to which the metadata belongs
290
- * @param {string} key The nested key path at which to store the value
291
- * @param {*} value The value to store in the metadata
327
+ * @param {Constructor<M>|string} model Target constructor to which the metadata belongs or a direct identifier string.
328
+ * @param {string} key Nested key path at which to store the value.
329
+ * @param {any} value Value to store in the metadata.
292
330
  * @return {void}
293
331
  */
294
332
  static set(model, key, value) {
@@ -307,11 +345,12 @@ class Metadata {
307
345
  }
308
346
  }
309
347
  /**
310
- * @description Registers a decoration-aware library and its version
348
+ * @description Registers a decoration-aware library and its version.
311
349
  * @summary Stores the version string for an integrating library under the shared libraries metadata symbol, preventing duplicate registrations for the same library identifier.
312
- * @param {string} library Package name or identifier to register
313
- * @param {string} version Semantic version string associated with the library
314
- * @throws {Error} If the library has already been registered
350
+ * @param {string} library Package name or identifier to register.
351
+ * @param {string} version Semantic version string associated with the library.
352
+ * @return {void}
353
+ * @throws {Error} If the library has already been registered.
315
354
  */
316
355
  static registerLibrary(library, version) {
317
356
  const symbol = Symbol.for(DecorationKeys.LIBRARIES);
@@ -320,13 +359,31 @@ class Metadata {
320
359
  throw new Error(`Library already ${library} registered with version ${version}`);
321
360
  this.innerSet(symbol, library, version);
322
361
  }
362
+ /**
363
+ * @description Lists registered decoration-aware libraries.
364
+ * @summary Returns the in-memory map of library identifiers to semantic versions that have been registered with the Decoration metadata store.
365
+ * @return {Record<string, string>} Map of registered library identifiers to their version strings.
366
+ */
367
+ static libraries() {
368
+ const symbol = Symbol.for(DecorationKeys.LIBRARIES);
369
+ return this.innerGet(symbol) || {};
370
+ }
371
+ /**
372
+ * @description Joins path segments using the current splitter.
373
+ * @summary Constructs a nested metadata key by concatenating string segments with the configured splitter for use with the metadata store.
374
+ * @param {...string} strs Key segments to join into a full metadata path.
375
+ * @return {string} Splitter-joined metadata key.
376
+ */
377
+ static key(...strs) {
378
+ return strs.join(this.splitter);
379
+ }
323
380
  }
324
381
 
325
382
  /**
326
- * @description Default resolver that returns the current default flavour
327
- * @summary Resolves the flavour for a given target by always returning the library's DefaultFlavour value.
328
- * @param {object} target The target object being decorated
329
- * @return {string} The resolved flavour identifier
383
+ * @description Default resolver that returns the current default flavour.
384
+ * @summary Resolves the flavour for a given target by always returning the library's `DefaultFlavour` value.
385
+ * @param {object} target Target object being decorated.
386
+ * @return {string} Resolved flavour identifier.
330
387
  * @function defaultFlavourResolver
331
388
  * @memberOf module:decoration
332
389
  */
@@ -335,13 +392,10 @@ function defaultFlavourResolver(target) {
335
392
  return DefaultFlavour;
336
393
  }
337
394
  /**
338
- * @description A decorator management class that handles flavoured decorators
339
- * @summary The Decoration class provides a builder pattern for creating and managing decorators with different flavours.
340
- * It supports registering, extending, and applying decorators with context-aware flavour resolution.
341
- * The class implements a fluent interface for defining, extending, and applying decorators with different flavours,
342
- * allowing for framework-specific decorator implementations while maintaining a consistent API.
343
- * @template T Type of the decorator (ClassDecorator | PropertyDecorator | MethodDecorator)
344
- * @param {string} [flavour] Optional flavour parameter for the decorator context
395
+ * @description A decorator management class that handles flavoured decorators.
396
+ * @summary The Decoration class provides a builder pattern for creating and managing decorators with different flavours. It supports registering, extending, and applying decorators with context-aware flavour resolution, allowing framework-specific implementations while maintaining a consistent API.
397
+ * @template T Type of the decorator (ClassDecorator | PropertyDecorator | MethodDecorator).
398
+ * @param {string} [flavour=DefaultFlavour] Optional flavour parameter for the decorator context.
345
399
  * @class
346
400
  * @example
347
401
  * ```typescript
@@ -378,34 +432,34 @@ function defaultFlavourResolver(target) {
378
432
  */
379
433
  class Decoration {
380
434
  /**
381
- * @description Static map of registered decorators
382
- * @summary Stores all registered decorators organized by key and flavour
435
+ * @description Static map of registered decorators.
436
+ * @summary Stores all registered decorators organised by key and flavour.
383
437
  */
384
438
  static { this.decorators = {}; }
385
439
  /**
386
- * @description Function to resolve flavour from a target
387
- * @summary Resolver function that determines the appropriate flavour for a given target
440
+ * @description Function to resolve flavour from a target.
441
+ * @summary Resolver function that determines the appropriate flavour for a given target.
388
442
  */
389
443
  static { this.flavourResolver = defaultFlavourResolver; }
390
444
  constructor(flavour = DefaultFlavour) {
391
445
  this.flavour = flavour;
392
446
  }
393
447
  /**
394
- * @description Sets the key for the decoration builder
395
- * @summary Initializes a new decoration chain with the specified key
396
- * @param {string} key The identifier for the decorator
397
- * @return {DecorationBuilderMid} Builder instance for method chaining
448
+ * @description Sets the key for the decoration builder.
449
+ * @summary Initialises a new decoration chain with the specified key.
450
+ * @param {string} key Identifier for the decorator.
451
+ * @return {DecorationBuilderMid} Builder instance for method chaining.
398
452
  */
399
453
  for(key) {
400
454
  this.key = key;
401
455
  return this;
402
456
  }
403
457
  /**
404
- * @description Adds decorators to the current context
405
- * @summary Internal method to add decorators with addon support
406
- * @param {boolean} [addon=false] Whether the decorators are addons
407
- * @param decorators Array of decorators
408
- * @return {this} Current instance for chaining
458
+ * @description Adds decorators to the current context.
459
+ * @summary Internal method to add decorators with addon support.
460
+ * @param {boolean} [addon=false] Indicates whether the decorators are additive extras.
461
+ * @param {...DecoratorData} decorators Decorators to register for the configured key.
462
+ * @return {this} Current instance for chaining.
409
463
  */
410
464
  decorate(addon = false, ...decorators) {
411
465
  if (!this.key)
@@ -423,10 +477,10 @@ class Decoration {
423
477
  return this;
424
478
  }
425
479
  /**
426
- * @description Defines the base decorators
427
- * @summary Sets the primary decorators for the current context
428
- * @param decorators Decorators to define
429
- * @return Builder instance for finishing the chain
480
+ * @description Defines the base decorators.
481
+ * @summary Sets the primary decorators for the current context.
482
+ * @param {...DecoratorData} decorators Decorators to define.
483
+ * @return {DecorationBuilderEnd} Builder instance for finishing the chain (also implements DecorationBuilderBuild).
430
484
  */
431
485
  define(...decorators) {
432
486
  if (decorators.find((d) => typeof d === "object") &&
@@ -435,10 +489,10 @@ class Decoration {
435
489
  return this.decorate(false, ...decorators);
436
490
  }
437
491
  /**
438
- * @description Extends existing decorators
439
- * @summary Adds additional decorators to the current context
440
- * @param decorators Additional decorators
441
- * @return {DecorationBuilderBuild} Builder instance for building the decorator
492
+ * @description Extends existing decorators.
493
+ * @summary Adds additional decorators to the current context.
494
+ * @param {...DecoratorData} decorators Additional decorators to register as addons.
495
+ * @return {DecorationBuilderBuild} Builder instance for building the decorator.
442
496
  */
443
497
  extend(...decorators) {
444
498
  if (decorators.find((d) => typeof d === "object") &&
@@ -447,12 +501,11 @@ class Decoration {
447
501
  return this.decorate(true, ...decorators);
448
502
  }
449
503
  /**
450
- * @description Factory that creates a context-aware decorator for a key/flavour
451
- * @summary Produces a decorator function bound to the provided key and flavour. The resulting decorator resolves the actual
452
- * decorators to apply at invocation time based on the target's resolved flavour and the registered base and extra decorators.
453
- * @param {string} key The decoration key used to look up registered decorators
454
- * @param {string} [f=DefaultFlavour] Optional explicit flavour to bind the factory to
455
- * @return {function(object, any, TypedPropertyDescriptor<any>): any} A decorator function that applies the resolved decorators
504
+ * @description Factory that creates a context-aware decorator for a key/flavour.
505
+ * @summary Produces a decorator function bound to the provided key and flavour. The resulting decorator resolves the actual decorators to apply at invocation time based on the target's resolved flavour and the registered base and extra decorators.
506
+ * @param {string} key Decoration key used to look up registered decorators.
507
+ * @param {string} [f=DefaultFlavour] Explicit flavour to bind the factory to.
508
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator} Decorator function that applies the resolved decorators.
456
509
  * @mermaid
457
510
  * sequenceDiagram
458
511
  * participant U as User Code
@@ -517,9 +570,9 @@ class Decoration {
517
570
  return contextDecorator;
518
571
  }
519
572
  /**
520
- * @description Creates the final decorator function
521
- * @summary Builds and returns the decorator factory function
522
- * @return {function(any, any?, TypedPropertyDescriptor?): any} The generated decorator function
573
+ * @description Creates the final decorator function.
574
+ * @summary Builds and returns the decorator factory function.
575
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator} Generated decorator function ready for application.
523
576
  */
524
577
  apply() {
525
578
  if (!this.key)
@@ -528,12 +581,13 @@ class Decoration {
528
581
  return this.decoratorFactory(this.key, this.flavour);
529
582
  }
530
583
  /**
531
- * @description Registers decorators for a specific key and flavour
532
- * @summary Internal method to store decorators in the static registry
533
- * @param {string} key Decorator key
534
- * @param {string} flavour Decorator flavour
535
- * @param [decorators] Primary decorators
536
- * @param [extras] Additional decorators
584
+ * @description Registers decorators for a specific key and flavour.
585
+ * @summary Internal method to store decorators in the static registry.
586
+ * @param {string} key Decorator key.
587
+ * @param {string} flavour Decorator flavour.
588
+ * @param {Set<DecoratorData>} [decorators] Primary decorators registered for the key.
589
+ * @param {Set<DecoratorData>} [extras] Additional decorators registered as flavour-specific addons.
590
+ * @return {void}
537
591
  */
538
592
  static register(key, flavour, decorators, extras) {
539
593
  if (!key) {
@@ -553,27 +607,28 @@ class Decoration {
553
607
  Decoration.decorators[key][flavour].extras = extras;
554
608
  }
555
609
  /**
556
- * @description Sets the global flavour resolver
557
- * @summary Configures the function used to determine decorator flavours
558
- * @param {FlavourResolver} resolver Function to resolve flavours
610
+ * @description Sets the global flavour resolver.
611
+ * @summary Configures the function used to determine decorator flavours.
612
+ * @param {FlavourResolver} resolver Function to resolve flavours.
613
+ * @return {void}
559
614
  */
560
615
  static setFlavourResolver(resolver) {
561
616
  Decoration.flavourResolver = resolver;
562
617
  }
563
618
  /**
564
- * @description Convenience static entry to start a decoration builder
619
+ * @description Convenience static entry to start a decoration builder.
565
620
  * @summary Creates a new Decoration instance and initiates the builder chain with the provided key.
566
- * @param {string} key The decoration key to configure
567
- * @return {DecorationBuilderMid} A builder instance for chaining definitions
621
+ * @param {string} key Decoration key to configure.
622
+ * @return {DecorationBuilderMid} Builder instance for chaining definitions.
568
623
  */
569
624
  static for(key) {
570
625
  return new Decoration().for(key);
571
626
  }
572
627
  /**
573
- * @description Starts a builder for a specific flavour
628
+ * @description Starts a builder for a specific flavour.
574
629
  * @summary Convenience method to begin a Decoration builder chain bound to the given flavour identifier, allowing registration of flavour-specific decorators.
575
- * @param {string} flavour The flavour name to bind to the builder
576
- * @return {DecorationBuilderStart} A builder start interface to continue configuration
630
+ * @param {string} flavour Flavour name to bind to the builder.
631
+ * @return {DecorationBuilderStart} Builder start interface to continue configuration.
577
632
  */
578
633
  static flavouredAs(flavour) {
579
634
  return new Decoration(flavour);
@@ -581,11 +636,11 @@ class Decoration {
581
636
  }
582
637
 
583
638
  /**
584
- * @description Assigns arbitrary metadata to a target using a string key
585
- * @summary Decorator factory that stores a key/value pair in the central Metadata store for the provided class or member.
586
- * @param {string} key The metadata key to associate with the target
587
- * @param {any} value The metadata value to store under the given key
588
- * @return A decorator that writes the metadata when applied
639
+ * @description Assigns arbitrary metadata to a target using a string key.
640
+ * @summary Decorator factory that stores a key/value pair in the central metadata store for the provided class or member.
641
+ * @param {string} key Metadata key to associate with the target.
642
+ * @param {any} value Metadata value to store under the given key.
643
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator} Decorator that writes the metadata when applied.
589
644
  * @function metadata
590
645
  * @category Decorators
591
646
  */
@@ -597,37 +652,93 @@ function metadata(key, value) {
597
652
  };
598
653
  }
599
654
  /**
600
- * @description Captures and stores a property's design type
601
- * @summary Decorator factory that reads the reflected design:type for a property and registers it in the Metadata store under the properties map.
602
- * @return A decorator that records the property's type metadata when applied
655
+ * @description Captures and stores a property's design type.
656
+ * @summary Decorator factory that reads the reflected `design:type` for a property and registers it in the metadata store under the properties map.
657
+ * @return {PropertyDecorator} Decorator that records the property's type metadata when applied.
603
658
  * @function prop
604
659
  * @category Property Decorators
605
660
  */
606
661
  function prop() {
607
662
  return function prop(model, prop) {
608
663
  const designType = Reflect.getOwnMetadata(DecorationKeys.DESIGN_TYPE, model, prop);
609
- return metadata(`${DecorationKeys.PROPERTIES}.${prop}`, designType)(model, prop);
664
+ return metadata(Metadata.key(DecorationKeys.PROPERTIES, prop), designType)(model, prop);
610
665
  };
611
666
  }
612
667
  /**
613
- * @description Records method design-time metadata
668
+ * @description Captures a single parameter type for the decorated method.
669
+ * @summary Decorator factory that ensures the method metadata is initialised and stores the reflected parameter constructor at the provided index.
670
+ * @return {ParameterDecorator} Decorator that records the parameter type when applied.
671
+ * @function param
672
+ * @category Parameter Decorators
673
+ * @mermaid
674
+ * sequenceDiagram
675
+ * participant U as User Code
676
+ * participant P as param()
677
+ * participant M as Metadata
678
+ * U->>P: param()(target, key, index)
679
+ * P->>U: method()(target, key, descriptor)
680
+ * P->>M: params(constructor, key)
681
+ * M-->>P: parameter constructors[]
682
+ * P->>M: set(methods.key.index, constructor)
683
+ * P-->>U: parameter recorded
684
+ */
685
+ function param() {
686
+ return function param(model, prop, index) {
687
+ if (!prop)
688
+ throw new Error(`The @param decorator can only be applied to methods`);
689
+ method()(model, prop, Object.getOwnPropertyDescriptor(model, prop));
690
+ const paramTpes = Metadata.params(model.constructor, prop);
691
+ if (!paramTpes)
692
+ throw new Error(`Missing parameter types for ${String(prop)}`);
693
+ if (index >= paramTpes.length)
694
+ throw new Error(`Parameter index ${index} out of range for ${String(prop)}`);
695
+ metadata(Metadata.key(DecorationKeys.METHODS, prop, index.toString()), paramTpes[index])(model, prop);
696
+ };
697
+ }
698
+ /**
699
+ * @description Extends a parameter decorator with additional metadata.
700
+ * @summary Applies the default `param()` decorator and augments the stored metadata with an arbitrary key/value pair.
701
+ * @param {string} key Metadata key to associate with the parameter.
702
+ * @param {any} value Metadata value persisted under the given key.
703
+ * @return {ParameterDecorator} Decorator that records both the parameter design type and additional metadata.
704
+ * @function paramMetadata
705
+ * @category Parameter Decorators
706
+ */
707
+ function paramMetadata(key, value) {
708
+ return function paramMetadata(target, prop, index) {
709
+ return apply(param(), metadata(Metadata.key(DecorationKeys.METHODS, prop, key), value))(target, prop, index);
710
+ };
711
+ }
712
+ /**
713
+ * @description Records method design-time metadata.
614
714
  * @summary Decorator factory that captures a method's reflected parameter and return types, storing them under the appropriate metadata keys so they can be inspected at runtime.
615
- * @return A decorator that persists the method's signature information into the Metadata store when applied
715
+ * @return {MethodDecorator} Decorator that persists the method's signature information into the metadata store when applied.
616
716
  * @function method
717
+ * @mermaid
718
+ * sequenceDiagram
719
+ * participant U as User Code
720
+ * participant F as method()
721
+ * participant M as Metadata
722
+ * U->>F: method()(target, key, descriptor)
723
+ * F->>U: Reflect.getOwnMetadata(design:paramtypes)
724
+ * F->>U: Reflect.getOwnMetadata(design:returntype)
725
+ * F->>M: set(methods.key.design:paramtypes, params)
726
+ * F->>M: set(methods.key.design:returntype, returnType)
727
+ * F-->>U: decorated function
617
728
  * @category Method Decorators
618
729
  */
619
730
  function method() {
620
731
  return function method(obj, prop, descriptor) {
621
732
  const designParams = Reflect.getOwnMetadata(DecorationKeys.DESIGN_PARAMS, obj, prop);
622
733
  const designReturn = Reflect.getOwnMetadata(DecorationKeys.DESIGN_RETURN, obj, prop);
623
- return apply(metadata(`${DecorationKeys.METHODS}.${prop}.${DecorationKeys.DESIGN_PARAMS}`, designParams), metadata(`${DecorationKeys.METHODS}.${prop}.${DecorationKeys.DESIGN_RETURN}`, designReturn))(obj, prop, descriptor);
734
+ return apply(metadata(Metadata.key(DecorationKeys.METHODS, prop, DecorationKeys.DESIGN_PARAMS), designParams), metadata(Metadata.key(DecorationKeys.METHODS, prop, DecorationKeys.DESIGN_RETURN), designReturn))(obj, prop, descriptor);
624
735
  };
625
736
  }
626
737
  /**
627
- * @description Decorator factory that applies multiple decorators to a single target
628
- * @summary Creates a composite decorator that applies multiple decorators in sequence, correctly handling class, method, and property decorators.
629
- * @param {Array<ClassDecorator | MethodDecorator | PropertyDecorator>} decorators - Array of decorators to apply
630
- * @return {Function} A decorator function that applies all provided decorators to the target
738
+ * @description Decorator factory that applies multiple decorators to a single target.
739
+ * @summary Creates a composite decorator that applies multiple decorators in sequence, correctly handling class, method, property, and parameter decorators.
740
+ * @param {Array<ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator>} decorators Collection of decorators to apply.
741
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator} Decorator function that applies all provided decorators to the target.
631
742
  * @function apply
632
743
  * @mermaid
633
744
  * sequenceDiagram
@@ -654,11 +765,11 @@ function apply(...decorators) {
654
765
  };
655
766
  }
656
767
  /**
657
- * @description Creates a property metadata decorator
658
- * @summary Convenience factory that combines metadata(key, value) and prop() to both set an arbitrary metadata key and record the property's design type.
659
- * @param {string} key The metadata key to set for the property
660
- * @param {*} value The metadata value to associate with the key
661
- * @return A decorator that sets the metadata and captures the property's type
768
+ * @description Creates a property metadata decorator.
769
+ * @summary Convenience factory that combines `metadata(key, value)` and `prop()` to both set an arbitrary metadata key and record the property's design type.
770
+ * @param {string} key Metadata key to set for the property.
771
+ * @param {any} value Metadata value to associate with the key.
772
+ * @return {PropertyDecorator} Decorator that sets the metadata and captures the property's type.
662
773
  * @function propMetadata
663
774
  * @category Property Decorators
664
775
  */
@@ -666,10 +777,22 @@ function propMetadata(key, value) {
666
777
  return apply(metadata(key, value), prop());
667
778
  }
668
779
  /**
669
- * @description Attaches a human-readable description to a class or member
670
- * @summary Decorator factory that stores a textual description in the Metadata store under the appropriate description key for a class or its property.
671
- * @param {string} desc The descriptive text to associate with the class or property
672
- * @return A decorator that records the description when applied
780
+ * @description Creates a method metadata decorator.
781
+ * @summary Convenience factory that combines `metadata(key, value)` and `method()` to both set an arbitrary metadata key and record the method's design return and param types.
782
+ * @param {string} key Metadata key to set for the property.
783
+ * @param {any} value Metadata value to associate with the key.
784
+ * @return {PropertyDecorator} Decorator that sets the metadata and captures the property's type.
785
+ * @function methodMetadata
786
+ * @category Method Decorators
787
+ */
788
+ function methodMetadata(key, value) {
789
+ return apply(metadata(key, value), method());
790
+ }
791
+ /**
792
+ * @description Attaches a human-readable description to a class or member.
793
+ * @summary Decorator factory that stores a textual description in the metadata store under the appropriate description key for a class or its property.
794
+ * @param {string} desc Descriptive text to associate with the class or property.
795
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator} Decorator that records the description when applied.
673
796
  * @function description
674
797
  * @category Decorators
675
798
  */
@@ -678,18 +801,17 @@ function description(desc) {
678
801
  return metadata([
679
802
  DecorationKeys.DESCRIPTION,
680
803
  prop ? prop.toString() : DecorationKeys.CLASS,
681
- ].join(ObjectKeySplitter), desc)(original, prop, descriptor);
804
+ ].join(Metadata.splitter), desc)(original, prop, descriptor);
682
805
  };
683
806
  }
684
807
 
685
808
  /**
686
- * @description Root entry point for the decoration module
687
- * @summary Aggregates and re-exports the public API of the decoration library, including core classes like {@link Decoration}, utility decorators, metadata helpers, and constants. This module is the primary import surface for consumers and exposes:
809
+ * @description Root entry point for the decoration module.
810
+ * @summary Aggregates and re-exports the public API of the decoration library, including {@link Decoration}, decorator utilities from {@link module:decoration|./decorators}, {@link Metadata}, and shared constants such as {@link DecorationKeys} and {@link DefaultFlavour}. This is the primary import surface for consumers and exposes:
688
811
  * - Core builder: {@link Decoration}
689
- * - Decorator utilities: {@link module:decoration | decorators in ./decorators}
812
+ * - Decorator utilities: {@link module:decoration|decorators in ./decorators}
690
813
  * - Metadata utilities: {@link Metadata}
691
814
  * - Constants and enums: {@link DecorationKeys}, {@link DefaultFlavour}
692
- *
693
815
  * @module decoration
694
816
  */
695
817
  /**
@@ -698,8 +820,8 @@ function description(desc) {
698
820
  * @const VERSION
699
821
  * @memberOf module:decoration
700
822
  */
701
- const VERSION = "0.0.7";
823
+ const VERSION = "0.0.8";
702
824
  Metadata.registerLibrary("@decaf-ts/decoration", VERSION);
703
825
 
704
- export { Decoration, DecorationKeys, DefaultFlavour, DefaultMetadata, Metadata, ObjectKeySplitter, VERSION, apply, description, getValueBySplitter, metadata, method, prop, propMetadata, setValueBySplitter };
705
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdGlvbi5lc20uY2pzIiwic291cmNlcyI6WyIuLi9zcmMvY29uc3RhbnRzLnRzIiwiLi4vc3JjL21ldGFkYXRhL01ldGFkYXRhLnRzIiwiLi4vc3JjL2RlY29yYXRpb24vRGVjb3JhdGlvbi50cyIsIi4uL3NyYy9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJhc2ljTWV0YWRhdGEgfSBmcm9tIFwiLi9tZXRhZGF0YS90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGZsYXZvdXIgaWRlbnRpZmllciBmb3IgdGhlIGRlY29yYXRvciBzeXN0ZW1cbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIGRlZmF1bHQgZmxhdm91ciB1c2VkIGJ5IHRoZSBEZWNvcmF0aW9uIGNsYXNzIHdoZW4gbm8gc3BlY2lmaWMgZmxhdm91ciBpcyBwcm92aWRlZC5cbiAqIFRoaXMgY29uc3RhbnQgaXMgdXNlZCB0aHJvdWdob3V0IHRoZSBsaWJyYXJ5IGFzIHRoZSBmYWxsYmFjayBmbGF2b3VyIGZvciBkZWNvcmF0b3JzLlxuICogQGNvbnN0IERlZmF1bHRGbGF2b3VyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRGbGF2b3VyID0gXCJkZWNhZlwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDaGFyYWN0ZXIgdXNlZCB0byBzcGxpdCBuZXN0ZWQgbWV0YWRhdGEga2V5c1xuICogQHN1bW1hcnkgVGhlIGRlbGltaXRlciB1c2VkIGJ5IHRoZSBtZXRhZGF0YSBzdG9yZSB0byB0cmF2ZXJzZSBuZXN0ZWQgb2JqZWN0IHBhdGhzIHdoZW4gcmVhZGluZy93cml0aW5nIHZhbHVlcy5cbiAqIEBjb25zdCBPYmplY3RLZXlTcGxpdHRlclxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBPYmplY3RLZXlTcGxpdHRlciA9IFwiLlwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFbnVtIGNvbnRhaW5pbmcgbWV0YWRhdGEga2V5cyB1c2VkIGZvciByZWZsZWN0aW9uIGluIHRoZSBtb2RlbCBzeXN0ZW1cbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIHZhcmlvdXMgTW9kZWwga2V5cyB1c2VkIGZvciByZWZsZWN0aW9uIGFuZCBtZXRhZGF0YSBzdG9yYWdlLlxuICogVGhlc2Uga2V5cyBhcmUgdXNlZCB0aHJvdWdob3V0IHRoZSBsaWJyYXJ5IHRvIHN0b3JlIGFuZCByZXRyaWV2ZSBtZXRhZGF0YSBhYm91dCBtb2RlbHMsXG4gKiB0aGVpciBwcm9wZXJ0aWVzLCBhbmQgdGhlaXIgYmVoYXZpb3IuXG4gKiBAcmVhZG9ubHlcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgZW51bSBEZWNvcmF0aW9uS2V5cyB7XG4gIExJQlJBUklFUyA9IFwibGlicmFyaWVzXCIsXG4gIC8qKiBTdG9yYWdlIGtleSB1c2VkIG9uIHRoZSBjb25zdHJ1Y3RvciB0byBtaXJyb3IgcnVudGltZSBtZXRhZGF0YSAqL1xuICBSRUZMRUNUID0gYF9fJHtEZWZhdWx0Rmxhdm91cn1gLFxuICAvKiogTWFwIG9mIG1vZGVsIHByb3BlcnR5IGtleXMgdG8gdGhlaXIgcmVmbGVjdGVkIGRlc2lnbiB0eXBlcyAqL1xuICBQUk9QRVJUSUVTID0gXCJwcm9wZXJ0aWVzXCIsXG4gIC8qKiBNYXAgb2YgbW9kZWwgbWV0aG9kIGtleXMgdG8gdGhlaXIgcmVmbGVjdGVkIGRlc2lnbiBwYXJhbXMgYW5kIHJldHVybiB0eXBlcyAqL1xuICBNRVRIT0RTID0gXCJtZXRob2RzXCIsXG4gIC8qKiBLZXkgdW5kZXIgd2hpY2ggdGhlIG1vZGVsJ3MgY29uc3RydWN0b3IgaXMgc3RvcmVkICovXG4gIENMQVNTID0gXCJjbGFzc1wiLFxuICAvKiogQ29udGFpbmVyIG9mIGh1bWFuLWZyaWVuZGx5IGRlc2NyaXB0aW9ucyBwZXIgY2xhc3MgYW5kIHByb3BlcnR5ICovXG4gIERFU0NSSVBUSU9OID0gXCJkZXNjcmlwdGlvblwiLFxuICAvKiogSG9sZHMgdGhlIG9yaWdpbmFsIGNvbnN0cnVjdG9yIC0gZm9yIGNvbnN0cnVjdG9yIG92ZXJyaWRlKiovXG4gIENPTlNUUlVDVE9SID0gXCJjb25zdHJ1Y3RvclwiLFxuICAvKiogUmVmbGVjdCBtZXRhZGF0YSBrZXkgZm9yIGRlc2lnbiB0aW1lIHR5cGUgb2YgYSBwcm9wZXJ0eSAqL1xuICBERVNJR05fVFlQRSA9IFwiZGVzaWduOnR5cGVcIixcbiAgLyoqIFJlZmxlY3QgbWV0YWRhdGEga2V5IGZvciBjb25zdHJ1Y3RvciBwYXJhbWV0ZXIgdHlwZXMgKi9cbiAgREVTSUdOX1BBUkFNUyA9IFwiZGVzaWduOnBhcmFtdHlwZXNcIixcbiAgLyoqIFJlZmxlY3QgbWV0YWRhdGEga2V5IGZvciBtZXRob2QgcmV0dXJuIHR5cGUgKi9cbiAgREVTSUdOX1JFVFVSTiA9IFwiZGVzaWduOnJldHVybnR5cGVcIixcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBtZXRhZGF0YSBpbnN0YW5jZVxuICogQHN1bW1hcnkgQ29uY3JldGUgZGVmYXVsdCBtZXRhZGF0YSBvYmplY3QgdXNlZCB3aGVuIGluaXRpYWxpemluZyBtZXRhZGF0YSBmb3IgYSBtb2RlbFxuICogQGNvbnN0IERlZmF1bHRNZXRhZGF0YVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0TWV0YWRhdGE6IEJhc2ljTWV0YWRhdGE8YW55PiA9IHtcbiAgW0RlY29yYXRpb25LZXlzLlBST1BFUlRJRVNdOiBbXSxcbn0gYXMgdW5rbm93biBhcyBCYXNpY01ldGFkYXRhPGFueT47XG4iLCJpbXBvcnQgeyBCYXNpY01ldGFkYXRhLCBDb25zdHJ1Y3RvciB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBEZWNvcmF0aW9uS2V5cywgT2JqZWN0S2V5U3BsaXR0ZXIgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgXCJyZWZsZWN0LW1ldGFkYXRhXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIG5lc3RlZCB2YWx1ZSBmcm9tIGFuIG9iamVjdCBnaXZlbiBhIHBhdGhcbiAqIEBzdW1tYXJ5IFdhbGtzIGFuIG9iamVjdCBzdHJ1Y3R1cmUgdXNpbmcgYSBzcGxpdHRlci1kZWxpbWl0ZWQgcGF0aCBhbmQgcmV0dXJucyB0aGUgdmFsdWUgYXQgdGhhdCBsb2NhdGlvbiBvciB1bmRlZmluZWQgaWYgYW55IGtleSBpcyBtaXNzaW5nLlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmogVGhlIG9iamVjdCB0byB0cmF2ZXJzZVxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggVGhlIHBhdGggdG8gdGhlIGRlc2lyZWQgdmFsdWUgKGUuZy4sIFwiYS5iLmNcIilcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc3BsaXR0ZXI9T2JqZWN0S2V5U3BsaXR0ZXJdIFRoZSBkZWxpbWl0ZXIgdXNlZCB0byBzcGxpdCB0aGUgcGF0aFxuICogQHJldHVybiB7Kn0gVGhlIHJlc29sdmVkIHZhbHVlIGF0IHRoZSBnaXZlbiBwYXRoIG9yIHVuZGVmaW5lZCBpZiBub3QgZm91bmRcbiAqIEBmdW5jdGlvbiBnZXRWYWx1ZUJ5U3BsaXR0ZXJcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgRiBhcyBnZXRWYWx1ZUJ5U3BsaXR0ZXJcbiAqICAgcGFydGljaXBhbnQgTyBhcyBPYmplY3RcbiAqICAgQy0+PkY6IChvYmosIHBhdGgsIHNwbGl0dGVyKVxuICogICBGLT4+Rjogc3BsaXQgcGF0aCBpbnRvIGtleXNcbiAqICAgbG9vcCBmb3IgZWFjaCBrZXlcbiAqICAgICBGLT4+TzogYWNjZXNzIGN1cnJlbnRba2V5XVxuICogICAgIGFsdCBtaXNzaW5nIG9yIG51bGxpc2hcbiAqICAgICAgIEYtLT4+QzogcmV0dXJuIHVuZGVmaW5lZFxuICogICAgIGVuZFxuICogICBlbmRcbiAqICAgRi0tPj5DOiByZXR1cm4gZmluYWwgdmFsdWVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VmFsdWVCeVNwbGl0dGVyKFxuICBvYmo6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gIHBhdGg6IHN0cmluZyxcbiAgc3BsaXR0ZXI6IHN0cmluZyA9IE9iamVjdEtleVNwbGl0dGVyXG4pOiBhbnkge1xuICBjb25zdCBrZXlzID0gcGF0aC5zcGxpdChzcGxpdHRlcik7XG4gIGxldCBjdXJyZW50ID0gb2JqO1xuXG4gIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICBpZiAoXG4gICAgICBjdXJyZW50ID09PSBudWxsIHx8XG4gICAgICBjdXJyZW50ID09PSB1bmRlZmluZWQgfHxcbiAgICAgICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoY3VycmVudCwga2V5KVxuICAgIClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY3VycmVudCA9IGN1cnJlbnRba2V5XTtcbiAgfVxuXG4gIHJldHVybiBjdXJyZW50O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXRzIGEgbmVzdGVkIHZhbHVlIG9uIGFuIG9iamVjdCBnaXZlbiBhIHBhdGhcbiAqIEBzdW1tYXJ5IFRyYXZlcnNlcyBvciBjcmVhdGVzIGludGVybWVkaWF0ZSBvYmplY3RzIGZvbGxvd2luZyBhIHNwbGl0dGVyLWRlbGltaXRlZCBwYXRoIGFuZCBhc3NpZ25zIHRoZSBwcm92aWRlZCB2YWx1ZSBhdCB0aGUgZGVzdGluYXRpb24ga2V5LlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmogVGhlIG9iamVjdCB0byBtdXRhdGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIFRoZSBkZXN0aW5hdGlvbiBwYXRoIChlLmcuLCBcImEuYi5jXCIpXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQgYXQgdGhlIGRlc3RpbmF0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ30gW3NwbGl0dGVyPU9iamVjdEtleVNwbGl0dGVyXSBUaGUgZGVsaW1pdGVyIHVzZWQgdG8gc3BsaXQgdGhlIHBhdGhcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAZnVuY3Rpb24gc2V0VmFsdWVCeVNwbGl0dGVyXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IEYgYXMgc2V0VmFsdWVCeVNwbGl0dGVyXG4gKiAgIHBhcnRpY2lwYW50IE8gYXMgT2JqZWN0XG4gKiAgIEMtPj5GOiAob2JqLCBwYXRoLCB2YWx1ZSwgc3BsaXR0ZXIpXG4gKiAgIEYtPj5GOiBzcGxpdCBwYXRoIGludG8ga2V5c1xuICogICBsb29wIGZvciBlYWNoIGtleVxuICogICAgIGFsdCBrZXkgbWlzc2luZ1xuICogICAgICAgRi0+Pk86IGNyZWF0ZSBpbnRlcm1lZGlhdGUgb2JqZWN0XG4gKiAgICAgZWxzZSBrZXkgZXhpc3RzXG4gKiAgICAgICBGLT4+TzogZGVzY2VuZCBpbnRvIGV4aXN0aW5nIG9iamVjdFxuICogICAgIGVuZFxuICogICBlbmRcbiAqICAgRi0tPj5DOiB2b2lkXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFZhbHVlQnlTcGxpdHRlcihcbiAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBwYXRoOiBzdHJpbmcsXG4gIHZhbHVlOiBhbnksXG4gIHNwbGl0dGVyID0gT2JqZWN0S2V5U3BsaXR0ZXJcbik6IHZvaWQge1xuICBjb25zdCBrZXlzID0gcGF0aC5zcGxpdChzcGxpdHRlcikuZmlsdGVyKChrKSA9PiBrLmxlbmd0aCA+IDApO1xuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICBsZXQgY3VycmVudDogUmVjb3JkPGFueSwgYW55PiA9IG9iajtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgY29uc3Qga2V5ID0ga2V5c1tpXTtcbiAgICBpZiAoXG4gICAgICBjdXJyZW50W2tleV0gPT09IHVuZGVmaW5lZCB8fFxuICAgICAgY3VycmVudFtrZXldID09PSBudWxsIHx8XG4gICAgICB0eXBlb2YgY3VycmVudFtrZXldICE9PSBcIm9iamVjdFwiXG4gICAgKSB7XG4gICAgICBjdXJyZW50W2tleV0gPSB7fTtcbiAgICB9XG4gICAgY3VycmVudCA9IGN1cnJlbnRba2V5XTtcbiAgfVxuXG4gIGNvbnN0IGxhc3RLZXkgPSBrZXlzW2tleXMubGVuZ3RoIC0gMV07XG4gIGN1cnJlbnRbbGFzdEtleV0gPSB2YWx1ZTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ2VudHJhbGl6ZWQgcnVudGltZSBtZXRhZGF0YSBzdG9yZSBib3VuZCB0byBjb25zdHJ1Y3RvcnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIHV0aWxpdGllcyB0byByZWFkIGFuZCB3cml0ZSBzdHJ1Y3R1cmVkIG1ldGFkYXRhIGZvciBjbGFzc2VzIGFuZCB0aGVpciBtZW1iZXJzLCB3aXRoIG9wdGlvbmFsIG1pcnJvcmluZyBvbnRvIHRoZSBjb25zdHJ1Y3RvciB2aWEgYSB3ZWxsLWtub3duIHN5bWJvbCBrZXkuIFN1cHBvcnRzIG5lc3RlZCBrZXkgcGF0aHMgdXNpbmcgYSBjb25maWd1cmFibGUgc3BsaXR0ZXIgYW5kIG9mZmVycyBib3RoIGluc3RhbmNlIGFuZCBzdGF0aWMgQVBJcy5cbiAqIEB0ZW1wbGF0ZSBNIFRoZSBtb2RlbCB0eXBlIHRoZSBtZXRhZGF0YSBiZWxvbmdzIHRvXG4gKiBAdGVtcGxhdGUgTUVUQSBFeHRlbmRzIEJhc2ljTWV0YWRhdGE8TT4gcmVwcmVzZW50aW5nIHRoZSBtZXRhZGF0YSBzdHJ1Y3R1cmVcbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIC8vIERlZmluZSBhbmQgcmVhZCBtZXRhZGF0YSBmb3IgYSBjbGFzc1xuICogY2xhc3MgVXNlciB7IG5hbWUhOiBzdHJpbmcgfVxuICogTWV0YWRhdGEuc2V0KFVzZXIsIFwiZGVzY3JpcHRpb24uY2xhc3NcIiwgXCJBIHVzZXIgbW9kZWxcIik7XG4gKiBNZXRhZGF0YS5zZXQoVXNlciwgXCJwcm9wZXJ0aWVzLm5hbWVcIiwgU3RyaW5nKTtcbiAqIGNvbnN0IGRlc2MgPSBNZXRhZGF0YS5nZXQoVXNlciwgXCJkZXNjcmlwdGlvbi5jbGFzc1wiKTsgLy8gXCJBIHVzZXIgbW9kZWxcIlxuICogY29uc3QgdHlwZSA9IE1ldGFkYXRhLnR5cGUoVXNlciwgXCJuYW1lXCIpOyAvLyBTdHJpbmdcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDb25zdHJ1Y3RvclxuICogICBwYXJ0aWNpcGFudCBTIGFzIE1ldGFkYXRhIChzdGF0aWMpXG4gKiAgIEMtPj5TOiBzZXQoVXNlciwgXCJwcm9wZXJ0aWVzLm5hbWVcIiwgU3RyaW5nKVxuICogICBDLT4+UzogZ2V0KFVzZXIsIFwicHJvcGVydGllcy5uYW1lXCIpXG4gKiAgIFMtLT4+QzogU3RyaW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW4tbWVtb3J5IHN0b3JhZ2Ugb2YgbWV0YWRhdGEgYnkgY29uc3RydWN0b3Igc3ltYm9sXG4gICAqIEBzdW1tYXJ5IE1hcHMgYSBTeW1ib2wgZGVyaXZlZCBmcm9tIHRoZSBjb25zdHJ1Y3RvciB0byBpdHMgbWV0YWRhdGEgb2JqZWN0LCBlbmFibGluZyBlZmZpY2llbnQgbG9va3VwLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgX21ldGFkYXRhOiBSZWNvcmQ8c3ltYm9sLCBhbnk+ID0ge307XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXRoIGRlbGltaXRlciBmb3IgbmVzdGVkIG1ldGFkYXRhIGtleXNcbiAgICogQHN1bW1hcnkgVXNlZCBieSBnZXQvc2V0IG9wZXJhdGlvbnMgdG8gbmF2aWdhdGUgbmVzdGVkIHN0cnVjdHVyZXMsIGRlZmF1bHRzIHRvIE9iamVjdEtleVNwbGl0dGVyLlxuICAgKi9cbiAgc3RhdGljIHNwbGl0dGVyID0gT2JqZWN0S2V5U3BsaXR0ZXI7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3ltYm9sIGtleSB1c2VkIHRvIG1pcnJvciBtZXRhZGF0YSBvbiB0aGUgY29uc3RydWN0b3JcbiAgICogQHN1bW1hcnkgV2hlbiBtaXJyb3JpbmcgaXMgZW5hYmxlZCwgdGhlIG1ldGFkYXRhIG9iamVjdCBpcyBkZWZpbmVkIG9uIHRoZSBjb25zdHJ1Y3RvciB1bmRlciB0aGlzIG5vbi1lbnVtZXJhYmxlIGtleS5cbiAgICovXG4gIHN0YXRpYyBiYXNlS2V5ID0gRGVjb3JhdGlvbktleXMuUkVGTEVDVDtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb250cm9scyB3aGV0aGVyIG1ldGFkYXRhIGlzIG1pcnJvcmVkIG9udG8gdGhlIGNvbnN0cnVjdG9yXG4gICAqIEBzdW1tYXJ5IFdoZW4gdHJ1ZSwgdGhlIG1ldGFkYXRhIG9iamVjdCBpcyBkZWZpbmVkIG9uIHRoZSBjb25zdHJ1Y3RvciB1bmRlciB0aGUgbm9uLWVudW1lcmFibGUgYmFzZUtleS5cbiAgICovXG4gIHN0YXRpYyBtaXJyb3I6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGlzdHMga25vd24gcHJvcGVydHkga2V5cyBmb3IgYSBtb2RlbFxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgYW5kIHJldHVybnMgdGhlIG5hbWVzIG9mIHByb3BlcnRpZXMgdGhhdCBoYXZlIHJlY29yZGVkIHR5cGUgaW5mb3JtYXRpb24uXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3JcbiAgICogQHJldHVybiB7c3RyaW5nW118dW5kZWZpbmVkfSBBcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBvciB1bmRlZmluZWQgaWYgbm8gbWV0YWRhdGEgZXhpc3RzXG4gICAqL1xuICBzdGF0aWMgcHJvcGVydGllcyhtb2RlbDogQ29uc3RydWN0b3IpOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuZ2V0KG1vZGVsKTtcbiAgICBpZiAoIW1ldGEpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG1ldGEucHJvcGVydGllcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExpc3RzIGtub3duIG1ldGhvZHMgZm9yIGEgbW9kZWxcbiAgICogQHN1bW1hcnkgUmVhZHMgdGhlIG1ldGFkYXRhIGVudHJ5IGFuZCByZXR1cm5zIHRoZSBtZXRob2QgbmFtZXMgdGhhdCBoYXZlIHJlY29yZGVkIHNpZ25hdHVyZSBtZXRhZGF0YSBmb3IgdGhlIHByb3ZpZGVkIGNvbnN0cnVjdG9yLlxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yfSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yXG4gICAqIEByZXR1cm4ge3N0cmluZ1tdfHVuZGVmaW5lZH0gQXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgb3IgdW5kZWZpbmVkIGlmIG5vIG1ldGFkYXRhIGV4aXN0c1xuICAgKi9cbiAgc3RhdGljIG1ldGhvZHMobW9kZWw6IENvbnN0cnVjdG9yKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmdldChtb2RlbCwgRGVjb3JhdGlvbktleXMuTUVUSE9EUyk7XG4gICAgaWYgKCFtZXRhKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhtZXRhKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgaHVtYW4tcmVhZGFibGUgZGVzY3JpcHRpb24gZm9yIGEgY2xhc3Mgb3IgYSBwcm9wZXJ0eVxuICAgKiBAc3VtbWFyeSBMb29rcyB1cCB0aGUgZGVzY3JpcHRpb24gc3RvcmVkIHVuZGVyIHRoZSBtZXRhZGF0YSBcImRlc2NyaXB0aW9uXCIgbWFwLiBJZiBhIHByb3BlcnR5IGtleSBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgcHJvcGVydHkncyBkZXNjcmlwdGlvbjsgb3RoZXJ3aXNlIHJldHVybnMgdGhlIGNsYXNzIGRlc2NyaXB0aW9uLlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yIHdob3NlIGRlc2NyaXB0aW9uIGlzIGJlaW5nIHJldHJpZXZlZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3Byb3BdIE9wdGlvbmFsIHByb3BlcnR5IGtleSBmb3Igd2hpY2ggdG8gZmV0Y2ggdGhlIGRlc2NyaXB0aW9uXG4gICAqIEByZXR1cm4ge3N0cmluZ3x1bmRlZmluZWR9IFRoZSBkZXNjcmlwdGlvbiB0ZXh0IGlmIHByZXNlbnQsIG90aGVyd2lzZSB1bmRlZmluZWRcbiAgICovXG4gIHN0YXRpYyBkZXNjcmlwdGlvbjxNPihcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgcHJvcD86IGtleW9mIE1cbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoXG4gICAgICBtb2RlbCxcbiAgICAgIFtEZWNvcmF0aW9uS2V5cy5ERVNDUklQVElPTiwgcHJvcCA/IHByb3AgOiBEZWNvcmF0aW9uS2V5cy5DTEFTU10uam9pbihcbiAgICAgICAgdGhpcy5zcGxpdHRlclxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcmVjb3JkZWQgcGFyYW1zIGZvciBhIG1ldGhvZFxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgdW5kZXIgXCJtZXRob2RzLjxwcm9wPi5kZXNpZ246cGFyYW1zXCIgdG8gcmV0dXJuIHRoZSBhcmd1bWVudHMgZm9yIHRoZSBpdmVuIG1ldGhvZC5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBUaGUgbWV0aG9kIG5hbWVcbiAgICogQHJldHVybiB7YW55W10gfCB1bmRlZmluZWR9IFRoZSBhcmd1bWVudCB0eXBlcyBvZiB0aGUgbWV0aG9kIG9yIHVuZGVmaW5lZCBpZiBub3QgYXZhaWxhYmxlXG4gICAqL1xuICBzdGF0aWMgcGFyYW1zPE0+KG1vZGVsOiBDb25zdHJ1Y3RvcjxNPiwgcHJvcDogc3RyaW5nKTogYW55W10gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLk1FVEhPRFMsIHByb3AsIERlY29yYXRpb25LZXlzLkRFU0lHTl9QQVJBTVNdLmpvaW4oXG4gICAgICAgIHRoaXMuc3BsaXR0ZXJcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHJlY29yZGVkIHJldHVybiB0eXBlIGZvciBhIG1ldGhvZFxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgdW5kZXIgXCJtZXRob2RzLjxwcm9wPi5kZXNpZ246cmV0dXJuXCIgdG8gcmV0dXJuIHRoZSByZXR1cm4gdHlwZSBmb3IgdGhlIGdpdmVuIG1ldGhvZC5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBUaGUgbWV0aG9kIG5hbWVcbiAgICogQHJldHVybiB7YW55fHVuZGVmaW5lZH0gVGhlIHJldHVybiB0eXBlIG9mIHRoZSBtZXRob2Qgb3IgdW5kZWZpbmVkIGlmIG5vdCBhdmFpbGFibGVcbiAgICovXG4gIHN0YXRpYyByZXR1cm48TT4obW9kZWw6IENvbnN0cnVjdG9yPE0+LCBwcm9wOiBzdHJpbmcpOiBhbnkgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLk1FVEhPRFMsIHByb3AsIERlY29yYXRpb25LZXlzLkRFU0lHTl9SRVRVUk5dLmpvaW4oXG4gICAgICAgIHRoaXMuc3BsaXR0ZXJcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHJlY29yZGVkIGRlc2lnbiB0eXBlIGZvciBhIHByb3BlcnR5XG4gICAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBtZXRhZGF0YSBlbnRyeSB1bmRlciBcInByb3BlcnRpZXMuPHByb3A+XCIgdG8gcmV0dXJuIHRoZSBjb25zdHJ1Y3RvciByZWNvcmRlZCBmb3IgdGhlIGdpdmVuIHByb3BlcnR5IG5hbWUuXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3AgVGhlIHByb3BlcnR5IG5hbWUgd2hvc2UgdHlwZSBzaG91bGQgYmUgcmV0dXJuZWRcbiAgICogQHJldHVybiB7Q29uc3RydWN0b3J8dW5kZWZpbmVkfSBUaGUgY29uc3RydWN0b3IgcmVmZXJlbmNlIG9mIHRoZSBwcm9wZXJ0eSB0eXBlIG9yIHVuZGVmaW5lZCBpZiBub3QgYXZhaWxhYmxlXG4gICAqL1xuICBzdGF0aWMgdHlwZShtb2RlbDogQ29uc3RydWN0b3IsIHByb3A6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLlBST1BFUlRJRVMsIHByb3BdLmpvaW4odGhpcy5zcGxpdHRlcilcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXNvbHZlcyB0aGUgY2Fub25pY2FsIGNvbnN0cnVjdG9yIGFzc29jaWF0ZWQgd2l0aCB0aGUgcHJvdmlkZWQgbW9kZWwgaGFuZGxlXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIHN0b3JlZCBjb25zdHJ1Y3RvciByZWZlcmVuY2Ugd2hlbiB0aGUgcHJvdmlkZWQgbW9kZWwgaXMgYSBwcm94eSBvciByZWR1Y2VkIHZhbHVlLiBGYWxscyBiYWNrIHRvIHRoZVxuICAgKiBvcmlnaW5hbCBtb2RlbCB3aGVuIG5vIGNvbnN0cnVjdG9yIG1ldGFkYXRhIGhhcyBiZWVuIHJlY29yZGVkIHlldC5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIG1vZGVsIHVzZWQgd2hlbiByZWNvcmRpbmcgbWV0YWRhdGFcbiAgICogQHJldHVybiB7Q29uc3RydWN0b3I8TT4gfCB1bmRlZmluZWR9IFRoZSBjYW5vbmljYWwgY29uc3RydWN0b3IgaWYgc3RvcmVkLCBvdGhlcndpc2UgdW5kZWZpbmVkXG4gICAqL1xuICBzdGF0aWMgY29uc3RyPE0+KG1vZGVsOiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIHJldHVybiB0aGlzLmdldChtb2RlbCwgRGVjb3JhdGlvbktleXMuQ09OU1RSVUNUT1IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0XG4gICAqIEBzdW1tYXJ5IFdoZW4gY2FsbGVkIHdpdGggYSBjb25zdHJ1Y3RvciBvbmx5LCByZXR1cm5zIHRoZSBlbnRpcmUgbWV0YWRhdGEgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgbW9kZWwuIFdoZW4gYSBrZXkgcGF0aCBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgdmFsdWUgc3RvcmVkIGF0IHRoYXQgbmVzdGVkIGtleS5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHRlbXBsYXRlIE1FVEFcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkXG4gICAqIEByZXR1cm4ge01FVEF8dW5kZWZpbmVkfSBUaGUgbWV0YWRhdGEgb2JqZWN0LCB0aGUgdmFsdWUgYXQgdGhlIGtleSBwYXRoLCBvciB1bmRlZmluZWQgaWYgbm90aGluZyBleGlzdHNcbiAgICovXG4gIHN0YXRpYyBnZXQ8TSwgTUVUQSBleHRlbmRzIEJhc2ljTWV0YWRhdGE8TT4gPSBCYXNpY01ldGFkYXRhPE0+PihcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT5cbiAgKTogTUVUQSB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0XG4gICAqIEBzdW1tYXJ5IFdoZW4gY2FsbGVkIHdpdGggYSBjb25zdHJ1Y3RvciBvbmx5LCByZXR1cm5zIHRoZSBlbnRpcmUgbWV0YWRhdGEgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgbW9kZWwuIFdoZW4gYSBrZXkgcGF0aCBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgdmFsdWUgc3RvcmVkIGF0IHRoYXQgbmVzdGVkIGtleS5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHRlbXBsYXRlIE1FVEFcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgbmVzdGVkIGtleSBwYXRoIHRvIGZldGNoIGEgc3BlY2lmaWMgdmFsdWVcbiAgICogQHJldHVybiB7TUVUQXwqfHVuZGVmaW5lZH0gVGhlIG1ldGFkYXRhIG9iamVjdCwgdGhlIHZhbHVlIGF0IHRoZSBrZXkgcGF0aCwgb3IgdW5kZWZpbmVkIGlmIG5vdGhpbmcgZXhpc3RzXG4gICAqL1xuICBzdGF0aWMgZ2V0KG1vZGVsOiBDb25zdHJ1Y3Rvciwga2V5OiBzdHJpbmcpOiBhbnk7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG1ldGFkYXRhIGZvciBhIG1vZGVsIG9yIGEgc3BlY2lmaWMga2V5IHdpdGhpbiBpdFxuICAgKiBAc3VtbWFyeSBXaGVuIGNhbGxlZCB3aXRoIGEgY29uc3RydWN0b3Igb25seSwgcmV0dXJucyB0aGUgZW50aXJlIG1ldGFkYXRhIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIG1vZGVsLiBXaGVuIGEga2V5IHBhdGggaXMgcHJvdmlkZWQsIHJldHVybnMgdGhlIHZhbHVlIHN0b3JlZCBhdCB0aGF0IG5lc3RlZCBrZXkuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEB0ZW1wbGF0ZSBNRVRBXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT4gfCBzdHJpbmd9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3IgdXNlZCB0byBsb2NhdGUgdGhlIG1ldGFkYXRhIHJlY29yZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2tleV0gT3B0aW9uYWwgbmVzdGVkIGtleSBwYXRoIHRvIGZldGNoIGEgc3BlY2lmaWMgdmFsdWVcbiAgICogQHJldHVybiB7TUVUQXwqfHVuZGVmaW5lZH0gVGhlIG1ldGFkYXRhIG9iamVjdCwgdGhlIHZhbHVlIGF0IHRoZSBrZXkgcGF0aCwgb3IgdW5kZWZpbmVkIGlmIG5vdGhpbmcgZXhpc3RzXG4gICAqL1xuICBzdGF0aWMgZ2V0KG1vZGVsOiBDb25zdHJ1Y3Rvciwga2V5Pzogc3RyaW5nKSB7XG4gICAgaWYgKGtleSAhPT0gRGVjb3JhdGlvbktleXMuQ09OU1RSVUNUT1IpIG1vZGVsID0gdGhpcy5jb25zdHIobW9kZWwpIHx8IG1vZGVsO1xuICAgIGNvbnN0IHN5bWJvbCA9IFN5bWJvbC5mb3IobW9kZWwudG9TdHJpbmcoKSk7XG4gICAgcmV0dXJuIHRoaXMuaW5uZXJHZXQoc3ltYm9sLCBrZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaW5uZXJHZXQoc3ltYm9sOiBzeW1ib2wsIGtleT86IHN0cmluZykge1xuICAgIGlmICghdGhpcy5fbWV0YWRhdGFbc3ltYm9sXSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoIWtleSkgcmV0dXJuIHRoaXMuX21ldGFkYXRhW3N5bWJvbF07XG4gICAgcmV0dXJuIGdldFZhbHVlQnlTcGxpdHRlcih0aGlzLl9tZXRhZGF0YVtzeW1ib2xdLCBrZXksIHRoaXMuc3BsaXR0ZXIpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaW5uZXJTZXQoc3ltYm9sOiBzeW1ib2wsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gICAgaWYgKCF0aGlzLl9tZXRhZGF0YVtzeW1ib2xdKSB0aGlzLl9tZXRhZGF0YVtzeW1ib2xdID0ge30gYXMgYW55O1xuICAgIHNldFZhbHVlQnlTcGxpdHRlcih0aGlzLl9tZXRhZGF0YVtzeW1ib2xdLCBrZXksIHZhbHVlLCB0aGlzLnNwbGl0dGVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV3JpdGVzIGEgbWV0YWRhdGEgdmFsdWUgYXQgYSBnaXZlbiBuZXN0ZWQga2V5IHBhdGhcbiAgICogQHN1bW1hcnkgRW5zdXJlcyB0aGUgbWV0YWRhdGEgcmVjb3JkIGV4aXN0cyBmb3IgdGhlIGNvbnN0cnVjdG9yLCBtaXJyb3JzIGl0IG9uIHRoZSBjb25zdHJ1Y3RvciB3aGVuIGVuYWJsZWQsIGFuZCBzZXRzIHRoZSBwcm92aWRlZCB2YWx1ZSBvbiB0aGUgbmVzdGVkIGtleSBwYXRoIHVzaW5nIHRoZSBjb25maWd1cmVkIHNwbGl0dGVyLlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+IHwgc3RyaW5nfSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yIHRvIHdoaWNoIHRoZSBtZXRhZGF0YSBiZWxvbmdzXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIG5lc3RlZCBrZXkgcGF0aCBhdCB3aGljaCB0byBzdG9yZSB0aGUgdmFsdWVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc3RvcmUgaW4gdGhlIG1ldGFkYXRhXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgc2V0KG1vZGVsOiBDb25zdHJ1Y3RvciB8IHN0cmluZywga2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIG1vZGVsICE9PSBcInN0cmluZ1wiKSBtb2RlbCA9IHRoaXMuY29uc3RyKG1vZGVsKSB8fCBtb2RlbDtcbiAgICBjb25zdCBzeW1ib2wgPSBTeW1ib2wuZm9yKG1vZGVsLnRvU3RyaW5nKCkpO1xuICAgIHRoaXMuaW5uZXJTZXQoc3ltYm9sLCBrZXksIHZhbHVlKTtcbiAgICBpZiAoXG4gICAgICBNZXRhZGF0YS5taXJyb3IgJiZcbiAgICAgICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kZWwsIHRoaXMuYmFzZUtleSlcbiAgICApIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2RlbCwgdGhpcy5iYXNlS2V5LCB7XG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIHZhbHVlOiB0aGlzLl9tZXRhZGF0YVtzeW1ib2xdLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlcnMgYSBkZWNvcmF0aW9uLWF3YXJlIGxpYnJhcnkgYW5kIGl0cyB2ZXJzaW9uXG4gICAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgdmVyc2lvbiBzdHJpbmcgZm9yIGFuIGludGVncmF0aW5nIGxpYnJhcnkgdW5kZXIgdGhlIHNoYXJlZCBsaWJyYXJpZXMgbWV0YWRhdGEgc3ltYm9sLCBwcmV2ZW50aW5nIGR1cGxpY2F0ZSByZWdpc3RyYXRpb25zIGZvciB0aGUgc2FtZSBsaWJyYXJ5IGlkZW50aWZpZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsaWJyYXJ5IFBhY2thZ2UgbmFtZSBvciBpZGVudGlmaWVyIHRvIHJlZ2lzdGVyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2ZXJzaW9uIFNlbWFudGljIHZlcnNpb24gc3RyaW5nIGFzc29jaWF0ZWQgd2l0aCB0aGUgbGlicmFyeVxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIGxpYnJhcnkgaGFzIGFscmVhZHkgYmVlbiByZWdpc3RlcmVkXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJMaWJyYXJ5KGxpYnJhcnk6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nKSB7XG4gICAgY29uc3Qgc3ltYm9sID0gU3ltYm9sLmZvcihEZWNvcmF0aW9uS2V5cy5MSUJSQVJJRVMpO1xuICAgIGNvbnN0IGxpYiA9IHRoaXMuaW5uZXJHZXQoc3ltYm9sLCBsaWJyYXJ5KTtcbiAgICBpZiAobGliKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTGlicmFyeSBhbHJlYWR5ICR7bGlicmFyeX0gcmVnaXN0ZXJlZCB3aXRoIHZlcnNpb24gJHt2ZXJzaW9ufWBcbiAgICAgICk7XG4gICAgdGhpcy5pbm5lclNldChzeW1ib2wsIGxpYnJhcnksIHZlcnNpb24pO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkLFxuICBEZWNvcmF0aW9uQnVpbGRlckVuZCxcbiAgRGVjb3JhdGlvbkJ1aWxkZXJNaWQsXG4gIERlY29yYXRpb25CdWlsZGVyU3RhcnQsXG4gIEZsYXZvdXJSZXNvbHZlcixcbiAgSURlY29yYXRpb25CdWlsZGVyLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgRGVmYXVsdEZsYXZvdXIgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgcmVzb2x2ZXIgdGhhdCByZXR1cm5zIHRoZSBjdXJyZW50IGRlZmF1bHQgZmxhdm91clxuICogQHN1bW1hcnkgUmVzb2x2ZXMgdGhlIGZsYXZvdXIgZm9yIGEgZ2l2ZW4gdGFyZ2V0IGJ5IGFsd2F5cyByZXR1cm5pbmcgdGhlIGxpYnJhcnkncyBEZWZhdWx0Rmxhdm91ciB2YWx1ZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSB0YXJnZXQgVGhlIHRhcmdldCBvYmplY3QgYmVpbmcgZGVjb3JhdGVkXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSByZXNvbHZlZCBmbGF2b3VyIGlkZW50aWZpZXJcbiAqIEBmdW5jdGlvbiBkZWZhdWx0Rmxhdm91clJlc29sdmVyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuZnVuY3Rpb24gZGVmYXVsdEZsYXZvdXJSZXNvbHZlcih0YXJnZXQ6IG9iamVjdCkge1xuICByZXR1cm4gRGVmYXVsdEZsYXZvdXI7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFVuaW9uIHR5cGUgY292ZXJpbmcgc3VwcG9ydGVkIGRlY29yYXRvciBraW5kc1xuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbnkgb2YgdGhlIHN0YW5kYXJkIFR5cGVTY3JpcHQgZGVjb3JhdG9yIHNpZ25hdHVyZXMgKGNsYXNzLCBwcm9wZXJ0eSwgb3IgbWV0aG9kKSwgZW5hYmxpbmcgZmxleGlibGUgcmVnaXN0cmF0aW9uIGFuZCBhcHBsaWNhdGlvbiB3aXRoaW4gdGhlIERlY29yYXRpb24gc3lzdGVtLlxuICogQHRlbXBsYXRlIFRcbiAqIEB0eXBlRGVmIERlY29yYXRvclR5cGVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IHR5cGUgRGVjb3JhdG9yVHlwZXMgPVxuICB8IENsYXNzRGVjb3JhdG9yXG4gIHwgUHJvcGVydHlEZWNvcmF0b3JcbiAgfCBNZXRob2REZWNvcmF0b3I7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFR5cGUgZGVmaW5pdGlvbiBmb3IgYSBkZWNvcmF0b3IgZmFjdG9yeSBmdW5jdGlvblxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZ1bmN0aW9uIHRoYXQgYWNjZXB0cyBhcmJpdHJhcnkgYXJndW1lbnRzIGFuZCByZXR1cm5zIGEgY29uY3JldGUgZGVjb3JhdG9yIGZ1bmN0aW9uIHRvIGJlIGFwcGxpZWQgdG8gYSB0YXJnZXQuXG4gKiBAdGVtcGxhdGUgQVxuICogQHR5cGVEZWYgRGVjb3JhdG9yRmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckZhY3RvcnkgPSAoLi4uYXJnczogYW55W10pID0+IERlY29yYXRvclR5cGVzO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBcmd1bWVudCBidW5kbGUgZm9yIGEgZGVjb3JhdG9yIGZhY3RvcnlcbiAqIEBzdW1tYXJ5IE9iamVjdCBmb3JtIHVzZWQgdG8gZGVmZXIgZGVjb3JhdG9yIGNyZWF0aW9uLCBjYXJyeWluZyBib3RoIHRoZSBmYWN0b3J5IGZ1bmN0aW9uIGFuZCBpdHMgYXJndW1lbnQgbGlzdCB0byBiZSBpbnZva2VkIGxhdGVyIGR1cmluZyBhcHBsaWNhdGlvbi5cbiAqIEB0eXBlRGVmIERlY29yYXRvckZhY3RvcnlBcmdzXG4gKiBAcHJvcGVydHkge0RlY29yYXRvckZhY3Rvcnl9IGRlY29yYXRvciBUaGUgZmFjdG9yeSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGEgZGVjb3JhdG9yIHdoZW4gaW52b2tlZFxuICogQHByb3BlcnR5IHthbnlbXX0gYXJncyBsaXN0IG9mIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBkZWNvcmF0b3IgZmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckZhY3RvcnlBcmdzID0ge1xuICBkZWNvcmF0b3I6IERlY29yYXRvckZhY3Rvcnk7XG4gIGFyZ3M6IGFueVtdO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVW5pb24gdGhhdCByZXByZXNlbnRzIGVpdGhlciBhIHJlYWR5LXRvLWFwcGx5IGRlY29yYXRvciBvciBhIGZhY3Rvcnkgd2l0aCBhcmd1bWVudHNcbiAqIEBzdW1tYXJ5IEFsbG93cyByZWdpc3RlcmluZyBkZWNvcmF0b3JzIGluIHR3byBmb3JtczogYXMgZGlyZWN0IGRlY29yYXRvciBmdW5jdGlvbnMgb3IgYXMgZGVmZXJyZWQgZmFjdG9yaWVzIHBhaXJlZCB3aXRoIHRoZWlyIGFyZ3VtZW50IGxpc3RzIGZvciBsYXRlciBpbnN0YW50aWF0aW9uLlxuICogQHR5cGVEZWYgRGVjb3JhdG9yRGF0YVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckRhdGEgPSBEZWNvcmF0b3JUeXBlcyB8IERlY29yYXRvckZhY3RvcnlBcmdzO1xuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBkZWNvcmF0b3IgbWFuYWdlbWVudCBjbGFzcyB0aGF0IGhhbmRsZXMgZmxhdm91cmVkIGRlY29yYXRvcnNcbiAqIEBzdW1tYXJ5IFRoZSBEZWNvcmF0aW9uIGNsYXNzIHByb3ZpZGVzIGEgYnVpbGRlciBwYXR0ZXJuIGZvciBjcmVhdGluZyBhbmQgbWFuYWdpbmcgZGVjb3JhdG9ycyB3aXRoIGRpZmZlcmVudCBmbGF2b3Vycy5cbiAqIEl0IHN1cHBvcnRzIHJlZ2lzdGVyaW5nLCBleHRlbmRpbmcsIGFuZCBhcHBseWluZyBkZWNvcmF0b3JzIHdpdGggY29udGV4dC1hd2FyZSBmbGF2b3VyIHJlc29sdXRpb24uXG4gKiBUaGUgY2xhc3MgaW1wbGVtZW50cyBhIGZsdWVudCBpbnRlcmZhY2UgZm9yIGRlZmluaW5nLCBleHRlbmRpbmcsIGFuZCBhcHBseWluZyBkZWNvcmF0b3JzIHdpdGggZGlmZmVyZW50IGZsYXZvdXJzLFxuICogYWxsb3dpbmcgZm9yIGZyYW1ld29yay1zcGVjaWZpYyBkZWNvcmF0b3IgaW1wbGVtZW50YXRpb25zIHdoaWxlIG1haW50YWluaW5nIGEgY29uc2lzdGVudCBBUEkuXG4gKiBAdGVtcGxhdGUgVCBUeXBlIG9mIHRoZSBkZWNvcmF0b3IgKENsYXNzRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IpXG4gKiBAcGFyYW0ge3N0cmluZ30gW2ZsYXZvdXJdIE9wdGlvbmFsIGZsYXZvdXIgcGFyYW1ldGVyIGZvciB0aGUgZGVjb3JhdG9yIGNvbnRleHRcbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIENyZWF0ZSBhIG5ldyBkZWNvcmF0aW9uIGZvciAnY29tcG9uZW50JyB3aXRoIGRlZmF1bHQgZmxhdm91clxuICogY29uc3QgY29tcG9uZW50RGVjb3JhdG9yID0gbmV3IERlY29yYXRpb24oKVxuICogICAuZm9yKCdjb21wb25lbnQnKVxuICogICAuZGVmaW5lKGN1c3RvbUNvbXBvbmVudERlY29yYXRvcik7XG4gKlxuICogLy8gQ3JlYXRlIGEgZmxhdm91cmVkIGRlY29yYXRpb25cbiAqIGNvbnN0IHZ1ZUNvbXBvbmVudCA9IG5ldyBEZWNvcmF0aW9uKCd2dWUnKVxuICogICAuZm9yKCdjb21wb25lbnQnKVxuICogICAuZGVmaW5lKHZ1ZUNvbXBvbmVudERlY29yYXRvcik7XG4gKlxuICogLy8gQXBwbHkgdGhlIGRlY29yYXRpb25cbiAqIEBjb21wb25lbnREZWNvcmF0b3JcbiAqIGNsYXNzIE15Q29tcG9uZW50IHt9XG4gKiBgYGBcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgRCBhcyBEZWNvcmF0aW9uXG4gKiAgIHBhcnRpY2lwYW50IFIgYXMgRmxhdm91clJlc29sdmVyXG4gKiAgIHBhcnRpY2lwYW50IEYgYXMgRGVjb3JhdG9yRmFjdG9yeVxuICpcbiAqICAgQy0+PkQ6IG5ldyBEZWNvcmF0aW9uKGZsYXZvdXIpXG4gKiAgIEMtPj5EOiBmb3Ioa2V5KVxuICogICBDLT4+RDogZGVmaW5lKGRlY29yYXRvcnMpXG4gKiAgIEQtPj5EOiByZWdpc3RlcihrZXksIGZsYXZvdXIsIGRlY29yYXRvcnMpXG4gKiAgIEQtPj5GOiBkZWNvcmF0b3JGYWN0b3J5KGtleSwgZmxhdm91cilcbiAqICAgRi0+PlI6IHJlc29sdmUodGFyZ2V0KVxuICogICBSLS0+PkY6IHJlc29sdmVkIGZsYXZvdXJcbiAqICAgRi0+PkY6IGFwcGx5IGRlY29yYXRvcnNcbiAqICAgRi0tPj5DOiBkZWNvcmF0ZWQgdGFyZ2V0XG4gKi9cbmV4cG9ydCBjbGFzcyBEZWNvcmF0aW9uIGltcGxlbWVudHMgSURlY29yYXRpb25CdWlsZGVyIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTdGF0aWMgbWFwIG9mIHJlZ2lzdGVyZWQgZGVjb3JhdG9yc1xuICAgKiBAc3VtbWFyeSBTdG9yZXMgYWxsIHJlZ2lzdGVyZWQgZGVjb3JhdG9ycyBvcmdhbml6ZWQgYnkga2V5IGFuZCBmbGF2b3VyXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBkZWNvcmF0b3JzOiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIFJlY29yZDxcbiAgICAgIHN0cmluZyxcbiAgICAgIHtcbiAgICAgICAgZGVjb3JhdG9ycz86IFNldDxEZWNvcmF0b3JEYXRhPjtcbiAgICAgICAgZXh0cmFzPzogU2V0PERlY29yYXRvckRhdGE+O1xuICAgICAgfVxuICAgID5cbiAgPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRnVuY3Rpb24gdG8gcmVzb2x2ZSBmbGF2b3VyIGZyb20gYSB0YXJnZXRcbiAgICogQHN1bW1hcnkgUmVzb2x2ZXIgZnVuY3Rpb24gdGhhdCBkZXRlcm1pbmVzIHRoZSBhcHByb3ByaWF0ZSBmbGF2b3VyIGZvciBhIGdpdmVuIHRhcmdldFxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZmxhdm91clJlc29sdmVyOiBGbGF2b3VyUmVzb2x2ZXIgPSBkZWZhdWx0Rmxhdm91clJlc29sdmVyO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0IG9mIGRlY29yYXRvcnMgZm9yIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICovXG4gIHByaXZhdGUgZGVjb3JhdG9ycz86IFNldDxEZWNvcmF0b3JEYXRhPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldCBvZiBhZGRpdGlvbmFsIGRlY29yYXRvcnNcbiAgICovXG4gIHByaXZhdGUgZXh0cmFzPzogU2V0PERlY29yYXRvckRhdGE+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3VycmVudCBkZWNvcmF0b3Iga2V5XG4gICAqL1xuICBwcml2YXRlIGtleT86IHN0cmluZztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZsYXZvdXI6IHN0cmluZyA9IERlZmF1bHRGbGF2b3VyKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUga2V5IGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgbmV3IGRlY29yYXRpb24gY2hhaW4gd2l0aCB0aGUgc3BlY2lmaWVkIGtleVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBpZGVudGlmaWVyIGZvciB0aGUgZGVjb3JhdG9yXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyTWlkfSBCdWlsZGVyIGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmdcbiAgICovXG4gIGZvcihrZXk6IHN0cmluZyk6IERlY29yYXRpb25CdWlsZGVyTWlkIHtcbiAgICB0aGlzLmtleSA9IGtleTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWRkcyBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHN1bW1hcnkgSW50ZXJuYWwgbWV0aG9kIHRvIGFkZCBkZWNvcmF0b3JzIHdpdGggYWRkb24gc3VwcG9ydFxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFthZGRvbj1mYWxzZV0gV2hldGhlciB0aGUgZGVjb3JhdG9ycyBhcmUgYWRkb25zXG4gICAqIEBwYXJhbSBkZWNvcmF0b3JzIEFycmF5IG9mIGRlY29yYXRvcnNcbiAgICogQHJldHVybiB7dGhpc30gQ3VycmVudCBpbnN0YW5jZSBmb3IgY2hhaW5pbmdcbiAgICovXG4gIHByaXZhdGUgZGVjb3JhdGUoXG4gICAgYWRkb246IGJvb2xlYW4gPSBmYWxzZSxcbiAgICAuLi5kZWNvcmF0b3JzOiBEZWNvcmF0b3JEYXRhW11cbiAgKTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLmtleSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImtleSBtdXN0IGJlIHByb3ZpZGVkIGJlZm9yZSBkZWNvcmF0b3JzIGNhbiBiZSBhZGRlZFwiKTtcbiAgICBpZiAoXG4gICAgICAoIWRlY29yYXRvcnMgfHwgIWRlY29yYXRvcnMubGVuZ3RoKSAmJlxuICAgICAgIWFkZG9uICYmXG4gICAgICB0aGlzLmZsYXZvdXIgIT09IERlZmF1bHRGbGF2b3VyXG4gICAgKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIk11c3QgcHJvdmlkZSBvdmVycmlkZXMgb3IgYWRkb25zIHRvIG92ZXJyaWRlIG9yIGV4dGVuZCBkZWNhZidzIGRlY29yYXRvcnNcIlxuICAgICAgKTtcbiAgICBpZiAodGhpcy5mbGF2b3VyID09PSBEZWZhdWx0Rmxhdm91ciAmJiBhZGRvbilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkRlZmF1bHQgZmxhdm91ciBjYW5ub3QgYmUgZXh0ZW5kZWRcIik7XG5cbiAgICB0aGlzW2FkZG9uID8gXCJleHRyYXNcIiA6IFwiZGVjb3JhdG9yc1wiXSA9IG5ldyBTZXQoW1xuICAgICAgLi4uKHRoaXNbYWRkb24gPyBcImV4dHJhc1wiIDogXCJkZWNvcmF0b3JzXCJdIHx8IG5ldyBTZXQoKSkudmFsdWVzKCksXG4gICAgICAuLi5kZWNvcmF0b3JzLFxuICAgIF0pO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgdGhlIGJhc2UgZGVjb3JhdG9yc1xuICAgKiBAc3VtbWFyeSBTZXRzIHRoZSBwcmltYXJ5IGRlY29yYXRvcnMgZm9yIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHBhcmFtIGRlY29yYXRvcnMgRGVjb3JhdG9ycyB0byBkZWZpbmVcbiAgICogQHJldHVybiBCdWlsZGVyIGluc3RhbmNlIGZvciBmaW5pc2hpbmcgdGhlIGNoYWluXG4gICAqL1xuICBkZWZpbmUoXG4gICAgLi4uZGVjb3JhdG9yczogRGVjb3JhdG9yRGF0YVtdXG4gICk6IERlY29yYXRpb25CdWlsZGVyRW5kICYgRGVjb3JhdGlvbkJ1aWxkZXJCdWlsZCB7XG4gICAgaWYgKFxuICAgICAgZGVjb3JhdG9ycy5maW5kKChkKSA9PiB0eXBlb2YgZCA9PT0gXCJvYmplY3RcIikgJiZcbiAgICAgIGRlY29yYXRvcnMubGVuZ3RoICE9PSAxXG4gICAgKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgV2hlbiB1c2luZyBhbiBvdmVycmlkYWJsZSBkZWNvcmF0b3IsIG9ubHkgb25lIGlzIGFsbG93ZWRgXG4gICAgICApO1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKGZhbHNlLCAuLi5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXh0ZW5kcyBleGlzdGluZyBkZWNvcmF0b3JzXG4gICAqIEBzdW1tYXJ5IEFkZHMgYWRkaXRpb25hbCBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHBhcmFtIGRlY29yYXRvcnMgQWRkaXRpb25hbCBkZWNvcmF0b3JzXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyQnVpbGR9IEJ1aWxkZXIgaW5zdGFuY2UgZm9yIGJ1aWxkaW5nIHRoZSBkZWNvcmF0b3JcbiAgICovXG4gIGV4dGVuZCguLi5kZWNvcmF0b3JzOiBEZWNvcmF0b3JEYXRhW10pOiBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkIHtcbiAgICBpZiAoXG4gICAgICBkZWNvcmF0b3JzLmZpbmQoKGQpID0+IHR5cGVvZiBkID09PSBcIm9iamVjdFwiKSAmJlxuICAgICAgZGVjb3JhdG9ycy5sZW5ndGggIT09IDFcbiAgICApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBXaGVuIGV4dGVuZGluZyB1c2luZyBhbiBvdmVycmlkYWJsZSBkZWNvcmF0b3IsIG9ubHkgb25lIGlzIGFsbG93ZWRgXG4gICAgICApO1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKHRydWUsIC4uLmRlY29yYXRvcnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBGYWN0b3J5IHRoYXQgY3JlYXRlcyBhIGNvbnRleHQtYXdhcmUgZGVjb3JhdG9yIGZvciBhIGtleS9mbGF2b3VyXG4gICAqIEBzdW1tYXJ5IFByb2R1Y2VzIGEgZGVjb3JhdG9yIGZ1bmN0aW9uIGJvdW5kIHRvIHRoZSBwcm92aWRlZCBrZXkgYW5kIGZsYXZvdXIuIFRoZSByZXN1bHRpbmcgZGVjb3JhdG9yIHJlc29sdmVzIHRoZSBhY3R1YWxcbiAgICogZGVjb3JhdG9ycyB0byBhcHBseSBhdCBpbnZvY2F0aW9uIHRpbWUgYmFzZWQgb24gdGhlIHRhcmdldCdzIHJlc29sdmVkIGZsYXZvdXIgYW5kIHRoZSByZWdpc3RlcmVkIGJhc2UgYW5kIGV4dHJhIGRlY29yYXRvcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGRlY29yYXRpb24ga2V5IHVzZWQgdG8gbG9vayB1cCByZWdpc3RlcmVkIGRlY29yYXRvcnNcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtmPURlZmF1bHRGbGF2b3VyXSBPcHRpb25hbCBleHBsaWNpdCBmbGF2b3VyIHRvIGJpbmQgdGhlIGZhY3RvcnkgdG9cbiAgICogQHJldHVybiB7ZnVuY3Rpb24ob2JqZWN0LCBhbnksIFR5cGVkUHJvcGVydHlEZXNjcmlwdG9yPGFueT4pOiBhbnl9IEEgZGVjb3JhdG9yIGZ1bmN0aW9uIHRoYXQgYXBwbGllcyB0aGUgcmVzb2x2ZWQgZGVjb3JhdG9yc1xuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXIgQ29kZVxuICAgKiAgIHBhcnRpY2lwYW50IEIgYXMgRGVjb3JhdGlvbiAoYnVpbGRlcilcbiAgICogICBwYXJ0aWNpcGFudCBGIGFzIGRlY29yYXRvckZhY3Rvcnkoa2V5LCBmKVxuICAgKiAgIHBhcnRpY2lwYW50IFIgYXMgZmxhdm91clJlc29sdmVyXG4gICAqICAgcGFydGljaXBhbnQgQSBhcyBBcHBsaWVkIERlY29yYXRvcnNcbiAgICogICBVLT4+QjogZGVmaW5lKCkvZXh0ZW5kKCkgYW5kIGFwcGx5KClcbiAgICogICBCLT4+RjogY3JlYXRlIGNvbnRleHQgZGVjb3JhdG9yXG4gICAqICAgRi0+PlI6IHJlc29sdmUodGFyZ2V0KVxuICAgKiAgIFItLT4+RjogZmxhdm91clxuICAgKiAgIEYtPj5BOiBjb2xsZWN0IGJhc2UgKyBleHRyYXNcbiAgICogICBsb29wIGVhY2ggZGVjb3JhdG9yXG4gICAqICAgICBBLT4+VTogaW52b2tlIGRlY29yYXRvcih0YXJnZXQsIGtleT8sIGRlc2M/KVxuICAgKiAgIGVuZFxuICAgKi9cbiAgcHJvdGVjdGVkIGRlY29yYXRvckZhY3Rvcnkoa2V5OiBzdHJpbmcsIGY6IHN0cmluZyA9IERlZmF1bHRGbGF2b3VyKSB7XG4gICAgZnVuY3Rpb24gY29udGV4dERlY29yYXRvcihcbiAgICAgIHRhcmdldDogb2JqZWN0LFxuICAgICAgcHJvcGVydHlLZXk/OiBhbnksXG4gICAgICBkZXNjcmlwdG9yPzogVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8YW55PlxuICAgICkge1xuICAgICAgY29uc3QgZmxhdm91ciA9IERlY29yYXRpb24uZmxhdm91clJlc29sdmVyKHRhcmdldCk7XG4gICAgICBjb25zdCBjYWNoZSA9IERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldO1xuICAgICAgbGV0IGRlY29yYXRvcnM7XG4gICAgICBjb25zdCBleHRyYXMgPSBjYWNoZVtmbGF2b3VyXVxuICAgICAgICA/IGNhY2hlW2ZsYXZvdXJdLmV4dHJhc1xuICAgICAgICA6IGNhY2hlW0RlZmF1bHRGbGF2b3VyXS5leHRyYXM7XG5cbiAgICAgIGlmIChcbiAgICAgICAgY2FjaGUgJiZcbiAgICAgICAgY2FjaGVbZmxhdm91cl0gJiZcbiAgICAgICAgY2FjaGVbZmxhdm91cl0uZGVjb3JhdG9ycyAmJlxuICAgICAgICBjYWNoZVtmbGF2b3VyXS5kZWNvcmF0b3JzLnNpemVcbiAgICAgICkge1xuICAgICAgICBkZWNvcmF0b3JzID0gY2FjaGVbZmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlY29yYXRvcnMgPSBjYWNoZVtEZWZhdWx0Rmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVjb3JhdG9yQXJncyA9IFtcbiAgICAgICAgLi4uKGNhY2hlW0RlZmF1bHRGbGF2b3VyXSBhcyBhbnkpLmRlY29yYXRvcnMudmFsdWVzKCksXG4gICAgICBdLnJlZHVjZSgoYWNjdW06IFJlY29yZDxudW1iZXIsIGFueT4sIGUsIGkpID0+IHtcbiAgICAgICAgaWYgKGUuYXJncykgYWNjdW1baV0gPSBlLmFyZ3M7XG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sIHt9KTtcblxuICAgICAgY29uc3QgdG9BcHBseSA9IFtcbiAgICAgICAgLi4uKGRlY29yYXRvcnMgPyBkZWNvcmF0b3JzLnZhbHVlcygpIDogW10pLFxuICAgICAgICAuLi4oZXh0cmFzID8gZXh0cmFzLnZhbHVlcygpIDogW10pLFxuICAgICAgXTtcblxuICAgICAgcmV0dXJuIHRvQXBwbHkucmVkdWNlKFxuICAgICAgICAoXywgZCkgPT4ge1xuICAgICAgICAgIHN3aXRjaCAodHlwZW9mIGQpIHtcbiAgICAgICAgICAgIGNhc2UgXCJvYmplY3RcIjoge1xuICAgICAgICAgICAgICBjb25zdCB7IGRlY29yYXRvciB9ID0gZCBhcyBEZWNvcmF0b3JGYWN0b3J5QXJncztcblxuICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIGRlY29yYXRvciguLi4oT2JqZWN0LnZhbHVlcyhkZWNvcmF0b3JBcmdzKVswXSB8fCBbXSkpIGFzIGFueVxuICAgICAgICAgICAgICApKHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgICAgICAgIHJldHVybiAoZCBhcyBhbnkpKHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIGRlY29yYXRvciB0eXBlOiAke3R5cGVvZiBkfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgeyB0YXJnZXQsIHByb3BlcnR5S2V5LCBkZXNjcmlwdG9yIH1cbiAgICAgICk7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb250ZXh0RGVjb3JhdG9yLCBcIm5hbWVcIiwge1xuICAgICAgdmFsdWU6IFtmLCBrZXldLmpvaW4oXCJfZGVjb3JhdG9yX2Zvcl9cIiksXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbnRleHREZWNvcmF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgdGhlIGZpbmFsIGRlY29yYXRvciBmdW5jdGlvblxuICAgKiBAc3VtbWFyeSBCdWlsZHMgYW5kIHJldHVybnMgdGhlIGRlY29yYXRvciBmYWN0b3J5IGZ1bmN0aW9uXG4gICAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55PywgVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I/KTogYW55fSBUaGUgZ2VuZXJhdGVkIGRlY29yYXRvciBmdW5jdGlvblxuICAgKi9cbiAgYXBwbHkoKTogKFxuICAgIHRhcmdldDogYW55LFxuICAgIHByb3BlcnR5S2V5PzogYW55LFxuICAgIGRlc2NyaXB0b3I/OiBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxhbnk+XG4gICkgPT4gYW55IHtcbiAgICBpZiAoIXRoaXMua2V5KVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIERlY29yYXRpb24ucmVnaXN0ZXIoXG4gICAgICB0aGlzLmtleSxcbiAgICAgIHRoaXMuZmxhdm91cixcbiAgICAgIHRoaXMuZGVjb3JhdG9ycyB8fCBuZXcgU2V0KCksXG4gICAgICB0aGlzLmV4dHJhc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuZGVjb3JhdG9yRmFjdG9yeSh0aGlzLmtleSwgdGhpcy5mbGF2b3VyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXJzIGRlY29yYXRvcnMgZm9yIGEgc3BlY2lmaWMga2V5IGFuZCBmbGF2b3VyXG4gICAqIEBzdW1tYXJ5IEludGVybmFsIG1ldGhvZCB0byBzdG9yZSBkZWNvcmF0b3JzIGluIHRoZSBzdGF0aWMgcmVnaXN0cnlcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBEZWNvcmF0b3Iga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIERlY29yYXRvciBmbGF2b3VyXG4gICAqIEBwYXJhbSBbZGVjb3JhdG9yc10gUHJpbWFyeSBkZWNvcmF0b3JzXG4gICAqIEBwYXJhbSBbZXh0cmFzXSBBZGRpdGlvbmFsIGRlY29yYXRvcnNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlZ2lzdGVyKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGZsYXZvdXI6IHN0cmluZyxcbiAgICBkZWNvcmF0b3JzPzogU2V0PERlY29yYXRvckRhdGE+LFxuICAgIGV4dHJhcz86IFNldDxEZWNvcmF0b3JEYXRhPlxuICApIHtcbiAgICBpZiAoIWtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIH1cbiAgICBpZiAoIWRlY29yYXRvcnMpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBkZWNvcmF0b3JzIHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIGlmICghZmxhdm91cilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGZsYXZvdXIgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG5cbiAgICBpZiAoIURlY29yYXRpb24uZGVjb3JhdG9yc1trZXldKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XSA9IHt9O1xuICAgIGlmICghRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV1bZmxhdm91cl0pXG4gICAgICBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXSA9IHt9O1xuICAgIGlmIChkZWNvcmF0b3JzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5kZWNvcmF0b3JzID0gZGVjb3JhdG9ycztcbiAgICBpZiAoZXh0cmFzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5leHRyYXMgPSBleHRyYXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGdsb2JhbCBmbGF2b3VyIHJlc29sdmVyXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGZ1bmN0aW9uIHVzZWQgdG8gZGV0ZXJtaW5lIGRlY29yYXRvciBmbGF2b3Vyc1xuICAgKiBAcGFyYW0ge0ZsYXZvdXJSZXNvbHZlcn0gcmVzb2x2ZXIgRnVuY3Rpb24gdG8gcmVzb2x2ZSBmbGF2b3Vyc1xuICAgKi9cbiAgc3RhdGljIHNldEZsYXZvdXJSZXNvbHZlcihyZXNvbHZlcjogRmxhdm91clJlc29sdmVyKSB7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyUmVzb2x2ZXIgPSByZXNvbHZlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udmVuaWVuY2Ugc3RhdGljIGVudHJ5IHRvIHN0YXJ0IGEgZGVjb3JhdGlvbiBidWlsZGVyXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgRGVjb3JhdGlvbiBpbnN0YW5jZSBhbmQgaW5pdGlhdGVzIHRoZSBidWlsZGVyIGNoYWluIHdpdGggdGhlIHByb3ZpZGVkIGtleS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgZGVjb3JhdGlvbiBrZXkgdG8gY29uZmlndXJlXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyTWlkfSBBIGJ1aWxkZXIgaW5zdGFuY2UgZm9yIGNoYWluaW5nIGRlZmluaXRpb25zXG4gICAqL1xuICBzdGF0aWMgZm9yKGtleTogc3RyaW5nKTogRGVjb3JhdGlvbkJ1aWxkZXJNaWQge1xuICAgIHJldHVybiBuZXcgRGVjb3JhdGlvbigpLmZvcihrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTdGFydHMgYSBidWlsZGVyIGZvciBhIHNwZWNpZmljIGZsYXZvdXJcbiAgICogQHN1bW1hcnkgQ29udmVuaWVuY2UgbWV0aG9kIHRvIGJlZ2luIGEgRGVjb3JhdGlvbiBidWlsZGVyIGNoYWluIGJvdW5kIHRvIHRoZSBnaXZlbiBmbGF2b3VyIGlkZW50aWZpZXIsIGFsbG93aW5nIHJlZ2lzdHJhdGlvbiBvZiBmbGF2b3VyLXNwZWNpZmljIGRlY29yYXRvcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIFRoZSBmbGF2b3VyIG5hbWUgdG8gYmluZCB0byB0aGUgYnVpbGRlclxuICAgKiBAcmV0dXJuIHtEZWNvcmF0aW9uQnVpbGRlclN0YXJ0fSBBIGJ1aWxkZXIgc3RhcnQgaW50ZXJmYWNlIHRvIGNvbnRpbnVlIGNvbmZpZ3VyYXRpb25cbiAgICovXG4gIHN0YXRpYyBmbGF2b3VyZWRBcyhmbGF2b3VyOiBzdHJpbmcpOiBEZWNvcmF0aW9uQnVpbGRlclN0YXJ0IHtcbiAgICByZXR1cm4gbmV3IERlY29yYXRpb24oZmxhdm91cik7XG4gIH1cbn1cbiIsImltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIi4vbWV0YWRhdGEvTWV0YWRhdGFcIjtcbmltcG9ydCB7IERlY29yYXRpb25LZXlzLCBPYmplY3RLZXlTcGxpdHRlciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBc3NpZ25zIGFyYml0cmFyeSBtZXRhZGF0YSB0byBhIHRhcmdldCB1c2luZyBhIHN0cmluZyBrZXlcbiAqIEBzdW1tYXJ5IERlY29yYXRvciBmYWN0b3J5IHRoYXQgc3RvcmVzIGEga2V5L3ZhbHVlIHBhaXIgaW4gdGhlIGNlbnRyYWwgTWV0YWRhdGEgc3RvcmUgZm9yIHRoZSBwcm92aWRlZCBjbGFzcyBvciBtZW1iZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBtZXRhZGF0YSBrZXkgdG8gYXNzb2NpYXRlIHdpdGggdGhlIHRhcmdldFxuICogQHBhcmFtIHthbnl9IHZhbHVlIFRoZSBtZXRhZGF0YSB2YWx1ZSB0byBzdG9yZSB1bmRlciB0aGUgZ2l2ZW4ga2V5XG4gKiBAcmV0dXJuIEEgZGVjb3JhdG9yIHRoYXQgd3JpdGVzIHRoZSBtZXRhZGF0YSB3aGVuIGFwcGxpZWRcbiAqIEBmdW5jdGlvbiBtZXRhZGF0YVxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1ldGFkYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gIHJldHVybiBmdW5jdGlvbiBtZXRhZGF0YShcbiAgICBtb2RlbDogYW55LFxuXG4gICAgcHJvcD86IGFueSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgZGVzY3JpcHRvcj86IFByb3BlcnR5RGVzY3JpcHRvclxuICApIHtcbiAgICBNZXRhZGF0YS5zZXQocHJvcCA/IG1vZGVsLmNvbnN0cnVjdG9yIDogbW9kZWwsIGtleSwgdmFsdWUpO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDYXB0dXJlcyBhbmQgc3RvcmVzIGEgcHJvcGVydHkncyBkZXNpZ24gdHlwZVxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCByZWFkcyB0aGUgcmVmbGVjdGVkIGRlc2lnbjp0eXBlIGZvciBhIHByb3BlcnR5IGFuZCByZWdpc3RlcnMgaXQgaW4gdGhlIE1ldGFkYXRhIHN0b3JlIHVuZGVyIHRoZSBwcm9wZXJ0aWVzIG1hcC5cbiAqIEByZXR1cm4gQSBkZWNvcmF0b3IgdGhhdCByZWNvcmRzIHRoZSBwcm9wZXJ0eSdzIHR5cGUgbWV0YWRhdGEgd2hlbiBhcHBsaWVkXG4gKiBAZnVuY3Rpb24gcHJvcFxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3AoKSB7XG4gIHJldHVybiBmdW5jdGlvbiBwcm9wKG1vZGVsOiBvYmplY3QsIHByb3A6IGFueSkge1xuICAgIGNvbnN0IGRlc2lnblR5cGUgPSBSZWZsZWN0LmdldE93bk1ldGFkYXRhKFxuICAgICAgRGVjb3JhdGlvbktleXMuREVTSUdOX1RZUEUsXG4gICAgICBtb2RlbCxcbiAgICAgIHByb3BcbiAgICApO1xuICAgIHJldHVybiBtZXRhZGF0YShgJHtEZWNvcmF0aW9uS2V5cy5QUk9QRVJUSUVTfS4ke3Byb3B9YCwgZGVzaWduVHlwZSkoXG4gICAgICBtb2RlbCxcbiAgICAgIHByb3BcbiAgICApO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZWNvcmRzIG1ldGhvZCBkZXNpZ24tdGltZSBtZXRhZGF0YVxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCBjYXB0dXJlcyBhIG1ldGhvZCdzIHJlZmxlY3RlZCBwYXJhbWV0ZXIgYW5kIHJldHVybiB0eXBlcywgc3RvcmluZyB0aGVtIHVuZGVyIHRoZSBhcHByb3ByaWF0ZSBtZXRhZGF0YSBrZXlzIHNvIHRoZXkgY2FuIGJlIGluc3BlY3RlZCBhdCBydW50aW1lLlxuICogQHJldHVybiBBIGRlY29yYXRvciB0aGF0IHBlcnNpc3RzIHRoZSBtZXRob2QncyBzaWduYXR1cmUgaW5mb3JtYXRpb24gaW50byB0aGUgTWV0YWRhdGEgc3RvcmUgd2hlbiBhcHBsaWVkXG4gKiBAZnVuY3Rpb24gbWV0aG9kXG4gKiBAY2F0ZWdvcnkgTWV0aG9kIERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1ldGhvZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIG1ldGhvZChvYmo6IGFueSwgcHJvcD86IGFueSwgZGVzY3JpcHRvcj86IGFueSkge1xuICAgIGNvbnN0IGRlc2lnblBhcmFtcyA9IFJlZmxlY3QuZ2V0T3duTWV0YWRhdGEoXG4gICAgICBEZWNvcmF0aW9uS2V5cy5ERVNJR05fUEFSQU1TLFxuICAgICAgb2JqLFxuICAgICAgcHJvcFxuICAgICk7XG4gICAgY29uc3QgZGVzaWduUmV0dXJuID0gUmVmbGVjdC5nZXRPd25NZXRhZGF0YShcbiAgICAgIERlY29yYXRpb25LZXlzLkRFU0lHTl9SRVRVUk4sXG4gICAgICBvYmosXG4gICAgICBwcm9wXG4gICAgKTtcbiAgICByZXR1cm4gYXBwbHkoXG4gICAgICBtZXRhZGF0YShcbiAgICAgICAgYCR7RGVjb3JhdGlvbktleXMuTUVUSE9EU30uJHtwcm9wfS4ke0RlY29yYXRpb25LZXlzLkRFU0lHTl9QQVJBTVN9YCxcbiAgICAgICAgZGVzaWduUGFyYW1zXG4gICAgICApLFxuICAgICAgbWV0YWRhdGEoXG4gICAgICAgIGAke0RlY29yYXRpb25LZXlzLk1FVEhPRFN9LiR7cHJvcH0uJHtEZWNvcmF0aW9uS2V5cy5ERVNJR05fUkVUVVJOfWAsXG4gICAgICAgIGRlc2lnblJldHVyblxuICAgICAgKVxuICAgICkob2JqLCBwcm9wLCBkZXNjcmlwdG9yKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCBhcHBsaWVzIG11bHRpcGxlIGRlY29yYXRvcnMgdG8gYSBzaW5nbGUgdGFyZ2V0XG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY29tcG9zaXRlIGRlY29yYXRvciB0aGF0IGFwcGxpZXMgbXVsdGlwbGUgZGVjb3JhdG9ycyBpbiBzZXF1ZW5jZSwgY29ycmVjdGx5IGhhbmRsaW5nIGNsYXNzLCBtZXRob2QsIGFuZCBwcm9wZXJ0eSBkZWNvcmF0b3JzLlxuICogQHBhcmFtIHtBcnJheTxDbGFzc0RlY29yYXRvciB8IE1ldGhvZERlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yPn0gZGVjb3JhdG9ycyAtIEFycmF5IG9mIGRlY29yYXRvcnMgdG8gYXBwbHlcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIGRlY29yYXRvciBmdW5jdGlvbiB0aGF0IGFwcGxpZXMgYWxsIHByb3ZpZGVkIGRlY29yYXRvcnMgdG8gdGhlIHRhcmdldFxuICogQGZ1bmN0aW9uIGFwcGx5XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlciBDb2RlXG4gKiAgIHBhcnRpY2lwYW50IEEgYXMgYXBwbHkoLi4uZGVjb3JhdG9ycylcbiAqICAgcGFydGljaXBhbnQgRCBhcyBEZWNvcmF0b3JcbiAqICAgVS0+PkE6IGdldCBkZWNvcmF0b3IoLi4uZGVjb3JhdG9ycylcbiAqICAgQS0+PlU6IHJldHVybnMgKHRhcmdldCwga2V5PywgZGVzYz8pID0+IHZvaWRcbiAqICAgVS0+PkE6IGludm9rZSBvbiB0YXJnZXRcbiAqICAgbG9vcCBmb3IgZWFjaCBkZWNvcmF0b3JcbiAqICAgICBBLT4+RDogaW52b2tlIGFwcHJvcHJpYXRlIGRlY29yYXRvciB0eXBlXG4gKiAgIGVuZFxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5KFxuICAuLi5kZWNvcmF0b3JzOiBBcnJheTxDbGFzc0RlY29yYXRvciB8IE1ldGhvZERlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yPlxuKSB7XG4gIHJldHVybiAoXG4gICAgdGFyZ2V0OiBvYmplY3QsXG4gICAgcHJvcGVydHlLZXk/OiBzdHJpbmcgfCBzeW1ib2wgfCB1bmtub3duLFxuICAgIGRlc2NyaXB0b3I/OiBQcm9wZXJ0eURlc2NyaXB0b3JcbiAgKSA9PiB7XG4gICAgZm9yIChjb25zdCBkZWNvcmF0b3Igb2YgZGVjb3JhdG9ycykge1xuICAgICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmICFkZXNjcmlwdG9yKSB7XG4gICAgICAgIChkZWNvcmF0b3IgYXMgQ2xhc3NEZWNvcmF0b3IpKHRhcmdldCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgKGRlY29yYXRvciBhcyBNZXRob2REZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvcikoXG4gICAgICAgIHRhcmdldCxcbiAgICAgICAgcHJvcGVydHlLZXkgYXMgc3RyaW5nIHwgc3ltYm9sLFxuICAgICAgICBkZXNjcmlwdG9yIGFzIFR5cGVkUHJvcGVydHlEZXNjcmlwdG9yPHVua25vd24+XG4gICAgICApO1xuICAgIH1cbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHByb3BlcnR5IG1ldGFkYXRhIGRlY29yYXRvclxuICogQHN1bW1hcnkgQ29udmVuaWVuY2UgZmFjdG9yeSB0aGF0IGNvbWJpbmVzIG1ldGFkYXRhKGtleSwgdmFsdWUpIGFuZCBwcm9wKCkgdG8gYm90aCBzZXQgYW4gYXJiaXRyYXJ5IG1ldGFkYXRhIGtleSBhbmQgcmVjb3JkIHRoZSBwcm9wZXJ0eSdzIGRlc2lnbiB0eXBlLlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgbWV0YWRhdGEga2V5IHRvIHNldCBmb3IgdGhlIHByb3BlcnR5XG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBtZXRhZGF0YSB2YWx1ZSB0byBhc3NvY2lhdGUgd2l0aCB0aGUga2V5XG4gKiBAcmV0dXJuIEEgZGVjb3JhdG9yIHRoYXQgc2V0cyB0aGUgbWV0YWRhdGEgYW5kIGNhcHR1cmVzIHRoZSBwcm9wZXJ0eSdzIHR5cGVcbiAqIEBmdW5jdGlvbiBwcm9wTWV0YWRhdGFcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm9wTWV0YWRhdGEoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgcmV0dXJuIGFwcGx5KG1ldGFkYXRhKGtleSwgdmFsdWUpLCBwcm9wKCkpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBdHRhY2hlcyBhIGh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9uIHRvIGEgY2xhc3Mgb3IgbWVtYmVyXG4gKiBAc3VtbWFyeSBEZWNvcmF0b3IgZmFjdG9yeSB0aGF0IHN0b3JlcyBhIHRleHR1YWwgZGVzY3JpcHRpb24gaW4gdGhlIE1ldGFkYXRhIHN0b3JlIHVuZGVyIHRoZSBhcHByb3ByaWF0ZSBkZXNjcmlwdGlvbiBrZXkgZm9yIGEgY2xhc3Mgb3IgaXRzIHByb3BlcnR5LlxuICogQHBhcmFtIHtzdHJpbmd9IGRlc2MgVGhlIGRlc2NyaXB0aXZlIHRleHQgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGNsYXNzIG9yIHByb3BlcnR5XG4gKiBAcmV0dXJuIEEgZGVjb3JhdG9yIHRoYXQgcmVjb3JkcyB0aGUgZGVzY3JpcHRpb24gd2hlbiBhcHBsaWVkXG4gKiBAZnVuY3Rpb24gZGVzY3JpcHRpb25cbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXNjcmlwdGlvbihkZXNjOiBzdHJpbmcpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGRlc2NyaXB0aW9uKG9yaWdpbmFsOiBhbnksIHByb3A/OiBhbnksIGRlc2NyaXB0b3I/OiBhbnkpIHtcbiAgICByZXR1cm4gbWV0YWRhdGEoXG4gICAgICBbXG4gICAgICAgIERlY29yYXRpb25LZXlzLkRFU0NSSVBUSU9OLFxuICAgICAgICBwcm9wID8gcHJvcC50b1N0cmluZygpIDogRGVjb3JhdGlvbktleXMuQ0xBU1MsXG4gICAgICBdLmpvaW4oT2JqZWN0S2V5U3BsaXR0ZXIpLFxuICAgICAgZGVzY1xuICAgICkob3JpZ2luYWwsIHByb3AsIGRlc2NyaXB0b3IpO1xuICB9O1xufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gUm9vdCBlbnRyeSBwb2ludCBmb3IgdGhlIGRlY29yYXRpb24gbW9kdWxlXG4gKiBAc3VtbWFyeSBBZ2dyZWdhdGVzIGFuZCByZS1leHBvcnRzIHRoZSBwdWJsaWMgQVBJIG9mIHRoZSBkZWNvcmF0aW9uIGxpYnJhcnksIGluY2x1ZGluZyBjb3JlIGNsYXNzZXMgbGlrZSB7QGxpbmsgRGVjb3JhdGlvbn0sIHV0aWxpdHkgZGVjb3JhdG9ycywgbWV0YWRhdGEgaGVscGVycywgYW5kIGNvbnN0YW50cy4gVGhpcyBtb2R1bGUgaXMgdGhlIHByaW1hcnkgaW1wb3J0IHN1cmZhY2UgZm9yIGNvbnN1bWVycyBhbmQgZXhwb3NlczpcbiAqIC0gQ29yZSBidWlsZGVyOiB7QGxpbmsgRGVjb3JhdGlvbn1cbiAqIC0gRGVjb3JhdG9yIHV0aWxpdGllczoge0BsaW5rIG1vZHVsZTpkZWNvcmF0aW9uIHwgZGVjb3JhdG9ycyBpbiAuL2RlY29yYXRvcnN9XG4gKiAtIE1ldGFkYXRhIHV0aWxpdGllczoge0BsaW5rIE1ldGFkYXRhfVxuICogLSBDb25zdGFudHMgYW5kIGVudW1zOiB7QGxpbmsgRGVjb3JhdGlvbktleXN9LCB7QGxpbmsgRGVmYXVsdEZsYXZvdXJ9XG4gKlxuICogQG1vZHVsZSBkZWNvcmF0aW9uXG4gKi9cblxuaW1wb3J0IHsgTWV0YWRhdGEgfSBmcm9tIFwiLi9tZXRhZGF0YS9pbmRleFwiO1xuXG5leHBvcnQgKiBmcm9tIFwiLi9kZWNvcmF0aW9uXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9tZXRhZGF0YVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgcmVmbGVjdGlvbiBwYWNrYWdlXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIHNlbWFudGljIHZlcnNpb24gbnVtYmVyIG9mIHRoZSBwYWNrYWdlXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuXG5NZXRhZGF0YS5yZWdpc3RlckxpYnJhcnkoXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiLCBWRVJTSU9OKTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBOzs7Ozs7QUFNRztBQUNJLE1BQU0sY0FBYyxHQUFHO0FBRTlCOzs7OztBQUtHO0FBQ0ksTUFBTSxpQkFBaUIsR0FBRztBQUVqQzs7Ozs7Ozs7O0FBU0c7SUFDUztBQUFaLENBQUEsVUFBWSxjQUFjLEVBQUE7QUFDeEIsSUFBQSxjQUFBLENBQUEsV0FBQSxDQUFBLEdBQUEsV0FBdUI7O0FBRXZCLElBQUEsY0FBQSxDQUFBLFNBQUEsQ0FBQSxHQUFBLFNBQStCOztBQUUvQixJQUFBLGNBQUEsQ0FBQSxZQUFBLENBQUEsR0FBQSxZQUF5Qjs7QUFFekIsSUFBQSxjQUFBLENBQUEsU0FBQSxDQUFBLEdBQUEsU0FBbUI7O0FBRW5CLElBQUEsY0FBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLE9BQWU7O0FBRWYsSUFBQSxjQUFBLENBQUEsYUFBQSxDQUFBLEdBQUEsYUFBMkI7O0FBRTNCLElBQUEsY0FBQSxDQUFBLGFBQUEsQ0FBQSxHQUFBLGFBQTJCOztBQUUzQixJQUFBLGNBQUEsQ0FBQSxhQUFBLENBQUEsR0FBQSxhQUEyQjs7QUFFM0IsSUFBQSxjQUFBLENBQUEsZUFBQSxDQUFBLEdBQUEsbUJBQW1DOztBQUVuQyxJQUFBLGNBQUEsQ0FBQSxlQUFBLENBQUEs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
826
+ export { Decoration, DecorationKeys, DefaultFlavour, DefaultMetadata, Metadata, ObjectKeySplitter, VERSION, apply, description, getValueBySplitter, metadata, method, methodMetadata, param, paramMetadata, prop, propMetadata, setValueBySplitter };
827
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdGlvbi5lc20uY2pzIiwic291cmNlcyI6WyIuLi9zcmMvY29uc3RhbnRzLnRzIiwiLi4vc3JjL21ldGFkYXRhL01ldGFkYXRhLnRzIiwiLi4vc3JjL2RlY29yYXRpb24vRGVjb3JhdGlvbi50cyIsIi4uL3NyYy9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJhc2ljTWV0YWRhdGEgfSBmcm9tIFwiLi9tZXRhZGF0YS90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGZsYXZvdXIgaWRlbnRpZmllciBmb3IgdGhlIGRlY29yYXRvciBzeXN0ZW0uXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBkZWZhdWx0IGZsYXZvdXIgdXNlZCBieSB0aGUgRGVjb3JhdGlvbiBjbGFzcyB3aGVuIG5vIHNwZWNpZmljIGZsYXZvdXIgaXMgcHJvdmlkZWQuIFRoaXMgY29uc3RhbnQgaXMgdXNlZCB0aHJvdWdob3V0IHRoZSBsaWJyYXJ5IGFzIHRoZSBmYWxsYmFjayBmbGF2b3VyIGZvciBkZWNvcmF0b3JzLlxuICogQGNvbnN0IERlZmF1bHRGbGF2b3VyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRGbGF2b3VyID0gXCJkZWNhZlwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDaGFyYWN0ZXIgdXNlZCB0byBzcGxpdCBuZXN0ZWQgbWV0YWRhdGEga2V5cy5cbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIGRlbGltaXRlciB0aGUgbWV0YWRhdGEgc3RvcmUgdXNlcyB0byB0cmF2ZXJzZSBuZXN0ZWQgb2JqZWN0IHBhdGhzIHdoZW4gcmVhZGluZyBvciB3cml0aW5nIHZhbHVlcy5cbiAqIEBjb25zdCBPYmplY3RLZXlTcGxpdHRlclxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBPYmplY3RLZXlTcGxpdHRlciA9IFwiLlwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNZXRhZGF0YSB0b2tlbiByZWdpc3RyeSBmb3IgdGhlIGRlY29yYXRpb24gc3lzdGVtLlxuICogQHN1bW1hcnkgRW51bWVyYXRlcyB0aGUga2V5cyB1c2VkIGR1cmluZyByZWZsZWN0aW9uIGFuZCBtZXRhZGF0YSBzdG9yYWdlIGZvciBjbGFzc2VzLCBwcm9wZXJ0aWVzLCBtZXRob2RzLCBkZXNjcmlwdGlvbnMsIGFuZCByZWdpc3RlcmVkIGxpYnJhcmllcy5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBjb25zdCBEZWNvcmF0aW9uS2V5c1xuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBlbnVtIERlY29yYXRpb25LZXlzIHtcbiAgLyoqIEBkZXNjcmlwdGlvbiBTdG9yYWdlIGJ1Y2tldCBmb3IgZGVjb3JhdGlvbi1hd2FyZSBsaWJyYXJ5IHJlZ2lzdHJhdGlvbnMuICovXG4gIExJQlJBUklFUyA9IFwibGlicmFyaWVzXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gU3RvcmFnZSBrZXkgbWlycm9yZWQgb24gY29uc3RydWN0b3JzIHRoYXQgaG9sZHMgcnVudGltZSBtZXRhZGF0YS4gKi9cbiAgUkVGTEVDVCA9IGBfXyR7RGVmYXVsdEZsYXZvdXJ9YCxcbiAgLyoqIEBkZXNjcmlwdGlvbiBDb250YWluZXIgb2YgcmVmbGVjdGVkIHByb3BlcnR5IG1ldGFkYXRhIGZvciBhIG1vZGVsLiAqL1xuICBQUk9QRVJUSUVTID0gXCJwcm9wZXJ0aWVzXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gQ29udGFpbmVyIG9mIHJlZmxlY3RlZCBtZXRob2QgbWV0YWRhdGEgZm9yIGEgbW9kZWwuICovXG4gIE1FVEhPRFMgPSBcIm1ldGhvZHNcIixcbiAgLyoqIEBkZXNjcmlwdGlvbiBLZXkgdW5kZXIgd2hpY2ggdGhlIG1vZGVsIGNvbnN0cnVjdG9yIHJlZmVyZW5jZSBpcyBwZXJzaXN0ZWQuICovXG4gIENMQVNTID0gXCJjbGFzc1wiLFxuICAvKiogQGRlc2NyaXB0aW9uIEh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9ucyBmb3IgY2xhc3NlcyBhbmQgbWVtYmVycy4gKi9cbiAgREVTQ1JJUFRJT04gPSBcImRlc2NyaXB0aW9uXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gU3RvcmFnZSBzbG90IHRyYWNraW5nIHRoZSBvcmlnaW5hbCBjb25zdHJ1Y3RvciB3aGVuIG92ZXJyaWRkZW4uICovXG4gIENPTlNUUlVDVE9SID0gXCJjb25zdHJ1Y3RvclwiLFxuICAvKiogQGRlc2NyaXB0aW9uIENvbGxlY3RlZCBwYXJhbWV0ZXIgbWV0YWRhdGEgZm9yIGNvbmZpZ3VyZWQgZGVjb3JhdG9ycy4gKi9cbiAgUEFSQU1FVEVSUyA9IFwicGFyYW1ldGVyc1wiLFxuICAvKiogQGRlc2NyaXB0aW9uIFJlZmxlY3QgbWV0YWRhdGEga2V5IGZvciBhIHByb3BlcnR5J3MgZGVzaWduIHR5cGUuICovXG4gIERFU0lHTl9UWVBFID0gXCJkZXNpZ246dHlwZVwiLFxuICAvKiogQGRlc2NyaXB0aW9uIFJlZmxlY3QgbWV0YWRhdGEga2V5IGZvciByZWNvcmRlZCBjb25zdHJ1Y3RvciBwYXJhbWV0ZXIgdHlwZXMuICovXG4gIERFU0lHTl9QQVJBTVMgPSBcImRlc2lnbjpwYXJhbXR5cGVzXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gUmVmbGVjdCBtZXRhZGF0YSBrZXkgZm9yIGEgbWV0aG9kJ3MgcmV0dXJuIHR5cGUuICovXG4gIERFU0lHTl9SRVRVUk4gPSBcImRlc2lnbjpyZXR1cm50eXBlXCIsXG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgbWV0YWRhdGEgaW5zdGFuY2UuXG4gKiBAc3VtbWFyeSBQcm92aWRlcyB0aGUgZGVmYXVsdCBtZXRhZGF0YSBzaGFwZSB1c2VkIHdoZW4gaW5pdGlhbGl6aW5nIG5ldyBtZXRhZGF0YSBlbnRyaWVzIGZvciBhIG1vZGVsLlxuICogQGNvbnN0IERlZmF1bHRNZXRhZGF0YVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0TWV0YWRhdGE6IEJhc2ljTWV0YWRhdGE8YW55PiA9IHtcbiAgW0RlY29yYXRpb25LZXlzLlBST1BFUlRJRVNdOiBbXSxcbn0gYXMgdW5rbm93biBhcyBCYXNpY01ldGFkYXRhPGFueT47XG4iLCJpbXBvcnQgeyBCYXNpY01ldGFkYXRhLCBDb25zdHJ1Y3RvciB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBEZWNvcmF0aW9uS2V5cywgT2JqZWN0S2V5U3BsaXR0ZXIgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgXCJyZWZsZWN0LW1ldGFkYXRhXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIG5lc3RlZCB2YWx1ZSBmcm9tIGFuIG9iamVjdCBnaXZlbiBhIHBhdGguXG4gKiBAc3VtbWFyeSBXYWxrcyBhbiBvYmplY3Qgc3RydWN0dXJlIHVzaW5nIGEgc3BsaXR0ZXItZGVsaW1pdGVkIHBhdGggYW5kIHJldHVybnMgdGhlIHZhbHVlIGF0IHRoYXQgbG9jYXRpb24gb3IgYHVuZGVmaW5lZGAgaWYgYW55IGtleSBpcyBtaXNzaW5nLlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmogT2JqZWN0IHRvIHRyYXZlcnNlIGZvciB0aGUgbG9va3VwLlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggU3BsaXR0ZXItZGVsaW1pdGVkIHBhdGggdG8gdGhlIGRlc2lyZWQgdmFsdWUgKGUuZy4sIFwiYS5iLmNcIikuXG4gKiBAcGFyYW0ge3N0cmluZ30gW3NwbGl0dGVyPU9iamVjdEtleVNwbGl0dGVyXSBEZWxpbWl0ZXIgdXNlZCB0byBzZXBhcmF0ZSB0aGUgcGF0aCBzZWdtZW50cy5cbiAqIEByZXR1cm4ge2FueXx1bmRlZmluZWR9IFZhbHVlIHJlc29sdmVkIGF0IHRoZSBnaXZlbiBwYXRoIG9yIGB1bmRlZmluZWRgIHdoZW4gbm90IGZvdW5kLlxuICogQGZ1bmN0aW9uIGdldFZhbHVlQnlTcGxpdHRlclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENhbGxlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIGdldFZhbHVlQnlTcGxpdHRlclxuICogICBwYXJ0aWNpcGFudCBPIGFzIE9iamVjdFxuICogICBDLT4+RjogKG9iaiwgcGF0aCwgc3BsaXR0ZXIpXG4gKiAgIEYtPj5GOiBzcGxpdCBwYXRoIGludG8ga2V5c1xuICogICBsb29wIGZvciBlYWNoIGtleVxuICogICAgIEYtPj5POiBhY2Nlc3MgY3VycmVudFtrZXldXG4gKiAgICAgYWx0IG1pc3Npbmcgb3IgbnVsbGlzaFxuICogICAgICAgRi0tPj5DOiByZXR1cm4gdW5kZWZpbmVkXG4gKiAgICAgZW5kXG4gKiAgIGVuZFxuICogICBGLS0+PkM6IHJldHVybiBmaW5hbCB2YWx1ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRWYWx1ZUJ5U3BsaXR0ZXIoXG4gIG9iajogUmVjb3JkPHN0cmluZywgYW55PixcbiAgcGF0aDogc3RyaW5nLFxuICBzcGxpdHRlcjogc3RyaW5nID0gT2JqZWN0S2V5U3BsaXR0ZXJcbik6IGFueSB7XG4gIGNvbnN0IGtleXMgPSBwYXRoLnNwbGl0KHNwbGl0dGVyKTtcbiAgbGV0IGN1cnJlbnQgPSBvYmo7XG5cbiAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgIGlmIChcbiAgICAgIGN1cnJlbnQgPT09IG51bGwgfHxcbiAgICAgIGN1cnJlbnQgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChjdXJyZW50LCBrZXkpXG4gICAgKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjdXJyZW50ID0gY3VycmVudFtrZXldO1xuICB9XG5cbiAgcmV0dXJuIGN1cnJlbnQ7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFNldHMgYSBuZXN0ZWQgdmFsdWUgb24gYW4gb2JqZWN0IGdpdmVuIGEgcGF0aC5cbiAqIEBzdW1tYXJ5IFRyYXZlcnNlcyBvciBjcmVhdGVzIGludGVybWVkaWF0ZSBvYmplY3RzIGZvbGxvd2luZyBhIHNwbGl0dGVyLWRlbGltaXRlZCBwYXRoIGFuZCBhc3NpZ25zIHRoZSBwcm92aWRlZCB2YWx1ZSBhdCB0aGUgZGVzdGluYXRpb24ga2V5LlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmogT2JqZWN0IHRvIG11dGF0ZSB3aGlsZSBkcmlsbGluZyBpbnRvIG5lc3RlZCBrZXlzLlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggU3BsaXR0ZXItZGVsaW1pdGVkIGRlc3RpbmF0aW9uIHBhdGggKGUuZy4sIFwiYS5iLmNcIikuXG4gKiBAcGFyYW0ge2FueX0gdmFsdWUgVmFsdWUgdG8gc2V0IGF0IHRoZSBkZXN0aW5hdGlvbiBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IFtzcGxpdHRlcj1PYmplY3RLZXlTcGxpdHRlcl0gRGVsaW1pdGVyIHVzZWQgdG8gc2VwYXJhdGUgdGhlIHBhdGggc2VnbWVudHMuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGZ1bmN0aW9uIHNldFZhbHVlQnlTcGxpdHRlclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENhbGxlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIHNldFZhbHVlQnlTcGxpdHRlclxuICogICBwYXJ0aWNpcGFudCBPIGFzIE9iamVjdFxuICogICBDLT4+RjogKG9iaiwgcGF0aCwgdmFsdWUsIHNwbGl0dGVyKVxuICogICBGLT4+Rjogc3BsaXQgcGF0aCBpbnRvIGtleXNcbiAqICAgbG9vcCBmb3IgZWFjaCBrZXlcbiAqICAgICBhbHQga2V5IG1pc3NpbmdcbiAqICAgICAgIEYtPj5POiBjcmVhdGUgaW50ZXJtZWRpYXRlIG9iamVjdFxuICogICAgIGVsc2Uga2V5IGV4aXN0c1xuICogICAgICAgRi0+Pk86IGRlc2NlbmQgaW50byBleGlzdGluZyBvYmplY3RcbiAqICAgICBlbmRcbiAqICAgZW5kXG4gKiAgIEYtLT4+Qzogdm9pZFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRWYWx1ZUJ5U3BsaXR0ZXIoXG4gIG9iajogUmVjb3JkPHN0cmluZywgYW55PixcbiAgcGF0aDogc3RyaW5nLFxuICB2YWx1ZTogYW55LFxuICBzcGxpdHRlciA9IE9iamVjdEtleVNwbGl0dGVyXG4pOiB2b2lkIHtcbiAgY29uc3Qga2V5cyA9IHBhdGguc3BsaXQoc3BsaXR0ZXIpLmZpbHRlcigoaykgPT4gay5sZW5ndGggPiAwKTtcbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgbGV0IGN1cnJlbnQ6IFJlY29yZDxhbnksIGFueT4gPSBvYmo7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgIGNvbnN0IGtleSA9IGtleXNbaV07XG4gICAgaWYgKFxuICAgICAgY3VycmVudFtrZXldID09PSB1bmRlZmluZWQgfHxcbiAgICAgIGN1cnJlbnRba2V5XSA9PT0gbnVsbCB8fFxuICAgICAgdHlwZW9mIGN1cnJlbnRba2V5XSAhPT0gXCJvYmplY3RcIlxuICAgICkge1xuICAgICAgY3VycmVudFtrZXldID0ge307XG4gICAgfVxuICAgIGN1cnJlbnQgPSBjdXJyZW50W2tleV07XG4gIH1cblxuICBjb25zdCBsYXN0S2V5ID0ga2V5c1trZXlzLmxlbmd0aCAtIDFdO1xuICBjdXJyZW50W2xhc3RLZXldID0gdmFsdWU7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENlbnRyYWxpemVkIHJ1bnRpbWUgbWV0YWRhdGEgc3RvcmUgYm91bmQgdG8gY29uc3RydWN0b3JzLlxuICogQHN1bW1hcnkgUHJvdmlkZXMgdXRpbGl0aWVzIHRvIHJlYWQgYW5kIHdyaXRlIHN0cnVjdHVyZWQgbWV0YWRhdGEgZm9yIGNsYXNzZXMgYW5kIHRoZWlyIG1lbWJlcnMsIHdpdGggb3B0aW9uYWwgbWlycm9yaW5nIG9udG8gdGhlIGNvbnN0cnVjdG9yIHZpYSBhIHdlbGwta25vd24gc3ltYm9sIGtleS4gU3VwcG9ydHMgbmVzdGVkIGtleSBwYXRocyB1c2luZyBhIGNvbmZpZ3VyYWJsZSBzcGxpdHRlciBhbmQgb2ZmZXJzIGJvdGggaW5zdGFuY2UgYW5kIHN0YXRpYyBBUElzLlxuICogQHRlbXBsYXRlIE0gVGhlIG1vZGVsIHR5cGUgdGhlIG1ldGFkYXRhIGJlbG9uZ3MgdG8uXG4gKiBAdGVtcGxhdGUgTUVUQSBFeHRlbmRzIEJhc2ljTWV0YWRhdGE8TT4gcmVwcmVzZW50aW5nIHRoZSBtZXRhZGF0YSBzdHJ1Y3R1cmUuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2ZsYXZvdXI9RGVmYXVsdEZsYXZvdXJdIE9wdGlvbmFsIGZsYXZvdXIgaWRlbnRpZmllciBhcHBsaWVkIHdoZW4gaW5zdGFudGlhdGluZyBoZWxwZXIgYnVpbGRlcnMuXG4gKiBAY2xhc3NcbiAqIEBleGFtcGxlXG4gKiAvLyBEZWZpbmUgYW5kIHJlYWQgbWV0YWRhdGEgZm9yIGEgY2xhc3NcbiAqIGNsYXNzIFVzZXIgeyBuYW1lITogc3RyaW5nIH1cbiAqIE1ldGFkYXRhLnNldChVc2VyLCBcImRlc2NyaXB0aW9uLmNsYXNzXCIsIFwiQSB1c2VyIG1vZGVsXCIpO1xuICogTWV0YWRhdGEuc2V0KFVzZXIsIFwicHJvcGVydGllcy5uYW1lXCIsIFN0cmluZyk7XG4gKiBjb25zdCBkZXNjID0gTWV0YWRhdGEuZ2V0KFVzZXIsIFwiZGVzY3JpcHRpb24uY2xhc3NcIik7IC8vIFwiQSB1c2VyIG1vZGVsXCJcbiAqIGNvbnN0IHR5cGUgPSBNZXRhZGF0YS50eXBlKFVzZXIsIFwibmFtZVwiKTsgLy8gU3RyaW5nXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ29uc3RydWN0b3JcbiAqICAgcGFydGljaXBhbnQgUyBhcyBNZXRhZGF0YSAoc3RhdGljKVxuICogICBDLT4+Uzogc2V0KFVzZXIsIFwicHJvcGVydGllcy5uYW1lXCIsIFN0cmluZylcbiAqICAgQy0+PlM6IGdldChVc2VyLCBcInByb3BlcnRpZXMubmFtZVwiKVxuICogICBTLS0+PkM6IFN0cmluZ1xuICovXG5leHBvcnQgY2xhc3MgTWV0YWRhdGEge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluLW1lbW9yeSBzdG9yYWdlIG9mIG1ldGFkYXRhIGJ5IGNvbnN0cnVjdG9yIHN5bWJvbFxuICAgKiBAc3VtbWFyeSBNYXBzIGEgU3ltYm9sIGRlcml2ZWQgZnJvbSB0aGUgY29uc3RydWN0b3IgdG8gaXRzIG1ldGFkYXRhIG9iamVjdCwgZW5hYmxpbmcgZWZmaWNpZW50IGxvb2t1cC5cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIF9tZXRhZGF0YTogUmVjb3JkPHN5bWJvbCwgYW55PiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGF0aCBkZWxpbWl0ZXIgZm9yIG5lc3RlZCBtZXRhZGF0YSBrZXlzXG4gICAqIEBzdW1tYXJ5IFVzZWQgYnkgZ2V0L3NldCBvcGVyYXRpb25zIHRvIG5hdmlnYXRlIG5lc3RlZCBzdHJ1Y3R1cmVzLCBkZWZhdWx0cyB0byBPYmplY3RLZXlTcGxpdHRlci5cbiAgICovXG4gIHN0YXRpYyBzcGxpdHRlciA9IE9iamVjdEtleVNwbGl0dGVyO1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN5bWJvbCBrZXkgdXNlZCB0byBtaXJyb3IgbWV0YWRhdGEgb24gdGhlIGNvbnN0cnVjdG9yXG4gICAqIEBzdW1tYXJ5IFdoZW4gbWlycm9yaW5nIGlzIGVuYWJsZWQsIHRoZSBtZXRhZGF0YSBvYmplY3QgaXMgZGVmaW5lZCBvbiB0aGUgY29uc3RydWN0b3IgdW5kZXIgdGhpcyBub24tZW51bWVyYWJsZSBrZXkuXG4gICAqL1xuICBzdGF0aWMgYmFzZUtleSA9IERlY29yYXRpb25LZXlzLlJFRkxFQ1Q7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udHJvbHMgd2hldGhlciBtZXRhZGF0YSBpcyBtaXJyb3JlZCBvbnRvIHRoZSBjb25zdHJ1Y3RvclxuICAgKiBAc3VtbWFyeSBXaGVuIHRydWUsIHRoZSBtZXRhZGF0YSBvYmplY3QgaXMgZGVmaW5lZCBvbiB0aGUgY29uc3RydWN0b3IgdW5kZXIgdGhlIG5vbi1lbnVtZXJhYmxlIGJhc2VLZXkuXG4gICAqL1xuICBzdGF0aWMgbWlycm9yOiBib29sZWFuID0gdHJ1ZTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge31cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExpc3RzIGtub3duIHByb3BlcnR5IGtleXMgZm9yIGEgbW9kZWwuXG4gICAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBtZXRhZGF0YSBlbnRyeSBhbmQgcmV0dXJucyB0aGUgbmFtZXMgb2YgcHJvcGVydGllcyB0aGF0IGhhdmUgcmVjb3JkZWQgdHlwZSBpbmZvcm1hdGlvbi5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gbW9kZWwgVGFyZ2V0IGNvbnN0cnVjdG9yIHdob3NlIHByb3BlcnR5IG1ldGFkYXRhIHNob3VsZCBiZSBpbnNwZWN0ZWQuXG4gICAqIEByZXR1cm4ge3N0cmluZ1tdfHVuZGVmaW5lZH0gQXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgb3IgYHVuZGVmaW5lZGAgaWYgbm8gbWV0YWRhdGEgZXhpc3RzLlxuICAgKi9cbiAgc3RhdGljIHByb3BlcnRpZXMobW9kZWw6IENvbnN0cnVjdG9yKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmdldChtb2RlbCk7XG4gICAgaWYgKCFtZXRhKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhtZXRhLnByb3BlcnRpZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaXN0cyBrbm93biBtZXRob2RzIGZvciBhIG1vZGVsLlxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgYW5kIHJldHVybnMgdGhlIG1ldGhvZCBuYW1lcyB0aGF0IGhhdmUgcmVjb3JkZWQgc2lnbmF0dXJlIG1ldGFkYXRhIGZvciB0aGUgcHJvdmlkZWQgY29uc3RydWN0b3IuXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRhcmdldCBjb25zdHJ1Y3RvciB3aG9zZSBtZXRob2QgbWV0YWRhdGEgc2hvdWxkIGJlIGluc3BlY3RlZC5cbiAgICogQHJldHVybiB7c3RyaW5nW118dW5kZWZpbmVkfSBBcnJheSBvZiBtZXRob2QgbmFtZXMgb3IgYHVuZGVmaW5lZGAgaWYgbm8gbWV0YWRhdGEgZXhpc3RzLlxuICAgKi9cbiAgc3RhdGljIG1ldGhvZHMobW9kZWw6IENvbnN0cnVjdG9yKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmdldChtb2RlbCwgRGVjb3JhdGlvbktleXMuTUVUSE9EUyk7XG4gICAgaWYgKCFtZXRhKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhtZXRhKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgaHVtYW4tcmVhZGFibGUgZGVzY3JpcHRpb24gZm9yIGEgY2xhc3Mgb3IgYSBwcm9wZXJ0eS5cbiAgICogQHN1bW1hcnkgTG9va3MgdXAgdGhlIGRlc2NyaXB0aW9uIHN0b3JlZCB1bmRlciB0aGUgbWV0YWRhdGEgXCJkZXNjcmlwdGlvblwiIG1hcC4gSWYgYSBwcm9wZXJ0eSBrZXkgaXMgcHJvdmlkZWQsIHJldHVybnMgdGhlIHByb3BlcnR5J3MgZGVzY3JpcHRpb247IG90aGVyd2lzZSByZXR1cm5zIHRoZSBjbGFzcyBkZXNjcmlwdGlvbi5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGFyZ2V0IGNvbnN0cnVjdG9yIHdob3NlIGRlc2NyaXB0aW9uIGlzIGJlaW5nIHJldHJpZXZlZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwcm9wXSBPcHRpb25hbCBwcm9wZXJ0eSBrZXkgKHR5cGVkIGFzIGBrZXlvZiBNYCkgZm9yIHdoaWNoIHRvIGZldGNoIHRoZSBkZXNjcmlwdGlvbi5cbiAgICogQHJldHVybiB7c3RyaW5nfHVuZGVmaW5lZH0gRGVzY3JpcHRpb24gdGV4dCBpZiBwcmVzZW50LCBvdGhlcndpc2UgYHVuZGVmaW5lZGAuXG4gICAqL1xuICBzdGF0aWMgZGVzY3JpcHRpb248TT4oXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+LFxuICAgIHByb3A/OiBrZXlvZiBNXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFxuICAgICAgbW9kZWwsXG4gICAgICBbRGVjb3JhdGlvbktleXMuREVTQ1JJUFRJT04sIHByb3AgPyBwcm9wIDogRGVjb3JhdGlvbktleXMuQ0xBU1NdLmpvaW4oXG4gICAgICAgIHRoaXMuc3BsaXR0ZXJcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHJlY29yZGVkIHBhcmFtcyBmb3IgYSBtZXRob2QuXG4gICAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBtZXRhZGF0YSBlbnRyeSB1bmRlciBgbWV0aG9kcy48cHJvcD4uZGVzaWduOnBhcmFtdHlwZXNgIHRvIHJldHVybiB0aGUgcGFyYW1ldGVyIGNvbnN0cnVjdG9ycyBmb3IgdGhlIGdpdmVuIG1ldGhvZC5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGFyZ2V0IGNvbnN0cnVjdG9yIG93bmluZyB0aGUgbWV0aG9kIG1ldGFkYXRhLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBNZXRob2QgbmFtZSB3aG9zZSBwYXJhbWV0ZXJzIHNob3VsZCBiZSBmZXRjaGVkLlxuICAgKiBAcmV0dXJuIHthbnlbXXx1bmRlZmluZWR9IEFycmF5IG9mIGNvbnN0cnVjdG9yIHJlZmVyZW5jZXMgZGVzY3JpYmluZyBlYWNoIHBhcmFtZXRlciBvciBgdW5kZWZpbmVkYCB3aGVuIG5vdCBhdmFpbGFibGUuXG4gICAqL1xuICBzdGF0aWMgcGFyYW1zPE0+KG1vZGVsOiBDb25zdHJ1Y3RvcjxNPiwgcHJvcDogc3RyaW5nKTogYW55W10gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLk1FVEhPRFMsIHByb3AsIERlY29yYXRpb25LZXlzLkRFU0lHTl9QQVJBTVNdLmpvaW4oXG4gICAgICAgIHRoaXMuc3BsaXR0ZXJcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSBzaW5nbGUgcmVjb3JkZWQgcGFyYW1ldGVyIHR5cGUgZm9yIGEgbWV0aG9kLlxuICAgKiBAc3VtbWFyeSBMb29rcyB1cCB0aGUgcGFyYW1ldGVyIG1ldGFkYXRhIGZvciB0aGUgcHJvdmlkZWQgaW5kZXgsIGVuZm9yY2luZyBib3VuZHMgYW5kIHJldHVybmluZyB0aGUgY29uc3RydWN0b3IgcmVmZXJlbmNlIGZvciB0aGF0IGFyZ3VtZW50LlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3Igb3duaW5nIHRoZSBtZXRob2QgbWV0YWRhdGEuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wIE1ldGhvZCBuYW1lIHdob3NlIHBhcmFtZXRlciBzaG91bGQgYmUgcmV0dXJuZWQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBaZXJvLWJhc2VkIGluZGV4IG9mIHRoZSBkZXNpcmVkIHBhcmFtZXRlciBtZXRhZGF0YS5cbiAgICogQHJldHVybiB7YW55fHVuZGVmaW5lZH0gQ29uc3RydWN0b3IgcmVmZXJlbmNlIGZvciB0aGUgcGFyYW1ldGVyIG9yIGB1bmRlZmluZWRgIGlmIG5vdCByZWNvcmRlZC5cbiAgICovXG4gIHN0YXRpYyBwYXJhbTxNPihcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgcHJvcDogc3RyaW5nLFxuICAgIGluZGV4OiBudW1iZXJcbiAgKTogYW55IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBwYXJhbXMgPSB0aGlzLnBhcmFtcyhtb2RlbCwgcHJvcCk7XG4gICAgaWYgKCFwYXJhbXMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgaWYgKGluZGV4ID4gcGFyYW1zLmxlbmd0aCAtIDEpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBQYXJhbWV0ZXIgaW5kZXggJHtpbmRleH0gb3V0IG9mIHJhbmdlIGZvciAke1N0cmluZyhwcm9wKX1gXG4gICAgICApO1xuICAgIHJldHVybiBwYXJhbXNbaW5kZXhdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHJlY29yZGVkIHJldHVybiB0eXBlIGZvciBhIG1ldGhvZC5cbiAgICogQHN1bW1hcnkgUmVhZHMgdGhlIG1ldGFkYXRhIGVudHJ5IHVuZGVyIGBtZXRob2RzLjxwcm9wPi5kZXNpZ246cmV0dXJudHlwZWAgdG8gcmV0dXJuIHRoZSByZXR1cm4gdHlwZSBmb3IgdGhlIGdpdmVuIG1ldGhvZC5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGFyZ2V0IGNvbnN0cnVjdG9yIHdob3NlIG1ldGhvZCBtZXRhZGF0YSBzaG91bGQgYmUgaW5zcGVjdGVkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBNZXRob2QgbmFtZSB3aG9zZSByZXR1cm4gdHlwZSBzaG91bGQgYmUgZmV0Y2hlZC5cbiAgICogQHJldHVybiB7YW55fHVuZGVmaW5lZH0gQ29uc3RydWN0b3IgcmVmZXJlbmNlIGZvciB0aGUgcmV0dXJuIHR5cGUgb3IgYHVuZGVmaW5lZGAgd2hlbiBub3QgYXZhaWxhYmxlLlxuICAgKi9cbiAgc3RhdGljIHJldHVybjxNPihtb2RlbDogQ29uc3RydWN0b3I8TT4sIHByb3A6IHN0cmluZyk6IGFueSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFxuICAgICAgbW9kZWwsXG4gICAgICBbRGVjb3JhdGlvbktleXMuTUVUSE9EUywgcHJvcCwgRGVjb3JhdGlvbktleXMuREVTSUdOX1JFVFVSTl0uam9pbihcbiAgICAgICAgdGhpcy5zcGxpdHRlclxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcmVjb3JkZWQgZGVzaWduIHR5cGUgZm9yIGEgcHJvcGVydHkuXG4gICAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBtZXRhZGF0YSBlbnRyeSB1bmRlciBgcHJvcGVydGllcy48cHJvcD5gIHRvIHJldHVybiB0aGUgY29uc3RydWN0b3IgcmVjb3JkZWQgZm9yIHRoZSBnaXZlbiBwcm9wZXJ0eSBuYW1lLlxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yfSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3Igd2hvc2UgcHJvcGVydHkgbWV0YWRhdGEgc2hvdWxkIGJlIGluc3BlY3RlZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3AgUHJvcGVydHkgbmFtZSB3aG9zZSB0eXBlIG1ldGFkYXRhIHNob3VsZCBiZSByZXR1cm5lZC5cbiAgICogQHJldHVybiB7Q29uc3RydWN0b3J8dW5kZWZpbmVkfSBDb25zdHJ1Y3RvciByZWZlcmVuY2UgZm9yIHRoZSBwcm9wZXJ0eSB0eXBlIG9yIGB1bmRlZmluZWRgIGlmIG5vdCBhdmFpbGFibGUuXG4gICAqL1xuICBzdGF0aWMgdHlwZShtb2RlbDogQ29uc3RydWN0b3IsIHByb3A6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLlBST1BFUlRJRVMsIHByb3BdLmpvaW4odGhpcy5zcGxpdHRlcilcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXNvbHZlcyB0aGUgY2Fub25pY2FsIGNvbnN0cnVjdG9yIGFzc29jaWF0ZWQgd2l0aCB0aGUgcHJvdmlkZWQgbW9kZWwgaGFuZGxlLlxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBzdG9yZWQgY29uc3RydWN0b3IgcmVmZXJlbmNlIHdoZW4gdGhlIHByb3ZpZGVkIG1vZGVsIGlzIGEgcHJveHkgb3IgcmVkdWNlZCB2YWx1ZS4gRmFsbHMgYmFjayB0byB0aGUgb3JpZ2luYWwgbW9kZWwgd2hlbiBubyBjb25zdHJ1Y3RvciBtZXRhZGF0YSBoYXMgYmVlbiByZWNvcmRlZCB5ZXQuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIE1vZGVsIHVzZWQgd2hlbiByZWNvcmRpbmcgbWV0YWRhdGEuXG4gICAqIEByZXR1cm4ge0NvbnN0cnVjdG9yPE0+fHVuZGVmaW5lZH0gQ2Fub25pY2FsIGNvbnN0cnVjdG9yIGlmIHN0b3JlZCwgb3RoZXJ3aXNlIGB1bmRlZmluZWRgLlxuICAgKi9cbiAgc3RhdGljIGNvbnN0cjxNPihtb2RlbDogQ29uc3RydWN0b3I8TT4pIHtcbiAgICByZXR1cm4gdGhpcy5nZXQobW9kZWwsIERlY29yYXRpb25LZXlzLkNPTlNUUlVDVE9SKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG1ldGFkYXRhIGZvciBhIG1vZGVsIG9yIGEgc3BlY2lmaWMga2V5IHdpdGhpbiBpdC5cbiAgICogQHN1bW1hcnkgV2hlbiBjYWxsZWQgd2l0aCBhIGNvbnN0cnVjdG9yIG9ubHksIHJldHVybnMgdGhlIGVudGlyZSBtZXRhZGF0YSBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBtb2RlbC4gV2hlbiBhIGtleSBwYXRoIGlzIHByb3ZpZGVkLCByZXR1cm5zIHRoZSB2YWx1ZSBzdG9yZWQgYXQgdGhhdCBuZXN0ZWQga2V5LlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAdGVtcGxhdGUgTUVUQVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3IgdXNlZCB0byBsb2NhdGUgdGhlIG1ldGFkYXRhIHJlY29yZC5cbiAgICogQHJldHVybiB7TUVUQXx1bmRlZmluZWR9IE1ldGFkYXRhIG9iamVjdCwgdGhlIHZhbHVlIGF0IHRoZSBrZXkgcGF0aCwgb3IgYHVuZGVmaW5lZGAgaWYgbm90aGluZyBleGlzdHMuXG4gICAqL1xuICBzdGF0aWMgZ2V0PE0sIE1FVEEgZXh0ZW5kcyBCYXNpY01ldGFkYXRhPE0+ID0gQmFzaWNNZXRhZGF0YTxNPj4oXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+XG4gICk6IE1FVEEgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG1ldGFkYXRhIGZvciBhIG1vZGVsIG9yIGEgc3BlY2lmaWMga2V5IHdpdGhpbiBpdC5cbiAgICogQHN1bW1hcnkgV2hlbiBjYWxsZWQgd2l0aCBhIGNvbnN0cnVjdG9yIG9ubHksIHJldHVybnMgdGhlIGVudGlyZSBtZXRhZGF0YSBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBtb2RlbC4gV2hlbiBhIGtleSBwYXRoIGlzIHByb3ZpZGVkLCByZXR1cm5zIHRoZSB2YWx1ZSBzdG9yZWQgYXQgdGhhdCBuZXN0ZWQga2V5LlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAdGVtcGxhdGUgTUVUQVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3IgdXNlZCB0byBsb2NhdGUgdGhlIG1ldGFkYXRhIHJlY29yZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBOZXN0ZWQga2V5IHBhdGggdG8gZmV0Y2ggYSBzcGVjaWZpYyB2YWx1ZS5cbiAgICogQHJldHVybiB7TUVUQXwqfHVuZGVmaW5lZH0gTWV0YWRhdGEgb2JqZWN0LCB0aGUgdmFsdWUgYXQgdGhlIGtleSBwYXRoLCBvciBgdW5kZWZpbmVkYCBpZiBub3RoaW5nIGV4aXN0cy5cbiAgICovXG4gIHN0YXRpYyBnZXQobW9kZWw6IENvbnN0cnVjdG9yLCBrZXk6IHN0cmluZyk6IGFueTtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0LlxuICAgKiBAc3VtbWFyeSBXaGVuIGNhbGxlZCB3aXRoIGEgY29uc3RydWN0b3Igb25seSwgcmV0dXJucyB0aGUgZW50aXJlIG1ldGFkYXRhIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIG1vZGVsLiBXaGVuIGEga2V5IHBhdGggaXMgcHJvdmlkZWQsIHJldHVybnMgdGhlIHZhbHVlIHN0b3JlZCBhdCB0aGF0IG5lc3RlZCBrZXkuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEB0ZW1wbGF0ZSBNRVRBXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT58c3RyaW5nfSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3IgdXNlZCB0byBsb2NhdGUgdGhlIG1ldGFkYXRhIHJlY29yZCBvciBhIHByZS1yZXNvbHZlZCBzeW1ib2wgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtrZXldIE9wdGlvbmFsIG5lc3RlZCBrZXkgcGF0aCB0byBmZXRjaCBhIHNwZWNpZmljIHZhbHVlLlxuICAgKiBAcmV0dXJuIHtNRVRBfCp8dW5kZWZpbmVkfSBNZXRhZGF0YSBvYmplY3QsIHRoZSB2YWx1ZSBhdCB0aGUga2V5IHBhdGgsIG9yIGB1bmRlZmluZWRgIGlmIG5vdGhpbmcgZXhpc3RzLlxuICAgKi9cbiAgc3RhdGljIGdldChtb2RlbDogQ29uc3RydWN0b3IsIGtleT86IHN0cmluZykge1xuICAgIGlmIChrZXkgIT09IERlY29yYXRpb25LZXlzLkNPTlNUUlVDVE9SKSBtb2RlbCA9IHRoaXMuY29uc3RyKG1vZGVsKSB8fCBtb2RlbDtcbiAgICBjb25zdCBzeW1ib2wgPSBTeW1ib2wuZm9yKG1vZGVsLnRvU3RyaW5nKCkpO1xuICAgIHJldHVybiB0aGlzLmlubmVyR2V0KHN5bWJvbCwga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG1ldGFkYXRhIHN0b3JlZCB1bmRlciBhIHN5bWJvbCBrZXkuXG4gICAqIEBzdW1tYXJ5IEludGVybmFsIGhlbHBlciB0aGF0IHJlc29sdmVzIGFuZCBvcHRpb25hbGx5IGRyaWxscyBpbnRvIHRoZSBpbi1tZW1vcnkgbWV0YWRhdGEgbWFwIGZvciB0aGUgcHJvdmlkZWQgc3ltYm9sIGFuZCBrZXkgcGF0aC5cbiAgICogQHBhcmFtIHtzeW1ib2x9IHN5bWJvbCBTeW1ib2wgcmVwcmVzZW50aW5nIHRoZSBtZXRhZGF0YSBidWNrZXQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfHN5bWJvbH0gW2tleV0gT3B0aW9uYWwgbmVzdGVkIGtleSByZWZlcmVuY2luZyBhIHNwZWNpZmljIG1ldGFkYXRhIGVudHJ5LlxuICAgKiBAcmV0dXJuIHthbnl9IFN0b3JlZCBtZXRhZGF0YSBvYmplY3Qgb3IgdmFsdWUgZm9yIHRoZSBwcm92aWRlZCBrZXksIG9yIGB1bmRlZmluZWRgIHdoZW4gYWJzZW50LlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgaW5uZXJHZXQoc3ltYm9sOiBzeW1ib2wsIGtleT86IHN0cmluZyB8IHN5bWJvbCkge1xuICAgIGlmICghdGhpcy5fbWV0YWRhdGFbc3ltYm9sXSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoIWtleSkgcmV0dXJuIHRoaXMuX21ldGFkYXRhW3N5bWJvbF07XG4gICAgaWYgKHR5cGVvZiBrZXkgPT09IFwic3RyaW5nXCIpXG4gICAgICByZXR1cm4gZ2V0VmFsdWVCeVNwbGl0dGVyKHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sIGtleSwgdGhpcy5zcGxpdHRlcik7XG4gICAgcmV0dXJuIHRoaXMuX21ldGFkYXRhW3N5bWJvbF1ba2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV3JpdGVzIG1ldGFkYXRhIHVuZGVyIGEgc3ltYm9sIGtleS5cbiAgICogQHN1bW1hcnkgSW50ZXJuYWwgaGVscGVyIHRoYXQgZW5zdXJlcyB0aGUgbWV0YWRhdGEgYnVja2V0IGV4aXN0cyBmb3IgdGhlIHByb3ZpZGVkIHN5bWJvbCBhbmQgcGVyc2lzdHMgdGhlIGdpdmVuIHZhbHVlLCBkcmlsbGluZyBpbnRvIG5lc3RlZCBzdHJ1Y3R1cmVzIHdoZW4gdGhlIGtleSBpcyBhIHN0cmluZyBwYXRoLlxuICAgKiBAcGFyYW0ge3N5bWJvbH0gc3ltYm9sIFN5bWJvbCByZXByZXNlbnRpbmcgdGhlIG1ldGFkYXRhIGJ1Y2tldC5cbiAgICogQHBhcmFtIHtzdHJpbmd8c3ltYm9sfSBrZXkgTmVzdGVkIGtleSBwYXRoIG9yIGRpcmVjdCBzeW1ib2wgdW5kZXIgd2hpY2ggdG8gc3RvcmUgdGhlIG1ldGFkYXRhIHZhbHVlLlxuICAgKiBAcGFyYW0ge2FueX0gdmFsdWUgVmFsdWUgcGVyc2lzdGVkIGluIHRoZSBtZXRhZGF0YSBzdG9yZS5cbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGlubmVyU2V0KHN5bWJvbDogc3ltYm9sLCBrZXk6IHN0cmluZyB8IHN5bWJvbCwgdmFsdWU6IGFueSkge1xuICAgIGlmICghdGhpcy5fbWV0YWRhdGFbc3ltYm9sXSkgdGhpcy5fbWV0YWRhdGFbc3ltYm9sXSA9IHt9IGFzIGFueTtcbiAgICBpZiAodHlwZW9mIGtleSA9PT0gXCJzdHJpbmdcIilcbiAgICAgIHJldHVybiBzZXRWYWx1ZUJ5U3BsaXR0ZXIoXG4gICAgICAgIHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sXG4gICAgICAgIGtleSxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIHRoaXMuc3BsaXR0ZXJcbiAgICAgICk7XG4gICAgdGhpcy5fbWV0YWRhdGFbc3ltYm9sXVtrZXldID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFdyaXRlcyBhIG1ldGFkYXRhIHZhbHVlIGF0IGEgZ2l2ZW4gbmVzdGVkIGtleSBwYXRoLlxuICAgKiBAc3VtbWFyeSBFbnN1cmVzIHRoZSBtZXRhZGF0YSByZWNvcmQgZXhpc3RzIGZvciB0aGUgY29uc3RydWN0b3IsIG1pcnJvcnMgaXQgb24gdGhlIGNvbnN0cnVjdG9yIHdoZW4gZW5hYmxlZCwgYW5kIHNldHMgdGhlIHByb3ZpZGVkIHZhbHVlIG9uIHRoZSBuZXN0ZWQga2V5IHBhdGggdXNpbmcgdGhlIGNvbmZpZ3VyZWQgc3BsaXR0ZXIuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT58c3RyaW5nfSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3IgdG8gd2hpY2ggdGhlIG1ldGFkYXRhIGJlbG9uZ3Mgb3IgYSBkaXJlY3QgaWRlbnRpZmllciBzdHJpbmcuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgTmVzdGVkIGtleSBwYXRoIGF0IHdoaWNoIHRvIHN0b3JlIHRoZSB2YWx1ZS5cbiAgICogQHBhcmFtIHthbnl9IHZhbHVlIFZhbHVlIHRvIHN0b3JlIGluIHRoZSBtZXRhZGF0YS5cbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHN0YXRpYyBzZXQobW9kZWw6IENvbnN0cnVjdG9yIHwgc3RyaW5nLCBrZXk6IHN0cmluZywgdmFsdWU6IGFueSk6IHZvaWQge1xuICAgIGlmICh0eXBlb2YgbW9kZWwgIT09IFwic3RyaW5nXCIpIG1vZGVsID0gdGhpcy5jb25zdHIobW9kZWwpIHx8IG1vZGVsO1xuICAgIGNvbnN0IHN5bWJvbCA9IFN5bWJvbC5mb3IobW9kZWwudG9TdHJpbmcoKSk7XG4gICAgdGhpcy5pbm5lclNldChzeW1ib2wsIGtleSwgdmFsdWUpO1xuICAgIGlmIChcbiAgICAgIE1ldGFkYXRhLm1pcnJvciAmJlxuICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbCwgdGhpcy5iYXNlS2V5KVxuICAgICkge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZGVsLCB0aGlzLmJhc2VLZXksIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVycyBhIGRlY29yYXRpb24tYXdhcmUgbGlicmFyeSBhbmQgaXRzIHZlcnNpb24uXG4gICAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgdmVyc2lvbiBzdHJpbmcgZm9yIGFuIGludGVncmF0aW5nIGxpYnJhcnkgdW5kZXIgdGhlIHNoYXJlZCBsaWJyYXJpZXMgbWV0YWRhdGEgc3ltYm9sLCBwcmV2ZW50aW5nIGR1cGxpY2F0ZSByZWdpc3RyYXRpb25zIGZvciB0aGUgc2FtZSBsaWJyYXJ5IGlkZW50aWZpZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsaWJyYXJ5IFBhY2thZ2UgbmFtZSBvciBpZGVudGlmaWVyIHRvIHJlZ2lzdGVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmVyc2lvbiBTZW1hbnRpYyB2ZXJzaW9uIHN0cmluZyBhc3NvY2lhdGVkIHdpdGggdGhlIGxpYnJhcnkuXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgbGlicmFyeSBoYXMgYWxyZWFkeSBiZWVuIHJlZ2lzdGVyZWQuXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJMaWJyYXJ5KGxpYnJhcnk6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nKSB7XG4gICAgY29uc3Qgc3ltYm9sID0gU3ltYm9sLmZvcihEZWNvcmF0aW9uS2V5cy5MSUJSQVJJRVMpO1xuICAgIGNvbnN0IGxpYiA9IHRoaXMuaW5uZXJHZXQoc3ltYm9sLCBsaWJyYXJ5KTtcbiAgICBpZiAobGliKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTGlicmFyeSBhbHJlYWR5ICR7bGlicmFyeX0gcmVnaXN0ZXJlZCB3aXRoIHZlcnNpb24gJHt2ZXJzaW9ufWBcbiAgICAgICk7XG4gICAgdGhpcy5pbm5lclNldChzeW1ib2wsIGxpYnJhcnksIHZlcnNpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaXN0cyByZWdpc3RlcmVkIGRlY29yYXRpb24tYXdhcmUgbGlicmFyaWVzLlxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBpbi1tZW1vcnkgbWFwIG9mIGxpYnJhcnkgaWRlbnRpZmllcnMgdG8gc2VtYW50aWMgdmVyc2lvbnMgdGhhdCBoYXZlIGJlZW4gcmVnaXN0ZXJlZCB3aXRoIHRoZSBEZWNvcmF0aW9uIG1ldGFkYXRhIHN0b3JlLlxuICAgKiBAcmV0dXJuIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+fSBNYXAgb2YgcmVnaXN0ZXJlZCBsaWJyYXJ5IGlkZW50aWZpZXJzIHRvIHRoZWlyIHZlcnNpb24gc3RyaW5ncy5cbiAgICovXG4gIHN0YXRpYyBsaWJyYXJpZXMoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gICAgY29uc3Qgc3ltYm9sID0gU3ltYm9sLmZvcihEZWNvcmF0aW9uS2V5cy5MSUJSQVJJRVMpO1xuICAgIHJldHVybiB0aGlzLmlubmVyR2V0KHN5bWJvbCkgfHwge307XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEpvaW5zIHBhdGggc2VnbWVudHMgdXNpbmcgdGhlIGN1cnJlbnQgc3BsaXR0ZXIuXG4gICAqIEBzdW1tYXJ5IENvbnN0cnVjdHMgYSBuZXN0ZWQgbWV0YWRhdGEga2V5IGJ5IGNvbmNhdGVuYXRpbmcgc3RyaW5nIHNlZ21lbnRzIHdpdGggdGhlIGNvbmZpZ3VyZWQgc3BsaXR0ZXIgZm9yIHVzZSB3aXRoIHRoZSBtZXRhZGF0YSBzdG9yZS5cbiAgICogQHBhcmFtIHsuLi5zdHJpbmd9IHN0cnMgS2V5IHNlZ21lbnRzIHRvIGpvaW4gaW50byBhIGZ1bGwgbWV0YWRhdGEgcGF0aC5cbiAgICogQHJldHVybiB7c3RyaW5nfSBTcGxpdHRlci1qb2luZWQgbWV0YWRhdGEga2V5LlxuICAgKi9cbiAgc3RhdGljIGtleSguLi5zdHJzOiBzdHJpbmdbXSkge1xuICAgIHJldHVybiBzdHJzLmpvaW4odGhpcy5zcGxpdHRlcik7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIERlY29yYXRpb25CdWlsZGVyQnVpbGQsXG4gIERlY29yYXRpb25CdWlsZGVyRW5kLFxuICBEZWNvcmF0aW9uQnVpbGRlck1pZCxcbiAgRGVjb3JhdGlvbkJ1aWxkZXJTdGFydCxcbiAgRmxhdm91clJlc29sdmVyLFxuICBJRGVjb3JhdGlvbkJ1aWxkZXIsXG59IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBEZWZhdWx0Rmxhdm91ciB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCByZXNvbHZlciB0aGF0IHJldHVybnMgdGhlIGN1cnJlbnQgZGVmYXVsdCBmbGF2b3VyLlxuICogQHN1bW1hcnkgUmVzb2x2ZXMgdGhlIGZsYXZvdXIgZm9yIGEgZ2l2ZW4gdGFyZ2V0IGJ5IGFsd2F5cyByZXR1cm5pbmcgdGhlIGxpYnJhcnkncyBgRGVmYXVsdEZsYXZvdXJgIHZhbHVlLlxuICogQHBhcmFtIHtvYmplY3R9IHRhcmdldCBUYXJnZXQgb2JqZWN0IGJlaW5nIGRlY29yYXRlZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gUmVzb2x2ZWQgZmxhdm91ciBpZGVudGlmaWVyLlxuICogQGZ1bmN0aW9uIGRlZmF1bHRGbGF2b3VyUmVzb2x2ZXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG5mdW5jdGlvbiBkZWZhdWx0Rmxhdm91clJlc29sdmVyKHRhcmdldDogb2JqZWN0KSB7XG4gIHJldHVybiBEZWZhdWx0Rmxhdm91cjtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVW5pb24gdHlwZSBjb3ZlcmluZyBzdXBwb3J0ZWQgZGVjb3JhdG9yIGtpbmRzLlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbnkgb2YgdGhlIHN0YW5kYXJkIFR5cGVTY3JpcHQgZGVjb3JhdG9yIHNpZ25hdHVyZXMgKGNsYXNzLCBwcm9wZXJ0eSwgb3IgbWV0aG9kKSwgZW5hYmxpbmcgZmxleGlibGUgcmVnaXN0cmF0aW9uIGFuZCBhcHBsaWNhdGlvbiB3aXRoaW4gdGhlIERlY29yYXRpb24gc3lzdGVtLlxuICogQHRlbXBsYXRlIFRcbiAqIEB0eXBlRGVmIERlY29yYXRvclR5cGVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IHR5cGUgRGVjb3JhdG9yVHlwZXMgPVxuICB8IENsYXNzRGVjb3JhdG9yXG4gIHwgUHJvcGVydHlEZWNvcmF0b3JcbiAgfCBNZXRob2REZWNvcmF0b3I7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFR5cGUgZGVmaW5pdGlvbiBmb3IgYSBkZWNvcmF0b3IgZmFjdG9yeSBmdW5jdGlvbi5cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgYXJiaXRyYXJ5IGFyZ3VtZW50cyBhbmQgcmV0dXJucyBhIGNvbmNyZXRlIGRlY29yYXRvciBmdW5jdGlvbiB0byBiZSBhcHBsaWVkIHRvIGEgdGFyZ2V0LlxuICogQHRlbXBsYXRlIEFcbiAqIEB0eXBlRGVmIERlY29yYXRvckZhY3RvcnlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgdHlwZSBEZWNvcmF0b3JGYWN0b3J5ID0gKC4uLmFyZ3M6IGFueVtdKSA9PiBEZWNvcmF0b3JUeXBlcztcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXJndW1lbnQgYnVuZGxlIGZvciBhIGRlY29yYXRvciBmYWN0b3J5LlxuICogQHN1bW1hcnkgT2JqZWN0IGZvcm0gdXNlZCB0byBkZWZlciBkZWNvcmF0b3IgY3JlYXRpb24sIGNhcnJ5aW5nIGJvdGggdGhlIGZhY3RvcnkgZnVuY3Rpb24gYW5kIGl0cyBhcmd1bWVudCBsaXN0IHRvIGJlIGludm9rZWQgbGF0ZXIgZHVyaW5nIGFwcGxpY2F0aW9uLlxuICogQHR5cGVEZWYgRGVjb3JhdG9yRmFjdG9yeUFyZ3NcbiAqIEBwcm9wZXJ0eSB7RGVjb3JhdG9yRmFjdG9yeX0gZGVjb3JhdG9yIEZhY3RvcnkgZnVuY3Rpb24gdGhhdCBwcm9kdWNlcyBhIGRlY29yYXRvciB3aGVuIGludm9rZWQuXG4gKiBAcHJvcGVydHkge2FueVtdfSBhcmdzIExpc3Qgb2YgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGRlY29yYXRvciBmYWN0b3J5LlxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckZhY3RvcnlBcmdzID0ge1xuICBkZWNvcmF0b3I6IERlY29yYXRvckZhY3Rvcnk7XG4gIGFyZ3M6IGFueVtdO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVW5pb24gdGhhdCByZXByZXNlbnRzIGVpdGhlciBhIHJlYWR5LXRvLWFwcGx5IGRlY29yYXRvciBvciBhIGZhY3Rvcnkgd2l0aCBhcmd1bWVudHMuXG4gKiBAc3VtbWFyeSBBbGxvd3MgcmVnaXN0ZXJpbmcgZGVjb3JhdG9ycyBpbiB0d28gZm9ybXM6IGFzIGRpcmVjdCBkZWNvcmF0b3IgZnVuY3Rpb25zIG9yIGFzIGRlZmVycmVkIGZhY3RvcmllcyBwYWlyZWQgd2l0aCB0aGVpciBhcmd1bWVudCBsaXN0cyBmb3IgbGF0ZXIgaW5zdGFudGlhdGlvbi5cbiAqIEB0eXBlRGVmIERlY29yYXRvckRhdGFcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgdHlwZSBEZWNvcmF0b3JEYXRhID0gRGVjb3JhdG9yVHlwZXMgfCBEZWNvcmF0b3JGYWN0b3J5QXJncztcbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgZGVjb3JhdG9yIG1hbmFnZW1lbnQgY2xhc3MgdGhhdCBoYW5kbGVzIGZsYXZvdXJlZCBkZWNvcmF0b3JzLlxuICogQHN1bW1hcnkgVGhlIERlY29yYXRpb24gY2xhc3MgcHJvdmlkZXMgYSBidWlsZGVyIHBhdHRlcm4gZm9yIGNyZWF0aW5nIGFuZCBtYW5hZ2luZyBkZWNvcmF0b3JzIHdpdGggZGlmZmVyZW50IGZsYXZvdXJzLiBJdCBzdXBwb3J0cyByZWdpc3RlcmluZywgZXh0ZW5kaW5nLCBhbmQgYXBwbHlpbmcgZGVjb3JhdG9ycyB3aXRoIGNvbnRleHQtYXdhcmUgZmxhdm91ciByZXNvbHV0aW9uLCBhbGxvd2luZyBmcmFtZXdvcmstc3BlY2lmaWMgaW1wbGVtZW50YXRpb25zIHdoaWxlIG1haW50YWluaW5nIGEgY29uc2lzdGVudCBBUEkuXG4gKiBAdGVtcGxhdGUgVCBUeXBlIG9mIHRoZSBkZWNvcmF0b3IgKENsYXNzRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IpLlxuICogQHBhcmFtIHtzdHJpbmd9IFtmbGF2b3VyPURlZmF1bHRGbGF2b3VyXSBPcHRpb25hbCBmbGF2b3VyIHBhcmFtZXRlciBmb3IgdGhlIGRlY29yYXRvciBjb250ZXh0LlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQ3JlYXRlIGEgbmV3IGRlY29yYXRpb24gZm9yICdjb21wb25lbnQnIHdpdGggZGVmYXVsdCBmbGF2b3VyXG4gKiBjb25zdCBjb21wb25lbnREZWNvcmF0b3IgPSBuZXcgRGVjb3JhdGlvbigpXG4gKiAgIC5mb3IoJ2NvbXBvbmVudCcpXG4gKiAgIC5kZWZpbmUoY3VzdG9tQ29tcG9uZW50RGVjb3JhdG9yKTtcbiAqXG4gKiAvLyBDcmVhdGUgYSBmbGF2b3VyZWQgZGVjb3JhdGlvblxuICogY29uc3QgdnVlQ29tcG9uZW50ID0gbmV3IERlY29yYXRpb24oJ3Z1ZScpXG4gKiAgIC5mb3IoJ2NvbXBvbmVudCcpXG4gKiAgIC5kZWZpbmUodnVlQ29tcG9uZW50RGVjb3JhdG9yKTtcbiAqXG4gKiAvLyBBcHBseSB0aGUgZGVjb3JhdGlvblxuICogQGNvbXBvbmVudERlY29yYXRvclxuICogY2xhc3MgTXlDb21wb25lbnQge31cbiAqIGBgYFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudFxuICogICBwYXJ0aWNpcGFudCBEIGFzIERlY29yYXRpb25cbiAqICAgcGFydGljaXBhbnQgUiBhcyBGbGF2b3VyUmVzb2x2ZXJcbiAqICAgcGFydGljaXBhbnQgRiBhcyBEZWNvcmF0b3JGYWN0b3J5XG4gKlxuICogICBDLT4+RDogbmV3IERlY29yYXRpb24oZmxhdm91cilcbiAqICAgQy0+PkQ6IGZvcihrZXkpXG4gKiAgIEMtPj5EOiBkZWZpbmUoZGVjb3JhdG9ycylcbiAqICAgRC0+PkQ6IHJlZ2lzdGVyKGtleSwgZmxhdm91ciwgZGVjb3JhdG9ycylcbiAqICAgRC0+PkY6IGRlY29yYXRvckZhY3Rvcnkoa2V5LCBmbGF2b3VyKVxuICogICBGLT4+UjogcmVzb2x2ZSh0YXJnZXQpXG4gKiAgIFItLT4+RjogcmVzb2x2ZWQgZmxhdm91clxuICogICBGLT4+RjogYXBwbHkgZGVjb3JhdG9yc1xuICogICBGLS0+PkM6IGRlY29yYXRlZCB0YXJnZXRcbiAqL1xuZXhwb3J0IGNsYXNzIERlY29yYXRpb24gaW1wbGVtZW50cyBJRGVjb3JhdGlvbkJ1aWxkZXIge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0YXRpYyBtYXAgb2YgcmVnaXN0ZXJlZCBkZWNvcmF0b3JzLlxuICAgKiBAc3VtbWFyeSBTdG9yZXMgYWxsIHJlZ2lzdGVyZWQgZGVjb3JhdG9ycyBvcmdhbmlzZWQgYnkga2V5IGFuZCBmbGF2b3VyLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZGVjb3JhdG9yczogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBSZWNvcmQ8XG4gICAgICBzdHJpbmcsXG4gICAgICB7XG4gICAgICAgIGRlY29yYXRvcnM/OiBTZXQ8RGVjb3JhdG9yRGF0YT47XG4gICAgICAgIGV4dHJhcz86IFNldDxEZWNvcmF0b3JEYXRhPjtcbiAgICAgIH1cbiAgICA+XG4gID4gPSB7fTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZ1bmN0aW9uIHRvIHJlc29sdmUgZmxhdm91ciBmcm9tIGEgdGFyZ2V0LlxuICAgKiBAc3VtbWFyeSBSZXNvbHZlciBmdW5jdGlvbiB0aGF0IGRldGVybWluZXMgdGhlIGFwcHJvcHJpYXRlIGZsYXZvdXIgZm9yIGEgZ2l2ZW4gdGFyZ2V0LlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZmxhdm91clJlc29sdmVyOiBGbGF2b3VyUmVzb2x2ZXIgPSBkZWZhdWx0Rmxhdm91clJlc29sdmVyO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0IG9mIGRlY29yYXRvcnMgZm9yIHRoZSBjdXJyZW50IGNvbnRleHQuXG4gICAqL1xuICBwcml2YXRlIGRlY29yYXRvcnM/OiBTZXQ8RGVjb3JhdG9yRGF0YT47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXQgb2YgYWRkaXRpb25hbCBkZWNvcmF0b3JzLlxuICAgKi9cbiAgcHJpdmF0ZSBleHRyYXM/OiBTZXQ8RGVjb3JhdG9yRGF0YT47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDdXJyZW50IGRlY29yYXRvciBrZXkuXG4gICAqL1xuICBwcml2YXRlIGtleT86IHN0cmluZztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZsYXZvdXI6IHN0cmluZyA9IERlZmF1bHRGbGF2b3VyKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUga2V5IGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyLlxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXNlcyBhIG5ldyBkZWNvcmF0aW9uIGNoYWluIHdpdGggdGhlIHNwZWNpZmllZCBrZXkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgSWRlbnRpZmllciBmb3IgdGhlIGRlY29yYXRvci5cbiAgICogQHJldHVybiB7RGVjb3JhdGlvbkJ1aWxkZXJNaWR9IEJ1aWxkZXIgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIGZvcihrZXk6IHN0cmluZyk6IERlY29yYXRpb25CdWlsZGVyTWlkIHtcbiAgICB0aGlzLmtleSA9IGtleTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWRkcyBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHQuXG4gICAqIEBzdW1tYXJ5IEludGVybmFsIG1ldGhvZCB0byBhZGQgZGVjb3JhdG9ycyB3aXRoIGFkZG9uIHN1cHBvcnQuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2FkZG9uPWZhbHNlXSBJbmRpY2F0ZXMgd2hldGhlciB0aGUgZGVjb3JhdG9ycyBhcmUgYWRkaXRpdmUgZXh0cmFzLlxuICAgKiBAcGFyYW0gey4uLkRlY29yYXRvckRhdGF9IGRlY29yYXRvcnMgRGVjb3JhdG9ycyB0byByZWdpc3RlciBmb3IgdGhlIGNvbmZpZ3VyZWQga2V5LlxuICAgKiBAcmV0dXJuIHt0aGlzfSBDdXJyZW50IGluc3RhbmNlIGZvciBjaGFpbmluZy5cbiAgICovXG4gIHByaXZhdGUgZGVjb3JhdGUoXG4gICAgYWRkb246IGJvb2xlYW4gPSBmYWxzZSxcbiAgICAuLi5kZWNvcmF0b3JzOiBEZWNvcmF0b3JEYXRhW11cbiAgKTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLmtleSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImtleSBtdXN0IGJlIHByb3ZpZGVkIGJlZm9yZSBkZWNvcmF0b3JzIGNhbiBiZSBhZGRlZFwiKTtcbiAgICBpZiAoXG4gICAgICAoIWRlY29yYXRvcnMgfHwgIWRlY29yYXRvcnMubGVuZ3RoKSAmJlxuICAgICAgIWFkZG9uICYmXG4gICAgICB0aGlzLmZsYXZvdXIgIT09IERlZmF1bHRGbGF2b3VyXG4gICAgKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIk11c3QgcHJvdmlkZSBvdmVycmlkZXMgb3IgYWRkb25zIHRvIG92ZXJyaWRlIG9yIGV4dGVuZCBkZWNhZidzIGRlY29yYXRvcnNcIlxuICAgICAgKTtcbiAgICBpZiAodGhpcy5mbGF2b3VyID09PSBEZWZhdWx0Rmxhdm91ciAmJiBhZGRvbilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkRlZmF1bHQgZmxhdm91ciBjYW5ub3QgYmUgZXh0ZW5kZWRcIik7XG5cbiAgICB0aGlzW2FkZG9uID8gXCJleHRyYXNcIiA6IFwiZGVjb3JhdG9yc1wiXSA9IG5ldyBTZXQoW1xuICAgICAgLi4uKHRoaXNbYWRkb24gPyBcImV4dHJhc1wiIDogXCJkZWNvcmF0b3JzXCJdIHx8IG5ldyBTZXQoKSkudmFsdWVzKCksXG4gICAgICAuLi5kZWNvcmF0b3JzLFxuICAgIF0pO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgdGhlIGJhc2UgZGVjb3JhdG9ycy5cbiAgICogQHN1bW1hcnkgU2V0cyB0aGUgcHJpbWFyeSBkZWNvcmF0b3JzIGZvciB0aGUgY3VycmVudCBjb250ZXh0LlxuICAgKiBAcGFyYW0gey4uLkRlY29yYXRvckRhdGF9IGRlY29yYXRvcnMgRGVjb3JhdG9ycyB0byBkZWZpbmUuXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyRW5kfSBCdWlsZGVyIGluc3RhbmNlIGZvciBmaW5pc2hpbmcgdGhlIGNoYWluIChhbHNvIGltcGxlbWVudHMgRGVjb3JhdGlvbkJ1aWxkZXJCdWlsZCkuXG4gICAqL1xuICBkZWZpbmUoXG4gICAgLi4uZGVjb3JhdG9yczogRGVjb3JhdG9yRGF0YVtdXG4gICk6IERlY29yYXRpb25CdWlsZGVyRW5kICYgRGVjb3JhdGlvbkJ1aWxkZXJCdWlsZCB7XG4gICAgaWYgKFxuICAgICAgZGVjb3JhdG9ycy5maW5kKChkKSA9PiB0eXBlb2YgZCA9PT0gXCJvYmplY3RcIikgJiZcbiAgICAgIGRlY29yYXRvcnMubGVuZ3RoICE9PSAxXG4gICAgKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgV2hlbiB1c2luZyBhbiBvdmVycmlkYWJsZSBkZWNvcmF0b3IsIG9ubHkgb25lIGlzIGFsbG93ZWRgXG4gICAgICApO1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKGZhbHNlLCAuLi5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXh0ZW5kcyBleGlzdGluZyBkZWNvcmF0b3JzLlxuICAgKiBAc3VtbWFyeSBBZGRzIGFkZGl0aW9uYWwgZGVjb3JhdG9ycyB0byB0aGUgY3VycmVudCBjb250ZXh0LlxuICAgKiBAcGFyYW0gey4uLkRlY29yYXRvckRhdGF9IGRlY29yYXRvcnMgQWRkaXRpb25hbCBkZWNvcmF0b3JzIHRvIHJlZ2lzdGVyIGFzIGFkZG9ucy5cbiAgICogQHJldHVybiB7RGVjb3JhdGlvbkJ1aWxkZXJCdWlsZH0gQnVpbGRlciBpbnN0YW5jZSBmb3IgYnVpbGRpbmcgdGhlIGRlY29yYXRvci5cbiAgICovXG4gIGV4dGVuZCguLi5kZWNvcmF0b3JzOiBEZWNvcmF0b3JEYXRhW10pOiBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkIHtcbiAgICBpZiAoXG4gICAgICBkZWNvcmF0b3JzLmZpbmQoKGQpID0+IHR5cGVvZiBkID09PSBcIm9iamVjdFwiKSAmJlxuICAgICAgZGVjb3JhdG9ycy5sZW5ndGggIT09IDFcbiAgICApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBXaGVuIGV4dGVuZGluZyB1c2luZyBhbiBvdmVycmlkYWJsZSBkZWNvcmF0b3IsIG9ubHkgb25lIGlzIGFsbG93ZWRgXG4gICAgICApO1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKHRydWUsIC4uLmRlY29yYXRvcnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBGYWN0b3J5IHRoYXQgY3JlYXRlcyBhIGNvbnRleHQtYXdhcmUgZGVjb3JhdG9yIGZvciBhIGtleS9mbGF2b3VyLlxuICAgKiBAc3VtbWFyeSBQcm9kdWNlcyBhIGRlY29yYXRvciBmdW5jdGlvbiBib3VuZCB0byB0aGUgcHJvdmlkZWQga2V5IGFuZCBmbGF2b3VyLiBUaGUgcmVzdWx0aW5nIGRlY29yYXRvciByZXNvbHZlcyB0aGUgYWN0dWFsIGRlY29yYXRvcnMgdG8gYXBwbHkgYXQgaW52b2NhdGlvbiB0aW1lIGJhc2VkIG9uIHRoZSB0YXJnZXQncyByZXNvbHZlZCBmbGF2b3VyIGFuZCB0aGUgcmVnaXN0ZXJlZCBiYXNlIGFuZCBleHRyYSBkZWNvcmF0b3JzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IERlY29yYXRpb24ga2V5IHVzZWQgdG8gbG9vayB1cCByZWdpc3RlcmVkIGRlY29yYXRvcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZj1EZWZhdWx0Rmxhdm91cl0gRXhwbGljaXQgZmxhdm91ciB0byBiaW5kIHRoZSBmYWN0b3J5IHRvLlxuICAgKiBAcmV0dXJuIHtDbGFzc0RlY29yYXRvcnxNZXRob2REZWNvcmF0b3J8UHJvcGVydHlEZWNvcmF0b3J8UGFyYW1ldGVyRGVjb3JhdG9yfSBEZWNvcmF0b3IgZnVuY3Rpb24gdGhhdCBhcHBsaWVzIHRoZSByZXNvbHZlZCBkZWNvcmF0b3JzLlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXIgQ29kZVxuICAgKiAgIHBhcnRpY2lwYW50IEIgYXMgRGVjb3JhdGlvbiAoYnVpbGRlcilcbiAgICogICBwYXJ0aWNpcGFudCBGIGFzIGRlY29yYXRvckZhY3Rvcnkoa2V5LCBmKVxuICAgKiAgIHBhcnRpY2lwYW50IFIgYXMgZmxhdm91clJlc29sdmVyXG4gICAqICAgcGFydGljaXBhbnQgQSBhcyBBcHBsaWVkIERlY29yYXRvcnNcbiAgICogICBVLT4+QjogZGVmaW5lKCkvZXh0ZW5kKCkgYW5kIGFwcGx5KClcbiAgICogICBCLT4+RjogY3JlYXRlIGNvbnRleHQgZGVjb3JhdG9yXG4gICAqICAgRi0+PlI6IHJlc29sdmUodGFyZ2V0KVxuICAgKiAgIFItLT4+RjogZmxhdm91clxuICAgKiAgIEYtPj5BOiBjb2xsZWN0IGJhc2UgKyBleHRyYXNcbiAgICogICBsb29wIGVhY2ggZGVjb3JhdG9yXG4gICAqICAgICBBLT4+VTogaW52b2tlIGRlY29yYXRvcih0YXJnZXQsIGtleT8sIGRlc2M/KVxuICAgKiAgIGVuZFxuICAgKi9cbiAgcHJvdGVjdGVkIGRlY29yYXRvckZhY3Rvcnkoa2V5OiBzdHJpbmcsIGY6IHN0cmluZyA9IERlZmF1bHRGbGF2b3VyKSB7XG4gICAgZnVuY3Rpb24gY29udGV4dERlY29yYXRvcihcbiAgICAgIHRhcmdldDogb2JqZWN0LFxuICAgICAgcHJvcGVydHlLZXk/OiBhbnksXG4gICAgICBkZXNjcmlwdG9yPzogVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8YW55PlxuICAgICkge1xuICAgICAgY29uc3QgZmxhdm91ciA9IERlY29yYXRpb24uZmxhdm91clJlc29sdmVyKHRhcmdldCk7XG4gICAgICBjb25zdCBjYWNoZSA9IERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldO1xuICAgICAgbGV0IGRlY29yYXRvcnM7XG4gICAgICBjb25zdCBleHRyYXMgPSBjYWNoZVtmbGF2b3VyXVxuICAgICAgICA/IGNhY2hlW2ZsYXZvdXJdLmV4dHJhc1xuICAgICAgICA6IGNhY2hlW0RlZmF1bHRGbGF2b3VyXS5leHRyYXM7XG5cbiAgICAgIGlmIChcbiAgICAgICAgY2FjaGUgJiZcbiAgICAgICAgY2FjaGVbZmxhdm91cl0gJiZcbiAgICAgICAgY2FjaGVbZmxhdm91cl0uZGVjb3JhdG9ycyAmJlxuICAgICAgICBjYWNoZVtmbGF2b3VyXS5kZWNvcmF0b3JzLnNpemVcbiAgICAgICkge1xuICAgICAgICBkZWNvcmF0b3JzID0gY2FjaGVbZmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlY29yYXRvcnMgPSBjYWNoZVtEZWZhdWx0Rmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVjb3JhdG9yQXJncyA9IFtcbiAgICAgICAgLi4uKGNhY2hlW0RlZmF1bHRGbGF2b3VyXSBhcyBhbnkpLmRlY29yYXRvcnMudmFsdWVzKCksXG4gICAgICBdLnJlZHVjZSgoYWNjdW06IFJlY29yZDxudW1iZXIsIGFueT4sIGUsIGkpID0+IHtcbiAgICAgICAgaWYgKGUuYXJncykgYWNjdW1baV0gPSBlLmFyZ3M7XG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sIHt9KTtcblxuICAgICAgY29uc3QgdG9BcHBseSA9IFtcbiAgICAgICAgLi4uKGRlY29yYXRvcnMgPyBkZWNvcmF0b3JzLnZhbHVlcygpIDogW10pLFxuICAgICAgICAuLi4oZXh0cmFzID8gZXh0cmFzLnZhbHVlcygpIDogW10pLFxuICAgICAgXTtcblxuICAgICAgcmV0dXJuIHRvQXBwbHkucmVkdWNlKFxuICAgICAgICAoXywgZCkgPT4ge1xuICAgICAgICAgIHN3aXRjaCAodHlwZW9mIGQpIHtcbiAgICAgICAgICAgIGNhc2UgXCJvYmplY3RcIjoge1xuICAgICAgICAgICAgICBjb25zdCB7IGRlY29yYXRvciB9ID0gZCBhcyBEZWNvcmF0b3JGYWN0b3J5QXJncztcblxuICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIGRlY29yYXRvciguLi4oT2JqZWN0LnZhbHVlcyhkZWNvcmF0b3JBcmdzKVswXSB8fCBbXSkpIGFzIGFueVxuICAgICAgICAgICAgICApKHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgICAgICAgIHJldHVybiAoZCBhcyBhbnkpKHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIGRlY29yYXRvciB0eXBlOiAke3R5cGVvZiBkfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgeyB0YXJnZXQsIHByb3BlcnR5S2V5LCBkZXNjcmlwdG9yIH1cbiAgICAgICk7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb250ZXh0RGVjb3JhdG9yLCBcIm5hbWVcIiwge1xuICAgICAgdmFsdWU6IFtmLCBrZXldLmpvaW4oXCJfZGVjb3JhdG9yX2Zvcl9cIiksXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbnRleHREZWNvcmF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgdGhlIGZpbmFsIGRlY29yYXRvciBmdW5jdGlvbi5cbiAgICogQHN1bW1hcnkgQnVpbGRzIGFuZCByZXR1cm5zIHRoZSBkZWNvcmF0b3IgZmFjdG9yeSBmdW5jdGlvbi5cbiAgICogQHJldHVybiB7Q2xhc3NEZWNvcmF0b3J8TWV0aG9kRGVjb3JhdG9yfFByb3BlcnR5RGVjb3JhdG9yfFBhcmFtZXRlckRlY29yYXRvcn0gR2VuZXJhdGVkIGRlY29yYXRvciBmdW5jdGlvbiByZWFkeSBmb3IgYXBwbGljYXRpb24uXG4gICAqL1xuICBhcHBseSgpOiAoXG4gICAgdGFyZ2V0OiBhbnksXG4gICAgcHJvcGVydHlLZXk/OiBhbnksXG4gICAgZGVzY3JpcHRvcj86IFR5cGVkUHJvcGVydHlEZXNjcmlwdG9yPGFueT5cbiAgKSA9PiBhbnkge1xuICAgIGlmICghdGhpcy5rZXkpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBrZXkgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG4gICAgRGVjb3JhdGlvbi5yZWdpc3RlcihcbiAgICAgIHRoaXMua2V5LFxuICAgICAgdGhpcy5mbGF2b3VyLFxuICAgICAgdGhpcy5kZWNvcmF0b3JzIHx8IG5ldyBTZXQoKSxcbiAgICAgIHRoaXMuZXh0cmFzXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5kZWNvcmF0b3JGYWN0b3J5KHRoaXMua2V5LCB0aGlzLmZsYXZvdXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlcnMgZGVjb3JhdG9ycyBmb3IgYSBzcGVjaWZpYyBrZXkgYW5kIGZsYXZvdXIuXG4gICAqIEBzdW1tYXJ5IEludGVybmFsIG1ldGhvZCB0byBzdG9yZSBkZWNvcmF0b3JzIGluIHRoZSBzdGF0aWMgcmVnaXN0cnkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgRGVjb3JhdG9yIGtleS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGZsYXZvdXIgRGVjb3JhdG9yIGZsYXZvdXIuXG4gICAqIEBwYXJhbSB7U2V0PERlY29yYXRvckRhdGE+fSBbZGVjb3JhdG9yc10gUHJpbWFyeSBkZWNvcmF0b3JzIHJlZ2lzdGVyZWQgZm9yIHRoZSBrZXkuXG4gICAqIEBwYXJhbSB7U2V0PERlY29yYXRvckRhdGE+fSBbZXh0cmFzXSBBZGRpdGlvbmFsIGRlY29yYXRvcnMgcmVnaXN0ZXJlZCBhcyBmbGF2b3VyLXNwZWNpZmljIGFkZG9ucy5cbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlZ2lzdGVyKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGZsYXZvdXI6IHN0cmluZyxcbiAgICBkZWNvcmF0b3JzPzogU2V0PERlY29yYXRvckRhdGE+LFxuICAgIGV4dHJhcz86IFNldDxEZWNvcmF0b3JEYXRhPlxuICApIHtcbiAgICBpZiAoIWtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIH1cbiAgICBpZiAoIWRlY29yYXRvcnMpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBkZWNvcmF0b3JzIHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIGlmICghZmxhdm91cilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGZsYXZvdXIgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG5cbiAgICBpZiAoIURlY29yYXRpb24uZGVjb3JhdG9yc1trZXldKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XSA9IHt9O1xuICAgIGlmICghRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV1bZmxhdm91cl0pXG4gICAgICBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXSA9IHt9O1xuICAgIGlmIChkZWNvcmF0b3JzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5kZWNvcmF0b3JzID0gZGVjb3JhdG9ycztcbiAgICBpZiAoZXh0cmFzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5leHRyYXMgPSBleHRyYXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGdsb2JhbCBmbGF2b3VyIHJlc29sdmVyLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBmdW5jdGlvbiB1c2VkIHRvIGRldGVybWluZSBkZWNvcmF0b3IgZmxhdm91cnMuXG4gICAqIEBwYXJhbSB7Rmxhdm91clJlc29sdmVyfSByZXNvbHZlciBGdW5jdGlvbiB0byByZXNvbHZlIGZsYXZvdXJzLlxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgc3RhdGljIHNldEZsYXZvdXJSZXNvbHZlcihyZXNvbHZlcjogRmxhdm91clJlc29sdmVyKSB7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyUmVzb2x2ZXIgPSByZXNvbHZlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udmVuaWVuY2Ugc3RhdGljIGVudHJ5IHRvIHN0YXJ0IGEgZGVjb3JhdGlvbiBidWlsZGVyLlxuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgbmV3IERlY29yYXRpb24gaW5zdGFuY2UgYW5kIGluaXRpYXRlcyB0aGUgYnVpbGRlciBjaGFpbiB3aXRoIHRoZSBwcm92aWRlZCBrZXkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgRGVjb3JhdGlvbiBrZXkgdG8gY29uZmlndXJlLlxuICAgKiBAcmV0dXJuIHtEZWNvcmF0aW9uQnVpbGRlck1pZH0gQnVpbGRlciBpbnN0YW5jZSBmb3IgY2hhaW5pbmcgZGVmaW5pdGlvbnMuXG4gICAqL1xuICBzdGF0aWMgZm9yKGtleTogc3RyaW5nKTogRGVjb3JhdGlvbkJ1aWxkZXJNaWQge1xuICAgIHJldHVybiBuZXcgRGVjb3JhdGlvbigpLmZvcihrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTdGFydHMgYSBidWlsZGVyIGZvciBhIHNwZWNpZmljIGZsYXZvdXIuXG4gICAqIEBzdW1tYXJ5IENvbnZlbmllbmNlIG1ldGhvZCB0byBiZWdpbiBhIERlY29yYXRpb24gYnVpbGRlciBjaGFpbiBib3VuZCB0byB0aGUgZ2l2ZW4gZmxhdm91ciBpZGVudGlmaWVyLCBhbGxvd2luZyByZWdpc3RyYXRpb24gb2YgZmxhdm91ci1zcGVjaWZpYyBkZWNvcmF0b3JzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmxhdm91ciBGbGF2b3VyIG5hbWUgdG8gYmluZCB0byB0aGUgYnVpbGRlci5cbiAgICogQHJldHVybiB7RGVjb3JhdGlvbkJ1aWxkZXJTdGFydH0gQnVpbGRlciBzdGFydCBpbnRlcmZhY2UgdG8gY29udGludWUgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHN0YXRpYyBmbGF2b3VyZWRBcyhmbGF2b3VyOiBzdHJpbmcpOiBEZWNvcmF0aW9uQnVpbGRlclN0YXJ0IHtcbiAgICByZXR1cm4gbmV3IERlY29yYXRpb24oZmxhdm91cik7XG4gIH1cbn1cbiIsImltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIi4vbWV0YWRhdGEvTWV0YWRhdGFcIjtcbmltcG9ydCB7IERlY29yYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFzc2lnbnMgYXJiaXRyYXJ5IG1ldGFkYXRhIHRvIGEgdGFyZ2V0IHVzaW5nIGEgc3RyaW5nIGtleS5cbiAqIEBzdW1tYXJ5IERlY29yYXRvciBmYWN0b3J5IHRoYXQgc3RvcmVzIGEga2V5L3ZhbHVlIHBhaXIgaW4gdGhlIGNlbnRyYWwgbWV0YWRhdGEgc3RvcmUgZm9yIHRoZSBwcm92aWRlZCBjbGFzcyBvciBtZW1iZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IE1ldGFkYXRhIGtleSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgdGFyZ2V0LlxuICogQHBhcmFtIHthbnl9IHZhbHVlIE1ldGFkYXRhIHZhbHVlIHRvIHN0b3JlIHVuZGVyIHRoZSBnaXZlbiBrZXkuXG4gKiBAcmV0dXJuIHtDbGFzc0RlY29yYXRvcnxNZXRob2REZWNvcmF0b3J8UHJvcGVydHlEZWNvcmF0b3J8UGFyYW1ldGVyRGVjb3JhdG9yfSBEZWNvcmF0b3IgdGhhdCB3cml0ZXMgdGhlIG1ldGFkYXRhIHdoZW4gYXBwbGllZC5cbiAqIEBmdW5jdGlvbiBtZXRhZGF0YVxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1ldGFkYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gIHJldHVybiBmdW5jdGlvbiBtZXRhZGF0YShcbiAgICBtb2RlbDogYW55LFxuXG4gICAgcHJvcD86IGFueSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgZGVzY3JpcHRvcj86IFByb3BlcnR5RGVzY3JpcHRvciB8IG51bWJlclxuICApIHtcbiAgICBNZXRhZGF0YS5zZXQocHJvcCA/IG1vZGVsLmNvbnN0cnVjdG9yIDogbW9kZWwsIGtleSwgdmFsdWUpO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDYXB0dXJlcyBhbmQgc3RvcmVzIGEgcHJvcGVydHkncyBkZXNpZ24gdHlwZS5cbiAqIEBzdW1tYXJ5IERlY29yYXRvciBmYWN0b3J5IHRoYXQgcmVhZHMgdGhlIHJlZmxlY3RlZCBgZGVzaWduOnR5cGVgIGZvciBhIHByb3BlcnR5IGFuZCByZWdpc3RlcnMgaXQgaW4gdGhlIG1ldGFkYXRhIHN0b3JlIHVuZGVyIHRoZSBwcm9wZXJ0aWVzIG1hcC5cbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBEZWNvcmF0b3IgdGhhdCByZWNvcmRzIHRoZSBwcm9wZXJ0eSdzIHR5cGUgbWV0YWRhdGEgd2hlbiBhcHBsaWVkLlxuICogQGZ1bmN0aW9uIHByb3BcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm9wKCkge1xuICByZXR1cm4gZnVuY3Rpb24gcHJvcChtb2RlbDogb2JqZWN0LCBwcm9wOiBhbnkpIHtcbiAgICBjb25zdCBkZXNpZ25UeXBlID0gUmVmbGVjdC5nZXRPd25NZXRhZGF0YShcbiAgICAgIERlY29yYXRpb25LZXlzLkRFU0lHTl9UWVBFLFxuICAgICAgbW9kZWwsXG4gICAgICBwcm9wXG4gICAgKTtcbiAgICByZXR1cm4gbWV0YWRhdGEoTWV0YWRhdGEua2V5KERlY29yYXRpb25LZXlzLlBST1BFUlRJRVMsIHByb3ApLCBkZXNpZ25UeXBlKShcbiAgICAgIG1vZGVsLFxuICAgICAgcHJvcFxuICAgICk7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENhcHR1cmVzIGEgc2luZ2xlIHBhcmFtZXRlciB0eXBlIGZvciB0aGUgZGVjb3JhdGVkIG1ldGhvZC5cbiAqIEBzdW1tYXJ5IERlY29yYXRvciBmYWN0b3J5IHRoYXQgZW5zdXJlcyB0aGUgbWV0aG9kIG1ldGFkYXRhIGlzIGluaXRpYWxpc2VkIGFuZCBzdG9yZXMgdGhlIHJlZmxlY3RlZCBwYXJhbWV0ZXIgY29uc3RydWN0b3IgYXQgdGhlIHByb3ZpZGVkIGluZGV4LlxuICogQHJldHVybiB7UGFyYW1ldGVyRGVjb3JhdG9yfSBEZWNvcmF0b3IgdGhhdCByZWNvcmRzIHRoZSBwYXJhbWV0ZXIgdHlwZSB3aGVuIGFwcGxpZWQuXG4gKiBAZnVuY3Rpb24gcGFyYW1cbiAqIEBjYXRlZ29yeSBQYXJhbWV0ZXIgRGVjb3JhdG9yc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXIgQ29kZVxuICogICBwYXJ0aWNpcGFudCBQIGFzIHBhcmFtKClcbiAqICAgcGFydGljaXBhbnQgTSBhcyBNZXRhZGF0YVxuICogICBVLT4+UDogcGFyYW0oKSh0YXJnZXQsIGtleSwgaW5kZXgpXG4gKiAgIFAtPj5VOiBtZXRob2QoKSh0YXJnZXQsIGtleSwgZGVzY3JpcHRvcilcbiAqICAgUC0+Pk06IHBhcmFtcyhjb25zdHJ1Y3Rvciwga2V5KVxuICogICBNLS0+PlA6IHBhcmFtZXRlciBjb25zdHJ1Y3RvcnNbXVxuICogICBQLT4+TTogc2V0KG1ldGhvZHMua2V5LmluZGV4LCBjb25zdHJ1Y3RvcilcbiAqICAgUC0tPj5VOiBwYXJhbWV0ZXIgcmVjb3JkZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcmFtKCkge1xuICByZXR1cm4gZnVuY3Rpb24gcGFyYW0oXG4gICAgbW9kZWw6IG9iamVjdCxcbiAgICBwcm9wOiBzdHJpbmcgfCBzeW1ib2wgfCB1bmRlZmluZWQsXG4gICAgaW5kZXg6IG51bWJlclxuICApIHtcbiAgICBpZiAoIXByb3ApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBAcGFyYW0gZGVjb3JhdG9yIGNhbiBvbmx5IGJlIGFwcGxpZWQgdG8gbWV0aG9kc2ApO1xuICAgIG1ldGhvZCgpKG1vZGVsLCBwcm9wLCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG1vZGVsLCBwcm9wKSk7XG4gICAgY29uc3QgcGFyYW1UcGVzID0gTWV0YWRhdGEucGFyYW1zKG1vZGVsLmNvbnN0cnVjdG9yIGFzIGFueSwgcHJvcCBhcyBzdHJpbmcpO1xuICAgIGlmICghcGFyYW1UcGVzKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBNaXNzaW5nIHBhcmFtZXRlciB0eXBlcyBmb3IgJHtTdHJpbmcocHJvcCl9YCk7XG4gICAgaWYgKGluZGV4ID49IHBhcmFtVHBlcy5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBQYXJhbWV0ZXIgaW5kZXggJHtpbmRleH0gb3V0IG9mIHJhbmdlIGZvciAke1N0cmluZyhwcm9wKX1gXG4gICAgICApO1xuICAgIG1ldGFkYXRhKFxuICAgICAgTWV0YWRhdGEua2V5KERlY29yYXRpb25LZXlzLk1FVEhPRFMsIHByb3AgYXMgc3RyaW5nLCBpbmRleC50b1N0cmluZygpKSxcbiAgICAgIHBhcmFtVHBlc1tpbmRleF1cbiAgICApKG1vZGVsLCBwcm9wKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXh0ZW5kcyBhIHBhcmFtZXRlciBkZWNvcmF0b3Igd2l0aCBhZGRpdGlvbmFsIG1ldGFkYXRhLlxuICogQHN1bW1hcnkgQXBwbGllcyB0aGUgZGVmYXVsdCBgcGFyYW0oKWAgZGVjb3JhdG9yIGFuZCBhdWdtZW50cyB0aGUgc3RvcmVkIG1ldGFkYXRhIHdpdGggYW4gYXJiaXRyYXJ5IGtleS92YWx1ZSBwYWlyLlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBNZXRhZGF0YSBrZXkgdG8gYXNzb2NpYXRlIHdpdGggdGhlIHBhcmFtZXRlci5cbiAqIEBwYXJhbSB7YW55fSB2YWx1ZSBNZXRhZGF0YSB2YWx1ZSBwZXJzaXN0ZWQgdW5kZXIgdGhlIGdpdmVuIGtleS5cbiAqIEByZXR1cm4ge1BhcmFtZXRlckRlY29yYXRvcn0gRGVjb3JhdG9yIHRoYXQgcmVjb3JkcyBib3RoIHRoZSBwYXJhbWV0ZXIgZGVzaWduIHR5cGUgYW5kIGFkZGl0aW9uYWwgbWV0YWRhdGEuXG4gKiBAZnVuY3Rpb24gcGFyYW1NZXRhZGF0YVxuICogQGNhdGVnb3J5IFBhcmFtZXRlciBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJhbU1ldGFkYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gIHJldHVybiBmdW5jdGlvbiBwYXJhbU1ldGFkYXRhKHRhcmdldDogYW55LCBwcm9wOiBhbnksIGluZGV4OiBudW1iZXIpIHtcbiAgICByZXR1cm4gYXBwbHkoXG4gICAgICBwYXJhbSgpLFxuICAgICAgbWV0YWRhdGEoTWV0YWRhdGEua2V5KERlY29yYXRpb25LZXlzLk1FVEhPRFMsIHByb3AsIGtleSksIHZhbHVlKVxuICAgICkodGFyZ2V0LCBwcm9wLCBpbmRleCk7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlY29yZHMgbWV0aG9kIGRlc2lnbi10aW1lIG1ldGFkYXRhLlxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCBjYXB0dXJlcyBhIG1ldGhvZCdzIHJlZmxlY3RlZCBwYXJhbWV0ZXIgYW5kIHJldHVybiB0eXBlcywgc3RvcmluZyB0aGVtIHVuZGVyIHRoZSBhcHByb3ByaWF0ZSBtZXRhZGF0YSBrZXlzIHNvIHRoZXkgY2FuIGJlIGluc3BlY3RlZCBhdCBydW50aW1lLlxuICogQHJldHVybiB7TWV0aG9kRGVjb3JhdG9yfSBEZWNvcmF0b3IgdGhhdCBwZXJzaXN0cyB0aGUgbWV0aG9kJ3Mgc2lnbmF0dXJlIGluZm9ybWF0aW9uIGludG8gdGhlIG1ldGFkYXRhIHN0b3JlIHdoZW4gYXBwbGllZC5cbiAqIEBmdW5jdGlvbiBtZXRob2RcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgVSBhcyBVc2VyIENvZGVcbiAqICAgcGFydGljaXBhbnQgRiBhcyBtZXRob2QoKVxuICogICBwYXJ0aWNpcGFudCBNIGFzIE1ldGFkYXRhXG4gKiAgIFUtPj5GOiBtZXRob2QoKSh0YXJnZXQsIGtleSwgZGVzY3JpcHRvcilcbiAqICAgRi0+PlU6IFJlZmxlY3QuZ2V0T3duTWV0YWRhdGEoZGVzaWduOnBhcmFtdHlwZXMpXG4gKiAgIEYtPj5VOiBSZWZsZWN0LmdldE93bk1ldGFkYXRhKGRlc2lnbjpyZXR1cm50eXBlKVxuICogICBGLT4+TTogc2V0KG1ldGhvZHMua2V5LmRlc2lnbjpwYXJhbXR5cGVzLCBwYXJhbXMpXG4gKiAgIEYtPj5NOiBzZXQobWV0aG9kcy5rZXkuZGVzaWduOnJldHVybnR5cGUsIHJldHVyblR5cGUpXG4gKiAgIEYtLT4+VTogZGVjb3JhdGVkIGZ1bmN0aW9uXG4gKiBAY2F0ZWdvcnkgTWV0aG9kIERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1ldGhvZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIG1ldGhvZChvYmo6IGFueSwgcHJvcD86IGFueSwgZGVzY3JpcHRvcj86IGFueSkge1xuICAgIGNvbnN0IGRlc2lnblBhcmFtcyA9IFJlZmxlY3QuZ2V0T3duTWV0YWRhdGEoXG4gICAgICBEZWNvcmF0aW9uS2V5cy5ERVNJR05fUEFSQU1TLFxuICAgICAgb2JqLFxuICAgICAgcHJvcFxuICAgICk7XG4gICAgY29uc3QgZGVzaWduUmV0dXJuID0gUmVmbGVjdC5nZXRPd25NZXRhZGF0YShcbiAgICAgIERlY29yYXRpb25LZXlzLkRFU0lHTl9SRVRVUk4sXG4gICAgICBvYmosXG4gICAgICBwcm9wXG4gICAgKTtcbiAgICByZXR1cm4gYXBwbHkoXG4gICAgICBtZXRhZGF0YShcbiAgICAgICAgTWV0YWRhdGEua2V5KFxuICAgICAgICAgIERlY29yYXRpb25LZXlzLk1FVEhPRFMsXG4gICAgICAgICAgcHJvcCxcbiAgICAgICAgICBEZWNvcmF0aW9uS2V5cy5ERVNJR05fUEFSQU1TXG4gICAgICAgICksXG4gICAgICAgIGRlc2lnblBhcmFtc1xuICAgICAgKSxcbiAgICAgIG1ldGFkYXRhKFxuICAgICAgICBNZXRhZGF0YS5rZXkoXG4gICAgICAgICAgRGVjb3JhdGlvbktleXMuTUVUSE9EUyxcbiAgICAgICAgICBwcm9wLFxuICAgICAgICAgIERlY29yYXRpb25LZXlzLkRFU0lHTl9SRVRVUk5cbiAgICAgICAgKSxcbiAgICAgICAgZGVzaWduUmV0dXJuXG4gICAgICApXG4gICAgKShvYmosIHByb3AsIGRlc2NyaXB0b3IpO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZmFjdG9yeSB0aGF0IGFwcGxpZXMgbXVsdGlwbGUgZGVjb3JhdG9ycyB0byBhIHNpbmdsZSB0YXJnZXQuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY29tcG9zaXRlIGRlY29yYXRvciB0aGF0IGFwcGxpZXMgbXVsdGlwbGUgZGVjb3JhdG9ycyBpbiBzZXF1ZW5jZSwgY29ycmVjdGx5IGhhbmRsaW5nIGNsYXNzLCBtZXRob2QsIHByb3BlcnR5LCBhbmQgcGFyYW1ldGVyIGRlY29yYXRvcnMuXG4gKiBAcGFyYW0ge0FycmF5PENsYXNzRGVjb3JhdG9yfE1ldGhvZERlY29yYXRvcnxQcm9wZXJ0eURlY29yYXRvcnxQYXJhbWV0ZXJEZWNvcmF0b3I+fSBkZWNvcmF0b3JzIENvbGxlY3Rpb24gb2YgZGVjb3JhdG9ycyB0byBhcHBseS5cbiAqIEByZXR1cm4ge0NsYXNzRGVjb3JhdG9yfE1ldGhvZERlY29yYXRvcnxQcm9wZXJ0eURlY29yYXRvcnxQYXJhbWV0ZXJEZWNvcmF0b3J9IERlY29yYXRvciBmdW5jdGlvbiB0aGF0IGFwcGxpZXMgYWxsIHByb3ZpZGVkIGRlY29yYXRvcnMgdG8gdGhlIHRhcmdldC5cbiAqIEBmdW5jdGlvbiBhcHBseVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXIgQ29kZVxuICogICBwYXJ0aWNpcGFudCBBIGFzIGFwcGx5KC4uLmRlY29yYXRvcnMpXG4gKiAgIHBhcnRpY2lwYW50IEQgYXMgRGVjb3JhdG9yXG4gKiAgIFUtPj5BOiBnZXQgZGVjb3JhdG9yKC4uLmRlY29yYXRvcnMpXG4gKiAgIEEtPj5VOiByZXR1cm5zICh0YXJnZXQsIGtleT8sIGRlc2M/KSA9PiB2b2lkXG4gKiAgIFUtPj5BOiBpbnZva2Ugb24gdGFyZ2V0XG4gKiAgIGxvb3AgZm9yIGVhY2ggZGVjb3JhdG9yXG4gKiAgICAgQS0+PkQ6IGludm9rZSBhcHByb3ByaWF0ZSBkZWNvcmF0b3IgdHlwZVxuICogICBlbmRcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseShcbiAgLi4uZGVjb3JhdG9yczogQXJyYXk8XG4gICAgQ2xhc3NEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IFBhcmFtZXRlckRlY29yYXRvclxuICA+XG4pIHtcbiAgcmV0dXJuIChcbiAgICB0YXJnZXQ6IG9iamVjdCxcbiAgICBwcm9wZXJ0eUtleT86IHN0cmluZyB8IHN5bWJvbCB8IHVua25vd24sXG4gICAgZGVzY3JpcHRvcj86IFByb3BlcnR5RGVzY3JpcHRvciB8IG51bWJlclxuICApID0+IHtcbiAgICBmb3IgKGNvbnN0IGRlY29yYXRvciBvZiBkZWNvcmF0b3JzKSB7XG4gICAgICBpZiAodGFyZ2V0IGluc3RhbmNlb2YgRnVuY3Rpb24gJiYgIWRlc2NyaXB0b3IpIHtcbiAgICAgICAgKGRlY29yYXRvciBhcyBDbGFzc0RlY29yYXRvcikodGFyZ2V0KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICAoZGVjb3JhdG9yIGFzIE1ldGhvZERlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yKShcbiAgICAgICAgdGFyZ2V0LFxuICAgICAgICBwcm9wZXJ0eUtleSBhcyBzdHJpbmcgfCBzeW1ib2wsXG4gICAgICAgIGRlc2NyaXB0b3IgYXMgVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8dW5rbm93bj5cbiAgICAgICk7XG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgcHJvcGVydHkgbWV0YWRhdGEgZGVjb3JhdG9yLlxuICogQHN1bW1hcnkgQ29udmVuaWVuY2UgZmFjdG9yeSB0aGF0IGNvbWJpbmVzIGBtZXRhZGF0YShrZXksIHZhbHVlKWAgYW5kIGBwcm9wKClgIHRvIGJvdGggc2V0IGFuIGFyYml0cmFyeSBtZXRhZGF0YSBrZXkgYW5kIHJlY29yZCB0aGUgcHJvcGVydHkncyBkZXNpZ24gdHlwZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgTWV0YWRhdGEga2V5IHRvIHNldCBmb3IgdGhlIHByb3BlcnR5LlxuICogQHBhcmFtIHthbnl9IHZhbHVlIE1ldGFkYXRhIHZhbHVlIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBrZXkuXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gRGVjb3JhdG9yIHRoYXQgc2V0cyB0aGUgbWV0YWRhdGEgYW5kIGNhcHR1cmVzIHRoZSBwcm9wZXJ0eSdzIHR5cGUuXG4gKiBAZnVuY3Rpb24gcHJvcE1ldGFkYXRhXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvcE1ldGFkYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gIHJldHVybiBhcHBseShtZXRhZGF0YShrZXksIHZhbHVlKSwgcHJvcCgpKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG1ldGhvZCBtZXRhZGF0YSBkZWNvcmF0b3IuXG4gKiBAc3VtbWFyeSBDb252ZW5pZW5jZSBmYWN0b3J5IHRoYXQgY29tYmluZXMgYG1ldGFkYXRhKGtleSwgdmFsdWUpYCBhbmQgYG1ldGhvZCgpYCB0byBib3RoIHNldCBhbiBhcmJpdHJhcnkgbWV0YWRhdGEga2V5IGFuZCByZWNvcmQgdGhlIG1ldGhvZCdzIGRlc2lnbiByZXR1cm4gYW5kIHBhcmFtIHR5cGVzLlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBNZXRhZGF0YSBrZXkgdG8gc2V0IGZvciB0aGUgcHJvcGVydHkuXG4gKiBAcGFyYW0ge2FueX0gdmFsdWUgTWV0YWRhdGEgdmFsdWUgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGtleS5cbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBEZWNvcmF0b3IgdGhhdCBzZXRzIHRoZSBtZXRhZGF0YSBhbmQgY2FwdHVyZXMgdGhlIHByb3BlcnR5J3MgdHlwZS5cbiAqIEBmdW5jdGlvbiBtZXRob2RNZXRhZGF0YVxuICogQGNhdGVnb3J5IE1ldGhvZCBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRob2RNZXRhZGF0YShrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICByZXR1cm4gYXBwbHkobWV0YWRhdGEoa2V5LCB2YWx1ZSksIG1ldGhvZCgpKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXR0YWNoZXMgYSBodW1hbi1yZWFkYWJsZSBkZXNjcmlwdGlvbiB0byBhIGNsYXNzIG9yIG1lbWJlci5cbiAqIEBzdW1tYXJ5IERlY29yYXRvciBmYWN0b3J5IHRoYXQgc3RvcmVzIGEgdGV4dHVhbCBkZXNjcmlwdGlvbiBpbiB0aGUgbWV0YWRhdGEgc3RvcmUgdW5kZXIgdGhlIGFwcHJvcHJpYXRlIGRlc2NyaXB0aW9uIGtleSBmb3IgYSBjbGFzcyBvciBpdHMgcHJvcGVydHkuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzYyBEZXNjcmlwdGl2ZSB0ZXh0IHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBjbGFzcyBvciBwcm9wZXJ0eS5cbiAqIEByZXR1cm4ge0NsYXNzRGVjb3JhdG9yfE1ldGhvZERlY29yYXRvcnxQcm9wZXJ0eURlY29yYXRvcn0gRGVjb3JhdG9yIHRoYXQgcmVjb3JkcyB0aGUgZGVzY3JpcHRpb24gd2hlbiBhcHBsaWVkLlxuICogQGZ1bmN0aW9uIGRlc2NyaXB0aW9uXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZGVzY3JpcHRpb24oZGVzYzogc3RyaW5nKSB7XG4gIHJldHVybiBmdW5jdGlvbiBkZXNjcmlwdGlvbihvcmlnaW5hbDogYW55LCBwcm9wPzogYW55LCBkZXNjcmlwdG9yPzogYW55KSB7XG4gICAgcmV0dXJuIG1ldGFkYXRhKFxuICAgICAgW1xuICAgICAgICBEZWNvcmF0aW9uS2V5cy5ERVNDUklQVElPTixcbiAgICAgICAgcHJvcCA/IHByb3AudG9TdHJpbmcoKSA6IERlY29yYXRpb25LZXlzLkNMQVNTLFxuICAgICAgXS5qb2luKE1ldGFkYXRhLnNwbGl0dGVyKSxcbiAgICAgIGRlc2NcbiAgICApKG9yaWdpbmFsLCBwcm9wLCBkZXNjcmlwdG9yKTtcbiAgfTtcbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIFJvb3QgZW50cnkgcG9pbnQgZm9yIHRoZSBkZWNvcmF0aW9uIG1vZHVsZS5cbiAqIEBzdW1tYXJ5IEFnZ3JlZ2F0ZXMgYW5kIHJlLWV4cG9ydHMgdGhlIHB1YmxpYyBBUEkgb2YgdGhlIGRlY29yYXRpb24gbGlicmFyeSwgaW5jbHVkaW5nIHtAbGluayBEZWNvcmF0aW9ufSwgZGVjb3JhdG9yIHV0aWxpdGllcyBmcm9tIHtAbGluayBtb2R1bGU6ZGVjb3JhdGlvbnwuL2RlY29yYXRvcnN9LCB7QGxpbmsgTWV0YWRhdGF9LCBhbmQgc2hhcmVkIGNvbnN0YW50cyBzdWNoIGFzIHtAbGluayBEZWNvcmF0aW9uS2V5c30gYW5kIHtAbGluayBEZWZhdWx0Rmxhdm91cn0uIFRoaXMgaXMgdGhlIHByaW1hcnkgaW1wb3J0IHN1cmZhY2UgZm9yIGNvbnN1bWVycyBhbmQgZXhwb3NlczpcbiAqIC0gQ29yZSBidWlsZGVyOiB7QGxpbmsgRGVjb3JhdGlvbn1cbiAqIC0gRGVjb3JhdG9yIHV0aWxpdGllczoge0BsaW5rIG1vZHVsZTpkZWNvcmF0aW9ufGRlY29yYXRvcnMgaW4gLi9kZWNvcmF0b3JzfVxuICogLSBNZXRhZGF0YSB1dGlsaXRpZXM6IHtAbGluayBNZXRhZGF0YX1cbiAqIC0gQ29uc3RhbnRzIGFuZCBlbnVtczoge0BsaW5rIERlY29yYXRpb25LZXlzfSwge0BsaW5rIERlZmF1bHRGbGF2b3VyfVxuICogQG1vZHVsZSBkZWNvcmF0aW9uXG4gKi9cblxuaW1wb3J0IHsgTWV0YWRhdGEgfSBmcm9tIFwiLi9tZXRhZGF0YS9pbmRleFwiO1xuXG5leHBvcnQgKiBmcm9tIFwiLi9kZWNvcmF0aW9uXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9tZXRhZGF0YVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgcmVmbGVjdGlvbiBwYWNrYWdlXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIHNlbWFudGljIHZlcnNpb24gbnVtYmVyIG9mIHRoZSBwYWNrYWdlXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuXG5NZXRhZGF0YS5yZWdpc3RlckxpYnJhcnkoXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiLCBWRVJTSU9OKTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBOzs7OztBQUtHO0FBQ0ksTUFBTSxjQUFjLEdBQUc7QUFFOUI7Ozs7O0FBS0c7QUFDSSxNQUFNLGlCQUFpQixHQUFHO0FBRWpDOzs7Ozs7O0FBT0c7SUFDUztBQUFaLENBQUEsVUFBWSxjQUFjLEVBQUE7O0FBRXhCLElBQUEsY0FBQSxDQUFBLFdBQUEsQ0FBQSxHQUFBLFdBQXVCOztBQUV2QixJQUFBLGNBQUEsQ0FBQSxTQUFBLENBQUEsR0FBQSxTQUErQjs7QUFFL0IsSUFBQSxjQUFBLENBQUEsWUFBQSxDQUFBLEdBQUEsWUFBeUI7O0FBRXpCLElBQUEsY0FBQSxDQUFBLFNBQUEsQ0FBQSxHQUFBLFNBQW1COztBQUVuQixJQUFBLGNBQUEsQ0FBQSxPQUFBLENBQUEsR0FBQSxPQUFlOztBQUVmLElBQUEsY0FBQSxDQUFBLGFBQUEsQ0FBQSxHQUFBLGFBQTJCOztBQUUzQixJQUFBLGNBQUEsQ0FBQSxhQUFBLENBQUEsR0FBQSxhQUEyQjs7QUFFM0IsSUFBQSxjQUFBLENBQUEsWUFBQSxDQUFBLEdBQUEsWUFBeUI7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