@decaf-ts/for-http 0.2.1 → 0.2.2

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,53 +1,164 @@
1
1
  import { Repository, Adapter, UnsupportedError } from '@decaf-ts/core';
2
2
  import { InternalError, findPrimaryKey } from '@decaf-ts/db-decorators';
3
3
 
4
+ /**
5
+ * @description Service class for REST API operations
6
+ * @summary Provides a comprehensive implementation for interacting with REST APIs.
7
+ * This class implements CRUD operations for single and bulk operations, as well as
8
+ * the Observable pattern to notify observers of changes. It works with HTTP adapters
9
+ * to perform the actual API requests and handles model conversion.
10
+ * @template M - The model type, extending Model
11
+ * @template Q - The query type used by the adapter
12
+ * @template A - The HTTP adapter type, extending HttpAdapter
13
+ * @template F - The HTTP flags type, extending HttpFlags
14
+ * @template C - The context type, extending Context<F>
15
+ * @param {A} adapter - The HTTP adapter instance
16
+ * @param {Constructor<M>} [clazz] - Optional constructor for the model class
17
+ * @example
18
+ * ```typescript
19
+ * // Create a service for User model with Axios adapter
20
+ * const axiosAdapter = new AxiosAdapter({
21
+ * protocol: 'https',
22
+ * host: 'api.example.com'
23
+ * });
24
+ * const userService = new RestService(axiosAdapter, User);
25
+ *
26
+ * // Create a new user
27
+ * const user = new User({ name: 'John Doe', email: 'john@example.com' });
28
+ * const createdUser = await userService.create(user);
29
+ *
30
+ * // Update a user
31
+ * createdUser.name = 'Jane Doe';
32
+ * const updatedUser = await userService.update(createdUser);
33
+ *
34
+ * // Delete a user
35
+ * await userService.delete(updatedUser.id);
36
+ * ```
37
+ * @class
38
+ */
4
39
  class RestService {
40
+ /**
41
+ * @description Gets the model class constructor
42
+ * @summary Retrieves the model class constructor associated with this service.
43
+ * Throws an error if no class definition is found.
44
+ * @return {Constructor<M>} The model class constructor
45
+ * @throws {InternalError} If no class definition is found
46
+ */
5
47
  get class() {
6
48
  if (!this._class)
7
49
  throw new InternalError("No class definition found for this repository");
8
50
  return this._class;
9
51
  }
52
+ /**
53
+ * @description Gets the primary key property name
54
+ * @summary Retrieves the name of the primary key property for the model.
55
+ * If not already determined, it finds the primary key using the model class.
56
+ * @return The primary key property name
57
+ */
10
58
  get pk() {
11
59
  if (!this._pk)
12
60
  this._pk = findPrimaryKey(new this.class()).id;
13
61
  return this._pk;
14
62
  }
63
+ /**
64
+ * @description Gets the HTTP adapter
65
+ * @summary Retrieves the HTTP adapter associated with this service.
66
+ * Throws an error if no adapter is found.
67
+ * @return {A} The HTTP adapter instance
68
+ * @throws {InternalError} If no adapter is found
69
+ */
15
70
  get adapter() {
16
71
  if (!this._adapter)
17
72
  throw new InternalError("No adapter found for this repository. did you use the @uses decorator or pass it in the constructor?");
18
73
  return this._adapter;
19
74
  }
75
+ /**
76
+ * @description Gets the table name for the model
77
+ * @summary Retrieves the table name associated with the model class.
78
+ * If not already determined, it gets the table name from the Repository utility.
79
+ * @return {string} The table name
80
+ */
20
81
  get tableName() {
21
82
  if (!this._tableName)
22
83
  this._tableName = Repository.table(this.class);
23
84
  return this._tableName;
24
85
  }
86
+ /**
87
+ * @description Initializes a new RestService instance
88
+ * @summary Creates a new service instance with the specified adapter and optional model class.
89
+ * The constructor stores the adapter and model class for later use in CRUD operations.
90
+ * @param {A} adapter - The HTTP adapter instance to use for API requests
91
+ * @param {Constructor<M>} [clazz] - Optional constructor for the model class
92
+ */
25
93
  constructor(adapter, clazz) {
26
94
  this.observers = [];
27
95
  this._adapter = adapter;
28
96
  if (clazz)
29
97
  this._class = clazz;
30
98
  }
99
+ /**
100
+ * @description Creates a new resource
101
+ * @summary Creates a new resource in the REST API using the provided model.
102
+ * The method prepares the model for the adapter, sends the create request,
103
+ * and then converts the response back to a model instance.
104
+ * @param {M} model - The model instance to create
105
+ * @param {...any[]} args - Additional arguments to pass to the adapter
106
+ * @return {Promise<M>} A promise that resolves with the created model instance
107
+ */
31
108
  async create(model, ...args) {
32
109
  // eslint-disable-next-line prefer-const
33
110
  let { record, id } = this.adapter.prepare(model, this.pk);
34
111
  record = await this.adapter.create(this.tableName, id, record, ...args);
35
112
  return this.adapter.revert(record, this.class, this.pk, id);
36
113
  }
114
+ /**
115
+ * @description Retrieves a resource by ID
116
+ * @summary Fetches a resource from the REST API using the provided ID.
117
+ * The method sends the read request and converts the response to a model instance.
118
+ * @param {string|number} id - The identifier of the resource to retrieve
119
+ * @param {...any[]} args - Additional arguments to pass to the adapter
120
+ * @return {Promise<M>} A promise that resolves with the retrieved model instance
121
+ */
37
122
  async read(id, ...args) {
38
123
  const m = await this.adapter.read(this.tableName, id, ...args);
39
124
  return this.adapter.revert(m, this.class, this.pk, id);
40
125
  }
126
+ /**
127
+ * @description Updates an existing resource
128
+ * @summary Updates an existing resource in the REST API using the provided model.
129
+ * The method prepares the model for the adapter, sends the update request,
130
+ * and then converts the response back to a model instance.
131
+ * @param {M} model - The model instance with updated data
132
+ * @param {...any[]} args - Additional arguments to pass to the adapter
133
+ * @return {Promise<M>} A promise that resolves with the updated model instance
134
+ */
41
135
  async update(model, ...args) {
42
136
  // eslint-disable-next-line prefer-const
43
137
  let { record, id } = this.adapter.prepare(model, this.pk);
44
138
  record = await this.adapter.update(this.tableName, id, record, ...args);
45
139
  return this.adapter.revert(record, this.class, this.pk, id);
46
140
  }
141
+ /**
142
+ * @description Deletes a resource by ID
143
+ * @summary Removes a resource from the REST API using the provided ID.
144
+ * The method sends the delete request and converts the response to a model instance.
145
+ * @param {string|number} id - The identifier of the resource to delete
146
+ * @param {...any[]} args - Additional arguments to pass to the adapter
147
+ * @return {Promise<M>} A promise that resolves with the deleted model instance
148
+ */
47
149
  async delete(id, ...args) {
48
150
  const m = await this.adapter.delete(this.tableName, id, ...args);
49
151
  return this.adapter.revert(m, this.class, this.pk, id);
50
152
  }
153
+ /**
154
+ * @description Creates multiple resources
155
+ * @summary Creates multiple resources in the REST API using the provided models.
156
+ * The method prepares each model for the adapter, sends a bulk create request,
157
+ * and then converts the responses back to model instances.
158
+ * @param {M[]} models - The model instances to create
159
+ * @param {...any[]} args - Additional arguments to pass to the adapter
160
+ * @return {Promise<M[]>} A promise that resolves with an array of created model instances
161
+ */
51
162
  async createAll(models, ...args) {
52
163
  if (!models.length)
53
164
  return models;
@@ -57,24 +168,51 @@ class RestService {
57
168
  records = await this.adapter.createAll(this.tableName, ids, records, ...args);
58
169
  return records.map((r, i) => this.adapter.revert(r, this.class, this.pk, ids[i]));
59
170
  }
171
+ /**
172
+ * @description Deletes multiple resources by IDs
173
+ * @summary Removes multiple resources from the REST API using the provided IDs.
174
+ * The method sends a bulk delete request and converts the responses to model instances.
175
+ * @param {string[]|number[]} keys - The identifiers of the resources to delete
176
+ * @param {...any[]} args - Additional arguments to pass to the adapter
177
+ * @return {Promise<M[]>} A promise that resolves with an array of deleted model instances
178
+ */
60
179
  async deleteAll(keys, ...args) {
61
180
  const results = await this.adapter.deleteAll(this.tableName, keys, ...args);
62
181
  return results.map((r, i) => this.adapter.revert(r, this.class, this.pk, keys[i]));
63
182
  }
183
+ /**
184
+ * @description Retrieves multiple resources by IDs
185
+ * @summary Fetches multiple resources from the REST API using the provided IDs.
186
+ * The method sends a bulk read request and converts the responses to model instances.
187
+ * @param {string[]|number[]} keys - The identifiers of the resources to retrieve
188
+ * @param {...any[]} args - Additional arguments to pass to the adapter
189
+ * @return {Promise<M[]>} A promise that resolves with an array of retrieved model instances
190
+ */
64
191
  async readAll(keys, ...args) {
65
192
  const records = await this.adapter.readAll(this.tableName, keys, ...args);
66
193
  return records.map((r, i) => this.adapter.revert(r, this.class, this.pk, keys[i]));
67
194
  }
195
+ /**
196
+ * @description Updates multiple resources
197
+ * @summary Updates multiple resources in the REST API using the provided models.
198
+ * The method prepares each model for the adapter, sends a bulk update request,
199
+ * and then converts the responses back to model instances.
200
+ * @param {M[]} models - The model instances with updated data
201
+ * @param {...any[]} args - Additional arguments to pass to the adapter
202
+ * @return {Promise<M[]>} A promise that resolves with an array of updated model instances
203
+ */
68
204
  async updateAll(models, ...args) {
69
205
  const records = models.map((m) => this.adapter.prepare(m, this.pk));
70
206
  const updated = await this.adapter.updateAll(this.tableName, records.map((r) => r.id), records.map((r) => r.record), ...args);
71
207
  return updated.map((u, i) => this.adapter.revert(u, this.class, this.pk, records[i].id));
72
208
  }
73
209
  /**
74
- * @summary Registers an {@link Observer}
75
- * @param {Observer} observer
76
- *
77
- * @see {Observable#observe}
210
+ * @description Registers an observer
211
+ * @summary Adds an observer to the list of observers that will be notified of changes.
212
+ * Throws an error if the observer is already registered.
213
+ * @param {Observer} observer - The observer to register
214
+ * @return {void}
215
+ * @throws {InternalError} If the observer is already registered
78
216
  */
79
217
  observe(observer) {
80
218
  const index = this.observers.indexOf(observer);
@@ -83,10 +221,12 @@ class RestService {
83
221
  this.observers.push(observer);
84
222
  }
85
223
  /**
86
- * @summary Unregisters an {@link Observer}
87
- * @param {Observer} observer
88
- *
89
- * @see {Observable#unObserve}
224
+ * @description Unregisters an observer
225
+ * @summary Removes an observer from the list of observers.
226
+ * Throws an error if the observer is not found.
227
+ * @param {Observer} observer - The observer to unregister
228
+ * @return {void}
229
+ * @throws {InternalError} If the observer is not found
90
230
  */
91
231
  unObserve(observer) {
92
232
  const index = this.observers.indexOf(observer);
@@ -95,8 +235,11 @@ class RestService {
95
235
  this.observers.splice(index, 1);
96
236
  }
97
237
  /**
98
- * @summary calls all registered {@link Observer}s to update themselves
99
- * @param {any[]} [args] optional arguments to be passed to the {@link Observer#refresh} method
238
+ * @description Notifies all registered observers
239
+ * @summary Calls the refresh method on all registered observers to update themselves.
240
+ * Any errors during observer refresh are logged as warnings but don't stop the process.
241
+ * @param {...any[]} [args] - Optional arguments to pass to the observer refresh method
242
+ * @return {Promise<void>} A promise that resolves when all observers have been updated
100
243
  */
101
244
  async updateObservers(...args) {
102
245
  const results = await Promise.allSettled(this.observers.map((o) => o.refresh(...args)));
@@ -107,25 +250,91 @@ class RestService {
107
250
  }
108
251
  }
109
252
 
253
+ /**
254
+ * @description Abstract HTTP adapter for REST API interactions
255
+ * @summary Provides a base implementation for HTTP adapters with methods for CRUD operations,
256
+ * URL construction, and error handling. This class extends the core Adapter class and
257
+ * implements the necessary methods for HTTP communication. Concrete implementations
258
+ * must provide specific HTTP client functionality.
259
+ * @template Y - The native HTTP client type
260
+ * @template Q - The query type used by the adapter
261
+ * @template F - The HTTP flags type, extending HttpFlags
262
+ * @template C - The context type, extending Context<F>
263
+ * @param {Y} native - The native HTTP client instance
264
+ * @param {HttpConfig} config - Configuration for the HTTP adapter
265
+ * @param {string} flavour - The adapter flavor identifier
266
+ * @param {string} [alias] - Optional alias for the adapter
267
+ * @example
268
+ * ```typescript
269
+ * // Example implementation with Axios
270
+ * class AxiosAdapter extends HttpAdapter<AxiosInstance, AxiosRequestConfig> {
271
+ * constructor(config: HttpConfig) {
272
+ * super(axios.create(), config, 'axios');
273
+ * }
274
+ *
275
+ * async request<V>(details: AxiosRequestConfig): Promise<V> {
276
+ * const response = await this.native.request(details);
277
+ * return response.data;
278
+ * }
279
+ *
280
+ * // Implement other abstract methods...
281
+ * }
282
+ * ```
283
+ * @class
284
+ */
110
285
  class HttpAdapter extends Adapter {
111
286
  constructor(native, config, flavour, alias) {
112
287
  super(native, flavour, alias);
113
288
  this.config = config;
114
289
  }
290
+ /**
291
+ * @description Generates operation flags with HTTP headers
292
+ * @summary Extends the base flags method to include HTTP-specific headers for operations.
293
+ * This method adds an empty headers object to the flags returned by the parent class.
294
+ * @template F - The Repository Flags type
295
+ * @template M - The model type
296
+ * @param {OperationKeys.CREATE|OperationKeys.READ|OperationKeys.UPDATE|OperationKeys.DELETE} operation - The operation type
297
+ * @param {Constructor<M>} model - The model constructor
298
+ * @param {Partial<F>} overrides - Optional flag overrides
299
+ * @return {F} The flags object with headers
300
+ */
115
301
  flags(operation, model, overrides) {
116
302
  return Object.assign(super.flags(operation, model, overrides), {
117
303
  headers: {},
118
304
  });
119
305
  }
306
+ /**
307
+ * @description Returns the repository constructor for this adapter
308
+ * @summary Provides the RestService class as the repository implementation for this HTTP adapter.
309
+ * This method is used to create repository instances that work with this adapter type.
310
+ * @template M - The model type
311
+ * @return {Constructor<Repository<M, Q, HttpAdapter<Y, Q, F, C>>>} The repository constructor
312
+ */
120
313
  repository() {
121
314
  return RestService;
122
315
  }
316
+ /**
317
+ * @description Constructs a URL for API requests
318
+ * @summary Builds a complete URL for API requests using the configured protocol and host,
319
+ * the specified table name, and optional query parameters. The method handles URL encoding.
320
+ * @param {string} tableName - The name of the table or endpoint
321
+ * @param {Record<string, string | number>} [queryParams] - Optional query parameters
322
+ * @return {string} The encoded URL string
323
+ */
123
324
  url(tableName, queryParams) {
124
325
  const url = new URL(`${this.config.protocol}://${this.config.host}/${tableName}`);
125
326
  if (queryParams)
126
327
  Object.entries(queryParams).forEach(([key, value]) => url.searchParams.append(key, value.toString()));
127
328
  return encodeURI(url.toString());
128
329
  }
330
+ /**
331
+ * @description Parses and converts errors to BaseError type
332
+ * @summary Processes errors that occur during HTTP operations and converts them to
333
+ * the appropriate BaseError type. Currently returns the error as-is, but can be
334
+ * extended to handle specific error messages differently.
335
+ * @param {Error} err - The error to parse
336
+ * @return {BaseError} The parsed error as a BaseError
337
+ */
129
338
  parseError(err) {
130
339
  const { message } = err;
131
340
  switch (message) {
@@ -133,34 +342,123 @@ class HttpAdapter extends Adapter {
133
342
  return err;
134
343
  }
135
344
  }
345
+ /**
346
+ * @description Initializes the HTTP adapter
347
+ * @summary Placeholder method for adapter initialization. This method is currently
348
+ * a no-op but can be overridden by subclasses to perform initialization tasks.
349
+ * @param {...any[]} args - Initialization arguments
350
+ * @return {Promise<void>} A promise that resolves when initialization is complete
351
+ */
136
352
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
137
353
  async initialize(...args) {
138
354
  // do nothing
139
355
  }
356
+ /**
357
+ * @description Executes a raw query
358
+ * @summary Method for executing raw queries directly with the HTTP client.
359
+ * This method is not supported by default in HTTP adapters and throws an UnsupportedError.
360
+ * Subclasses can override this method to provide implementation.
361
+ * @template R - The result type
362
+ * @param {Q} rawInput - The raw query input
363
+ * @param {boolean} process - Whether to process the result
364
+ * @param {...any[]} args - Additional arguments
365
+ * @return {Promise<R>} A promise that resolves with the query result
366
+ * @throws {UnsupportedError} Always throws as this method is not supported by default
367
+ */
140
368
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
141
369
  raw(rawInput, process, ...args) {
142
370
  throw new UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class");
143
371
  }
372
+ /**
373
+ * @description Creates a sequence
374
+ * @summary Method for creating a sequence for generating unique identifiers.
375
+ * This method is not supported by default in HTTP adapters and throws an UnsupportedError.
376
+ * Subclasses can override this method to provide implementation.
377
+ * @param {SequenceOptions} options - Options for creating the sequence
378
+ * @return {Promise<Sequence>} A promise that resolves with the created sequence
379
+ * @throws {UnsupportedError} Always throws as this method is not supported by default
380
+ */
144
381
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
145
382
  Sequence(options) {
146
383
  throw new UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class");
147
384
  }
385
+ /**
386
+ * @description Creates a statement for querying
387
+ * @summary Method for creating a statement for building and executing queries.
388
+ * This method is not supported by default in HTTP adapters and throws an UnsupportedError.
389
+ * Subclasses can override this method to provide implementation.
390
+ * @template M - The model type
391
+ * @template ! - The raw query type
392
+ * @return {Statement<Q, M, any>} A statement object for building queries
393
+ * @throws {UnsupportedError} Always throws as this method is not supported by default
394
+ */
148
395
  Statement() {
149
396
  throw new UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class");
150
397
  }
398
+ /**
399
+ * @description Parses a condition into a query
400
+ * @summary Method for parsing a condition object into a query format understood by the HTTP client.
401
+ * This method is not supported by default in HTTP adapters and throws an UnsupportedError.
402
+ * Subclasses can override this method to provide implementation.
403
+ * @param {Condition<any>} condition - The condition to parse
404
+ * @return {Q} The parsed query
405
+ * @throws {UnsupportedError} Always throws as this method is not supported by default
406
+ */
151
407
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
152
408
  parseCondition(condition) {
153
409
  throw new UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class");
154
410
  }
155
411
  }
156
412
 
413
+ /**
414
+ * @description Repository for REST API interactions
415
+ * @summary A specialized repository implementation for interacting with REST APIs.
416
+ * This class extends the core Repository class and works with HTTP adapters to
417
+ * provide CRUD operations for models via REST endpoints.
418
+ * This Is NOT the default repository for the HTTP adapter. That would be {@link RestService}.
419
+ * Use this only in the specific case of needing to run the CURD model logic (decoration) before submitting to the backend
420
+ * @template M - The model type, extending Model
421
+ * @template Q - The query type used by the adapter
422
+ * @template A - The HTTP adapter type, extending HttpAdapter
423
+ * @template F - The HTTP flags type, extending HttpFlags
424
+ * @template C - The context type, extending Context<F>
425
+ * @param {A} adapter - The HTTP adapter instance
426
+ * @param {Constructor<M>} [clazz] - Optional constructor for the model class
427
+ * @example
428
+ * ```typescript
429
+ * // Create a repository for User model with Axios adapter
430
+ * const axiosAdapter = new AxiosAdapter({
431
+ * protocol: 'https',
432
+ * host: 'api.example.com'
433
+ * });
434
+ * const userRepository = new RestRepository(axiosAdapter, User);
435
+ *
436
+ * // Use the repository for CRUD operations
437
+ * const user = await userRepository.findById('123');
438
+ * ```
439
+ * @class RestRepository
440
+ * @see {@link RestService}
441
+ */
157
442
  class RestRepository extends Repository {
158
443
  constructor(adapter, clazz) {
159
444
  super(adapter, clazz);
160
445
  }
161
446
  }
162
447
 
163
- const VERSION = "0.2.1";
448
+ /**
449
+ * @description HTTP client module for REST API interactions
450
+ * @summary This module provides classes and utilities for interacting with REST APIs.
451
+ * It exposes repository and service classes for making HTTP requests, along with
452
+ * type definitions and adapters for different HTTP clients. The module includes
453
+ * {@link RestRepository} and {@link RestService} for API interactions.
454
+ * @module for-http
455
+ */
456
+ /**
457
+ * @description Current version of the for-http module
458
+ * @summary Version identifier for the module
459
+ * @const VERSION
460
+ */
461
+ const VERSION = "0.2.2";
164
462
 
165
463
  export { HttpAdapter, RestRepository, RestService, VERSION };
166
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWh0dHAuZXNtLmNqcyIsInNvdXJjZXMiOlsiLi4vc3JjL1Jlc3RTZXJ2aWNlLnRzIiwiLi4vc3JjL2FkYXB0ZXIudHMiLCIuLi9zcmMvUmVzdFJlcG9zaXRvcnkudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQnVsa0NydWRPcGVyYXRvcixcbiAgQ29udGV4dCxcbiAgQ3J1ZE9wZXJhdG9yLFxuICBmaW5kUHJpbWFyeUtleSxcbiAgSW50ZXJuYWxFcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBPYnNlcnZlciwgUmVwb3NpdG9yeSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgSHR0cEFkYXB0ZXIgfSBmcm9tIFwiLi9hZGFwdGVyXCI7XG5pbXBvcnQgeyBIdHRwRmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY2xhc3MgUmVzdFNlcnZpY2U8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFEsXG4gICAgQSBleHRlbmRzIEh0dHBBZGFwdGVyPGFueSwgUSwgRiwgQz4sXG4gICAgRiBleHRlbmRzIEh0dHBGbGFncyA9IEh0dHBGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4gID5cbiAgaW1wbGVtZW50cyBDcnVkT3BlcmF0b3I8TT4sIEJ1bGtDcnVkT3BlcmF0b3I8TT4sIE9ic2VydmFibGVcbntcbiAgcHJpdmF0ZSByZWFkb25seSBfY2xhc3MhOiBDb25zdHJ1Y3RvcjxNPjtcbiAgcHJpdmF0ZSBfcGshOiBrZXlvZiBNO1xuXG4gIGdldCBjbGFzcygpIHtcbiAgICBpZiAoIXRoaXMuX2NsYXNzKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJObyBjbGFzcyBkZWZpbml0aW9uIGZvdW5kIGZvciB0aGlzIHJlcG9zaXRvcnlcIik7XG4gICAgcmV0dXJuIHRoaXMuX2NsYXNzO1xuICB9XG5cbiAgZ2V0IHBrKCkge1xuICAgIGlmICghdGhpcy5fcGspIHRoaXMuX3BrID0gZmluZFByaW1hcnlLZXkobmV3IHRoaXMuY2xhc3MoKSkuaWQ7XG4gICAgcmV0dXJuIHRoaXMuX3BrO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9ic2VydmVyczogT2JzZXJ2ZXJbXSA9IFtdO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2FkYXB0ZXIhOiBBO1xuICBwcml2YXRlIF90YWJsZU5hbWUhOiBzdHJpbmc7XG5cbiAgcHJvdGVjdGVkIGdldCBhZGFwdGVyKCk6IEEge1xuICAgIGlmICghdGhpcy5fYWRhcHRlcilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBcIk5vIGFkYXB0ZXIgZm91bmQgZm9yIHRoaXMgcmVwb3NpdG9yeS4gZGlkIHlvdSB1c2UgdGhlIEB1c2VzIGRlY29yYXRvciBvciBwYXNzIGl0IGluIHRoZSBjb25zdHJ1Y3Rvcj9cIlxuICAgICAgKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRlcjtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgdGFibGVOYW1lKCkge1xuICAgIGlmICghdGhpcy5fdGFibGVOYW1lKSB0aGlzLl90YWJsZU5hbWUgPSBSZXBvc2l0b3J5LnRhYmxlKHRoaXMuY2xhc3MpO1xuICAgIHJldHVybiB0aGlzLl90YWJsZU5hbWU7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihhZGFwdGVyOiBBLCBjbGF6ej86IENvbnN0cnVjdG9yPE0+KSB7XG4gICAgdGhpcy5fYWRhcHRlciA9IGFkYXB0ZXI7XG4gICAgaWYgKGNsYXp6KSB0aGlzLl9jbGFzcyA9IGNsYXp6O1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlKG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkIH0gPSB0aGlzLmFkYXB0ZXIucHJlcGFyZShtb2RlbCwgdGhpcy5wayk7XG4gICAgcmVjb3JkID0gYXdhaXQgdGhpcy5hZGFwdGVyLmNyZWF0ZSh0aGlzLnRhYmxlTmFtZSwgaWQsIHJlY29yZCwgLi4uYXJncyk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQocmVjb3JkLCB0aGlzLmNsYXNzLCB0aGlzLnBrLCBpZCk7XG4gIH1cblxuICBhc3luYyByZWFkKGlkOiBzdHJpbmcgfCBudW1iZXIsIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNPiB7XG4gICAgY29uc3QgbSA9IGF3YWl0IHRoaXMuYWRhcHRlci5yZWFkKHRoaXMudGFibGVOYW1lLCBpZCwgLi4uYXJncyk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQobSwgdGhpcy5jbGFzcywgdGhpcy5waywgaWQpO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlKG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkIH0gPSB0aGlzLmFkYXB0ZXIucHJlcGFyZShtb2RlbCwgdGhpcy5wayk7XG4gICAgcmVjb3JkID0gYXdhaXQgdGhpcy5hZGFwdGVyLnVwZGF0ZSh0aGlzLnRhYmxlTmFtZSwgaWQsIHJlY29yZCwgLi4uYXJncyk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQocmVjb3JkLCB0aGlzLmNsYXNzLCB0aGlzLnBrLCBpZCk7XG4gIH1cblxuICBhc3luYyBkZWxldGUoaWQ6IHN0cmluZyB8IG51bWJlciwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+IHtcbiAgICBjb25zdCBtID0gYXdhaXQgdGhpcy5hZGFwdGVyLmRlbGV0ZSh0aGlzLnRhYmxlTmFtZSwgaWQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KG0sIHRoaXMuY2xhc3MsIHRoaXMucGssIGlkKTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZUFsbChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIGlmICghbW9kZWxzLmxlbmd0aCkgcmV0dXJuIG1vZGVscztcbiAgICBjb25zdCBwcmVwYXJlZCA9IG1vZGVscy5tYXAoKG0pID0+IHRoaXMuYWRhcHRlci5wcmVwYXJlKG0sIHRoaXMucGspKTtcbiAgICBjb25zdCBpZHMgPSBwcmVwYXJlZC5tYXAoKHApID0+IHAuaWQpO1xuICAgIGxldCByZWNvcmRzID0gcHJlcGFyZWQubWFwKChwKSA9PiBwLnJlY29yZCk7XG4gICAgcmVjb3JkcyA9IGF3YWl0IHRoaXMuYWRhcHRlci5jcmVhdGVBbGwoXG4gICAgICB0aGlzLnRhYmxlTmFtZSxcbiAgICAgIGlkcyBhcyAoc3RyaW5nIHwgbnVtYmVyKVtdLFxuICAgICAgcmVjb3JkcyxcbiAgICAgIC4uLmFyZ3NcbiAgICApO1xuICAgIHJldHVybiByZWNvcmRzLm1hcCgociwgaSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5yZXZlcnQociwgdGhpcy5jbGFzcywgdGhpcy5waywgaWRzW2ldIGFzIHN0cmluZyB8IG51bWJlcilcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlQWxsKGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgdGhpcy5hZGFwdGVyLmRlbGV0ZUFsbCh0aGlzLnRhYmxlTmFtZSwga2V5cywgLi4uYXJncyk7XG4gICAgcmV0dXJuIHJlc3VsdHMubWFwKChyLCBpKSA9PlxuICAgICAgdGhpcy5hZGFwdGVyLnJldmVydChyLCB0aGlzLmNsYXNzLCB0aGlzLnBrLCBrZXlzW2ldKVxuICAgICk7XG4gIH1cblxuICBhc3luYyByZWFkQWxsKGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCByZWNvcmRzID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJlYWRBbGwodGhpcy50YWJsZU5hbWUsIGtleXMsIC4uLmFyZ3MpO1xuICAgIHJldHVybiByZWNvcmRzLm1hcCgociwgaSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5yZXZlcnQociwgdGhpcy5jbGFzcywgdGhpcy5waywga2V5c1tpXSlcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlQWxsKG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgY29uc3QgcmVjb3JkcyA9IG1vZGVscy5tYXAoKG0pID0+IHRoaXMuYWRhcHRlci5wcmVwYXJlKG0sIHRoaXMucGspKTtcbiAgICBjb25zdCB1cGRhdGVkID0gYXdhaXQgdGhpcy5hZGFwdGVyLnVwZGF0ZUFsbChcbiAgICAgIHRoaXMudGFibGVOYW1lLFxuICAgICAgcmVjb3Jkcy5tYXAoKHIpID0+IHIuaWQpLFxuICAgICAgcmVjb3Jkcy5tYXAoKHIpID0+IHIucmVjb3JkKSxcbiAgICAgIC4uLmFyZ3NcbiAgICApO1xuICAgIHJldHVybiB1cGRhdGVkLm1hcCgodSwgaSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5yZXZlcnQodSwgdGhpcy5jbGFzcywgdGhpcy5waywgcmVjb3Jkc1tpXS5pZClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFJlZ2lzdGVycyBhbiB7QGxpbmsgT2JzZXJ2ZXJ9XG4gICAqIEBwYXJhbSB7T2JzZXJ2ZXJ9IG9ic2VydmVyXG4gICAqXG4gICAqIEBzZWUge09ic2VydmFibGUjb2JzZXJ2ZX1cbiAgICovXG4gIG9ic2VydmUob2JzZXJ2ZXI6IE9ic2VydmVyKTogdm9pZCB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLm9ic2VydmVycy5pbmRleE9mKG9ic2VydmVyKTtcbiAgICBpZiAoaW5kZXggIT09IC0xKSB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk9ic2VydmVyIGFscmVhZHkgcmVnaXN0ZXJlZFwiKTtcbiAgICB0aGlzLm9ic2VydmVycy5wdXNoKG9ic2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBVbnJlZ2lzdGVycyBhbiB7QGxpbmsgT2JzZXJ2ZXJ9XG4gICAqIEBwYXJhbSB7T2JzZXJ2ZXJ9IG9ic2VydmVyXG4gICAqXG4gICAqIEBzZWUge09ic2VydmFibGUjdW5PYnNlcnZlfVxuICAgKi9cbiAgdW5PYnNlcnZlKG9ic2VydmVyOiBPYnNlcnZlcik6IHZvaWQge1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5vYnNlcnZlcnMuaW5kZXhPZihvYnNlcnZlcik7XG4gICAgaWYgKGluZGV4ID09PSAtMSkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJGYWlsZWQgdG8gZmluZCBPYnNlcnZlclwiKTtcbiAgICB0aGlzLm9ic2VydmVycy5zcGxpY2UoaW5kZXgsIDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IGNhbGxzIGFsbCByZWdpc3RlcmVkIHtAbGluayBPYnNlcnZlcn1zIHRvIHVwZGF0ZSB0aGVtc2VsdmVzXG4gICAqIEBwYXJhbSB7YW55W119IFthcmdzXSBvcHRpb25hbCBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIHRoZSB7QGxpbmsgT2JzZXJ2ZXIjcmVmcmVzaH0gbWV0aG9kXG4gICAqL1xuICBhc3luYyB1cGRhdGVPYnNlcnZlcnMoLi4uYXJnczogYW55W10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgICAgdGhpcy5vYnNlcnZlcnMubWFwKChvKSA9PiBvLnJlZnJlc2goLi4uYXJncykpXG4gICAgKTtcbiAgICByZXN1bHRzLmZvckVhY2goKHJlc3VsdCwgaSkgPT4ge1xuICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09IFwicmVqZWN0ZWRcIilcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGBGYWlsZWQgdG8gdXBkYXRlIG9ic2VydmFibGUgJHt0aGlzLm9ic2VydmVyc1tpXX06ICR7cmVzdWx0LnJlYXNvbn1gXG4gICAgICAgICk7XG4gICAgfSk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIEFkYXB0ZXIsXG4gIENvbmRpdGlvbixcbiAgUmVwb3NpdG9yeSxcbiAgU2VxdWVuY2UsXG4gIFNlcXVlbmNlT3B0aW9ucyxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBCYXNlRXJyb3IsIENvbnRleHQsIE9wZXJhdGlvbktleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEh0dHBDb25maWcsIEh0dHBGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBSZXN0U2VydmljZSB9IGZyb20gXCIuL1Jlc3RTZXJ2aWNlXCI7XG5pbXBvcnQgeyBTdGF0ZW1lbnQgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEh0dHBBZGFwdGVyPFxuICBZLFxuICBRLFxuICBGIGV4dGVuZHMgSHR0cEZsYWdzID0gSHR0cEZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+IGV4dGVuZHMgQWRhcHRlcjxZLCBRLCBGLCBDPiB7XG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihcbiAgICBuYXRpdmU6IFksXG4gICAgcHJvdGVjdGVkIGNvbmZpZzogSHR0cENvbmZpZyxcbiAgICBmbGF2b3VyOiBzdHJpbmcsXG4gICAgYWxpYXM/OiBzdHJpbmdcbiAgKSB7XG4gICAgc3VwZXIobmF0aXZlLCBmbGF2b3VyLCBhbGlhcyk7XG4gIH1cblxuICBvdmVycmlkZSBmbGFnczxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9wZXJhdGlvbjpcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5DUkVBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5SRUFEXG4gICAgICB8IE9wZXJhdGlvbktleXMuVVBEQVRFXG4gICAgICB8IE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBvdmVycmlkZXM6IFBhcnRpYWw8Rj5cbiAgKSB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oc3VwZXIuZmxhZ3M8TT4ob3BlcmF0aW9uLCBtb2RlbCwgb3ZlcnJpZGVzKSwge1xuICAgICAgaGVhZGVyczoge30sXG4gICAgfSk7XG4gIH1cblxuICBvdmVycmlkZSByZXBvc2l0b3J5PE0gZXh0ZW5kcyBNb2RlbD4oKTogQ29uc3RydWN0b3I8XG4gICAgUmVwb3NpdG9yeTxNLCBRLCBIdHRwQWRhcHRlcjxZLCBRLCBGLCBDPj5cbiAgPiB7XG4gICAgcmV0dXJuIFJlc3RTZXJ2aWNlIGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8XG4gICAgICBSZXBvc2l0b3J5PE0sIFEsIEh0dHBBZGFwdGVyPFksIFEsIEYsIEM+PlxuICAgID47XG4gIH1cblxuICBwcm90ZWN0ZWQgdXJsKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIHF1ZXJ5UGFyYW1zPzogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyPlxuICApIHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKFxuICAgICAgYCR7dGhpcy5jb25maWcucHJvdG9jb2x9Oi8vJHt0aGlzLmNvbmZpZy5ob3N0fS8ke3RhYmxlTmFtZX1gXG4gICAgKTtcbiAgICBpZiAocXVlcnlQYXJhbXMpXG4gICAgICBPYmplY3QuZW50cmllcyhxdWVyeVBhcmFtcykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PlxuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChrZXksIHZhbHVlLnRvU3RyaW5nKCkpXG4gICAgICApO1xuXG4gICAgcmV0dXJuIGVuY29kZVVSSSh1cmwudG9TdHJpbmcoKSk7XG4gIH1cblxuICBwYXJzZUVycm9yKGVycjogRXJyb3IpOiBCYXNlRXJyb3Ige1xuICAgIGNvbnN0IHsgbWVzc2FnZSB9ID0gZXJyO1xuICAgIHN3aXRjaCAobWVzc2FnZSkge1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIGVyciBhcyBCYXNlRXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBhc3luYyBpbml0aWFsaXplKC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gZG8gbm90aGluZ1xuICB9XG5cbiAgYWJzdHJhY3QgcmVxdWVzdDxWPihkZXRhaWxzOiBRKTogUHJvbWlzZTxWPjtcblxuICBhYnN0cmFjdCBvdmVycmlkZSBjcmVhdGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIGFic3RyYWN0IG92ZXJyaWRlIHJlYWQoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIGFic3RyYWN0IG92ZXJyaWRlIHVwZGF0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj47XG5cbiAgYWJzdHJhY3Qgb3ZlcnJpZGUgZGVsZXRlKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PjtcblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIHJhdzxSPihyYXdJbnB1dDogUSwgcHJvY2VzczogYm9vbGVhbiwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPFI+IHtcbiAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcbiAgICAgIFwiQXBpIGlzIG5vdCBuYXRpdmVseSBhdmFpbGFibGUgZm9yIEh0dHBBZGFwdGVycy4gSWYgcmVxdWlyZWQsIHBsZWFzZSBleHRlbmRzIHRoaXMgY2xhc3NcIlxuICAgICk7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIFNlcXVlbmNlKG9wdGlvbnM6IFNlcXVlbmNlT3B0aW9ucyk6IFByb21pc2U8U2VxdWVuY2U+IHtcbiAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcbiAgICAgIFwiQXBpIGlzIG5vdCBuYXRpdmVseSBhdmFpbGFibGUgZm9yIEh0dHBBZGFwdGVycy4gSWYgcmVxdWlyZWQsIHBsZWFzZSBleHRlbmRzIHRoaXMgY2xhc3NcIlxuICAgICk7XG4gIH1cblxuICBvdmVycmlkZSBTdGF0ZW1lbnQ8TSBleHRlbmRzIE1vZGVsPigpOiBTdGF0ZW1lbnQ8USwgTSwgYW55PiB7XG4gICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXG4gICAgICBcIkFwaSBpcyBub3QgbmF0aXZlbHkgYXZhaWxhYmxlIGZvciBIdHRwQWRhcHRlcnMuIElmIHJlcXVpcmVkLCBwbGVhc2UgZXh0ZW5kcyB0aGlzIGNsYXNzXCJcbiAgICApO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBwYXJzZUNvbmRpdGlvbihjb25kaXRpb246IENvbmRpdGlvbjxhbnk+KTogUSB7XG4gICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXG4gICAgICBcIkFwaSBpcyBub3QgbmF0aXZlbHkgYXZhaWxhYmxlIGZvciBIdHRwQWRhcHRlcnMuIElmIHJlcXVpcmVkLCBwbGVhc2UgZXh0ZW5kcyB0aGlzIGNsYXNzXCJcbiAgICApO1xuICB9XG59XG4iLCJpbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBIdHRwQWRhcHRlciB9IGZyb20gXCIuL2FkYXB0ZXJcIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEh0dHBGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmV4cG9ydCBjbGFzcyBSZXN0UmVwb3NpdG9yeTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBRLFxuICBBIGV4dGVuZHMgSHR0cEFkYXB0ZXI8YW55LCBRLCBGLCBDPixcbiAgRiBleHRlbmRzIEh0dHBGbGFncyA9IEh0dHBGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPiBleHRlbmRzIFJlcG9zaXRvcnk8TSwgUSwgQT4ge1xuICBjb25zdHJ1Y3RvcihhZGFwdGVyOiBBLCBjbGF6ej86IENvbnN0cnVjdG9yPE0+KSB7XG4gICAgc3VwZXIoYWRhcHRlciwgY2xhenopO1xuICB9XG59XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9hZGFwdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9SZXN0UmVwb3NpdG9yeVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vUmVzdFNlcnZpY2VcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3R5cGVzXCI7XG5cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztNQVlhLFdBQVcsQ0FBQTtBQVl0QixJQUFBLElBQUksS0FBSyxHQUFBO1FBQ1AsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNO0FBQ2QsWUFBQSxNQUFNLElBQUksYUFBYSxDQUFDLCtDQUErQyxDQUFDO1FBQzFFLE9BQU8sSUFBSSxDQUFDLE1BQU07O0FBR3BCLElBQUEsSUFBSSxFQUFFLEdBQUE7UUFDSixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUc7QUFBRSxZQUFBLElBQUksQ0FBQyxHQUFHLEdBQUcsY0FBYyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsRUFBRTtRQUM3RCxPQUFPLElBQUksQ0FBQyxHQUFHOztBQVFqQixJQUFBLElBQWMsT0FBTyxHQUFBO1FBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtBQUNoQixZQUFBLE1BQU0sSUFBSSxhQUFhLENBQ3JCLHNHQUFzRyxDQUN2RztRQUNILE9BQU8sSUFBSSxDQUFDLFFBQVE7O0FBR3RCLElBQUEsSUFBYyxTQUFTLEdBQUE7UUFDckIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVO1lBQUUsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDcEUsT0FBTyxJQUFJLENBQUMsVUFBVTs7SUFHeEIsV0FBWSxDQUFBLE9BQVUsRUFBRSxLQUFzQixFQUFBO1FBbEJwQyxJQUFTLENBQUEsU0FBQSxHQUFlLEVBQUU7QUFtQmxDLFFBQUEsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPO0FBQ3ZCLFFBQUEsSUFBSSxLQUFLO0FBQUUsWUFBQSxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUs7O0FBR2hDLElBQUEsTUFBTSxNQUFNLENBQUMsS0FB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
464
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWh0dHAuZXNtLmNqcyIsInNvdXJjZXMiOlsiLi4vc3JjL1Jlc3RTZXJ2aWNlLnRzIiwiLi4vc3JjL2FkYXB0ZXIudHMiLCIuLi9zcmMvUmVzdFJlcG9zaXRvcnkudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQnVsa0NydWRPcGVyYXRvcixcbiAgQ29udGV4dCxcbiAgQ3J1ZE9wZXJhdG9yLFxuICBmaW5kUHJpbWFyeUtleSxcbiAgSW50ZXJuYWxFcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBPYnNlcnZlciwgUmVwb3NpdG9yeSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgSHR0cEFkYXB0ZXIgfSBmcm9tIFwiLi9hZGFwdGVyXCI7XG5pbXBvcnQgeyBIdHRwRmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXJ2aWNlIGNsYXNzIGZvciBSRVNUIEFQSSBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBhIGNvbXByZWhlbnNpdmUgaW1wbGVtZW50YXRpb24gZm9yIGludGVyYWN0aW5nIHdpdGggUkVTVCBBUElzLlxuICogVGhpcyBjbGFzcyBpbXBsZW1lbnRzIENSVUQgb3BlcmF0aW9ucyBmb3Igc2luZ2xlIGFuZCBidWxrIG9wZXJhdGlvbnMsIGFzIHdlbGwgYXNcbiAqIHRoZSBPYnNlcnZhYmxlIHBhdHRlcm4gdG8gbm90aWZ5IG9ic2VydmVycyBvZiBjaGFuZ2VzLiBJdCB3b3JrcyB3aXRoIEhUVFAgYWRhcHRlcnNcbiAqIHRvIHBlcmZvcm0gdGhlIGFjdHVhbCBBUEkgcmVxdWVzdHMgYW5kIGhhbmRsZXMgbW9kZWwgY29udmVyc2lvbi5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUsIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFEgLSBUaGUgcXVlcnkgdHlwZSB1c2VkIGJ5IHRoZSBhZGFwdGVyXG4gKiBAdGVtcGxhdGUgQSAtIFRoZSBIVFRQIGFkYXB0ZXIgdHlwZSwgZXh0ZW5kaW5nIEh0dHBBZGFwdGVyXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSBIVFRQIGZsYWdzIHR5cGUsIGV4dGVuZGluZyBIdHRwRmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSwgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7QX0gYWRhcHRlciAtIFRoZSBIVFRQIGFkYXB0ZXIgaW5zdGFuY2VcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IFtjbGF6el0gLSBPcHRpb25hbCBjb25zdHJ1Y3RvciBmb3IgdGhlIG1vZGVsIGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQ3JlYXRlIGEgc2VydmljZSBmb3IgVXNlciBtb2RlbCB3aXRoIEF4aW9zIGFkYXB0ZXJcbiAqIGNvbnN0IGF4aW9zQWRhcHRlciA9IG5ldyBBeGlvc0FkYXB0ZXIoe1xuICogICBwcm90b2NvbDogJ2h0dHBzJyxcbiAqICAgaG9zdDogJ2FwaS5leGFtcGxlLmNvbSdcbiAqIH0pO1xuICogY29uc3QgdXNlclNlcnZpY2UgPSBuZXcgUmVzdFNlcnZpY2UoYXhpb3NBZGFwdGVyLCBVc2VyKTtcbiAqXG4gKiAvLyBDcmVhdGUgYSBuZXcgdXNlclxuICogY29uc3QgdXNlciA9IG5ldyBVc2VyKHsgbmFtZTogJ0pvaG4gRG9lJywgZW1haWw6ICdqb2huQGV4YW1wbGUuY29tJyB9KTtcbiAqIGNvbnN0IGNyZWF0ZWRVc2VyID0gYXdhaXQgdXNlclNlcnZpY2UuY3JlYXRlKHVzZXIpO1xuICpcbiAqIC8vIFVwZGF0ZSBhIHVzZXJcbiAqIGNyZWF0ZWRVc2VyLm5hbWUgPSAnSmFuZSBEb2UnO1xuICogY29uc3QgdXBkYXRlZFVzZXIgPSBhd2FpdCB1c2VyU2VydmljZS51cGRhdGUoY3JlYXRlZFVzZXIpO1xuICpcbiAqIC8vIERlbGV0ZSBhIHVzZXJcbiAqIGF3YWl0IHVzZXJTZXJ2aWNlLmRlbGV0ZSh1cGRhdGVkVXNlci5pZCk7XG4gKiBgYGBcbiAqIEBjbGFzc1xuICovXG5leHBvcnQgY2xhc3MgUmVzdFNlcnZpY2U8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFEsXG4gICAgQSBleHRlbmRzIEh0dHBBZGFwdGVyPGFueSwgUSwgRiwgQz4sXG4gICAgRiBleHRlbmRzIEh0dHBGbGFncyA9IEh0dHBGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4gID5cbiAgaW1wbGVtZW50cyBDcnVkT3BlcmF0b3I8TT4sIEJ1bGtDcnVkT3BlcmF0b3I8TT4sIE9ic2VydmFibGVcbntcbiAgcHJpdmF0ZSByZWFkb25seSBfY2xhc3MhOiBDb25zdHJ1Y3RvcjxNPjtcbiAgcHJpdmF0ZSBfcGshOiBrZXlvZiBNO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgbW9kZWwgY2xhc3MgY29uc3RydWN0b3JcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBtb2RlbCBjbGFzcyBjb25zdHJ1Y3RvciBhc3NvY2lhdGVkIHdpdGggdGhpcyBzZXJ2aWNlLlxuICAgKiBUaHJvd3MgYW4gZXJyb3IgaWYgbm8gY2xhc3MgZGVmaW5pdGlvbiBpcyBmb3VuZC5cbiAgICogQHJldHVybiB7Q29uc3RydWN0b3I8TT59IFRoZSBtb2RlbCBjbGFzcyBjb25zdHJ1Y3RvclxuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiBubyBjbGFzcyBkZWZpbml0aW9uIGlzIGZvdW5kXG4gICAqL1xuICBnZXQgY2xhc3MoKSB7XG4gICAgaWYgKCF0aGlzLl9jbGFzcylcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTm8gY2xhc3MgZGVmaW5pdGlvbiBmb3VuZCBmb3IgdGhpcyByZXBvc2l0b3J5XCIpO1xuICAgIHJldHVybiB0aGlzLl9jbGFzcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgcHJpbWFyeSBrZXkgcHJvcGVydHkgbmFtZVxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIG5hbWUgb2YgdGhlIHByaW1hcnkga2V5IHByb3BlcnR5IGZvciB0aGUgbW9kZWwuXG4gICAqIElmIG5vdCBhbHJlYWR5IGRldGVybWluZWQsIGl0IGZpbmRzIHRoZSBwcmltYXJ5IGtleSB1c2luZyB0aGUgbW9kZWwgY2xhc3MuXG4gICAqIEByZXR1cm4gVGhlIHByaW1hcnkga2V5IHByb3BlcnR5IG5hbWVcbiAgICovXG4gIGdldCBwaygpIHtcbiAgICBpZiAoIXRoaXMuX3BrKSB0aGlzLl9wayA9IGZpbmRQcmltYXJ5S2V5KG5ldyB0aGlzLmNsYXNzKCkpLmlkO1xuICAgIHJldHVybiB0aGlzLl9waztcbiAgfVxuXG4gIHByb3RlY3RlZCBvYnNlcnZlcnM6IE9ic2VydmVyW10gPSBbXTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9hZGFwdGVyITogQTtcbiAgcHJpdmF0ZSBfdGFibGVOYW1lITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgSFRUUCBhZGFwdGVyXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgSFRUUCBhZGFwdGVyIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHNlcnZpY2UuXG4gICAqIFRocm93cyBhbiBlcnJvciBpZiBubyBhZGFwdGVyIGlzIGZvdW5kLlxuICAgKiBAcmV0dXJuIHtBfSBUaGUgSFRUUCBhZGFwdGVyIGluc3RhbmNlXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIG5vIGFkYXB0ZXIgaXMgZm91bmRcbiAgICovXG4gIHByb3RlY3RlZCBnZXQgYWRhcHRlcigpOiBBIHtcbiAgICBpZiAoIXRoaXMuX2FkYXB0ZXIpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgXCJObyBhZGFwdGVyIGZvdW5kIGZvciB0aGlzIHJlcG9zaXRvcnkuIGRpZCB5b3UgdXNlIHRoZSBAdXNlcyBkZWNvcmF0b3Igb3IgcGFzcyBpdCBpbiB0aGUgY29uc3RydWN0b3I/XCJcbiAgICAgICk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0ZXI7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRhYmxlIG5hbWUgZm9yIHRoZSBtb2RlbFxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIHRhYmxlIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBtb2RlbCBjbGFzcy5cbiAgICogSWYgbm90IGFscmVhZHkgZGV0ZXJtaW5lZCwgaXQgZ2V0cyB0aGUgdGFibGUgbmFtZSBmcm9tIHRoZSBSZXBvc2l0b3J5IHV0aWxpdHkuXG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHRhYmxlIG5hbWVcbiAgICovXG4gIHByb3RlY3RlZCBnZXQgdGFibGVOYW1lKCkge1xuICAgIGlmICghdGhpcy5fdGFibGVOYW1lKSB0aGlzLl90YWJsZU5hbWUgPSBSZXBvc2l0b3J5LnRhYmxlKHRoaXMuY2xhc3MpO1xuICAgIHJldHVybiB0aGlzLl90YWJsZU5hbWU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIGEgbmV3IFJlc3RTZXJ2aWNlIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgc2VydmljZSBpbnN0YW5jZSB3aXRoIHRoZSBzcGVjaWZpZWQgYWRhcHRlciBhbmQgb3B0aW9uYWwgbW9kZWwgY2xhc3MuXG4gICAqIFRoZSBjb25zdHJ1Y3RvciBzdG9yZXMgdGhlIGFkYXB0ZXIgYW5kIG1vZGVsIGNsYXNzIGZvciBsYXRlciB1c2UgaW4gQ1JVRCBvcGVyYXRpb25zLlxuICAgKiBAcGFyYW0ge0F9IGFkYXB0ZXIgLSBUaGUgSFRUUCBhZGFwdGVyIGluc3RhbmNlIHRvIHVzZSBmb3IgQVBJIHJlcXVlc3RzXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IFtjbGF6el0gLSBPcHRpb25hbCBjb25zdHJ1Y3RvciBmb3IgdGhlIG1vZGVsIGNsYXNzXG4gICAqL1xuICBjb25zdHJ1Y3RvcihhZGFwdGVyOiBBLCBjbGF6ej86IENvbnN0cnVjdG9yPE0+KSB7XG4gICAgdGhpcy5fYWRhcHRlciA9IGFkYXB0ZXI7XG4gICAgaWYgKGNsYXp6KSB0aGlzLl9jbGFzcyA9IGNsYXp6O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IHJlc291cmNlXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgcmVzb3VyY2UgaW4gdGhlIFJFU1QgQVBJIHVzaW5nIHRoZSBwcm92aWRlZCBtb2RlbC5cbiAgICogVGhlIG1ldGhvZCBwcmVwYXJlcyB0aGUgbW9kZWwgZm9yIHRoZSBhZGFwdGVyLCBzZW5kcyB0aGUgY3JlYXRlIHJlcXVlc3QsXG4gICAqIGFuZCB0aGVuIGNvbnZlcnRzIHRoZSByZXNwb25zZSBiYWNrIHRvIGEgbW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGNyZWF0ZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIGFzeW5jIGNyZWF0ZShtb2RlbDogTSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IHsgcmVjb3JkLCBpZCB9ID0gdGhpcy5hZGFwdGVyLnByZXBhcmUobW9kZWwsIHRoaXMucGspO1xuICAgIHJlY29yZCA9IGF3YWl0IHRoaXMuYWRhcHRlci5jcmVhdGUodGhpcy50YWJsZU5hbWUsIGlkLCByZWNvcmQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHJlY29yZCwgdGhpcy5jbGFzcywgdGhpcy5waywgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSByZXNvdXJjZSBieSBJRFxuICAgKiBAc3VtbWFyeSBGZXRjaGVzIGEgcmVzb3VyY2UgZnJvbSB0aGUgUkVTVCBBUEkgdXNpbmcgdGhlIHByb3ZpZGVkIElELlxuICAgKiBUaGUgbWV0aG9kIHNlbmRzIHRoZSByZWFkIHJlcXVlc3QgYW5kIGNvbnZlcnRzIHRoZSByZXNwb25zZSB0byBhIG1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIGlkZW50aWZpZXIgb2YgdGhlIHJlc291cmNlIHRvIHJldHJpZXZlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJldHJpZXZlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgYXN5bmMgcmVhZChpZDogc3RyaW5nIHwgbnVtYmVyLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT4ge1xuICAgIGNvbnN0IG0gPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmVhZCh0aGlzLnRhYmxlTmFtZSwgaWQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KG0sIHRoaXMuY2xhc3MsIHRoaXMucGssIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhbiBleGlzdGluZyByZXNvdXJjZVxuICAgKiBAc3VtbWFyeSBVcGRhdGVzIGFuIGV4aXN0aW5nIHJlc291cmNlIGluIHRoZSBSRVNUIEFQSSB1c2luZyB0aGUgcHJvdmlkZWQgbW9kZWwuXG4gICAqIFRoZSBtZXRob2QgcHJlcGFyZXMgdGhlIG1vZGVsIGZvciB0aGUgYWRhcHRlciwgc2VuZHMgdGhlIHVwZGF0ZSByZXF1ZXN0LFxuICAgKiBhbmQgdGhlbiBjb252ZXJ0cyB0aGUgcmVzcG9uc2UgYmFjayB0byBhIG1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHdpdGggdXBkYXRlZCBkYXRhXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHVwZGF0ZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIGFzeW5jIHVwZGF0ZShtb2RlbDogTSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IHsgcmVjb3JkLCBpZCB9ID0gdGhpcy5hZGFwdGVyLnByZXBhcmUobW9kZWwsIHRoaXMucGspO1xuICAgIHJlY29yZCA9IGF3YWl0IHRoaXMuYWRhcHRlci51cGRhdGUodGhpcy50YWJsZU5hbWUsIGlkLCByZWNvcmQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHJlY29yZCwgdGhpcy5jbGFzcywgdGhpcy5waywgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgcmVzb3VyY2UgYnkgSURcbiAgICogQHN1bW1hcnkgUmVtb3ZlcyBhIHJlc291cmNlIGZyb20gdGhlIFJFU1QgQVBJIHVzaW5nIHRoZSBwcm92aWRlZCBJRC5cbiAgICogVGhlIG1ldGhvZCBzZW5kcyB0aGUgZGVsZXRlIHJlcXVlc3QgYW5kIGNvbnZlcnRzIHRoZSByZXNwb25zZSB0byBhIG1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIGlkZW50aWZpZXIgb2YgdGhlIHJlc291cmNlIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgYWRhcHRlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBkZWxldGVkIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBhc3luYyBkZWxldGUoaWQ6IHN0cmluZyB8IG51bWJlciwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+IHtcbiAgICBjb25zdCBtID0gYXdhaXQgdGhpcy5hZGFwdGVyLmRlbGV0ZSh0aGlzLnRhYmxlTmFtZSwgaWQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KG0sIHRoaXMuY2xhc3MsIHRoaXMucGssIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBtdWx0aXBsZSByZXNvdXJjZXNcbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBtdWx0aXBsZSByZXNvdXJjZXMgaW4gdGhlIFJFU1QgQVBJIHVzaW5nIHRoZSBwcm92aWRlZCBtb2RlbHMuXG4gICAqIFRoZSBtZXRob2QgcHJlcGFyZXMgZWFjaCBtb2RlbCBmb3IgdGhlIGFkYXB0ZXIsIHNlbmRzIGEgYnVsayBjcmVhdGUgcmVxdWVzdCxcbiAgICogYW5kIHRoZW4gY29udmVydHMgdGhlIHJlc3BvbnNlcyBiYWNrIHRvIG1vZGVsIGluc3RhbmNlcy5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBtb2RlbCBpbnN0YW5jZXMgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBhbiBhcnJheSBvZiBjcmVhdGVkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgYXN5bmMgY3JlYXRlQWxsKG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgaWYgKCFtb2RlbHMubGVuZ3RoKSByZXR1cm4gbW9kZWxzO1xuICAgIGNvbnN0IHByZXBhcmVkID0gbW9kZWxzLm1hcCgobSkgPT4gdGhpcy5hZGFwdGVyLnByZXBhcmUobSwgdGhpcy5waykpO1xuICAgIGNvbnN0IGlkcyA9IHByZXBhcmVkLm1hcCgocCkgPT4gcC5pZCk7XG4gICAgbGV0IHJlY29yZHMgPSBwcmVwYXJlZC5tYXAoKHApID0+IHAucmVjb3JkKTtcbiAgICByZWNvcmRzID0gYXdhaXQgdGhpcy5hZGFwdGVyLmNyZWF0ZUFsbChcbiAgICAgIHRoaXMudGFibGVOYW1lLFxuICAgICAgaWRzIGFzIChzdHJpbmcgfCBudW1iZXIpW10sXG4gICAgICByZWNvcmRzLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHJlY29yZHMubWFwKChyLCBpKSA9PlxuICAgICAgdGhpcy5hZGFwdGVyLnJldmVydChyLCB0aGlzLmNsYXNzLCB0aGlzLnBrLCBpZHNbaV0gYXMgc3RyaW5nIHwgbnVtYmVyKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgbXVsdGlwbGUgcmVzb3VyY2VzIGJ5IElEc1xuICAgKiBAc3VtbWFyeSBSZW1vdmVzIG11bHRpcGxlIHJlc291cmNlcyBmcm9tIHRoZSBSRVNUIEFQSSB1c2luZyB0aGUgcHJvdmlkZWQgSURzLlxuICAgKiBUaGUgbWV0aG9kIHNlbmRzIGEgYnVsayBkZWxldGUgcmVxdWVzdCBhbmQgY29udmVydHMgdGhlIHJlc3BvbnNlcyB0byBtb2RlbCBpbnN0YW5jZXMuXG4gICAqIEBwYXJhbSB7c3RyaW5nW118bnVtYmVyW119IGtleXMgLSBUaGUgaWRlbnRpZmllcnMgb2YgdGhlIHJlc291cmNlcyB0byBkZWxldGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGFkYXB0ZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGFuIGFycmF5IG9mIGRlbGV0ZWQgbW9kZWwgaW5zdGFuY2VzXG4gICAqL1xuICBhc3luYyBkZWxldGVBbGwoa2V5czogc3RyaW5nW10gfCBudW1iZXJbXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuZGVsZXRlQWxsKHRoaXMudGFibGVOYW1lLCBrZXlzLCAuLi5hcmdzKTtcbiAgICByZXR1cm4gcmVzdWx0cy5tYXAoKHIsIGkpID0+XG4gICAgICB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHIsIHRoaXMuY2xhc3MsIHRoaXMucGssIGtleXNbaV0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG11bHRpcGxlIHJlc291cmNlcyBieSBJRHNcbiAgICogQHN1bW1hcnkgRmV0Y2hlcyBtdWx0aXBsZSByZXNvdXJjZXMgZnJvbSB0aGUgUkVTVCBBUEkgdXNpbmcgdGhlIHByb3ZpZGVkIElEcy5cbiAgICogVGhlIG1ldGhvZCBzZW5kcyBhIGJ1bGsgcmVhZCByZXF1ZXN0IGFuZCBjb252ZXJ0cyB0aGUgcmVzcG9uc2VzIHRvIG1vZGVsIGluc3RhbmNlcy5cbiAgICogQHBhcmFtIHtzdHJpbmdbXXxudW1iZXJbXX0ga2V5cyAtIFRoZSBpZGVudGlmaWVycyBvZiB0aGUgcmVzb3VyY2VzIHRvIHJldHJpZXZlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBhbiBhcnJheSBvZiByZXRyaWV2ZWQgbW9kZWwgaW5zdGFuY2VzXG4gICAqL1xuICBhc3luYyByZWFkQWxsKGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCByZWNvcmRzID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJlYWRBbGwodGhpcy50YWJsZU5hbWUsIGtleXMsIC4uLmFyZ3MpO1xuICAgIHJldHVybiByZWNvcmRzLm1hcCgociwgaSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5yZXZlcnQociwgdGhpcy5jbGFzcywgdGhpcy5waywga2V5c1tpXSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIG11bHRpcGxlIHJlc291cmNlc1xuICAgKiBAc3VtbWFyeSBVcGRhdGVzIG11bHRpcGxlIHJlc291cmNlcyBpbiB0aGUgUkVTVCBBUEkgdXNpbmcgdGhlIHByb3ZpZGVkIG1vZGVscy5cbiAgICogVGhlIG1ldGhvZCBwcmVwYXJlcyBlYWNoIG1vZGVsIGZvciB0aGUgYWRhcHRlciwgc2VuZHMgYSBidWxrIHVwZGF0ZSByZXF1ZXN0LFxuICAgKiBhbmQgdGhlbiBjb252ZXJ0cyB0aGUgcmVzcG9uc2VzIGJhY2sgdG8gbW9kZWwgaW5zdGFuY2VzLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIG1vZGVsIGluc3RhbmNlcyB3aXRoIHVwZGF0ZWQgZGF0YVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgYWRhcHRlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYW4gYXJyYXkgb2YgdXBkYXRlZCBtb2RlbCBpbnN0YW5jZXNcbiAgICovXG4gIGFzeW5jIHVwZGF0ZUFsbChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIGNvbnN0IHJlY29yZHMgPSBtb2RlbHMubWFwKChtKSA9PiB0aGlzLmFkYXB0ZXIucHJlcGFyZShtLCB0aGlzLnBrKSk7XG4gICAgY29uc3QgdXBkYXRlZCA9IGF3YWl0IHRoaXMuYWRhcHRlci51cGRhdGVBbGwoXG4gICAgICB0aGlzLnRhYmxlTmFtZSxcbiAgICAgIHJlY29yZHMubWFwKChyKSA9PiByLmlkKSxcbiAgICAgIHJlY29yZHMubWFwKChyKSA9PiByLnJlY29yZCksXG4gICAgICAuLi5hcmdzXG4gICAgKTtcbiAgICByZXR1cm4gdXBkYXRlZC5tYXAoKHUsIGkpID0+XG4gICAgICB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHUsIHRoaXMuY2xhc3MsIHRoaXMucGssIHJlY29yZHNbaV0uaWQpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXJzIGFuIG9ic2VydmVyXG4gICAqIEBzdW1tYXJ5IEFkZHMgYW4gb2JzZXJ2ZXIgdG8gdGhlIGxpc3Qgb2Ygb2JzZXJ2ZXJzIHRoYXQgd2lsbCBiZSBub3RpZmllZCBvZiBjaGFuZ2VzLlxuICAgKiBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIG9ic2VydmVyIGlzIGFscmVhZHkgcmVnaXN0ZXJlZC5cbiAgICogQHBhcmFtIHtPYnNlcnZlcn0gb2JzZXJ2ZXIgLSBUaGUgb2JzZXJ2ZXIgdG8gcmVnaXN0ZXJcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgdGhlIG9ic2VydmVyIGlzIGFscmVhZHkgcmVnaXN0ZXJlZFxuICAgKi9cbiAgb2JzZXJ2ZShvYnNlcnZlcjogT2JzZXJ2ZXIpOiB2b2lkIHtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMub2JzZXJ2ZXJzLmluZGV4T2Yob2JzZXJ2ZXIpO1xuICAgIGlmIChpbmRleCAhPT0gLTEpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiT2JzZXJ2ZXIgYWxyZWFkeSByZWdpc3RlcmVkXCIpO1xuICAgIHRoaXMub2JzZXJ2ZXJzLnB1c2gob2JzZXJ2ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVbnJlZ2lzdGVycyBhbiBvYnNlcnZlclxuICAgKiBAc3VtbWFyeSBSZW1vdmVzIGFuIG9ic2VydmVyIGZyb20gdGhlIGxpc3Qgb2Ygb2JzZXJ2ZXJzLlxuICAgKiBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIG9ic2VydmVyIGlzIG5vdCBmb3VuZC5cbiAgICogQHBhcmFtIHtPYnNlcnZlcn0gb2JzZXJ2ZXIgLSBUaGUgb2JzZXJ2ZXIgdG8gdW5yZWdpc3RlclxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiB0aGUgb2JzZXJ2ZXIgaXMgbm90IGZvdW5kXG4gICAqL1xuICB1bk9ic2VydmUob2JzZXJ2ZXI6IE9ic2VydmVyKTogdm9pZCB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLm9ic2VydmVycy5pbmRleE9mKG9ic2VydmVyKTtcbiAgICBpZiAoaW5kZXggPT09IC0xKSB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkZhaWxlZCB0byBmaW5kIE9ic2VydmVyXCIpO1xuICAgIHRoaXMub2JzZXJ2ZXJzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE5vdGlmaWVzIGFsbCByZWdpc3RlcmVkIG9ic2VydmVyc1xuICAgKiBAc3VtbWFyeSBDYWxscyB0aGUgcmVmcmVzaCBtZXRob2Qgb24gYWxsIHJlZ2lzdGVyZWQgb2JzZXJ2ZXJzIHRvIHVwZGF0ZSB0aGVtc2VsdmVzLlxuICAgKiBBbnkgZXJyb3JzIGR1cmluZyBvYnNlcnZlciByZWZyZXNoIGFyZSBsb2dnZWQgYXMgd2FybmluZ3MgYnV0IGRvbid0IHN0b3AgdGhlIHByb2Nlc3MuXG4gICAqIEBwYXJhbSB7Li4uYW55W119IFthcmdzXSAtIE9wdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBvYnNlcnZlciByZWZyZXNoIG1ldGhvZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBvYnNlcnZlcnMgaGF2ZSBiZWVuIHVwZGF0ZWRcbiAgICovXG4gIGFzeW5jIHVwZGF0ZU9ic2VydmVycyguLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoXG4gICAgICB0aGlzLm9ic2VydmVycy5tYXAoKG8pID0+IG8ucmVmcmVzaCguLi5hcmdzKSlcbiAgICApO1xuICAgIHJlc3VsdHMuZm9yRWFjaCgocmVzdWx0LCBpKSA9PiB7XG4gICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gXCJyZWplY3RlZFwiKVxuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYEZhaWxlZCB0byB1cGRhdGUgb2JzZXJ2YWJsZSAke3RoaXMub2JzZXJ2ZXJzW2ldfTogJHtyZXN1bHQucmVhc29ufWBcbiAgICAgICAgKTtcbiAgICB9KTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgQWRhcHRlcixcbiAgQ29uZGl0aW9uLFxuICBSZXBvc2l0b3J5LFxuICBTZXF1ZW5jZSxcbiAgU2VxdWVuY2VPcHRpb25zLFxuICBVbnN1cHBvcnRlZEVycm9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IEJhc2VFcnJvciwgQ29udGV4dCwgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgSHR0cENvbmZpZywgSHR0cEZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IFJlc3RTZXJ2aWNlIH0gZnJvbSBcIi4vUmVzdFNlcnZpY2VcIjtcbmltcG9ydCB7IFN0YXRlbWVudCB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBYnN0cmFjdCBIVFRQIGFkYXB0ZXIgZm9yIFJFU1QgQVBJIGludGVyYWN0aW9uc1xuICogQHN1bW1hcnkgUHJvdmlkZXMgYSBiYXNlIGltcGxlbWVudGF0aW9uIGZvciBIVFRQIGFkYXB0ZXJzIHdpdGggbWV0aG9kcyBmb3IgQ1JVRCBvcGVyYXRpb25zLFxuICogVVJMIGNvbnN0cnVjdGlvbiwgYW5kIGVycm9yIGhhbmRsaW5nLiBUaGlzIGNsYXNzIGV4dGVuZHMgdGhlIGNvcmUgQWRhcHRlciBjbGFzcyBhbmRcbiAqIGltcGxlbWVudHMgdGhlIG5lY2Vzc2FyeSBtZXRob2RzIGZvciBIVFRQIGNvbW11bmljYXRpb24uIENvbmNyZXRlIGltcGxlbWVudGF0aW9uc1xuICogbXVzdCBwcm92aWRlIHNwZWNpZmljIEhUVFAgY2xpZW50IGZ1bmN0aW9uYWxpdHkuXG4gKiBAdGVtcGxhdGUgWSAtIFRoZSBuYXRpdmUgSFRUUCBjbGllbnQgdHlwZVxuICogQHRlbXBsYXRlIFEgLSBUaGUgcXVlcnkgdHlwZSB1c2VkIGJ5IHRoZSBhZGFwdGVyXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSBIVFRQIGZsYWdzIHR5cGUsIGV4dGVuZGluZyBIdHRwRmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSwgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7WX0gbmF0aXZlIC0gVGhlIG5hdGl2ZSBIVFRQIGNsaWVudCBpbnN0YW5jZVxuICogQHBhcmFtIHtIdHRwQ29uZmlnfSBjb25maWcgLSBDb25maWd1cmF0aW9uIGZvciB0aGUgSFRUUCBhZGFwdGVyXG4gKiBAcGFyYW0ge3N0cmluZ30gZmxhdm91ciAtIFRoZSBhZGFwdGVyIGZsYXZvciBpZGVudGlmaWVyXG4gKiBAcGFyYW0ge3N0cmluZ30gW2FsaWFzXSAtIE9wdGlvbmFsIGFsaWFzIGZvciB0aGUgYWRhcHRlclxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEV4YW1wbGUgaW1wbGVtZW50YXRpb24gd2l0aCBBeGlvc1xuICogY2xhc3MgQXhpb3NBZGFwdGVyIGV4dGVuZHMgSHR0cEFkYXB0ZXI8QXhpb3NJbnN0YW5jZSwgQXhpb3NSZXF1ZXN0Q29uZmlnPiB7XG4gKiAgIGNvbnN0cnVjdG9yKGNvbmZpZzogSHR0cENvbmZpZykge1xuICogICAgIHN1cGVyKGF4aW9zLmNyZWF0ZSgpLCBjb25maWcsICdheGlvcycpO1xuICogICB9XG4gKlxuICogICBhc3luYyByZXF1ZXN0PFY+KGRldGFpbHM6IEF4aW9zUmVxdWVzdENvbmZpZyk6IFByb21pc2U8Vj4ge1xuICogICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5uYXRpdmUucmVxdWVzdChkZXRhaWxzKTtcbiAqICAgICByZXR1cm4gcmVzcG9uc2UuZGF0YTtcbiAqICAgfVxuICpcbiAqICAgLy8gSW1wbGVtZW50IG90aGVyIGFic3RyYWN0IG1ldGhvZHMuLi5cbiAqIH1cbiAqIGBgYFxuICogQGNsYXNzXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBIdHRwQWRhcHRlcjxcbiAgWSxcbiAgUSxcbiAgRiBleHRlbmRzIEh0dHBGbGFncyA9IEh0dHBGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPiBleHRlbmRzIEFkYXB0ZXI8WSwgUSwgRiwgQz4ge1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgbmF0aXZlOiBZLFxuICAgIHByb3RlY3RlZCBjb25maWc6IEh0dHBDb25maWcsXG4gICAgZmxhdm91cjogc3RyaW5nLFxuICAgIGFsaWFzPzogc3RyaW5nXG4gICkge1xuICAgIHN1cGVyKG5hdGl2ZSwgZmxhdm91ciwgYWxpYXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgb3BlcmF0aW9uIGZsYWdzIHdpdGggSFRUUCBoZWFkZXJzXG4gICAqIEBzdW1tYXJ5IEV4dGVuZHMgdGhlIGJhc2UgZmxhZ3MgbWV0aG9kIHRvIGluY2x1ZGUgSFRUUC1zcGVjaWZpYyBoZWFkZXJzIGZvciBvcGVyYXRpb25zLlxuICAgKiBUaGlzIG1ldGhvZCBhZGRzIGFuIGVtcHR5IGhlYWRlcnMgb2JqZWN0IHRvIHRoZSBmbGFncyByZXR1cm5lZCBieSB0aGUgcGFyZW50IGNsYXNzLlxuICAgKiBAdGVtcGxhdGUgRiAtIFRoZSBSZXBvc2l0b3J5IEZsYWdzIHR5cGVcbiAgICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZVxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXMuQ1JFQVRFfE9wZXJhdGlvbktleXMuUkVBRHxPcGVyYXRpb25LZXlzLlVQREFURXxPcGVyYXRpb25LZXlzLkRFTEVURX0gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiB0eXBlXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7UGFydGlhbDxGPn0gb3ZlcnJpZGVzIC0gT3B0aW9uYWwgZmxhZyBvdmVycmlkZXNcbiAgICogQHJldHVybiB7Rn0gVGhlIGZsYWdzIG9iamVjdCB3aXRoIGhlYWRlcnNcbiAgICovXG4gIG92ZXJyaWRlIGZsYWdzPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgb3BlcmF0aW9uOlxuICAgICAgfCBPcGVyYXRpb25LZXlzLkNSRUFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLlJFQURcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5VUERBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+LFxuICAgIG92ZXJyaWRlczogUGFydGlhbDxGPlxuICApIHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihzdXBlci5mbGFnczxNPihvcGVyYXRpb24sIG1vZGVsLCBvdmVycmlkZXMpLCB7XG4gICAgICBoZWFkZXJzOiB7fSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0dXJucyB0aGUgcmVwb3NpdG9yeSBjb25zdHJ1Y3RvciBmb3IgdGhpcyBhZGFwdGVyXG4gICAqIEBzdW1tYXJ5IFByb3ZpZGVzIHRoZSBSZXN0U2VydmljZSBjbGFzcyBhcyB0aGUgcmVwb3NpdG9yeSBpbXBsZW1lbnRhdGlvbiBmb3IgdGhpcyBIVFRQIGFkYXB0ZXIuXG4gICAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gY3JlYXRlIHJlcG9zaXRvcnkgaW5zdGFuY2VzIHRoYXQgd29yayB3aXRoIHRoaXMgYWRhcHRlciB0eXBlLlxuICAgKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlXG4gICAqIEByZXR1cm4ge0NvbnN0cnVjdG9yPFJlcG9zaXRvcnk8TSwgUSwgSHR0cEFkYXB0ZXI8WSwgUSwgRiwgQz4+Pn0gVGhlIHJlcG9zaXRvcnkgY29uc3RydWN0b3JcbiAgICovXG4gIG92ZXJyaWRlIHJlcG9zaXRvcnk8TSBleHRlbmRzIE1vZGVsPigpOiBDb25zdHJ1Y3RvcjxcbiAgICBSZXBvc2l0b3J5PE0sIFEsIEh0dHBBZGFwdGVyPFksIFEsIEYsIEM+PlxuICA+IHtcbiAgICByZXR1cm4gUmVzdFNlcnZpY2UgYXMgdW5rbm93biBhcyBDb25zdHJ1Y3RvcjxcbiAgICAgIFJlcG9zaXRvcnk8TSwgUSwgSHR0cEFkYXB0ZXI8WSwgUSwgRiwgQz4+XG4gICAgPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29uc3RydWN0cyBhIFVSTCBmb3IgQVBJIHJlcXVlc3RzXG4gICAqIEBzdW1tYXJ5IEJ1aWxkcyBhIGNvbXBsZXRlIFVSTCBmb3IgQVBJIHJlcXVlc3RzIHVzaW5nIHRoZSBjb25maWd1cmVkIHByb3RvY29sIGFuZCBob3N0LFxuICAgKiB0aGUgc3BlY2lmaWVkIHRhYmxlIG5hbWUsIGFuZCBvcHRpb25hbCBxdWVyeSBwYXJhbWV0ZXJzLiBUaGUgbWV0aG9kIGhhbmRsZXMgVVJMIGVuY29kaW5nLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlIG9yIGVuZHBvaW50XG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyPn0gW3F1ZXJ5UGFyYW1zXSAtIE9wdGlvbmFsIHF1ZXJ5IHBhcmFtZXRlcnNcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgZW5jb2RlZCBVUkwgc3RyaW5nXG4gICAqL1xuICBwcm90ZWN0ZWQgdXJsKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIHF1ZXJ5UGFyYW1zPzogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyPlxuICApIHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKFxuICAgICAgYCR7dGhpcy5jb25maWcucHJvdG9jb2x9Oi8vJHt0aGlzLmNvbmZpZy5ob3N0fS8ke3RhYmxlTmFtZX1gXG4gICAgKTtcbiAgICBpZiAocXVlcnlQYXJhbXMpXG4gICAgICBPYmplY3QuZW50cmllcyhxdWVyeVBhcmFtcykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PlxuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChrZXksIHZhbHVlLnRvU3RyaW5nKCkpXG4gICAgICApO1xuXG4gICAgcmV0dXJuIGVuY29kZVVSSSh1cmwudG9TdHJpbmcoKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhbmQgY29udmVydHMgZXJyb3JzIHRvIEJhc2VFcnJvciB0eXBlXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBlcnJvcnMgdGhhdCBvY2N1ciBkdXJpbmcgSFRUUCBvcGVyYXRpb25zIGFuZCBjb252ZXJ0cyB0aGVtIHRvXG4gICAqIHRoZSBhcHByb3ByaWF0ZSBCYXNlRXJyb3IgdHlwZS4gQ3VycmVudGx5IHJldHVybnMgdGhlIGVycm9yIGFzLWlzLCBidXQgY2FuIGJlXG4gICAqIGV4dGVuZGVkIHRvIGhhbmRsZSBzcGVjaWZpYyBlcnJvciBtZXNzYWdlcyBkaWZmZXJlbnRseS5cbiAgICogQHBhcmFtIHtFcnJvcn0gZXJyIC0gVGhlIGVycm9yIHRvIHBhcnNlXG4gICAqIEByZXR1cm4ge0Jhc2VFcnJvcn0gVGhlIHBhcnNlZCBlcnJvciBhcyBhIEJhc2VFcnJvclxuICAgKi9cbiAgcGFyc2VFcnJvcihlcnI6IEVycm9yKTogQmFzZUVycm9yIHtcbiAgICBjb25zdCB7IG1lc3NhZ2UgfSA9IGVycjtcbiAgICBzd2l0Y2ggKG1lc3NhZ2UpIHtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBlcnIgYXMgQmFzZUVycm9yO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIEhUVFAgYWRhcHRlclxuICAgKiBAc3VtbWFyeSBQbGFjZWhvbGRlciBtZXRob2QgZm9yIGFkYXB0ZXIgaW5pdGlhbGl6YXRpb24uIFRoaXMgbWV0aG9kIGlzIGN1cnJlbnRseVxuICAgKiBhIG5vLW9wIGJ1dCBjYW4gYmUgb3ZlcnJpZGRlbiBieSBzdWJjbGFzc2VzIHRvIHBlcmZvcm0gaW5pdGlhbGl6YXRpb24gdGFza3MuXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBJbml0aWFsaXphdGlvbiBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBpbml0aWFsaXphdGlvbiBpcyBjb21wbGV0ZVxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBhc3luYyBpbml0aWFsaXplKC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gZG8gbm90aGluZ1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZW5kcyBhbiBIVFRQIHJlcXVlc3RcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBzdWJjbGFzc2VzIHRvIHNlbmQgSFRUUCByZXF1ZXN0c1xuICAgKiB1c2luZyB0aGUgbmF0aXZlIEhUVFAgY2xpZW50LiBUaGlzIGlzIHRoZSBjb3JlIG1ldGhvZCBmb3IgbWFraW5nIEFQSSBjYWxscy5cbiAgICogQHRlbXBsYXRlIFYgLSBUaGUgcmVzcG9uc2UgdmFsdWUgdHlwZVxuICAgKiBAcGFyYW0ge1F9IGRldGFpbHMgLSBUaGUgcmVxdWVzdCBkZXRhaWxzIHNwZWNpZmljIHRvIHRoZSBIVFRQIGNsaWVudFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFY+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSByZXNwb25zZSBkYXRhXG4gICAqL1xuICBhYnN0cmFjdCByZXF1ZXN0PFY+KGRldGFpbHM6IFEpOiBQcm9taXNlPFY+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyByZXNvdXJjZVxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IHN1YmNsYXNzZXMgdG8gY3JlYXRlIGEgbmV3IHJlc291cmNlXG4gICAqIHZpYSBIVFRQLiBUaGlzIHR5cGljYWxseSBjb3JyZXNwb25kcyB0byBhIFBPU1QgcmVxdWVzdC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZSBvciBlbmRwb2ludFxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIGlkZW50aWZpZXIgZm9yIHRoZSByZXNvdXJjZVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG1vZGVsIC0gVGhlIGRhdGEgbW9kZWwgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjcmVhdGVkIHJlc291cmNlXG4gICAqL1xuICBhYnN0cmFjdCBvdmVycmlkZSBjcmVhdGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgcmVzb3VyY2UgYnkgSURcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBzdWJjbGFzc2VzIHRvIHJldHJpZXZlIGEgcmVzb3VyY2VcbiAgICogdmlhIEhUVFAuIFRoaXMgdHlwaWNhbGx5IGNvcnJlc3BvbmRzIHRvIGEgR0VUIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUgb3IgZW5kcG9pbnRcbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfGJpZ2ludH0gaWQgLSBUaGUgaWRlbnRpZmllciBmb3IgdGhlIHJlc291cmNlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSByZXRyaWV2ZWQgcmVzb3VyY2VcbiAgICovXG4gIGFic3RyYWN0IG92ZXJyaWRlIHJlYWQoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhbiBleGlzdGluZyByZXNvdXJjZVxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IHN1YmNsYXNzZXMgdG8gdXBkYXRlIGEgcmVzb3VyY2VcbiAgICogdmlhIEhUVFAuIFRoaXMgdHlwaWNhbGx5IGNvcnJlc3BvbmRzIHRvIGEgUFVUIG9yIFBBVENIIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUgb3IgZW5kcG9pbnRcbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCAtIFRoZSBpZGVudGlmaWVyIGZvciB0aGUgcmVzb3VyY2VcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSB1cGRhdGVkIGRhdGEgbW9kZWxcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHVwZGF0ZWQgcmVzb3VyY2VcbiAgICovXG4gIGFic3RyYWN0IG92ZXJyaWRlIHVwZGF0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgcmVzb3VyY2UgYnkgSURcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBzdWJjbGFzc2VzIHRvIGRlbGV0ZSBhIHJlc291cmNlXG4gICAqIHZpYSBIVFRQLiBUaGlzIHR5cGljYWxseSBjb3JyZXNwb25kcyB0byBhIERFTEVURSByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlIG9yIGVuZHBvaW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcnxiaWdpbnR9IGlkIC0gVGhlIGlkZW50aWZpZXIgZm9yIHRoZSByZXNvdXJjZSB0byBkZWxldGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGRlbGV0aW9uIHJlc3VsdFxuICAgKi9cbiAgYWJzdHJhY3Qgb3ZlcnJpZGUgZGVsZXRlKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IHF1ZXJ5XG4gICAqIEBzdW1tYXJ5IE1ldGhvZCBmb3IgZXhlY3V0aW5nIHJhdyBxdWVyaWVzIGRpcmVjdGx5IHdpdGggdGhlIEhUVFAgY2xpZW50LlxuICAgKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGRlZmF1bHQgaW4gSFRUUCBhZGFwdGVycyBhbmQgdGhyb3dzIGFuIFVuc3VwcG9ydGVkRXJyb3IuXG4gICAqIFN1YmNsYXNzZXMgY2FuIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIHByb3ZpZGUgaW1wbGVtZW50YXRpb24uXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlc3VsdCB0eXBlXG4gICAqIEBwYXJhbSB7UX0gcmF3SW5wdXQgLSBUaGUgcmF3IHF1ZXJ5IGlucHV0XG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gcHJvY2VzcyAtIFdoZXRoZXIgdG8gcHJvY2VzcyB0aGUgcmVzdWx0XG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPFI+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBxdWVyeSByZXN1bHRcbiAgICogQHRocm93cyB7VW5zdXBwb3J0ZWRFcnJvcn0gQWx3YXlzIHRocm93cyBhcyB0aGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGRlZmF1bHRcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgcmF3PFI+KHJhd0lucHV0OiBRLCBwcm9jZXNzOiBib29sZWFuLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8Uj4ge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgXCJBcGkgaXMgbm90IG5hdGl2ZWx5IGF2YWlsYWJsZSBmb3IgSHR0cEFkYXB0ZXJzLiBJZiByZXF1aXJlZCwgcGxlYXNlIGV4dGVuZHMgdGhpcyBjbGFzc1wiXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHNlcXVlbmNlXG4gICAqIEBzdW1tYXJ5IE1ldGhvZCBmb3IgY3JlYXRpbmcgYSBzZXF1ZW5jZSBmb3IgZ2VuZXJhdGluZyB1bmlxdWUgaWRlbnRpZmllcnMuXG4gICAqIFRoaXMgbWV0aG9kIGlzIG5vdCBzdXBwb3J0ZWQgYnkgZGVmYXVsdCBpbiBIVFRQIGFkYXB0ZXJzIGFuZCB0aHJvd3MgYW4gVW5zdXBwb3J0ZWRFcnJvci5cbiAgICogU3ViY2xhc3NlcyBjYW4gb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gcHJvdmlkZSBpbXBsZW1lbnRhdGlvbi5cbiAgICogQHBhcmFtIHtTZXF1ZW5jZU9wdGlvbnN9IG9wdGlvbnMgLSBPcHRpb25zIGZvciBjcmVhdGluZyB0aGUgc2VxdWVuY2VcbiAgICogQHJldHVybiB7UHJvbWlzZTxTZXF1ZW5jZT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGNyZWF0ZWQgc2VxdWVuY2VcbiAgICogQHRocm93cyB7VW5zdXBwb3J0ZWRFcnJvcn0gQWx3YXlzIHRocm93cyBhcyB0aGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGRlZmF1bHRcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgU2VxdWVuY2Uob3B0aW9uczogU2VxdWVuY2VPcHRpb25zKTogUHJvbWlzZTxTZXF1ZW5jZT4ge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgXCJBcGkgaXMgbm90IG5hdGl2ZWx5IGF2YWlsYWJsZSBmb3IgSHR0cEFkYXB0ZXJzLiBJZiByZXF1aXJlZCwgcGxlYXNlIGV4dGVuZHMgdGhpcyBjbGFzc1wiXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHN0YXRlbWVudCBmb3IgcXVlcnlpbmdcbiAgICogQHN1bW1hcnkgTWV0aG9kIGZvciBjcmVhdGluZyBhIHN0YXRlbWVudCBmb3IgYnVpbGRpbmcgYW5kIGV4ZWN1dGluZyBxdWVyaWVzLlxuICAgKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGRlZmF1bHQgaW4gSFRUUCBhZGFwdGVycyBhbmQgdGhyb3dzIGFuIFVuc3VwcG9ydGVkRXJyb3IuXG4gICAqIFN1YmNsYXNzZXMgY2FuIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIHByb3ZpZGUgaW1wbGVtZW50YXRpb24uXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGVcbiAgICogQHRlbXBsYXRlICEgLSBUaGUgcmF3IHF1ZXJ5IHR5cGVcbiAgICogQHJldHVybiB7U3RhdGVtZW50PFEsIE0sIGFueT59IEEgc3RhdGVtZW50IG9iamVjdCBmb3IgYnVpbGRpbmcgcXVlcmllc1xuICAgKiBAdGhyb3dzIHtVbnN1cHBvcnRlZEVycm9yfSBBbHdheXMgdGhyb3dzIGFzIHRoaXMgbWV0aG9kIGlzIG5vdCBzdXBwb3J0ZWQgYnkgZGVmYXVsdFxuICAgKi9cbiAgb3ZlcnJpZGUgU3RhdGVtZW50PE0gZXh0ZW5kcyBNb2RlbD4oKTogU3RhdGVtZW50PFEsIE0sIGFueT4ge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgXCJBcGkgaXMgbm90IG5hdGl2ZWx5IGF2YWlsYWJsZSBmb3IgSHR0cEFkYXB0ZXJzLiBJZiByZXF1aXJlZCwgcGxlYXNlIGV4dGVuZHMgdGhpcyBjbGFzc1wiXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGEgY29uZGl0aW9uIGludG8gYSBxdWVyeVxuICAgKiBAc3VtbWFyeSBNZXRob2QgZm9yIHBhcnNpbmcgYSBjb25kaXRpb24gb2JqZWN0IGludG8gYSBxdWVyeSBmb3JtYXQgdW5kZXJzdG9vZCBieSB0aGUgSFRUUCBjbGllbnQuXG4gICAqIFRoaXMgbWV0aG9kIGlzIG5vdCBzdXBwb3J0ZWQgYnkgZGVmYXVsdCBpbiBIVFRQIGFkYXB0ZXJzIGFuZCB0aHJvd3MgYW4gVW5zdXBwb3J0ZWRFcnJvci5cbiAgICogU3ViY2xhc3NlcyBjYW4gb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gcHJvdmlkZSBpbXBsZW1lbnRhdGlvbi5cbiAgICogQHBhcmFtIHtDb25kaXRpb248YW55Pn0gY29uZGl0aW9uIC0gVGhlIGNvbmRpdGlvbiB0byBwYXJzZVxuICAgKiBAcmV0dXJuIHtRfSBUaGUgcGFyc2VkIHF1ZXJ5XG4gICAqIEB0aHJvd3Mge1Vuc3VwcG9ydGVkRXJyb3J9IEFsd2F5cyB0aHJvd3MgYXMgdGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSBkZWZhdWx0XG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIHBhcnNlQ29uZGl0aW9uKGNvbmRpdGlvbjogQ29uZGl0aW9uPGFueT4pOiBRIHtcbiAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcbiAgICAgIFwiQXBpIGlzIG5vdCBuYXRpdmVseSBhdmFpbGFibGUgZm9yIEh0dHBBZGFwdGVycy4gSWYgcmVxdWlyZWQsIHBsZWFzZSBleHRlbmRzIHRoaXMgY2xhc3NcIlxuICAgICk7XG4gIH1cbn1cbiIsImltcG9ydCB7IFJlcG9zaXRvcnkgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IEh0dHBBZGFwdGVyIH0gZnJvbSBcIi4vYWRhcHRlclwiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgSHR0cEZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVwb3NpdG9yeSBmb3IgUkVTVCBBUEkgaW50ZXJhY3Rpb25zXG4gKiBAc3VtbWFyeSBBIHNwZWNpYWxpemVkIHJlcG9zaXRvcnkgaW1wbGVtZW50YXRpb24gZm9yIGludGVyYWN0aW5nIHdpdGggUkVTVCBBUElzLlxuICogVGhpcyBjbGFzcyBleHRlbmRzIHRoZSBjb3JlIFJlcG9zaXRvcnkgY2xhc3MgYW5kIHdvcmtzIHdpdGggSFRUUCBhZGFwdGVycyB0b1xuICogcHJvdmlkZSBDUlVEIG9wZXJhdGlvbnMgZm9yIG1vZGVscyB2aWEgUkVTVCBlbmRwb2ludHMuXG4gKiBUaGlzIElzIE5PVCB0aGUgZGVmYXVsdCByZXBvc2l0b3J5IGZvciB0aGUgSFRUUCBhZGFwdGVyLiBUaGF0IHdvdWxkIGJlIHtAbGluayBSZXN0U2VydmljZX0uXG4gKiBVc2UgdGhpcyBvbmx5IGluIHRoZSBzcGVjaWZpYyBjYXNlIG9mIG5lZWRpbmcgdG8gcnVuIHRoZSBDVVJEIG1vZGVsIGxvZ2ljIChkZWNvcmF0aW9uKSBiZWZvcmUgc3VibWl0dGluZyB0byB0aGUgYmFja2VuZFxuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSwgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUSAtIFRoZSBxdWVyeSB0eXBlIHVzZWQgYnkgdGhlIGFkYXB0ZXJcbiAqIEB0ZW1wbGF0ZSBBIC0gVGhlIEhUVFAgYWRhcHRlciB0eXBlLCBleHRlbmRpbmcgSHR0cEFkYXB0ZXJcbiAqIEB0ZW1wbGF0ZSBGIC0gVGhlIEhUVFAgZmxhZ3MgdHlwZSwgZXh0ZW5kaW5nIEh0dHBGbGFnc1xuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlLCBleHRlbmRpbmcgQ29udGV4dDxGPlxuICogQHBhcmFtIHtBfSBhZGFwdGVyIC0gVGhlIEhUVFAgYWRhcHRlciBpbnN0YW5jZVxuICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gW2NsYXp6XSAtIE9wdGlvbmFsIGNvbnN0cnVjdG9yIGZvciB0aGUgbW9kZWwgY2xhc3NcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgYSByZXBvc2l0b3J5IGZvciBVc2VyIG1vZGVsIHdpdGggQXhpb3MgYWRhcHRlclxuICogY29uc3QgYXhpb3NBZGFwdGVyID0gbmV3IEF4aW9zQWRhcHRlcih7XG4gKiAgIHByb3RvY29sOiAnaHR0cHMnLFxuICogICBob3N0OiAnYXBpLmV4YW1wbGUuY29tJ1xuICogfSk7XG4gKiBjb25zdCB1c2VyUmVwb3NpdG9yeSA9IG5ldyBSZXN0UmVwb3NpdG9yeShheGlvc0FkYXB0ZXIsIFVzZXIpO1xuICpcbiAqIC8vIFVzZSB0aGUgcmVwb3NpdG9yeSBmb3IgQ1JVRCBvcGVyYXRpb25zXG4gKiBjb25zdCB1c2VyID0gYXdhaXQgdXNlclJlcG9zaXRvcnkuZmluZEJ5SWQoJzEyMycpO1xuICogYGBgXG4gKiBAY2xhc3MgUmVzdFJlcG9zaXRvcnlcbiAqIEBzZWUge0BsaW5rIFJlc3RTZXJ2aWNlfVxuICovXG5leHBvcnQgY2xhc3MgUmVzdFJlcG9zaXRvcnk8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUSxcbiAgQSBleHRlbmRzIEh0dHBBZGFwdGVyPGFueSwgUSwgRiwgQz4sXG4gIEYgZXh0ZW5kcyBIdHRwRmxhZ3MgPSBIdHRwRmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4gZXh0ZW5kcyBSZXBvc2l0b3J5PE0sIFEsIEE+IHtcbiAgY29uc3RydWN0b3IoYWRhcHRlcjogQSwgY2xheno/OiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIHN1cGVyKGFkYXB0ZXIsIGNsYXp6KTtcbiAgfVxufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gSFRUUCBjbGllbnQgbW9kdWxlIGZvciBSRVNUIEFQSSBpbnRlcmFjdGlvbnNcbiAqIEBzdW1tYXJ5IFRoaXMgbW9kdWxlIHByb3ZpZGVzIGNsYXNzZXMgYW5kIHV0aWxpdGllcyBmb3IgaW50ZXJhY3Rpbmcgd2l0aCBSRVNUIEFQSXMuXG4gKiBJdCBleHBvc2VzIHJlcG9zaXRvcnkgYW5kIHNlcnZpY2UgY2xhc3NlcyBmb3IgbWFraW5nIEhUVFAgcmVxdWVzdHMsIGFsb25nIHdpdGhcbiAqIHR5cGUgZGVmaW5pdGlvbnMgYW5kIGFkYXB0ZXJzIGZvciBkaWZmZXJlbnQgSFRUUCBjbGllbnRzLiBUaGUgbW9kdWxlIGluY2x1ZGVzXG4gKiB7QGxpbmsgUmVzdFJlcG9zaXRvcnl9IGFuZCB7QGxpbmsgUmVzdFNlcnZpY2V9IGZvciBBUEkgaW50ZXJhY3Rpb25zLlxuICogQG1vZHVsZSBmb3ItaHR0cFxuICovXG5leHBvcnQgKiBmcm9tIFwiLi9hZGFwdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9SZXN0UmVwb3NpdG9yeVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vUmVzdFNlcnZpY2VcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgZm9yLWh0dHAgbW9kdWxlXG4gKiBAc3VtbWFyeSBWZXJzaW9uIGlkZW50aWZpZXIgZm9yIHRoZSBtb2R1bGVcbiAqIEBjb25zdCBWRVJTSU9OXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQVlBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBa0NHO01BQ1UsV0FBVyxDQUFBO0FBWXRCOzs7Ozs7QUFNRztBQUNILElBQUEsSUFBSSxLQUFLLEdBQUE7UUFDUCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU07QUFDZCxZQUFBLE1BQU0sSUFBSSxhQUFhLENBQUMsK0NBQStDLENBQUM7UUFDMUUsT0FBTyxJQUFJLENBQUMsTUFBTTs7QUFHcEI7Ozs7O0FBS0c7QUFDSCxJQUFBLElBQUksRUFBRSxHQUFBO1FBQ0osSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHO0FBQUUsWUFBQSxJQUFJLENBQUMsR0FBRyxHQUFHLGNBQWMsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUU7UUFDN0QsT0FBTyxJQUFJLENBQUMsR0FBRzs7QUFRakI7Ozs7OztBQU1HO0FBQ0gsSUFBQSxJQUFjLE9BQU8sR0FBQTtRQUNuQixJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVE7QUFDaEIsWUFBQSxNQUFNLElBQUksYUFBYSxDQUNyQixzR0FBc0csQ0FDdkc7UUFDSCxPQUFPLElBQUksQ0FBQyxRQUFROztBQUd0Qjs7Ozs7QUFLRztBQUNILElBQUEsSUFBYyxTQUFTLEdBQUE7UUFDckIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVO1lBQUUsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDcEUsT0FBTyxJQUFJLENBQUMsVUFBVTs7QUFHeEI7Ozs7OztBQU1HO0lBQ0gsV0FBWSxDQUFBLE9BQVUsRUFBRSxLQUFzQixFQUFBO1FBdENwQyxJQUFTLENBQUEsU0FBQSxHQUFlLEVBQUU7QUF1Q2xDLFFBQUEsSUFBSSxD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