@decaf-ts/transactional-decorators 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/LICENSE.md +17 -152
  2. package/README.md +242 -17
  3. package/dist/transactional-decorators.cjs +2 -544
  4. package/dist/transactional-decorators.cjs.map +1 -0
  5. package/dist/transactional-decorators.js +2 -0
  6. package/dist/transactional-decorators.js.map +1 -0
  7. package/lib/Transaction.cjs +87 -39
  8. package/lib/Transaction.d.ts +86 -38
  9. package/lib/Transaction.js.map +1 -0
  10. package/lib/constants.cjs +14 -1
  11. package/lib/constants.d.ts +13 -0
  12. package/lib/constants.js.map +1 -0
  13. package/lib/decorators.cjs +35 -11
  14. package/lib/decorators.d.ts +34 -10
  15. package/lib/decorators.js.map +1 -0
  16. package/lib/esm/Transaction.d.ts +86 -38
  17. package/lib/esm/Transaction.js +90 -42
  18. package/lib/esm/Transaction.js.map +1 -0
  19. package/lib/esm/constants.d.ts +13 -0
  20. package/lib/esm/constants.js +14 -1
  21. package/lib/esm/constants.js.map +1 -0
  22. package/lib/esm/decorators.d.ts +34 -10
  23. package/lib/esm/decorators.js +37 -13
  24. package/lib/esm/decorators.js.map +1 -0
  25. package/lib/esm/index.d.ts +7 -13
  26. package/lib/esm/index.js +14 -20
  27. package/lib/esm/index.js.map +1 -0
  28. package/lib/esm/interfaces/TransactionLock.d.ts +13 -11
  29. package/lib/esm/interfaces/TransactionLock.js +1 -1
  30. package/lib/esm/interfaces/TransactionLock.js.map +1 -0
  31. package/lib/esm/interfaces/index.d.ts +5 -0
  32. package/lib/esm/interfaces/index.js +7 -2
  33. package/lib/esm/interfaces/index.js.map +1 -0
  34. package/lib/esm/locks/Lock.d.ts +13 -5
  35. package/lib/esm/locks/Lock.js +14 -6
  36. package/lib/esm/locks/Lock.js.map +1 -0
  37. package/lib/esm/locks/SyncronousLock.d.ts +3 -4
  38. package/lib/esm/locks/SyncronousLock.js +14 -2
  39. package/lib/esm/locks/SyncronousLock.js.map +1 -0
  40. package/lib/esm/locks/index.d.ts +5 -0
  41. package/lib/esm/locks/index.js +8 -3
  42. package/lib/esm/locks/index.js.map +1 -0
  43. package/lib/esm/types.d.ts +13 -3
  44. package/lib/esm/types.js +1 -1
  45. package/lib/esm/types.js.map +1 -0
  46. package/lib/esm/utils.js +1 -1
  47. package/lib/esm/utils.js.map +1 -0
  48. package/lib/index.cjs +8 -14
  49. package/lib/index.d.ts +7 -13
  50. package/lib/index.js.map +1 -0
  51. package/lib/interfaces/TransactionLock.cjs +1 -1
  52. package/lib/interfaces/TransactionLock.d.ts +13 -11
  53. package/lib/interfaces/TransactionLock.js.map +1 -0
  54. package/lib/interfaces/index.cjs +6 -1
  55. package/lib/interfaces/index.d.ts +5 -0
  56. package/lib/interfaces/index.js.map +1 -0
  57. package/lib/locks/Lock.cjs +14 -6
  58. package/lib/locks/Lock.d.ts +13 -5
  59. package/lib/locks/Lock.js.map +1 -0
  60. package/lib/locks/SyncronousLock.cjs +13 -1
  61. package/lib/locks/SyncronousLock.d.ts +3 -4
  62. package/lib/locks/SyncronousLock.js.map +1 -0
  63. package/lib/locks/index.cjs +6 -1
  64. package/lib/locks/index.d.ts +5 -0
  65. package/lib/locks/index.js.map +1 -0
  66. package/lib/types.cjs +1 -1
  67. package/lib/types.d.ts +13 -3
  68. package/lib/types.js.map +1 -0
  69. package/lib/utils.cjs +1 -1
  70. package/lib/utils.js.map +1 -0
  71. package/package.json +24 -25
  72. package/dist/transactional-decorators.esm.cjs +0 -533
@@ -1,533 +0,0 @@
1
- import { Reflection, metadata } from '@decaf-ts/reflection';
2
- import { getAllPropertyDecoratorsRecursive, DBKeys, InternalError } from '@decaf-ts/db-decorators';
3
-
4
- /**
5
- * @summary Simple Promise based Lock class
6
- *
7
- * @class Lock
8
- * @category Transactions
9
- */
10
- class Lock {
11
- constructor() {
12
- this.queue = [];
13
- this.locked = false;
14
- }
15
- /**
16
- * @summary executes when lock is available
17
- * @param {Function} func
18
- */
19
- async execute(func) {
20
- await this.acquire();
21
- let result;
22
- try {
23
- result = await Promise.resolve(func());
24
- }
25
- catch (e) {
26
- this.release();
27
- throw e;
28
- }
29
- this.release();
30
- return result;
31
- }
32
- /**
33
- * @summary waits to acquire the lock
34
- * @param {string} [issuer]
35
- */
36
- async acquire() {
37
- // eslint-disable-next-line @typescript-eslint/no-this-alias
38
- const self = this;
39
- if (self.locked) {
40
- return new Promise((resolve) => self.queue.push(resolve));
41
- }
42
- else {
43
- self.locked = true;
44
- return Promise.resolve();
45
- }
46
- }
47
- /**
48
- * @summary releases the lock
49
- */
50
- release() {
51
- // eslint-disable-next-line @typescript-eslint/no-this-alias
52
- const self = this;
53
- const next = self.queue.shift();
54
- if (next) {
55
- if (typeof globalThis.window === "undefined")
56
- globalThis.process.nextTick(next); // if you are on node
57
- else
58
- setTimeout(next, 0); // if you are in the browser
59
- }
60
- else {
61
- self.locked = false;
62
- }
63
- }
64
- }
65
-
66
- class SyncronousLock {
67
- constructor(counter = 1, onBegin, onEnd) {
68
- this.currentTransaction = undefined;
69
- this.lock = new Lock();
70
- this.counter = counter;
71
- this.pendingTransactions = [];
72
- this.onBegin = onBegin;
73
- this.onEnd = onEnd;
74
- }
75
- /**
76
- * @summary Submits a transaction to be processed
77
- * @param {Transaction} transaction
78
- */
79
- submit(transaction) {
80
- // eslint-disable-next-line @typescript-eslint/no-this-alias
81
- const self = this;
82
- self.lock.acquire().then(() => {
83
- if (self.currentTransaction &&
84
- self.currentTransaction.id === transaction.id) {
85
- self.lock.release();
86
- return transaction.fire();
87
- }
88
- if (self.counter > 0) {
89
- self.counter--;
90
- self.lock.release();
91
- return self.fireTransaction(transaction);
92
- }
93
- else {
94
- self.pendingTransactions.push(transaction);
95
- self.lock.release();
96
- }
97
- });
98
- }
99
- /**
100
- * @summary Executes a transaction
101
- *
102
- * @param {Transaction} transaction
103
- * @private
104
- */
105
- fireTransaction(transaction) {
106
- // eslint-disable-next-line @typescript-eslint/no-this-alias
107
- const self = this;
108
- self.lock.acquire().then(() => {
109
- self.currentTransaction = transaction;
110
- self.lock.release();
111
- if (self.onBegin)
112
- self.onBegin().then(() => {
113
- // all.call(
114
- // self,
115
- // `Firing transaction {0}. {1} remaining...`,
116
- // transaction.id,
117
- // this.pendingTransactions.length,
118
- // );
119
- transaction.fire();
120
- });
121
- else {
122
- // all.call(
123
- // self,
124
- // `Firing transaction {0}. {1} remaining...`,
125
- // transaction.id,
126
- // this.pendingTransactions.length,
127
- // );
128
- transaction.fire();
129
- }
130
- });
131
- }
132
- /**
133
- * @summary Releases The lock after the conclusion of a transaction
134
- */
135
- async release(err) {
136
- // eslint-disable-next-line @typescript-eslint/no-this-alias
137
- const self = this;
138
- return new Promise((resolve) => {
139
- self.lock.acquire().then(() => {
140
- if (!self.currentTransaction)
141
- console.warn("Trying to release an unexisting transaction. should never happen...");
142
- // debug.call(
143
- // self,
144
- // "Releasing transaction: {0}",
145
- // self.currentTransaction?.toString(true, true),
146
- // );
147
- self.currentTransaction = undefined;
148
- self.lock.release();
149
- const afterConclusionCB = () => {
150
- self.lock.acquire().then(() => {
151
- if (self.pendingTransactions.length > 0) {
152
- const transaction = self.pendingTransactions.shift();
153
- const cb = () => self.fireTransaction(transaction);
154
- //
155
- // all(
156
- // `Releasing Transaction Lock on transaction {0}`,
157
- // transaction.id,
158
- // );
159
- if (typeof globalThis.window ===
160
- "undefined")
161
- globalThis.process.nextTick(cb); // if you are on node
162
- else
163
- setTimeout(cb, 0); // if you are in the browser
164
- }
165
- else {
166
- self.counter++;
167
- }
168
- self.lock.release();
169
- resolve();
170
- });
171
- };
172
- if (self.onEnd)
173
- self.onEnd(err).then(() => afterConclusionCB());
174
- else
175
- afterConclusionCB();
176
- });
177
- });
178
- }
179
- }
180
-
181
- const TransactionalKeys = {
182
- REFLECT: "model.transactional.",
183
- TRANSACTIONAL: "transactional",
184
- };
185
-
186
- function getObjectName(obj) {
187
- if (!obj)
188
- return;
189
- if (typeof obj === "string")
190
- return obj;
191
- if (obj.constructor &&
192
- obj.constructor.name &&
193
- ["Function", "Object"].indexOf(obj.constructor.name) === -1)
194
- return obj.constructor.name;
195
- if (typeof obj === "function" && obj.name)
196
- return obj.name;
197
- return obj.toString();
198
- }
199
-
200
- /**
201
- * @summary Transaction Class
202
- *
203
- * @param {string} source
204
- * @param {string} [method]
205
- * @param {function(): void} [action]
206
- * @param {any[]} [metadata]
207
- *
208
- * @class Transaction
209
- *
210
- * @category Transactions
211
- */
212
- class Transaction {
213
- constructor(source, method, action, metadata) {
214
- this.id = Date.now();
215
- this.action = action;
216
- this.method = method;
217
- this.log = [[this.id, source, method].join(" | ")];
218
- this.source = source;
219
- this.metadata = metadata;
220
- }
221
- /**
222
- * @summary Pushes a transaction to que queue and waits its resolution
223
- *
224
- * @param {any} issuer any class. will be used as this when calling the callbackMethod
225
- * @param {Function} callbackMethod callback function containing the transaction. will be called with the issuear as this
226
- * @param {any[]} args arguments to pass to the method. Last one must be the callback
227
- */
228
- static push(issuer, callbackMethod, ...args) {
229
- const callback = args.pop();
230
- if (!callback || typeof callback !== "function")
231
- throw new Error("Missing callback");
232
- const cb = (err, ...args) => {
233
- Transaction.getLock()
234
- .release(err)
235
- .then(() => callback(err, ...args));
236
- };
237
- const transaction = new Transaction(issuer.constructor.name, callbackMethod.name ? getObjectName(callbackMethod) : "Anonymous", () => {
238
- return callbackMethod.call(transaction.bindToTransaction(issuer), ...args, cb);
239
- });
240
- Transaction.getLock().submit(transaction);
241
- }
242
- /**
243
- * @summary Sets the lock to be used
244
- * @param lock
245
- */
246
- static setLock(lock) {
247
- this.lock = lock;
248
- }
249
- /**
250
- * @summary gets the lock
251
- */
252
- static getLock() {
253
- if (!this.lock)
254
- this.lock = new SyncronousLock();
255
- return this.lock;
256
- }
257
- /**
258
- * @summary submits a transaction
259
- * @param {Transaction} transaction
260
- */
261
- static submit(transaction) {
262
- Transaction.getLock().submit(transaction);
263
- }
264
- /**
265
- * @summary releases the lock
266
- * @param {Err} err
267
- */
268
- static async release(err) {
269
- return Transaction.getLock().release(err);
270
- }
271
- /**
272
- * @summary retrieves the metadata for the transaction
273
- */
274
- getMetadata() {
275
- return this.metadata ? [...this.metadata] : undefined;
276
- }
277
- /**
278
- * @summary Binds a new operation to the current transaction
279
- * @param {Transaction} nextTransaction
280
- */
281
- bindTransaction(nextTransaction) {
282
- // all(`Binding the {0} to {1}`, nextTransaction, this);
283
- this.log.push(...nextTransaction.log);
284
- nextTransaction.bindTransaction = this.bindToTransaction.bind(this);
285
- nextTransaction.bindToTransaction = this.bindToTransaction.bind(this);
286
- this.action = nextTransaction.action;
287
- }
288
- /**
289
- * @summary Binds the Transactional Decorated Object to the transaction
290
- * @description by having all {@link transactional} decorated
291
- * methods always pass the current Transaction as an argument
292
- *
293
- * @param {any} obj
294
- * @return {any} the bound {@param obj}
295
- */
296
- bindToTransaction(obj) {
297
- const transactionalMethods = getAllPropertyDecoratorsRecursive(obj, undefined, TransactionalKeys.REFLECT);
298
- if (!transactionalMethods)
299
- return obj;
300
- // eslint-disable-next-line @typescript-eslint/no-this-alias
301
- const self = this;
302
- const boundObj = Reflection.getAllProperties(obj).reduce((accum, k) => {
303
- if (Object.keys(transactionalMethods).indexOf(k) !== -1 &&
304
- transactionalMethods[k].find((o) => o.key === TransactionalKeys.TRANSACTIONAL))
305
- accum[k] = (...args) => obj[k].call(obj.__originalObj || obj, self, ...args);
306
- else if (k === "clazz" || k === "constructor")
307
- accum[k] = obj[k];
308
- else if (typeof obj[k] === "function")
309
- accum[k] = obj[k].bind(obj.__originalObj || obj);
310
- else if (typeof obj[k] === "object" && obj[k].constructor) {
311
- const decs = Reflection.getClassDecorators(TransactionalKeys.REFLECT, obj[k]);
312
- if (decs.find((e) => e.key === TransactionalKeys.TRANSACTIONAL))
313
- accum[k] = self.bindToTransaction(obj[k]);
314
- else
315
- accum[k] = obj[k];
316
- }
317
- else
318
- accum[k] = obj[k];
319
- return accum;
320
- }, {});
321
- boundObj[DBKeys.ORIGINAL] = obj[DBKeys.ORIGINAL] || obj;
322
- boundObj.toString = () => getObjectName(boundObj[DBKeys.ORIGINAL]) +
323
- " proxy for transaction " +
324
- this.id;
325
- return boundObj;
326
- }
327
- /**
328
- * @summary Fires the Transaction
329
- */
330
- fire() {
331
- if (!this.action)
332
- throw new Error(`Missing the method`);
333
- return this.action();
334
- }
335
- /**
336
- * @summary toString override
337
- * @param {boolean} [withId] defaults to true
338
- * @param {boolean} [withLog] defaults to true
339
- */
340
- toString(withId = true, withLog = false) {
341
- return `${withId ? `[${this.id}]` : ""}[Transaction][${this.source}.${this.method}${withLog ? `]\nTransaction Log:\n${this.log.join("\n")}` : "]"}`;
342
- }
343
- /**
344
- * @summary gets the transactions reflections key
345
- * @function getRepoKey
346
- * @param {string} key
347
- * @memberOf module:db-decorators.Transactions
348
- * */
349
- static key(key) {
350
- return TransactionalKeys.REFLECT + key;
351
- }
352
- }
353
-
354
- /**
355
- * @summary Sets a class Async method as transactional
356
- *
357
- * @param {any[]} [data] option metadata available to the {@link TransactionLock}
358
- *
359
- * @function transactional
360
- *
361
- * @memberOf module:db-decorators.Decorators.transactions
362
- */
363
- function transactional(...data) {
364
- return function (target, propertyKey, descriptor) {
365
- if (!descriptor)
366
- throw new InternalError("Missing descriptor. Should be impossible");
367
- metadata(Transaction.key(TransactionalKeys.TRANSACTIONAL), data)(target, propertyKey);
368
- const originalMethod = descriptor.value;
369
- const methodWrapper = function (...args) {
370
- // eslint-disable-next-line @typescript-eslint/no-this-alias
371
- const self = this;
372
- return new Promise((resolve, reject) => {
373
- const cb = (err, result) => {
374
- Transaction.release(err).then(() => {
375
- if (err)
376
- return reject(err);
377
- resolve(result);
378
- });
379
- };
380
- let transaction = args.shift();
381
- if (transaction instanceof Transaction) {
382
- const updatedTransaction = new Transaction(this.constructor.name, propertyKey, async () => {
383
- originalMethod
384
- .call(updatedTransaction.bindToTransaction(self), ...args)
385
- .then(resolve)
386
- .catch(reject);
387
- }, data.length ? data : undefined);
388
- transaction.bindTransaction(updatedTransaction);
389
- transaction.fire();
390
- }
391
- else {
392
- args.unshift(transaction);
393
- transaction = new Transaction(this.constructor.name, propertyKey, () => {
394
- originalMethod
395
- .call(transaction.bindToTransaction(self), ...args)
396
- .then((result) => cb(undefined, result))
397
- .catch(cb);
398
- }, data.length ? data : undefined);
399
- Transaction.submit(transaction);
400
- }
401
- });
402
- };
403
- Object.defineProperty(methodWrapper, "name", {
404
- value: propertyKey,
405
- });
406
- descriptor.value = methodWrapper;
407
- };
408
- }
409
- //
410
- // /**
411
- // * @summary Sets a class Async method as transactional
412
- // *
413
- // * @param {any[]} [metadata] option metadata available to the {@link TransactionLock}
414
- // *
415
- // * @function transactionalAsync
416
- // *
417
- // * @memberOf module:db-decorators.Decorators.transactions
418
- // */
419
- // export function transactionalAsync(...metadata: any[]) {
420
- // return function (
421
- // target: any,
422
- // propertyKey: string,
423
- // descriptor: PropertyDescriptor,
424
- // ) {
425
- // metadasta(getTransactionalKey(TransactionalKeys.TRANSACTIONAL))
426
- // Reflect.defineMetadata(
427
- // ,
428
- // {
429
- // type: "async",
430
- // metadata: metadata.length ? metadata : undefined,
431
- // } as TransactionalMetadata,
432
- // target,
433
- // propertyKey,
434
- // );
435
- //
436
- // const originalMethod = descriptor.value;
437
- //
438
- // const methodWrapper = function (this: any, ...args: any[]) {
439
- // const callback: Callback = args.pop();
440
- // if (!callback || typeof callback !== "function")
441
- // throw new CriticalError(`Missing Callback`);
442
- //
443
- // const cb = (err?: Err, ...args: any[]) => {
444
- // Transaction.release(err).then((_) => callback(err, ...args));
445
- // };
446
- //
447
- // const self = this;
448
- //
449
- // let transaction = args.shift();
450
- // if (transaction instanceof Transaction) {
451
- // const updatedTransaction: Transaction = new Transaction(
452
- // this.constructor.name,
453
- // propertyKey,
454
- // () => {
455
- // try {
456
- // return originalMethod.call(
457
- // updatedTransaction.bindToTransaction(self),
458
- // ...args,
459
- // callback,
460
- // );
461
- // } catch (e: any) {
462
- // return callback(e);
463
- // }
464
- // },
465
- // metadata.length ? metadata : undefined,
466
- // );
467
- //
468
- // transaction.bindTransaction(updatedTransaction);
469
- // transaction.fire();
470
- // } else {
471
- // args.unshift(transaction);
472
- // transaction = undefined;
473
- // transaction = new Transaction(
474
- // this.constructor.name,
475
- // propertyKey,
476
- // () => {
477
- // try {
478
- // return originalMethod.call(
479
- // transaction.bindToTransaction(self),
480
- // ...args,
481
- // cb,
482
- // );
483
- // } catch (e: any) {
484
- // return cb(e);
485
- // }
486
- // },
487
- // metadata.length ? metadata : undefined,
488
- // );
489
- // Transaction.submit(transaction);
490
- // }
491
- // };
492
- //
493
- // Object.defineProperty(methodWrapper, "name", {
494
- // value: propertyKey,
495
- // });
496
- // descriptor.value = methodWrapper;
497
- // };
498
- // }
499
- /**
500
- * @summary Util function to wrap super calls with the transaction when the super's method is also transactional
501
- *
502
- * @param {Function} method the super method (must be bound to the proper this), eg: super.create.bind(this)
503
- * @param {any[]} args the arguments to call the method with
504
- *
505
- * @memberOf module:db-decorators.Transaction
506
- */
507
- function transactionalSuperCall(method, ...args) {
508
- const lock = Transaction.getLock();
509
- const currentTransaction = lock.currentTransaction;
510
- return method(currentTransaction, ...args);
511
- }
512
-
513
- /**
514
- * @summary Module summary
515
- * @description Module description
516
- * @module ts-workspace
517
- */
518
- /**
519
- * @summary Namespace summary
520
- * @description Namespace description
521
- * @namespace Namespace
522
- * @memberOf module:ts-workspace
523
- */
524
- /**
525
- * @summary stores the current package version
526
- * @description this is how you should document a constant
527
- * @const VERSION
528
- * @memberOf module:ts-workspace
529
- */
530
- const VERSION = "0.1.2";
531
-
532
- export { Lock, SyncronousLock, Transaction, TransactionalKeys, VERSION, transactional, transactionalSuperCall };
533
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25hbC1kZWNvcmF0b3JzLmVzbS5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9sb2Nrcy9Mb2NrLnRzIiwiLi4vc3JjL2xvY2tzL1N5bmNyb25vdXNMb2NrLnRzIiwiLi4vc3JjL2NvbnN0YW50cy50cyIsIi4uL3NyYy91dGlscy50cyIsIi4uL3NyYy9UcmFuc2FjdGlvbi50cyIsIi4uL3NyYy9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExvY2tDYWxsYWJsZSB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFNpbXBsZSBQcm9taXNlIGJhc2VkIExvY2sgY2xhc3NcbiAqXG4gKiBAY2xhc3MgTG9ja1xuICogQGNhdGVnb3J5IFRyYW5zYWN0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgTG9jayB7XG4gIHByaXZhdGUgcXVldWU6IExvY2tDYWxsYWJsZVtdID0gW107XG4gIHByaXZhdGUgbG9ja2VkID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IGV4ZWN1dGVzIHdoZW4gbG9jayBpcyBhdmFpbGFibGVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuY1xuICAgKi9cbiAgYXN5bmMgZXhlY3V0ZShmdW5jOiAoKSA9PiBhbnkpIHtcbiAgICBhd2FpdCB0aGlzLmFjcXVpcmUoKTtcbiAgICBsZXQgcmVzdWx0OiBhbnk7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShmdW5jKCkpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhpcy5yZWxlYXNlKCk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgICB0aGlzLnJlbGVhc2UoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IHdhaXRzIHRvIGFjcXVpcmUgdGhlIGxvY2tcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtpc3N1ZXJdXG4gICAqL1xuICBhc3luYyBhY3F1aXJlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGlmIChzZWxmLmxvY2tlZCkge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiBzZWxmLnF1ZXVlLnB1c2gocmVzb2x2ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZWxmLmxvY2tlZCA9IHRydWU7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IHJlbGVhc2VzIHRoZSBsb2NrXG4gICAqL1xuICByZWxlYXNlKCkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGNvbnN0IG5leHQ6IExvY2tDYWxsYWJsZSB8IHVuZGVmaW5lZCA9IHNlbGYucXVldWUuc2hpZnQoKTtcbiAgICBpZiAobmV4dCkge1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgKGdsb2JhbFRoaXMgYXMgdW5rbm93biBhcyB7IHdpbmRvdzogYW55IH0pLndpbmRvdyA9PT0gXCJ1bmRlZmluZWRcIlxuICAgICAgKVxuICAgICAgICBnbG9iYWxUaGlzLnByb2Nlc3MubmV4dFRpY2sobmV4dCk7IC8vIGlmIHlvdSBhcmUgb24gbm9kZVxuICAgICAgZWxzZSBzZXRUaW1lb3V0KG5leHQsIDApOyAvLyBpZiB5b3UgYXJlIGluIHRoZSBicm93c2VyXG4gICAgfSBlbHNlIHtcbiAgICAgIHNlbGYubG9ja2VkID0gZmFsc2U7XG4gICAgfVxuICB9XG59XG4iLCIvKipcbiAqIEBzdW1tYXJ5IFNpbXBsZSBTeW5jaHJvbm91cyBMb2NrIGltcGxlbWVudGF0aW9uXG4gKiBAZGVzY3JpcHRpb24gZm9yIHRyYW5zYWN0aW9uIG1hbmFnZW1lbnRcbiAqIGFkYXB0ZWQgZnJvbSB7QGxpbmsgaHR0cHM6Ly93d3cudGFsa2luZ2hpZ2h0ZWNoLmNvbS9lbi9jcmVhdGluZy1hLWpzLWxvY2stZm9yLWEtcmVzb3VyY2UvfVxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBbY291bnRlcl0gdGhlIG51bWJlciBvZiBzaW11bHRhbmVvdXMgdHJhbnNhY3Rpb25zIGFsbG93ZWQuIGRlZmF1bHRzIHRvIDFcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvbkJlZ2luXSB0byBiZSBjYWxsZWQgYXQgdGhlIHN0YXJ0IG9mIHRoZSB0cmFuc2FjdGlvblxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uRW5kXSB0byBiZSBjYWxsZWQgYXQgdGhlIGNvbmNsdXNpb24gb2YgdGhlIHRyYW5zYWN0aW9uXG4gKlxuICogQGNsYXNzIFN5bmNyb25vdXNMb2NrXG4gKiBAaW1wbGVtZW50cyBUcmFuc2FjdGlvbkxvY2tcbiAqXG4gKiBAY2F0ZWdvcnkgVHJhbnNhY3Rpb25zXG4gKi8gaW1wb3J0IHsgVHJhbnNhY3Rpb24gfSBmcm9tIFwiLi4vVHJhbnNhY3Rpb25cIjtcbmltcG9ydCB7IFRyYW5zYWN0aW9uTG9jayB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL1RyYW5zYWN0aW9uTG9ja1wiO1xuaW1wb3J0IHsgTG9jayB9IGZyb20gXCIuL0xvY2tcIjtcblxuZXhwb3J0IGNsYXNzIFN5bmNyb25vdXNMb2NrIGltcGxlbWVudHMgVHJhbnNhY3Rpb25Mb2NrIHtcbiAgcHJpdmF0ZSBjb3VudGVyOiBudW1iZXI7XG4gIHByaXZhdGUgcGVuZGluZ1RyYW5zYWN0aW9uczogVHJhbnNhY3Rpb25bXTtcbiAgY3VycmVudFRyYW5zYWN0aW9uPzogVHJhbnNhY3Rpb24gPSB1bmRlZmluZWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgb25CZWdpbj86ICgpID0+IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgcmVhZG9ubHkgb25FbmQ/OiAoZXJyPzogRXJyb3IpID0+IFByb21pc2U8dm9pZD47XG5cbiAgcHJpdmF0ZSByZWFkb25seSBsb2NrID0gbmV3IExvY2soKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBjb3VudGVyOiBudW1iZXIgPSAxLFxuICAgIG9uQmVnaW4/OiAoKSA9PiBQcm9taXNlPHZvaWQ+LFxuICAgIG9uRW5kPzogKGVycj86IEVycm9yKSA9PiBQcm9taXNlPHZvaWQ+LFxuICApIHtcbiAgICB0aGlzLmNvdW50ZXIgPSBjb3VudGVyO1xuICAgIHRoaXMucGVuZGluZ1RyYW5zYWN0aW9ucyA9IFtdO1xuICAgIHRoaXMub25CZWdpbiA9IG9uQmVnaW47XG4gICAgdGhpcy5vbkVuZCA9IG9uRW5kO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFN1Ym1pdHMgYSB0cmFuc2FjdGlvbiB0byBiZSBwcm9jZXNzZWRcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbn0gdHJhbnNhY3Rpb25cbiAgICovXG4gIHN1Ym1pdCh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pOiB2b2lkIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBzZWxmLmxvY2suYWNxdWlyZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKFxuICAgICAgICBzZWxmLmN1cnJlbnRUcmFuc2FjdGlvbiAmJlxuICAgICAgICBzZWxmLmN1cnJlbnRUcmFuc2FjdGlvbi5pZCA9PT0gdHJhbnNhY3Rpb24uaWRcbiAgICAgICkge1xuICAgICAgICBzZWxmLmxvY2sucmVsZWFzZSgpO1xuICAgICAgICByZXR1cm4gdHJhbnNhY3Rpb24uZmlyZSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2VsZi5jb3VudGVyID4gMCkge1xuICAgICAgICBzZWxmLmNvdW50ZXItLTtcbiAgICAgICAgc2VsZi5sb2NrLnJlbGVhc2UoKTtcbiAgICAgICAgcmV0dXJuIHNlbGYuZmlyZVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlbGYucGVuZGluZ1RyYW5zYWN0aW9ucy5wdXNoKHRyYW5zYWN0aW9uKTtcbiAgICAgICAgc2VsZi5sb2NrLnJlbGVhc2UoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyBhIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb259IHRyYW5zYWN0aW9uXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGZpcmVUcmFuc2FjdGlvbih0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBzZWxmLmxvY2suYWNxdWlyZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgc2VsZi5jdXJyZW50VHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbjtcbiAgICAgIHNlbGYubG9jay5yZWxlYXNlKCk7XG4gICAgICBpZiAoc2VsZi5vbkJlZ2luKVxuICAgICAgICBzZWxmLm9uQmVnaW4oKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAvLyBhbGwuY2FsbChcbiAgICAgICAgICAvLyAgIHNlbGYsXG4gICAgICAgICAgLy8gICBgRmlyaW5nIHRyYW5zYWN0aW9uIHswfS4gezF9IHJlbWFpbmluZy4uLmAsXG4gICAgICAgICAgLy8gICB0cmFuc2FjdGlvbi5pZCxcbiAgICAgICAgICAvLyAgIHRoaXMucGVuZGluZ1RyYW5zYWN0aW9ucy5sZW5ndGgsXG4gICAgICAgICAgLy8gKTtcbiAgICAgICAgICB0cmFuc2FjdGlvbi5maXJlKCk7XG4gICAgICAgIH0pO1xuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIGFsbC5jYWxsKFxuICAgICAgICAvLyAgIHNlbGYsXG4gICAgICAgIC8vICAgYEZpcmluZyB0cmFuc2FjdGlvbiB7MH0uIHsxfSByZW1haW5pbmcuLi5gLFxuICAgICAgICAvLyAgIHRyYW5zYWN0aW9uLmlkLFxuICAgICAgICAvLyAgIHRoaXMucGVuZGluZ1RyYW5zYWN0aW9ucy5sZW5ndGgsXG4gICAgICAgIC8vICk7XG4gICAgICAgIHRyYW5zYWN0aW9uLmZpcmUoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogQHN1bW1hcnkgUmVsZWFzZXMgVGhlIGxvY2sgYWZ0ZXIgdGhlIGNvbmNsdXNpb24gb2YgYSB0cmFuc2FjdGlvblxuICAgKi9cbiAgYXN5bmMgcmVsZWFzZShlcnI/OiBFcnJvcik6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgc2VsZi5sb2NrLmFjcXVpcmUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKCFzZWxmLmN1cnJlbnRUcmFuc2FjdGlvbilcbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICBcIlRyeWluZyB0byByZWxlYXNlIGFuIHVuZXhpc3RpbmcgdHJhbnNhY3Rpb24uIHNob3VsZCBuZXZlciBoYXBwZW4uLi5cIixcbiAgICAgICAgICApO1xuICAgICAgICAvLyBkZWJ1Zy5jYWxsKFxuICAgICAgICAvLyAgIHNlbGYsXG4gICAgICAgIC8vICAgXCJSZWxlYXNpbmcgdHJhbnNhY3Rpb246IHswfVwiLFxuICAgICAgICAvLyAgIHNlbGYuY3VycmVudFRyYW5zYWN0aW9uPy50b1N0cmluZyh0cnVlLCB0cnVlKSxcbiAgICAgICAgLy8gKTtcbiAgICAgICAgc2VsZi5jdXJyZW50VHJhbnNhY3Rpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgIHNlbGYubG9jay5yZWxlYXNlKCk7XG5cbiAgICAgICAgY29uc3QgYWZ0ZXJDb25jbHVzaW9uQ0IgPSAoKSA9PiB7XG4gICAgICAgICAgc2VsZi5sb2NrLmFjcXVpcmUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdUcmFuc2FjdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9XG4gICAgICAgICAgICAgICAgc2VsZi5wZW5kaW5nVHJhbnNhY3Rpb25zLnNoaWZ0KCkgYXMgVHJhbnNhY3Rpb247XG5cbiAgICAgICAgICAgICAgY29uc3QgY2IgPSAoKSA9PiBzZWxmLmZpcmVUcmFuc2FjdGlvbih0cmFuc2FjdGlvbik7XG4gICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgIC8vIGFsbChcbiAgICAgICAgICAgICAgLy8gICBgUmVsZWFzaW5nIFRyYW5zYWN0aW9uIExvY2sgb24gdHJhbnNhY3Rpb24gezB9YCxcbiAgICAgICAgICAgICAgLy8gICB0cmFuc2FjdGlvbi5pZCxcbiAgICAgICAgICAgICAgLy8gKTtcblxuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgdHlwZW9mIChnbG9iYWxUaGlzIGFzIHVua25vd24gYXMgeyB3aW5kb3c6IGFueSB9KS53aW5kb3cgPT09XG4gICAgICAgICAgICAgICAgXCJ1bmRlZmluZWRcIlxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgZ2xvYmFsVGhpcy5wcm9jZXNzLm5leHRUaWNrKGNiKTsgLy8gaWYgeW91IGFyZSBvbiBub2RlXG4gICAgICAgICAgICAgIGVsc2Ugc2V0VGltZW91dChjYiwgMCk7IC8vIGlmIHlvdSBhcmUgaW4gdGhlIGJyb3dzZXJcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHNlbGYuY291bnRlcisrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5sb2NrLnJlbGVhc2UoKTtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoc2VsZi5vbkVuZCkgc2VsZi5vbkVuZChlcnIpLnRoZW4oKCkgPT4gYWZ0ZXJDb25jbHVzaW9uQ0IoKSk7XG4gICAgICAgIGVsc2UgYWZ0ZXJDb25jbHVzaW9uQ0IoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59XG4iLCJleHBvcnQgY29uc3QgVHJhbnNhY3Rpb25hbEtleXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gIFJFRkxFQ1Q6IFwibW9kZWwudHJhbnNhY3Rpb25hbC5cIixcbiAgVFJBTlNBQ1RJT05BTDogXCJ0cmFuc2FjdGlvbmFsXCIsXG59O1xuIiwiZXhwb3J0IGZ1bmN0aW9uIGdldE9iamVjdE5hbWUob2JqOiBhbnkpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIW9iaikgcmV0dXJuO1xuICBpZiAodHlwZW9mIG9iaiA9PT0gXCJzdHJpbmdcIikgcmV0dXJuIG9iajtcbiAgaWYgKFxuICAgIG9iai5jb25zdHJ1Y3RvciAmJlxuICAgIG9iai5jb25zdHJ1Y3Rvci5uYW1lICYmXG4gICAgW1wiRnVuY3Rpb25cIiwgXCJPYmplY3RcIl0uaW5kZXhPZihvYmouY29uc3RydWN0b3IubmFtZSkgPT09IC0xXG4gIClcbiAgICByZXR1cm4gb2JqLmNvbnN0cnVjdG9yLm5hbWU7XG4gIGlmICh0eXBlb2Ygb2JqID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLm5hbWUpIHJldHVybiBvYmoubmFtZTtcbiAgcmV0dXJuIG9iai50b1N0cmluZygpO1xufVxuIiwiaW1wb3J0IHsgVHJhbnNhY3Rpb25Mb2NrIH0gZnJvbSBcIi4vaW50ZXJmYWNlcy9UcmFuc2FjdGlvbkxvY2tcIjtcbmltcG9ydCB7IFJlZmxlY3Rpb24gfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IENhbGxiYWNrIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IFN5bmNyb25vdXNMb2NrIH0gZnJvbSBcIi4vbG9ja3MvU3luY3Jvbm91c0xvY2tcIjtcbmltcG9ydCB7XG4gIERCS2V5cyxcbiAgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IGdldE9iamVjdE5hbWUgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25hbEtleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBUcmFuc2FjdGlvbiBDbGFzc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWV0aG9kXVxuICogQHBhcmFtIHtmdW5jdGlvbigpOiB2b2lkfSBbYWN0aW9uXVxuICogQHBhcmFtIHthbnlbXX0gW21ldGFkYXRhXVxuICpcbiAqIEBjbGFzcyBUcmFuc2FjdGlvblxuICpcbiAqIEBjYXRlZ29yeSBUcmFuc2FjdGlvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIFRyYW5zYWN0aW9uIHtcbiAgcmVhZG9ubHkgaWQ6IG51bWJlcjtcbiAgcHJvdGVjdGVkIGFjdGlvbj86ICgpID0+IGFueTtcbiAgcmVhZG9ubHkgbWV0aG9kPzogc3RyaW5nO1xuICByZWFkb25seSBzb3VyY2U/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGxvZzogc3RyaW5nW107XG4gIHByaXZhdGUgcmVhZG9ubHkgbWV0YWRhdGE/OiBhbnlbXTtcblxuICBwcml2YXRlIHN0YXRpYyBsb2NrOiBUcmFuc2FjdGlvbkxvY2s7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc291cmNlOiBzdHJpbmcsXG4gICAgbWV0aG9kPzogc3RyaW5nLFxuICAgIGFjdGlvbj86ICgpID0+IGFueSxcbiAgICBtZXRhZGF0YT86IGFueVtdXG4gICkge1xuICAgIHRoaXMuaWQgPSBEYXRlLm5vdygpO1xuICAgIHRoaXMuYWN0aW9uID0gYWN0aW9uO1xuICAgIHRoaXMubWV0aG9kID0gbWV0aG9kO1xuICAgIHRoaXMubG9nID0gW1t0aGlzLmlkLCBzb3VyY2UsIG1ldGhvZF0uam9pbihcIiB8IFwiKV07XG4gICAgdGhpcy5zb3VyY2UgPSBzb3VyY2U7XG4gICAgdGhpcy5tZXRhZGF0YSA9IG1ldGFkYXRhO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFB1c2hlcyBhIHRyYW5zYWN0aW9uIHRvIHF1ZSBxdWV1ZSBhbmQgd2FpdHMgaXRzIHJlc29sdXRpb25cbiAgICpcbiAgICogQHBhcmFtIHthbnl9IGlzc3VlciBhbnkgY2xhc3MuIHdpbGwgYmUgdXNlZCBhcyB0aGlzIHdoZW4gY2FsbGluZyB0aGUgY2FsbGJhY2tNZXRob2RcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tNZXRob2QgY2FsbGJhY2sgZnVuY3Rpb24gY29udGFpbmluZyB0aGUgdHJhbnNhY3Rpb24uIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIGlzc3VlYXIgYXMgdGhpc1xuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuIExhc3Qgb25lIG11c3QgYmUgdGhlIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0aWMgcHVzaChcbiAgICBpc3N1ZXI6IGFueSxcbiAgICBjYWxsYmFja01ldGhvZDogKC4uLmFyZ3p6OiAoYW55IHwgQ2FsbGJhY2spW10pID0+IHZvaWQsXG4gICAgLi4uYXJnczogKGFueSB8IENhbGxiYWNrKVtdXG4gICkge1xuICAgIGNvbnN0IGNhbGxiYWNrOiBDYWxsYmFjayA9IGFyZ3MucG9wKCk7XG4gICAgaWYgKCFjYWxsYmFjayB8fCB0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgY2FsbGJhY2tcIik7XG4gICAgY29uc3QgY2IgPSAoZXJyPzogRXJyb3IsIC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICBUcmFuc2FjdGlvbi5nZXRMb2NrKClcbiAgICAgICAgLnJlbGVhc2UoZXJyKVxuICAgICAgICAudGhlbigoKSA9PiBjYWxsYmFjayhlcnIsIC4uLmFyZ3MpKTtcbiAgICB9O1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbihcbiAgICAgIGlzc3Vlci5jb25zdHJ1Y3Rvci5uYW1lLFxuICAgICAgY2FsbGJhY2tNZXRob2QubmFtZSA/IGdldE9iamVjdE5hbWUoY2FsbGJhY2tNZXRob2QpIDogXCJBbm9ueW1vdXNcIixcbiAgICAgICgpID0+IHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrTWV0aG9kLmNhbGwoXG4gICAgICAgICAgdHJhbnNhY3Rpb24uYmluZFRvVHJhbnNhY3Rpb24oaXNzdWVyKSxcbiAgICAgICAgICAuLi5hcmdzLFxuICAgICAgICAgIGNiXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgKTtcbiAgICBUcmFuc2FjdGlvbi5nZXRMb2NrKCkuc3VibWl0KHRyYW5zYWN0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBTZXRzIHRoZSBsb2NrIHRvIGJlIHVzZWRcbiAgICogQHBhcmFtIGxvY2tcbiAgICovXG4gIHN0YXRpYyBzZXRMb2NrKGxvY2s6IFRyYW5zYWN0aW9uTG9jaykge1xuICAgIHRoaXMubG9jayA9IGxvY2s7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgZ2V0cyB0aGUgbG9ja1xuICAgKi9cbiAgc3RhdGljIGdldExvY2soKTogVHJhbnNhY3Rpb25Mb2NrIHtcbiAgICBpZiAoIXRoaXMubG9jaykgdGhpcy5sb2NrID0gbmV3IFN5bmNyb25vdXNMb2NrKCk7XG4gICAgcmV0dXJuIHRoaXMubG9jaztcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBzdWJtaXRzIGEgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbn0gdHJhbnNhY3Rpb25cbiAgICovXG4gIHN0YXRpYyBzdWJtaXQodHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKSB7XG4gICAgVHJhbnNhY3Rpb24uZ2V0TG9jaygpLnN1Ym1pdCh0cmFuc2FjdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgcmVsZWFzZXMgdGhlIGxvY2tcbiAgICogQHBhcmFtIHtFcnJ9IGVyclxuICAgKi9cbiAgc3RhdGljIGFzeW5jIHJlbGVhc2UoZXJyPzogRXJyb3IpIHtcbiAgICByZXR1cm4gVHJhbnNhY3Rpb24uZ2V0TG9jaygpLnJlbGVhc2UoZXJyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSByZXRyaWV2ZXMgdGhlIG1ldGFkYXRhIGZvciB0aGUgdHJhbnNhY3Rpb25cbiAgICovXG4gIGdldE1ldGFkYXRhKCkge1xuICAgIHJldHVybiB0aGlzLm1ldGFkYXRhID8gWy4uLnRoaXMubWV0YWRhdGFdIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IEJpbmRzIGEgbmV3IG9wZXJhdGlvbiB0byB0aGUgY3VycmVudCB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9ufSBuZXh0VHJhbnNhY3Rpb25cbiAgICovXG4gIGJpbmRUcmFuc2FjdGlvbihuZXh0VHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKSB7XG4gICAgLy8gYWxsKGBCaW5kaW5nIHRoZSB7MH0gdG8gezF9YCwgbmV4dFRyYW5zYWN0aW9uLCB0aGlzKTtcbiAgICB0aGlzLmxvZy5wdXNoKC4uLm5leHRUcmFuc2FjdGlvbi5sb2cpO1xuICAgIG5leHRUcmFuc2FjdGlvbi5iaW5kVHJhbnNhY3Rpb24gPSB0aGlzLmJpbmRUb1RyYW5zYWN0aW9uLmJpbmQodGhpcyk7XG4gICAgbmV4dFRyYW5zYWN0aW9uLmJpbmRUb1RyYW5zYWN0aW9uID0gdGhpcy5iaW5kVG9UcmFuc2FjdGlvbi5iaW5kKHRoaXMpO1xuICAgIHRoaXMuYWN0aW9uID0gbmV4dFRyYW5zYWN0aW9uLmFjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBCaW5kcyB0aGUgVHJhbnNhY3Rpb25hbCBEZWNvcmF0ZWQgT2JqZWN0IHRvIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAZGVzY3JpcHRpb24gYnkgaGF2aW5nIGFsbCB7QGxpbmsgdHJhbnNhY3Rpb25hbH0gZGVjb3JhdGVkXG4gICAqIG1ldGhvZHMgYWx3YXlzIHBhc3MgdGhlIGN1cnJlbnQgVHJhbnNhY3Rpb24gYXMgYW4gYXJndW1lbnRcbiAgICpcbiAgICogQHBhcmFtIHthbnl9IG9ialxuICAgKiBAcmV0dXJuIHthbnl9IHRoZSBib3VuZCB7QHBhcmFtIG9ian1cbiAgICovXG4gIGJpbmRUb1RyYW5zYWN0aW9uKG9iajogYW55KTogYW55IHtcbiAgICBjb25zdCB0cmFuc2FjdGlvbmFsTWV0aG9kcyA9IGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZShcbiAgICAgIG9iaixcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIFRyYW5zYWN0aW9uYWxLZXlzLlJFRkxFQ1RcbiAgICApO1xuICAgIGlmICghdHJhbnNhY3Rpb25hbE1ldGhvZHMpIHJldHVybiBvYmo7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby10aGlzLWFsaWFzXG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICBjb25zdCBib3VuZE9iaiA9IFJlZmxlY3Rpb24uZ2V0QWxsUHJvcGVydGllcyhvYmopLnJlZHVjZShcbiAgICAgIChhY2N1bTogYW55LCBrOiBzdHJpbmcpID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIE9iamVjdC5rZXlzKHRyYW5zYWN0aW9uYWxNZXRob2RzKS5pbmRleE9mKGspICE9PSAtMSAmJlxuICAgICAgICAgIHRyYW5zYWN0aW9uYWxNZXRob2RzW2tdLmZpbmQoXG4gICAgICAgICAgICAobykgPT4gby5rZXkgPT09IFRyYW5zYWN0aW9uYWxLZXlzLlRSQU5TQUNUSU9OQUxcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICAgICBhY2N1bVtrXSA9ICguLi5hcmdzOiBhbnlbXSkgPT5cbiAgICAgICAgICAgIG9ialtrXS5jYWxsKG9iai5fX29yaWdpbmFsT2JqIHx8IG9iaiwgc2VsZiwgLi4uYXJncyk7XG4gICAgICAgIGVsc2UgaWYgKGsgPT09IFwiY2xhenpcIiB8fCBrID09PSBcImNvbnN0cnVjdG9yXCIpIGFjY3VtW2tdID0gb2JqW2tdO1xuICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqW2tdID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgICAgYWNjdW1ba10gPSBvYmpba10uYmluZChvYmouX19vcmlnaW5hbE9iaiB8fCBvYmopO1xuICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqW2tdID09PSBcIm9iamVjdFwiICYmIG9ialtrXS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgIGNvbnN0IGRlY3MgPSBSZWZsZWN0aW9uLmdldENsYXNzRGVjb3JhdG9ycyhcbiAgICAgICAgICAgIFRyYW5zYWN0aW9uYWxLZXlzLlJFRkxFQ1QsXG4gICAgICAgICAgICBvYmpba11cbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChkZWNzLmZpbmQoKGU6IGFueSkgPT4gZS5rZXkgPT09IFRyYW5zYWN0aW9uYWxLZXlzLlRSQU5TQUNUSU9OQUwpKVxuICAgICAgICAgICAgYWNjdW1ba10gPSBzZWxmLmJpbmRUb1RyYW5zYWN0aW9uKG9ialtrXSk7XG4gICAgICAgICAgZWxzZSBhY2N1bVtrXSA9IG9ialtrXTtcbiAgICAgICAgfSBlbHNlIGFjY3VtW2tdID0gb2JqW2tdO1xuXG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sXG4gICAgICB7fVxuICAgICk7XG5cbiAgICBib3VuZE9ialtEQktleXMuT1JJR0lOQUxdID0gb2JqW0RCS2V5cy5PUklHSU5BTF0gfHwgb2JqO1xuICAgIGJvdW5kT2JqLnRvU3RyaW5nID0gKCkgPT5cbiAgICAgIGdldE9iamVjdE5hbWUoYm91bmRPYmpbREJLZXlzLk9SSUdJTkFMXSkgK1xuICAgICAgXCIgcHJveHkgZm9yIHRyYW5zYWN0aW9uIFwiICtcbiAgICAgIHRoaXMuaWQ7XG5cbiAgICByZXR1cm4gYm91bmRPYmo7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgRmlyZXMgdGhlIFRyYW5zYWN0aW9uXG4gICAqL1xuICBmaXJlKCkge1xuICAgIGlmICghdGhpcy5hY3Rpb24pIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyB0aGUgbWV0aG9kYCk7XG4gICAgcmV0dXJuIHRoaXMuYWN0aW9uKCk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgdG9TdHJpbmcgb3ZlcnJpZGVcbiAgICogQHBhcmFtIHtib29sZWFufSBbd2l0aElkXSBkZWZhdWx0cyB0byB0cnVlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3dpdGhMb2ddIGRlZmF1bHRzIHRvIHRydWVcbiAgICovXG4gIHRvU3RyaW5nKHdpdGhJZCA9IHRydWUsIHdpdGhMb2cgPSBmYWxzZSkge1xuICAgIHJldHVybiBgJHt3aXRoSWQgPyBgWyR7dGhpcy5pZH1dYCA6IFwiXCJ9W1RyYW5zYWN0aW9uXVske3RoaXMuc291cmNlfS4ke3RoaXMubWV0aG9kfSR7XG4gICAgICB3aXRoTG9nID8gYF1cXG5UcmFuc2FjdGlvbiBMb2c6XFxuJHt0aGlzLmxvZy5qb2luKFwiXFxuXCIpfWAgOiBcIl1cIlxuICAgIH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IGdldHMgdGhlIHRyYW5zYWN0aW9ucyByZWZsZWN0aW9ucyBrZXlcbiAgICogQGZ1bmN0aW9uIGdldFJlcG9LZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICAgKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuVHJhbnNhY3Rpb25zXG4gICAqICovXG4gIHN0YXRpYyBrZXkoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gVHJhbnNhY3Rpb25hbEtleXMuUkVGTEVDVCArIGtleTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgVHJhbnNhY3Rpb25hbEtleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IG1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbiB9IGZyb20gXCIuL1RyYW5zYWN0aW9uXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgU2V0cyBhIGNsYXNzIEFzeW5jIG1ldGhvZCBhcyB0cmFuc2FjdGlvbmFsXG4gKlxuICogQHBhcmFtIHthbnlbXX0gIFtkYXRhXSBvcHRpb24gbWV0YWRhdGEgYXZhaWxhYmxlIHRvIHRoZSB7QGxpbmsgVHJhbnNhY3Rpb25Mb2NrfVxuICpcbiAqIEBmdW5jdGlvbiB0cmFuc2FjdGlvbmFsXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLkRlY29yYXRvcnMudHJhbnNhY3Rpb25zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2FjdGlvbmFsKC4uLmRhdGE6IGFueVtdKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoXG4gICAgdGFyZ2V0OiBhbnksXG4gICAgcHJvcGVydHlLZXk/OiBhbnksXG4gICAgZGVzY3JpcHRvcj86IFByb3BlcnR5RGVzY3JpcHRvclxuICApIHtcbiAgICBpZiAoIWRlc2NyaXB0b3IpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk1pc3NpbmcgZGVzY3JpcHRvci4gU2hvdWxkIGJlIGltcG9zc2libGVcIik7XG4gICAgbWV0YWRhdGEoVHJhbnNhY3Rpb24ua2V5KFRyYW5zYWN0aW9uYWxLZXlzLlRSQU5TQUNUSU9OQUwpLCBkYXRhKShcbiAgICAgIHRhcmdldCxcbiAgICAgIHByb3BlcnR5S2V5XG4gICAgKTtcblxuICAgIGNvbnN0IG9yaWdpbmFsTWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgIGNvbnN0IG1ldGhvZFdyYXBwZXIgPSBmdW5jdGlvbiAodGhpczogYW55LCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8YW55PiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPGFueT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBjb25zdCBjYiA9IChlcnI/OiBFcnJvciwgcmVzdWx0PzogYW55KSA9PiB7XG4gICAgICAgICAgVHJhbnNhY3Rpb24ucmVsZWFzZShlcnIpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGVycikgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGxldCB0cmFuc2FjdGlvbiA9IGFyZ3Muc2hpZnQoKTtcbiAgICAgICAgaWYgKHRyYW5zYWN0aW9uIGluc3RhbmNlb2YgVHJhbnNhY3Rpb24pIHtcbiAgICAgICAgICBjb25zdCB1cGRhdGVkVHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uID0gbmV3IFRyYW5zYWN0aW9uKFxuICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lLFxuICAgICAgICAgICAgcHJvcGVydHlLZXksXG4gICAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgIG9yaWdpbmFsTWV0aG9kXG4gICAgICAgICAgICAgICAgLmNhbGwodXBkYXRlZFRyYW5zYWN0aW9uLmJpbmRUb1RyYW5zYWN0aW9uKHNlbGYpLCAuLi5hcmdzKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlc29sdmUpXG4gICAgICAgICAgICAgICAgLmNhdGNoKHJlamVjdCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGF0YS5sZW5ndGggPyBkYXRhIDogdW5kZWZpbmVkXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRyYW5zYWN0aW9uLmJpbmRUcmFuc2FjdGlvbih1cGRhdGVkVHJhbnNhY3Rpb24pO1xuICAgICAgICAgIHRyYW5zYWN0aW9uLmZpcmUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhcmdzLnVuc2hpZnQodHJhbnNhY3Rpb24pO1xuICAgICAgICAgIHRyYW5zYWN0aW9uID0gbmV3IFRyYW5zYWN0aW9uKFxuICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lLFxuICAgICAgICAgICAgcHJvcGVydHlLZXksXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgIG9yaWdpbmFsTWV0aG9kXG4gICAgICAgICAgICAgICAgLmNhbGwodHJhbnNhY3Rpb24uYmluZFRvVHJhbnNhY3Rpb24oc2VsZiksIC4uLmFyZ3MpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlc3VsdDogYW55KSA9PiBjYih1bmRlZmluZWQsIHJlc3VsdCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGNiKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkYXRhLmxlbmd0aCA/IGRhdGEgOiB1bmRlZmluZWRcbiAgICAgICAgICApO1xuICAgICAgICAgIFRyYW5zYWN0aW9uLnN1Ym1pdCh0cmFuc2FjdGlvbik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobWV0aG9kV3JhcHBlciwgXCJuYW1lXCIsIHtcbiAgICAgIHZhbHVlOiBwcm9wZXJ0eUtleSxcbiAgICB9KTtcbiAgICBkZXNjcmlwdG9yLnZhbHVlID0gbWV0aG9kV3JhcHBlcjtcbiAgfTtcbn1cbi8vXG4vLyAvKipcbi8vICAqIEBzdW1tYXJ5IFNldHMgYSBjbGFzcyBBc3luYyBtZXRob2QgYXMgdHJhbnNhY3Rpb25hbFxuLy8gICpcbi8vICAqIEBwYXJhbSB7YW55W119ICBbbWV0YWRhdGFdIG9wdGlvbiBtZXRhZGF0YSBhdmFpbGFibGUgdG8gdGhlIHtAbGluayBUcmFuc2FjdGlvbkxvY2t9XG4vLyAgKlxuLy8gICogQGZ1bmN0aW9uIHRyYW5zYWN0aW9uYWxBc3luY1xuLy8gICpcbi8vICAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5EZWNvcmF0b3JzLnRyYW5zYWN0aW9uc1xuLy8gICovXG4vLyBleHBvcnQgZnVuY3Rpb24gdHJhbnNhY3Rpb25hbEFzeW5jKC4uLm1ldGFkYXRhOiBhbnlbXSkge1xuLy8gICByZXR1cm4gZnVuY3Rpb24gKFxuLy8gICAgIHRhcmdldDogYW55LFxuLy8gICAgIHByb3BlcnR5S2V5OiBzdHJpbmcsXG4vLyAgICAgZGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yLFxuLy8gICApIHtcbi8vICAgICBtZXRhZGFzdGEoZ2V0VHJhbnNhY3Rpb25hbEtleShUcmFuc2FjdGlvbmFsS2V5cy5UUkFOU0FDVElPTkFMKSlcbi8vICAgICBSZWZsZWN0LmRlZmluZU1ldGFkYXRhKFxuLy8gICAgICAgLFxuLy8gICAgICAge1xuLy8gICAgICAgICB0eXBlOiBcImFzeW5jXCIsXG4vLyAgICAgICAgIG1ldGFkYXRhOiBtZXRhZGF0YS5sZW5ndGggPyBtZXRhZGF0YSA6IHVuZGVmaW5lZCxcbi8vICAgICAgIH0gYXMgVHJhbnNhY3Rpb25hbE1ldGFkYXRhLFxuLy8gICAgICAgdGFyZ2V0LFxuLy8gICAgICAgcHJvcGVydHlLZXksXG4vLyAgICAgKTtcbi8vXG4vLyAgICAgY29uc3Qgb3JpZ2luYWxNZXRob2QgPSBkZXNjcmlwdG9yLnZhbHVlO1xuLy9cbi8vICAgICBjb25zdCBtZXRob2RXcmFwcGVyID0gZnVuY3Rpb24gKHRoaXM6IGFueSwgLi4uYXJnczogYW55W10pIHtcbi8vICAgICAgIGNvbnN0IGNhbGxiYWNrOiBDYWxsYmFjayA9IGFyZ3MucG9wKCk7XG4vLyAgICAgICBpZiAoIWNhbGxiYWNrIHx8IHR5cGVvZiBjYWxsYmFjayAhPT0gXCJmdW5jdGlvblwiKVxuLy8gICAgICAgICB0aHJvdyBuZXcgQ3JpdGljYWxFcnJvcihgTWlzc2luZyBDYWxsYmFja2ApO1xuLy9cbi8vICAgICAgIGNvbnN0IGNiID0gKGVycj86IEVyciwgLi4uYXJnczogYW55W10pID0+IHtcbi8vICAgICAgICAgVHJhbnNhY3Rpb24ucmVsZWFzZShlcnIpLnRoZW4oKF8pID0+IGNhbGxiYWNrKGVyciwgLi4uYXJncykpO1xuLy8gICAgICAgfTtcbi8vXG4vLyAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbi8vXG4vLyAgICAgICBsZXQgdHJhbnNhY3Rpb24gPSBhcmdzLnNoaWZ0KCk7XG4vLyAgICAgICBpZiAodHJhbnNhY3Rpb24gaW5zdGFuY2VvZiBUcmFuc2FjdGlvbikge1xuLy8gICAgICAgICBjb25zdCB1cGRhdGVkVHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uID0gbmV3IFRyYW5zYWN0aW9uKFxuLy8gICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IubmFtZSxcbi8vICAgICAgICAgICBwcm9wZXJ0eUtleSxcbi8vICAgICAgICAgICAoKSA9PiB7XG4vLyAgICAgICAgICAgICB0cnkge1xuLy8gICAgICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxNZXRob2QuY2FsbChcbi8vICAgICAgICAgICAgICAgICB1cGRhdGVkVHJhbnNhY3Rpb24uYmluZFRvVHJhbnNhY3Rpb24oc2VsZiksXG4vLyAgICAgICAgICAgICAgICAgLi4uYXJncyxcbi8vICAgICAgICAgICAgICAgICBjYWxsYmFjayxcbi8vICAgICAgICAgICAgICAgKTtcbi8vICAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuLy8gICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZSk7XG4vLyAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgfSxcbi8vICAgICAgICAgICBtZXRhZGF0YS5sZW5ndGggPyBtZXRhZGF0YSA6IHVuZGVmaW5lZCxcbi8vICAgICAgICAgKTtcbi8vXG4vLyAgICAgICAgIHRyYW5zYWN0aW9uLmJpbmRUcmFuc2FjdGlvbih1cGRhdGVkVHJhbnNhY3Rpb24pO1xuLy8gICAgICAgICB0cmFuc2FjdGlvbi5maXJlKCk7XG4vLyAgICAgICB9IGVsc2Uge1xuLy8gICAgICAgICBhcmdzLnVuc2hpZnQodHJhbnNhY3Rpb24pO1xuLy8gICAgICAgICB0cmFuc2FjdGlvbiA9IHVuZGVmaW5lZDtcbi8vICAgICAgICAgdHJhbnNhY3Rpb24gPSBuZXcgVHJhbnNhY3Rpb24oXG4vLyAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lLFxuLy8gICAgICAgICAgIHByb3BlcnR5S2V5LFxuLy8gICAgICAgICAgICgpID0+IHtcbi8vICAgICAgICAgICAgIHRyeSB7XG4vLyAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbE1ldGhvZC5jYWxsKFxuLy8gICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uLmJpbmRUb1RyYW5zYWN0aW9uKHNlbGYpLFxuLy8gICAgICAgICAgICAgICAgIC4uLmFyZ3MsXG4vLyAgICAgICAgICAgICAgICAgY2IsXG4vLyAgICAgICAgICAgICAgICk7XG4vLyAgICAgICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbi8vICAgICAgICAgICAgICAgcmV0dXJuIGNiKGUpO1xuLy8gICAgICAgICAgICAgfVxuLy8gICAgICAgICAgIH0sXG4vLyAgICAgICAgICAgbWV0YWRhdGEubGVuZ3RoID8gbWV0YWRhdGEgOiB1bmRlZmluZWQsXG4vLyAgICAgICAgICk7XG4vLyAgICAgICAgIFRyYW5zYWN0aW9uLnN1Ym1pdCh0cmFuc2FjdGlvbik7XG4vLyAgICAgICB9XG4vLyAgICAgfTtcbi8vXG4vLyAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1ldGhvZFdyYXBwZXIsIFwibmFtZVwiLCB7XG4vLyAgICAgICB2YWx1ZTogcHJvcGVydHlLZXksXG4vLyAgICAgfSk7XG4vLyAgICAgZGVzY3JpcHRvci52YWx1ZSA9IG1ldGhvZFdyYXBwZXI7XG4vLyAgIH07XG4vLyB9XG5cbi8qKlxuICogQHN1bW1hcnkgVXRpbCBmdW5jdGlvbiB0byB3cmFwIHN1cGVyIGNhbGxzIHdpdGggdGhlIHRyYW5zYWN0aW9uIHdoZW4gdGhlIHN1cGVyJ3MgbWV0aG9kIGlzIGFsc28gdHJhbnNhY3Rpb25hbFxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG1ldGhvZCB0aGUgc3VwZXIgbWV0aG9kIChtdXN0IGJlIGJvdW5kIHRvIHRoZSBwcm9wZXIgdGhpcyksIGVnOiBzdXBlci5jcmVhdGUuYmluZCh0aGlzKVxuICogQHBhcmFtIHthbnlbXX0gYXJncyB0aGUgYXJndW1lbnRzIHRvIGNhbGwgdGhlIG1ldGhvZCB3aXRoXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLlRyYW5zYWN0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2FjdGlvbmFsU3VwZXJDYWxsKG1ldGhvZDogYW55LCAuLi5hcmdzOiBhbnkpIHtcbiAgY29uc3QgbG9jayA9IFRyYW5zYWN0aW9uLmdldExvY2soKTtcbiAgY29uc3QgY3VycmVudFRyYW5zYWN0aW9uID0gbG9jay5jdXJyZW50VHJhbnNhY3Rpb247XG4gIHJldHVybiBtZXRob2QoY3VycmVudFRyYW5zYWN0aW9uLCAuLi5hcmdzKTtcbn1cbiIsImV4cG9ydCAqIGZyb20gXCIuL2ludGVyZmFjZXNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2xvY2tzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1RyYW5zYWN0aW9uXCI7XG5leHBvcnQgKiBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IE1vZHVsZSBzdW1tYXJ5XG4gKiBAZGVzY3JpcHRpb24gTW9kdWxlIGRlc2NyaXB0aW9uXG4gKiBAbW9kdWxlIHRzLXdvcmtzcGFjZVxuICovXG5cbi8qKlxuICogQHN1bW1hcnkgTmFtZXNwYWNlIHN1bW1hcnlcbiAqIEBkZXNjcmlwdGlvbiBOYW1lc3BhY2UgZGVzY3JpcHRpb25cbiAqIEBuYW1lc3BhY2UgTmFtZXNwYWNlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnRzLXdvcmtzcGFjZVxuICovXG5cbi8qKlxuICogQHN1bW1hcnkgc3RvcmVzIHRoZSBjdXJyZW50IHBhY2thZ2UgdmVyc2lvblxuICogQGRlc2NyaXB0aW9uIHRoaXMgaXMgaG93IHlvdSBzaG91bGQgZG9jdW1lbnQgYSBjb25zdGFudFxuICogQGNvbnN0IFZFUlNJT05cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dHMtd29ya3NwYWNlXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBOzs7OztBQUtHO01BQ1UsSUFBSSxDQUFBO0FBQWpCLElBQUEsV0FBQSxHQUFBO1FBQ1UsSUFBSyxDQUFBLEtBQUEsR0FBbUIsRUFBRTtRQUMxQixJQUFNLENBQUEsTUFBQSxHQUFHLEtBQUs7O0FBRXRCOzs7QUFHRztJQUNILE1BQU0sT0FBTyxDQUFDLElBQWUsRUFBQTtBQUMzQixRQUFBLE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRTtBQUNwQixRQUFBLElBQUksTUFBVztBQUNmLFFBQUEsSUFBSTtZQUNGLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7O1FBQ3RDLE9BQU8sQ0FBTSxFQUFFO1lBQ2YsSUFBSSxDQUFDLE9BQU8sRUFBRTtBQUNkLFlBQUEsTUFBTSxDQUFDOztRQUVULElBQUksQ0FBQyxPQUFPLEVBQUU7QUFDZCxRQUFBLE9BQU8sTUFBTTs7QUFHZjs7O0FBR0c7QUFDSCxJQUFBLE1BQU0sT0FBTyxHQUFBOztRQUVYLE1BQU0sSUFBSSxHQUFHLElBQUk7QUFDakIsUUFBQSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7QUFDZixZQUFBLE9BQU8sSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7O2FBQzFEO0FBQ0wsWUFBQSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUk7QUFDbEIsWUFBQSxPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUU7OztBQUk1Qjs7QUFFRztJQUNILE9BQU8sR0FBQTs7UUFFTCxNQUFNLElBQUksR0FBRyxJQUFJO1FBQ2pCLE1BQU0sSUFBSSxHQUE2QixJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRTtRQUN6RCxJQUFJLElBQUksRUFBRTtBQUNSLFlBQUEsSUFDRSxPQUFRLFVBQXlDLENBQUMsTUFBTSxLQUFLLFdBQVc7Z0JBRXhFLFVBQVUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDOztBQUMvQixnQkFBQSxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDOzthQUNwQjtBQUNMLFlBQUEsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLOzs7QUFHeEI7O01DNUNZLGNBQWMsQ0FBQTtBQVN6QixJQUFBLFdBQUEsQ0FDRSxPQUFrQixHQUFBLENBQUMsRUFDbkIsT0FBNkIsRUFDN0IsS0FBc0MsRUFBQTtRQVR4QyxJQUFrQixDQUFBLGtCQUFBLEdBQWlCLFNBQVM7QUFJM0IsUUFBQSxJQUFBLENBQUEsSUFBSSxHQUFHLElBQUksSUFBSSxFQUFFO0FBT2hDLFFBQUEsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPO0FBQ3RCLFFBQUEsSUFBSSxDQUFDLG1CQUFtQixHQUFHLEVBQUU7QUFDN0IsUUFBQSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU87QUFDdEIsUUFBQSxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUs7O0FBR3BCOzs7QUFHRztBQUNILElBQUEsTUFBTSxDQUFDLFdBQXdCLEVBQUE7O1FBRTdCLE1BQU0sSUFBSSxHQUFHLElBQUk7UUFDakIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBSztZQUM1QixJQUNFLElBQUksQ0FBQyxrQkFBa0I7Z0JBQ3ZCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLEtBQUssV0FBVyxDQUFDLEVBQUUsRUFDN0M7QUFDQSxnQkFBQSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtBQUNuQixnQkFBQSxPQUFPLFdBQVcsQ0FBQyxJQUFJLEVBQUU7O0FBRzNCLFlBQUEsSUFBSSxJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsRUFBRTtnQkFDcEIsSUFBSSxDQUFDLE9BQU8sRUFBRTtBQUNkLGdCQUFBLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO0FBQ25CLGdCQUFBLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUM7O2lCQUNuQztBQUNMLGdCQUFBLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDO0FBQzFDLGdCQUFBLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFOztBQUV2QixTQUFDLENBQUM7O0FBR0o7Ozs7O0FBS0c7QUFDSyxJQUFBLGVBQWUsQ0FBQyxXQUF3QixFQUFBOztRQUU5QyxNQUFNLElBQUksR0FBRyxJQUFJO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQUs7QUFDNUIsWUFBQSxJQUFJLENBQUMsa0JBQWtCLEdBQUcsV0FBVztBQUNyQyxZQUFBLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ25CLElBQUksSUFBSSxDQUFDLE9BQU87QUFDZCxnQkFBQSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQUs7Ozs7Ozs7b0JBT3ZCLFdBQVcsQ0FBQyxJQUFJLEVBQUU7QUFDcEIsaUJBQUMsQ0FBQztpQkFDQzs7Ozs7OztnQkFPSCxXQUFXLENBQUMsSUFBSSxFQUFFOztBQUV0QixTQUFDLENBQUM7O0FBRUo7O0FBRUc7SUFDSCxNQUFNLE9BQU8sQ0FBQyxHQUFXLEVBQUE7O1FBRXZCLE1BQU0sSUFBSSxHQUFHLElBQUk7QUFDakIsUUFBQSxPQUFPLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxLQUFJO1lBQ25DLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQUs7Z0JBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCO0FBQzFCLG9CQUFBLE9BQU8sQ0FBQyxJQUFJLENBQ1YscUVBQXFFLENBQ3RFOzs7Ozs7QUFNSCxnQkFBQSxJQUFJLENBQUMsa0JBQWtCLEdBQUcsU0FBUztBQUNuQyxnQkFBQSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFFbkIsTUFBTSxpQkFBaUIsR0FBRyxNQUFLO29CQUM3QixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFLO3dCQUM1QixJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFOzRCQUN2QyxNQUFNLFdBQVcsR0FDZixJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxFQUFpQjs0QkFFakQsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQzs7Ozs7OzRCQU9sRCxJQUNFLE9BQVEsVUFBeUMsQ0FBQyxNQUFNO2dDQUN4RCxXQUFXO2dDQUVYLFVBQVUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDOztBQUM3QixnQ0FBQSxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDOzs2QkFDbEI7NEJBQ0wsSUFBSSxDQUFDLE9BQU8sRUFBRTs7QUFFaEIsd0JBQUEsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7QUFDbkIsd0JBQUEsT0FBTyxFQUFFO0FBQ1gscUJBQUMsQ0FBQztBQUNKLGlCQUFDO2dCQUVELElBQUksSUFBSSxDQUFDLEtBQUs7QUFBRSxvQkFBQSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLGlCQUFpQixFQUFFLENBQUM7O0FBQzFELG9CQUFBLGlCQUFpQixFQUFFO0FBQzFCLGFBQUMsQ0FBQztBQUNKLFNBQUMsQ0FBQzs7QUFFTDs7QUNySlksTUFBQSxpQkFBaUIsR0FBMkI7QUFDdkQsSUFBQSxPQUFPLEVBQUUsc0JBQXNCO0FBQy9CLElBQUEsYUFBYSxFQUFFLGVBQWU7OztBQ0YxQixTQUFVLGFBQWEsQ0FBQyxHQUFRLEVBQUE7QUFDcEMsSUFBQSxJQUFJLENBQUMsR0FBRztRQUFFO0lBQ1YsSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRO0FBQUUsUUFBQSxPQUFPLEdBQUc7SUFDdkMsSUFDRSxHQUFHLENBQUMsV0FBVztRQUNmLEdBQUcsQ0FBQyxXQUFXLENBQUMsSUFBSTtBQUNwQixRQUFBLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUU7QUFFM0QsUUFBQSxPQUFPLEdBQUcsQ0FBQyxXQUFXLENBQUMsSUFBSTtBQUM3QixJQUFBLElBQUksT0FBTyxHQUFHLEtBQUssVUFBVSxJQUFJLEdBQUcsQ0FBQyxJQUFJO1FBQUUsT0FBTyxHQUFHLENBQUMsSUFBSTtBQUMxRCxJQUFBLE9BQU8sR0FBRyxDQUFDLFFBQVEsRUFBRTtBQUN2Qjs7QUNBQTs7Ozs7Ozs7Ozs7QUFXRztNQUNVLFdBQVcsQ0FBQTtBQVV0QixJQUFBLFdBQUEsQ0FDRSxNQUFjLEVBQ2QsTUFBZSxFQUNmLE1BQWtCLEVBQ2xCLFFBQWdCLEVBQUE7QUFFaEIsUUFBQSxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUU7QUFDcEIsUUFBQSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU07QUFDcEIsUUFBQSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU07QUFDcEIsUUFBQSxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDbEQsUUFBQSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU07QUFDcEIsUUFBQSxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVE7O0FBRzFCOzs7Ozs7QUFNRztJQUNILE9BQU8sSUFBSSxDQUNULE1BQVcsRUFDWCxjQUFzRCxFQUN0RCxHQUFHLElBQXdCLEVBQUE7QUFFM0IsUUFBQSxNQUFNLFFBQVEsR0FBYSxJQUFJLENBQUMsR0FBRyxFQUFFO0FBQ3JDLFFBQUEsSUFBSSxDQUFDLFFBQVEsSUFBSSxPQUFPLFFBQVEsS0FBSyxVQUFVO0FBQzdDLFlBQUEsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztRQUNyQyxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQVcsRUFBRSxHQUFHLElBQVcsS0FBSTtZQUN6QyxXQUFXLENBQUMsT0FBTztpQkFDaEIsT0FBTyxDQUFDLEdBQUc7QUFDWCxpQkFBQSxJQUFJLENBQUMsTUFBTSxRQUFRLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7QUFDdkMsU0FBQztRQUNELE1BQU0sV0FBVyxHQUFnQixJQUFJLFdBQVcsQ0FDOUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQ3ZCLGNBQWMsQ0FBQyxJQUFJLEdBQUcsYUFBYSxDQUFDLGNBQWMsQ0FBQyxHQUFHLFdBQVcsRUFDakUsTUFBSztBQUNILFlBQUEsT0FBTyxjQUFjLENBQUMsSUFBSSxDQUN4QixXQUFXLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLEVBQ3JDLEdBQUcsSUFBSSxFQUNQLEVBQUUsQ0FDSDtBQUNILFNBQUMsQ0FDRjtRQUNELFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDOztBQUczQzs7O0FBR0c7SUFDSCxPQUFPLE9BQU8sQ0FBQyxJQUFxQixFQUFBO0FBQ2xDLFFBQUEsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJOztBQUdsQjs7QUFFRztBQUNILElBQUEsT0FBTyxPQUFPLEdBQUE7UUFDWixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUk7QUFBRSxZQUFBLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxjQUFjLEVBQUU7UUFDaEQsT0FBTyxJQUFJLENBQUMsSUFBSTs7QUFHbEI7OztBQUdHO0lBQ0gsT0FBTyxNQUFNLENBQUMsV0FBd0IsRUFBQTtRQUNwQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQzs7QUFHM0M7OztBQUdHO0FBQ0gsSUFBQSxhQUFhLE9BQU8sQ0FBQyxHQUFXLEVBQUE7UUFDOUIsT0FBTyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQzs7QUFHM0M7O0FBRUc7SUFDSCxXQUFXLEdBQUE7QUFDVCxRQUFBLE9BQU8sSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLFNBQVM7O0FBR3ZEOzs7QUFHRztBQUNILElBQUEsZUFBZSxDQUFDLGVBQTRCLEVBQUE7O1FBRTFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQztRQUNyQyxlQUFlLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ25FLGVBQWUsQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztBQUNyRSxRQUFBLElBQUksQ0FBQyxNQUFNLEdBQUcsZUFBZSxDQUFDLE1BQU07O0FBR3RDOzs7Ozs7O0FBT0c7QUFDSCxJQUFBLGlCQUFpQixDQUFDLEdBQVEsRUFBQTtBQUN4QixRQUFBLE1BQU0sb0JBQW9CLEdBQUcsaUNBQWlDLENBQzVELEdBQUcsRUFDSCxTQUFTLEVBQ1QsaUJBQWlCLENBQUMsT0FBTyxDQUMxQjtBQUNELFFBQUEsSUFBSSxDQUFDLG9CQUFvQjtBQUFFLFlBQUEsT0FBTyxHQUFHOztRQUVyQyxNQUFNLElBQUksR0FBRyxJQUFJO0FBRWpCLFFBQUEsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FDdEQsQ0FBQyxLQUFVLEVBQUUsQ0FBUyxLQUFJO0FBQ3hCLFlBQUEsSUFDRSxNQUFNLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUU7QUFDbkQsZ0JBQUEsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUMxQixDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxLQUFLLGlCQUFpQixDQUFDLGFBQWEsQ0FDakQ7QUFFRCxnQkFBQSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQVcsS0FDeEIsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxJQUFJLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDbkQsaUJBQUEsSUFBSSxDQUFDLEtBQUssT0FBTyxJQUFJLENBQUMsS0FBSyxhQUFhO2dCQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQzNELGlCQUFBLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssVUFBVTtBQUNuQyxnQkFBQSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxJQUFJLEdBQUcsQ0FBQztBQUM3QyxpQkFBQSxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFO0FBQ3pELGdCQUFBLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxrQkFBa0IsQ0FDeEMsaUJBQWlCLENBQUMsT0FBTyxFQUN6QixHQUFHLENBQUMsQ0FBQyxDQUFDLENBQ1A7QUFDRCxnQkFBQSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFNLEtBQUssQ0FBQyxDQUFDLEdBQUcsS0FBSyxpQkFBaUIsQ0FBQyxhQUFhLENBQUM7QUFDbEUsb0JBQUEsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7O29CQUN0QyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQzs7O2dCQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUV4QixZQUFBLE9BQU8sS0FBSztTQUNiLEVBQ0QsRUFBRSxDQUNIO0FBRUQsUUFBQSxRQUFRLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksR0FBRztBQUN2RCxRQUFBLFFBQVEsQ0FBQyxRQUFRLEdBQUcsTUFDbEIsYUFBYSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDeEMseUJBQXlCO1lBQ3pCLElBQUksQ0FBQyxFQUFFO0FBRVQsUUFBQSxPQUFPLFFBQVE7O0FBR2pCOztBQUVHO0lBQ0gsSUFBSSxHQUFBO1FBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNO0FBQUUsWUFBQSxNQUFNLElBQUksS0FBSyxDQUFDLENBQUEsa0JBQUEsQ0FBb0IsQ0FBQztBQUN2RCxRQUFBLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRTs7QUFHdEI7Ozs7QUFJRztBQUNILElBQUEsUUFBUSxDQUFDLE1BQU0sR0FBRyxJQUFJLEVBQUUsT0FBTyxHQUFHLEtBQUssRUFBQTtBQUNyQyxRQUFBLE9BQU8sR0FBRyxNQUFNLEdBQUcsQ0FBQSxDQUFBLEVBQUksSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLEVBQUUsQ0FBQSxjQUFBLEVBQWlCLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQSxFQUMvRSxPQUFPLEdBQUcsQ0FBd0IscUJBQUEsRUFBQSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBRSxDQUFBLEdBQUcsR0FDNUQsRUFBRTs7QUFHSjs7Ozs7QUFLSztJQUNMLE9BQU8sR0FBRyxDQUFDLEdBQVcsRUFBQTtBQUNwQixRQUFBLE9BQU8saUJBQWlCLENBQUMsT0FBTyxHQUFHLEdBQUc7O0FBRXpDOztBQ2xORDs7Ozs7Ozs7QUFRRztBQUNhLFNBQUEsYUFBYSxDQUFDLEdBQUcsSUFBVyxFQUFBO0FBQzFDLElBQUEsT0FBTyxVQUNMLE1BQVcsRUFDWCxXQUFpQixFQUNqQixVQUErQixFQUFBO0FBRS9CLFFBQUEsSUFBSSxDQUFDLFVBQVU7QUFDYixZQUFBLE1BQU0sSUFBSSxhQUFhLENBQUMsMENBQTBDLENBQUM7QUFDckUsUUFBQSxRQUFRLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FDOUQsTUFBTSxFQUNOLFdBQVcsQ0FDWjtBQUVELFFBQUEsTUFBTSxjQUFjLEdBQUcsVUFBVSxDQUFDLEtBQUs7QUFFdkMsUUFBQSxNQUFNLGFBQWEsR0FBRyxVQUFxQixHQUFHLElBQVcsRUFBQTs7WUFFdkQsTUFBTSxJQUFJLEdBQUcsSUFBSTtZQUNqQixPQUFPLElBQUksT0FBTyxDQUFNLENBQUMsT0FBTyxFQUFFLE1BQU0sS0FBSTtBQUMxQyxnQkFBQSxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQVcsRUFBRSxNQUFZLEtBQUk7b0JBQ3ZDLFdBQVcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQUs7QUFDakMsd0JBQUEsSUFBSSxHQUFHO0FBQUUsNEJBQUEsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDO3dCQUMzQixPQUFPLENBQUMsTUFBTSxDQUFDO0FBQ2pCLHFCQUFDLENBQUM7QUFDSixpQkFBQztBQUVELGdCQUFBLElBQUksV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUU7QUFDOUIsZ0JBQUEsSUFBSSxXQUFXLFlBQVksV0FBVyxFQUFFO0FBQ3RDLG9CQUFBLE1BQU0sa0JBQWtCLEdBQWdCLElBQUksV0FBVyxDQUNyRCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFDckIsV0FBVyxFQUNYLFlBQVc7d0JBQ1Q7NkJBQ0csSUFBSSxDQUFDLGtCQUFrQixDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSTs2QkFDeEQsSUFBSSxDQUFDLE9BQU87NkJBQ1osS0FBSyxDQUFDLE1BQU0sQ0FBQztBQUNsQixxQkFBQyxFQUNELElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxHQUFHLFNBQVMsQ0FDL0I7QUFFRCxvQkFBQSxXQUFXLENBQUMsZUFBZSxDQUFDLGtCQUFrQixDQUFDO29CQUMvQyxXQUFXLENBQUMsSUFBSSxFQUFFOztxQkFDYjtBQUNMLG9CQUFBLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDO0FBQ3pCLG9CQUFBLFdBQVcsR0FBRyxJQUFJLFdBQVcsQ0FDM0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQ3JCLFdBQVcsRUFDWCxNQUFLO3dCQUNIOzZCQUNHLElBQUksQ0FBQyxXQUFXLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJO0FBQ2pELDZCQUFBLElBQUksQ0FBQyxDQUFDLE1BQVcsS0FBSyxFQUFFLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQzs2QkFDM0MsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUNkLHFCQUFDLEVBQ0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLEdBQUcsU0FBUyxDQUMvQjtBQUNELG9CQUFBLFdBQVcsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDOztBQUVuQyxhQUFDLENBQUM7QUFDSixTQUFDO0FBRUQsUUFBQSxNQUFNLENBQUMsY0FBYyxDQUFDLGFBQWEsRUFBRSxNQUFNLEVBQUU7QUFDM0MsWUFBQSxLQUFLLEVBQUUsV0FBVztBQUNuQixTQUFBLENBQUM7QUFDRixRQUFBLFVBQVUsQ0FBQyxLQUFLLEdBQUcsYUFBYTtBQUNsQyxLQUFDO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7OztBQU9HO1NBQ2Esc0JBQXNCLENBQUMsTUFBVyxFQUFFLEdBQUcsSUFBUyxFQUFBO0FBQzlELElBQUEsTUFBTSxJQUFJLEdBQUcsV0FBVyxDQUFDLE9BQU8sRUFBRTtBQUNsQyxJQUFBLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLGtCQUFrQjtBQUNsRCxJQUFBLE9BQU8sTUFBTSxDQUFDLGtCQUFrQixFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQzVDOztBQ2hMQTs7OztBQUlHO0FBRUg7Ozs7O0FBS0c7QUFFSDs7Ozs7QUFLRztBQUNJLE1BQU0sT0FBTyxHQUFHOzs7OyJ9