mobx-keystone-loro 1.0.0

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 (37) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +21 -0
  3. package/README.md +119 -0
  4. package/dist/mobx-keystone-loro.esm.js +957 -0
  5. package/dist/mobx-keystone-loro.esm.mjs +957 -0
  6. package/dist/mobx-keystone-loro.umd.js +957 -0
  7. package/dist/types/binding/LoroTextModel.d.ts +72 -0
  8. package/dist/types/binding/applyLoroEventToMobx.d.ts +9 -0
  9. package/dist/types/binding/applyMobxChangeToLoroObject.d.ts +7 -0
  10. package/dist/types/binding/bindLoroToMobxKeystone.d.ts +33 -0
  11. package/dist/types/binding/convertJsonToLoroData.d.ts +51 -0
  12. package/dist/types/binding/convertLoroDataToJson.d.ts +11 -0
  13. package/dist/types/binding/loroBindingContext.d.ts +39 -0
  14. package/dist/types/binding/loroSnapshotTracking.d.ts +26 -0
  15. package/dist/types/binding/moveWithinArray.d.ts +36 -0
  16. package/dist/types/binding/resolveLoroPath.d.ts +11 -0
  17. package/dist/types/index.d.ts +8 -0
  18. package/dist/types/plainTypes.d.ts +6 -0
  19. package/dist/types/utils/error.d.ts +4 -0
  20. package/dist/types/utils/getOrCreateLoroCollectionAtom.d.ts +7 -0
  21. package/dist/types/utils/isBindableLoroContainer.d.ts +9 -0
  22. package/package.json +92 -0
  23. package/src/binding/LoroTextModel.ts +211 -0
  24. package/src/binding/applyLoroEventToMobx.ts +280 -0
  25. package/src/binding/applyMobxChangeToLoroObject.ts +182 -0
  26. package/src/binding/bindLoroToMobxKeystone.ts +353 -0
  27. package/src/binding/convertJsonToLoroData.ts +315 -0
  28. package/src/binding/convertLoroDataToJson.ts +68 -0
  29. package/src/binding/loroBindingContext.ts +46 -0
  30. package/src/binding/loroSnapshotTracking.ts +36 -0
  31. package/src/binding/moveWithinArray.ts +112 -0
  32. package/src/binding/resolveLoroPath.ts +37 -0
  33. package/src/index.ts +16 -0
  34. package/src/plainTypes.ts +7 -0
  35. package/src/utils/error.ts +12 -0
  36. package/src/utils/getOrCreateLoroCollectionAtom.ts +17 -0
  37. package/src/utils/isBindableLoroContainer.ts +13 -0
@@ -0,0 +1,957 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { LoroMap, LoroMovableList, LoroText, isContainer } from "loro-crdt";
5
+ import { createAtom, computed, remove, action } from "mobx";
6
+ import { createContext, types, getSnapshotModelType, Model, tProp, frozen, getParentToChildPath, modelAction, model, modelSnapshotOutWithMetadata, toFrozenSnapshot, resolvePath, runUnprotected, isModel, isDataModel, modelIdKey, isFrozenSnapshot, getSnapshotModelId, fromSnapshot, frozenKey, DeepChangeType, onGlobalDeepChange, getSnapshot, onDeepChange, onSnapshot, isTreeNode } from "mobx-keystone";
7
+ let nanoid = (size = 21) => crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
8
+ byte &= 63;
9
+ if (byte < 36) {
10
+ id += byte.toString(36);
11
+ } else if (byte < 62) {
12
+ id += (byte - 26).toString(36).toUpperCase();
13
+ } else if (byte > 62) {
14
+ id += "-";
15
+ } else {
16
+ id += "_";
17
+ }
18
+ return id;
19
+ }, "");
20
+ const atomMap = /* @__PURE__ */ new WeakMap();
21
+ function getOrCreateLoroCollectionAtom(collection) {
22
+ let atom = atomMap.get(collection);
23
+ if (!atom) {
24
+ atom = createAtom(`loroCollectionAtom`);
25
+ atomMap.set(collection, atom);
26
+ }
27
+ return atom;
28
+ }
29
+ class MobxKeystoneLoroError extends Error {
30
+ constructor(msg) {
31
+ super(msg);
32
+ Object.setPrototypeOf(this, MobxKeystoneLoroError.prototype);
33
+ }
34
+ }
35
+ function failure(message) {
36
+ throw new MobxKeystoneLoroError(message);
37
+ }
38
+ const loroBindingContext = createContext(void 0);
39
+ function resolveLoroPath(loroObject, path) {
40
+ let currentLoroObject = loroObject;
41
+ path.forEach((pathPart, i) => {
42
+ if (currentLoroObject instanceof LoroMap) {
43
+ getOrCreateLoroCollectionAtom(currentLoroObject).reportObserved();
44
+ const key = String(pathPart);
45
+ currentLoroObject = currentLoroObject.get(key);
46
+ } else if (currentLoroObject instanceof LoroMovableList) {
47
+ getOrCreateLoroCollectionAtom(currentLoroObject).reportObserved();
48
+ const key = Number(pathPart);
49
+ currentLoroObject = currentLoroObject.get(key);
50
+ } else {
51
+ throw failure(
52
+ `LoroMap or LoroMovableList was expected at path ${JSON.stringify(
53
+ path.slice(0, i)
54
+ )} in order to resolve path ${JSON.stringify(path)}, but got ${currentLoroObject} instead`
55
+ );
56
+ }
57
+ });
58
+ return currentLoroObject;
59
+ }
60
+ var __defProp2 = Object.defineProperty;
61
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
62
+ var __decorateClass = (decorators, target, key, kind) => {
63
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
64
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
65
+ if (decorator = decorators[i])
66
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
67
+ if (kind && result) __defProp2(target, key, result);
68
+ return result;
69
+ };
70
+ const loroTextModelId = "mobx-keystone-loro/LoroTextModel";
71
+ let LoroTextModel = class extends Model({
72
+ /**
73
+ * The current delta representing the rich text content.
74
+ * Uses Quill delta format.
75
+ */
76
+ deltaList: tProp(types.frozen(types.unchecked()), () => frozen([]))
77
+ }) {
78
+ constructor() {
79
+ super(...arguments);
80
+ /**
81
+ * Atom that gets changed when the associated Loro text changes.
82
+ */
83
+ __publicField(this, "loroTextChangedAtom", createAtom("loroTextChangedAtom"));
84
+ }
85
+ /**
86
+ * Creates a LoroTextModel with initial text content.
87
+ */
88
+ static withText(text) {
89
+ return new LoroTextModel({
90
+ deltaList: frozen([{ insert: text }])
91
+ });
92
+ }
93
+ /**
94
+ * Creates a LoroTextModel with initial delta.
95
+ */
96
+ static withDelta(delta) {
97
+ return new LoroTextModel({
98
+ deltaList: frozen(delta)
99
+ });
100
+ }
101
+ get loroText() {
102
+ const ctx = loroBindingContext.get(this);
103
+ if ((ctx == null ? void 0 : ctx.boundObject) == null) {
104
+ return void 0;
105
+ }
106
+ try {
107
+ const path = getParentToChildPath(ctx.boundObject, this);
108
+ if (!path) {
109
+ return void 0;
110
+ }
111
+ if (path.length === 0) {
112
+ const loroObject2 = ctx.loroObject;
113
+ if (loroObject2 instanceof LoroText) {
114
+ getOrCreateLoroCollectionAtom(loroObject2).reportObserved();
115
+ return loroObject2;
116
+ }
117
+ return void 0;
118
+ }
119
+ const loroObject = resolveLoroPath(ctx.loroObject, path);
120
+ if (loroObject instanceof LoroText) {
121
+ getOrCreateLoroCollectionAtom(loroObject).reportObserved();
122
+ return loroObject;
123
+ }
124
+ } catch {
125
+ }
126
+ return void 0;
127
+ }
128
+ get text() {
129
+ this.loroTextChangedAtom.reportObserved();
130
+ return this.deltaToText(this.deltaList.data);
131
+ }
132
+ get currentDelta() {
133
+ this.loroTextChangedAtom.reportObserved();
134
+ const loroText = this.loroText;
135
+ if (loroText) {
136
+ try {
137
+ return loroText.toDelta();
138
+ } catch {
139
+ }
140
+ }
141
+ return this.deltaList.data;
142
+ }
143
+ /**
144
+ * Converts delta to plain text.
145
+ */
146
+ deltaToText(delta) {
147
+ let result = "";
148
+ for (const op of delta) {
149
+ if ("insert" in op && typeof op.insert === "string") {
150
+ result += op.insert;
151
+ }
152
+ }
153
+ return result;
154
+ }
155
+ setDelta(delta) {
156
+ this.deltaList = frozen(delta);
157
+ }
158
+ insertText(index, text) {
159
+ const loroText = this.loroText;
160
+ if (loroText) {
161
+ loroText.insert(index, text);
162
+ } else {
163
+ const currentText = this.text;
164
+ const newText = currentText.slice(0, index) + text + currentText.slice(index);
165
+ this.deltaList = frozen([{ insert: newText }]);
166
+ }
167
+ }
168
+ deleteText(index, length) {
169
+ const loroText = this.loroText;
170
+ if (loroText) {
171
+ loroText.delete(index, length);
172
+ } else {
173
+ const currentText = this.text;
174
+ const newText = currentText.slice(0, index) + currentText.slice(index + length);
175
+ this.deltaList = frozen([{ insert: newText }]);
176
+ }
177
+ }
178
+ _updateDeltaFromLoro(delta) {
179
+ this.deltaList = frozen(delta);
180
+ }
181
+ };
182
+ __decorateClass([
183
+ computed
184
+ ], LoroTextModel.prototype, "loroText", 1);
185
+ __decorateClass([
186
+ computed
187
+ ], LoroTextModel.prototype, "text", 1);
188
+ __decorateClass([
189
+ computed
190
+ ], LoroTextModel.prototype, "currentDelta", 1);
191
+ __decorateClass([
192
+ modelAction
193
+ ], LoroTextModel.prototype, "setDelta", 1);
194
+ __decorateClass([
195
+ modelAction
196
+ ], LoroTextModel.prototype, "insertText", 1);
197
+ __decorateClass([
198
+ modelAction
199
+ ], LoroTextModel.prototype, "deleteText", 1);
200
+ __decorateClass([
201
+ modelAction
202
+ ], LoroTextModel.prototype, "_updateDeltaFromLoro", 1);
203
+ LoroTextModel = __decorateClass([
204
+ model(loroTextModelId)
205
+ ], LoroTextModel);
206
+ const loroTextModelType = types.model(LoroTextModel);
207
+ function isLoroTextModelSnapshot(value) {
208
+ return getSnapshotModelType(value) === loroTextModelId;
209
+ }
210
+ function convertLoroDataToJson(value) {
211
+ if (value === null) {
212
+ return null;
213
+ }
214
+ if (typeof value !== "object") {
215
+ if (value === void 0) {
216
+ throw new Error("undefined values are not supported by Loro");
217
+ }
218
+ return value;
219
+ }
220
+ if (isContainer(value)) {
221
+ if (value instanceof LoroMap) {
222
+ const result2 = {};
223
+ for (const [k, v] of value.entries()) {
224
+ result2[k] = convertLoroDataToJson(v);
225
+ }
226
+ return result2;
227
+ }
228
+ if (value instanceof LoroMovableList) {
229
+ const result2 = [];
230
+ for (let i = 0; i < value.length; i++) {
231
+ result2.push(convertLoroDataToJson(value.get(i)));
232
+ }
233
+ return result2;
234
+ }
235
+ if (value instanceof LoroText) {
236
+ const deltas = value.toDelta();
237
+ return modelSnapshotOutWithMetadata(LoroTextModel, {
238
+ deltaList: toFrozenSnapshot(deltas)
239
+ });
240
+ }
241
+ throw failure(`unsupported bindable Loro container type`);
242
+ }
243
+ if (Array.isArray(value)) {
244
+ return value.map((item) => convertLoroDataToJson(item));
245
+ }
246
+ const result = {};
247
+ for (const [k, v] of Object.entries(value)) {
248
+ result[k] = convertLoroDataToJson(v);
249
+ }
250
+ return result;
251
+ }
252
+ function applyLoroEventToMobx(event, loroDoc, boundObject, rootPath, reconciliationMap, newlyInsertedContainers) {
253
+ if (newlyInsertedContainers.has(event.target)) {
254
+ return;
255
+ }
256
+ const eventPath = loroDoc.getPathToContainer(event.target);
257
+ if (!eventPath) {
258
+ return;
259
+ }
260
+ const relativePath = resolveEventPath(eventPath, rootPath);
261
+ if (relativePath === void 0) {
262
+ return;
263
+ }
264
+ const { value: target } = resolvePath(boundObject, relativePath);
265
+ if (!target) {
266
+ throw failure(`cannot resolve path ${JSON.stringify(relativePath)}`);
267
+ }
268
+ runUnprotected(() => {
269
+ const diff = event.diff;
270
+ if (diff.type === "map") {
271
+ applyMapEventToMobx(diff, loroDoc, event.target, target, reconciliationMap);
272
+ } else if (diff.type === "list") {
273
+ applyListEventToMobx(
274
+ diff,
275
+ loroDoc,
276
+ event.target,
277
+ target,
278
+ reconciliationMap,
279
+ newlyInsertedContainers
280
+ );
281
+ } else if (diff.type === "text") {
282
+ applyTextEventToMobx(loroDoc, event.target, target);
283
+ }
284
+ });
285
+ }
286
+ function processDeletedValue(val, reconciliationMap) {
287
+ if (isModel(val) || isDataModel(val)) {
288
+ const id = modelIdKey in val ? val[modelIdKey] : void 0;
289
+ if (id) {
290
+ reconciliationMap.set(id, val);
291
+ }
292
+ }
293
+ }
294
+ function reviveValue(jsonValue, reconciliationMap) {
295
+ if (jsonValue === null || typeof jsonValue !== "object") {
296
+ return jsonValue;
297
+ }
298
+ if (isFrozenSnapshot(jsonValue)) {
299
+ return frozen(jsonValue.data);
300
+ }
301
+ if (reconciliationMap) {
302
+ const modelId = getSnapshotModelId(jsonValue);
303
+ if (modelId) {
304
+ const existing = reconciliationMap.get(modelId);
305
+ if (existing) {
306
+ reconciliationMap.delete(modelId);
307
+ return existing;
308
+ }
309
+ }
310
+ }
311
+ return fromSnapshot(jsonValue);
312
+ }
313
+ function applyMapEventToMobx(diff, loroDoc, containerTarget, target, reconciliationMap) {
314
+ const container = loroDoc.getContainerById(containerTarget);
315
+ if (!container || !(container instanceof LoroMap)) {
316
+ throw failure(`${containerTarget} was not a Loro map`);
317
+ }
318
+ for (const key of Object.keys(diff.updated)) {
319
+ const loroValue = container.get(key);
320
+ if (loroValue === void 0) {
321
+ if (key in target) {
322
+ processDeletedValue(target[key], reconciliationMap);
323
+ if (isModel(target)) {
324
+ remove(target.$, key);
325
+ } else {
326
+ remove(target, key);
327
+ }
328
+ }
329
+ } else {
330
+ if (key in target) {
331
+ processDeletedValue(target[key], reconciliationMap);
332
+ }
333
+ const jsonValue = convertLoroDataToJson(loroValue);
334
+ target[key] = reviveValue(jsonValue, reconciliationMap);
335
+ }
336
+ }
337
+ }
338
+ function applyListEventToMobx(diff, loroDoc, containerTarget, target, reconciliationMap, newlyInsertedContainers) {
339
+ const container = loroDoc.getContainerById(containerTarget);
340
+ if (!container || !(container instanceof LoroMovableList)) {
341
+ throw failure(`${containerTarget} was not a Loro movable list`);
342
+ }
343
+ let currentIndex = 0;
344
+ for (const change of diff.diff) {
345
+ if (change.retain) {
346
+ currentIndex += change.retain;
347
+ }
348
+ if (change.delete) {
349
+ const deletedItems = target.slice(currentIndex, currentIndex + change.delete);
350
+ deletedItems.forEach((item) => {
351
+ processDeletedValue(item, reconciliationMap);
352
+ });
353
+ target.splice(currentIndex, change.delete);
354
+ }
355
+ if (change.insert) {
356
+ const insertedItems = change.insert;
357
+ const values = insertedItems.map((loroValue) => {
358
+ if (isContainer(loroValue)) {
359
+ newlyInsertedContainers.add(loroValue.id);
360
+ collectNestedContainerIds(loroValue, newlyInsertedContainers);
361
+ }
362
+ const jsonValue = convertLoroDataToJson(loroValue);
363
+ return reviveValue(jsonValue, reconciliationMap);
364
+ });
365
+ target.splice(currentIndex, 0, ...values);
366
+ currentIndex += values.length;
367
+ }
368
+ }
369
+ }
370
+ function applyTextEventToMobx(loroDoc, containerTarget, target) {
371
+ const container = loroDoc.getContainerById(containerTarget);
372
+ if (!container || !(container instanceof LoroText)) {
373
+ throw failure(`${containerTarget} was not a Loro text container`);
374
+ }
375
+ if (!("deltaList" in target)) {
376
+ throw failure("target does not have a deltaList property - expected LoroTextModel");
377
+ }
378
+ target.deltaList = frozen(container.toDelta());
379
+ }
380
+ function collectNestedContainerIds(container, containerIds) {
381
+ if (!isContainer(container)) {
382
+ return;
383
+ }
384
+ containerIds.add(container.id);
385
+ if (container instanceof LoroMap) {
386
+ for (const key of Object.keys(container.toJSON())) {
387
+ const value = container.get(key);
388
+ collectNestedContainerIds(value, containerIds);
389
+ }
390
+ }
391
+ if (container instanceof LoroMovableList) {
392
+ for (let i = 0; i < container.length; i++) {
393
+ collectNestedContainerIds(container.get(i), containerIds);
394
+ }
395
+ }
396
+ }
397
+ function resolveEventPath(eventPath, rootPath) {
398
+ if (eventPath.length < rootPath.length) {
399
+ return void 0;
400
+ }
401
+ for (let i = 0; i < rootPath.length; i++) {
402
+ if (eventPath[i] !== rootPath[i]) {
403
+ return void 0;
404
+ }
405
+ }
406
+ return eventPath.slice(rootPath.length);
407
+ }
408
+ function isBindableLoroContainer(value) {
409
+ return value instanceof LoroMap || value instanceof LoroMovableList || value instanceof LoroText;
410
+ }
411
+ const loroContainerToSnapshot = /* @__PURE__ */ new WeakMap();
412
+ function setLoroContainerSnapshot(container, snapshot) {
413
+ loroContainerToSnapshot.set(container, snapshot);
414
+ }
415
+ function isLoroContainerUpToDate(container, snapshot) {
416
+ return loroContainerToSnapshot.get(container) === snapshot;
417
+ }
418
+ function isPlainPrimitive(v) {
419
+ const t = typeof v;
420
+ return t === "string" || t === "number" || t === "boolean" || v === null || v === void 0;
421
+ }
422
+ function isPlainArray(v) {
423
+ return Array.isArray(v);
424
+ }
425
+ function isPlainObject(v) {
426
+ return typeof v === "object" && v !== null && !Array.isArray(v);
427
+ }
428
+ function extractTextDeltaFromSnapshot(delta) {
429
+ if (isFrozenSnapshot(delta)) {
430
+ const data = delta.data;
431
+ if (Array.isArray(data)) {
432
+ return data;
433
+ }
434
+ }
435
+ if (Array.isArray(delta)) {
436
+ return delta;
437
+ }
438
+ return [];
439
+ }
440
+ function applyDeltaToLoroText(text, deltas) {
441
+ let position = 0;
442
+ const markOperations = [];
443
+ for (const delta of deltas) {
444
+ if (delta.insert !== void 0) {
445
+ const content = delta.insert;
446
+ text.insert(position, content);
447
+ if (delta.attributes && Object.keys(delta.attributes).length > 0) {
448
+ markOperations.push({
449
+ start: position,
450
+ end: position + content.length,
451
+ attributes: delta.attributes
452
+ });
453
+ }
454
+ position += content.length;
455
+ } else if (delta.retain) {
456
+ position += delta.retain;
457
+ } else if (delta.delete) {
458
+ text.delete(position, delta.delete);
459
+ }
460
+ }
461
+ for (const op of markOperations) {
462
+ for (const [key, value] of Object.entries(op.attributes)) {
463
+ text.mark({ start: op.start, end: op.end }, key, value);
464
+ }
465
+ }
466
+ }
467
+ function convertJsonToLoroData(v) {
468
+ if (isPlainPrimitive(v)) {
469
+ return v;
470
+ }
471
+ if (isPlainArray(v)) {
472
+ const list = new LoroMovableList();
473
+ applyJsonArrayToLoroMovableList(list, v);
474
+ return list;
475
+ }
476
+ if (isPlainObject(v)) {
477
+ if (v[frozenKey] === true) {
478
+ return v;
479
+ }
480
+ if (isLoroTextModelSnapshot(v)) {
481
+ const text = new LoroText();
482
+ const deltas = extractTextDeltaFromSnapshot(v.deltaList);
483
+ if (deltas.length > 0) {
484
+ applyDeltaToLoroText(text, deltas);
485
+ }
486
+ return text;
487
+ }
488
+ const map = new LoroMap();
489
+ applyJsonObjectToLoroMap(map, v);
490
+ return map;
491
+ }
492
+ throw new Error(`unsupported value type: ${v}`);
493
+ }
494
+ const applyJsonArrayToLoroMovableList = (dest, source, options = {}) => {
495
+ const { mode = "add" } = options;
496
+ if (mode === "add") {
497
+ for (const item of source) {
498
+ const converted = convertJsonToLoroData(item);
499
+ if (isBindableLoroContainer(converted)) {
500
+ dest.pushContainer(converted);
501
+ } else {
502
+ dest.push(converted);
503
+ }
504
+ }
505
+ return;
506
+ }
507
+ if (isLoroContainerUpToDate(dest, source)) {
508
+ return;
509
+ }
510
+ const destLen = dest.length;
511
+ const srcLen = source.length;
512
+ if (destLen > srcLen) {
513
+ dest.delete(srcLen, destLen - srcLen);
514
+ }
515
+ const minLen = Math.min(destLen, srcLen);
516
+ for (let i = 0; i < minLen; i++) {
517
+ const srcItem = source[i];
518
+ const destItem = dest.get(i);
519
+ if (isPlainObject(srcItem) && destItem instanceof LoroMap) {
520
+ applyJsonObjectToLoroMap(destItem, srcItem, options);
521
+ continue;
522
+ }
523
+ if (isPlainArray(srcItem) && destItem instanceof LoroMovableList) {
524
+ applyJsonArrayToLoroMovableList(destItem, srcItem, options);
525
+ continue;
526
+ }
527
+ if (isPlainPrimitive(srcItem) && destItem === srcItem) {
528
+ continue;
529
+ }
530
+ dest.delete(i, 1);
531
+ const converted = convertJsonToLoroData(srcItem);
532
+ if (isBindableLoroContainer(converted)) {
533
+ dest.insertContainer(i, converted);
534
+ } else {
535
+ dest.insert(i, converted);
536
+ }
537
+ }
538
+ for (let i = destLen; i < srcLen; i++) {
539
+ const converted = convertJsonToLoroData(source[i]);
540
+ if (isBindableLoroContainer(converted)) {
541
+ dest.pushContainer(converted);
542
+ } else {
543
+ dest.push(converted);
544
+ }
545
+ }
546
+ setLoroContainerSnapshot(dest, source);
547
+ };
548
+ const applyJsonObjectToLoroMap = (dest, source, options = {}) => {
549
+ const { mode = "add" } = options;
550
+ if (mode === "add") {
551
+ for (const k of Object.keys(source)) {
552
+ const v = source[k];
553
+ if (v !== void 0) {
554
+ const converted = convertJsonToLoroData(v);
555
+ if (isBindableLoroContainer(converted)) {
556
+ dest.setContainer(k, converted);
557
+ } else {
558
+ dest.set(k, converted);
559
+ }
560
+ }
561
+ }
562
+ return;
563
+ }
564
+ if (isLoroContainerUpToDate(dest, source)) {
565
+ return;
566
+ }
567
+ const sourceKeysWithValues = new Set(Object.keys(source).filter((k) => source[k] !== void 0));
568
+ for (const key of dest.keys()) {
569
+ if (!sourceKeysWithValues.has(key)) {
570
+ dest.delete(key);
571
+ }
572
+ }
573
+ for (const k of Object.keys(source)) {
574
+ const v = source[k];
575
+ if (v === void 0) {
576
+ continue;
577
+ }
578
+ const existing = dest.get(k);
579
+ if (isPlainObject(v) && existing instanceof LoroMap) {
580
+ applyJsonObjectToLoroMap(existing, v, options);
581
+ continue;
582
+ }
583
+ if (isPlainArray(v) && existing instanceof LoroMovableList) {
584
+ applyJsonArrayToLoroMovableList(existing, v, options);
585
+ continue;
586
+ }
587
+ if (isPlainPrimitive(v) && existing === v) {
588
+ continue;
589
+ }
590
+ const converted = convertJsonToLoroData(v);
591
+ if (isBindableLoroContainer(converted)) {
592
+ dest.setContainer(k, converted);
593
+ } else {
594
+ dest.set(k, converted);
595
+ }
596
+ }
597
+ setLoroContainerSnapshot(dest, source);
598
+ };
599
+ function convertValue(v) {
600
+ if (v === null || v === void 0 || typeof v !== "object") {
601
+ return v;
602
+ }
603
+ if (Array.isArray(v) && v.length === 0) {
604
+ return new LoroMovableList();
605
+ }
606
+ if (isLoroTextModelSnapshot(v)) {
607
+ return v;
608
+ }
609
+ return convertJsonToLoroData(v);
610
+ }
611
+ function insertIntoList(list, index, value) {
612
+ if (value instanceof LoroMap || value instanceof LoroMovableList || value instanceof LoroText) {
613
+ list.insertContainer(index, value);
614
+ } else if (isLoroTextModelSnapshot(value)) {
615
+ const attachedText = list.insertContainer(index, new LoroText());
616
+ const deltas = extractTextDeltaFromSnapshot(value.deltaList);
617
+ if (deltas.length > 0) {
618
+ applyDeltaToLoroText(attachedText, deltas);
619
+ }
620
+ } else {
621
+ list.insert(index, value);
622
+ }
623
+ }
624
+ function setInMap(map, key, value) {
625
+ if (value === void 0) {
626
+ map.delete(key);
627
+ } else if (value instanceof LoroMap || value instanceof LoroMovableList || value instanceof LoroText) {
628
+ map.setContainer(key, value);
629
+ } else if (isLoroTextModelSnapshot(value)) {
630
+ const attachedText = map.setContainer(key, new LoroText());
631
+ const deltas = extractTextDeltaFromSnapshot(value.deltaList);
632
+ if (deltas.length > 0) {
633
+ applyDeltaToLoroText(attachedText, deltas);
634
+ }
635
+ } else {
636
+ map.set(key, value);
637
+ }
638
+ }
639
+ function applyMobxChangeToLoroObject(change, loroObject) {
640
+ const loroContainer = resolveLoroPath(loroObject, change.path);
641
+ if (!loroContainer) {
642
+ throw failure(
643
+ `cannot apply change to missing Loro container at path: ${JSON.stringify(change.path)}`
644
+ );
645
+ }
646
+ switch (change.type) {
647
+ case "ArrayMove": {
648
+ if (!(loroContainer instanceof LoroMovableList)) {
649
+ throw failure(`ArrayMove change requires a LoroMovableList container`);
650
+ }
651
+ loroContainer.move(change.fromIndex, change.toIndex);
652
+ break;
653
+ }
654
+ case DeepChangeType.ArraySplice: {
655
+ if (!(loroContainer instanceof LoroMovableList)) {
656
+ throw failure(`ArraySplice change requires a LoroMovableList container`);
657
+ }
658
+ if (change.removedValues.length > 0) {
659
+ loroContainer.delete(change.index, change.removedValues.length);
660
+ }
661
+ if (change.addedValues.length > 0) {
662
+ const valuesToInsert = change.addedValues.map(convertValue);
663
+ for (let i = 0; i < valuesToInsert.length; i++) {
664
+ insertIntoList(loroContainer, change.index + i, valuesToInsert[i]);
665
+ }
666
+ }
667
+ break;
668
+ }
669
+ case DeepChangeType.ArrayUpdate: {
670
+ if (!(loroContainer instanceof LoroMovableList)) {
671
+ throw failure(`ArrayUpdate change requires a LoroMovableList container`);
672
+ }
673
+ const converted = convertValue(change.newValue);
674
+ if (converted instanceof LoroMap || converted instanceof LoroMovableList || converted instanceof LoroText) {
675
+ loroContainer.setContainer(change.index, converted);
676
+ } else if (isLoroTextModelSnapshot(converted)) {
677
+ const attachedText = loroContainer.setContainer(change.index, new LoroText());
678
+ const deltas = extractTextDeltaFromSnapshot(converted.deltaList);
679
+ if (deltas.length > 0) {
680
+ applyDeltaToLoroText(attachedText, deltas);
681
+ }
682
+ } else {
683
+ loroContainer.set(change.index, converted);
684
+ }
685
+ break;
686
+ }
687
+ case DeepChangeType.ObjectAdd:
688
+ case DeepChangeType.ObjectUpdate: {
689
+ if (loroContainer instanceof LoroText) {
690
+ if (change.key === "deltaList") {
691
+ const deltas = extractTextDeltaFromSnapshot(change.newValue);
692
+ if (loroContainer.length > 0) {
693
+ loroContainer.delete(0, loroContainer.length);
694
+ }
695
+ if (deltas.length > 0) {
696
+ applyDeltaToLoroText(loroContainer, deltas);
697
+ }
698
+ }
699
+ } else if (loroContainer instanceof LoroMap) {
700
+ const converted = convertValue(change.newValue);
701
+ setInMap(loroContainer, change.key, converted);
702
+ } else {
703
+ throw failure(`ObjectAdd/ObjectUpdate change requires a LoroMap or LoroText container`);
704
+ }
705
+ break;
706
+ }
707
+ case DeepChangeType.ObjectRemove: {
708
+ if (loroContainer instanceof LoroText) ;
709
+ else if (loroContainer instanceof LoroMap) {
710
+ loroContainer.delete(change.key);
711
+ } else {
712
+ throw failure(`ObjectRemove change requires a LoroMap or LoroText container`);
713
+ }
714
+ break;
715
+ }
716
+ default: {
717
+ const _exhaustiveCheck = change;
718
+ throw failure(`unsupported change type: ${_exhaustiveCheck.type}`);
719
+ }
720
+ }
721
+ }
722
+ let activeMoveContext;
723
+ function moveWithinArray(array, fromIndex, toIndex) {
724
+ if (fromIndex < 0 || fromIndex >= array.length) {
725
+ throw new Error(`fromIndex ${fromIndex} is out of bounds (array length: ${array.length})`);
726
+ }
727
+ if (toIndex < 0 || toIndex > array.length) {
728
+ throw new Error(`toIndex ${toIndex} is out of bounds (array length: ${array.length})`);
729
+ }
730
+ if (fromIndex === toIndex) {
731
+ return;
732
+ }
733
+ activeMoveContext = {
734
+ array,
735
+ fromIndex,
736
+ toIndex,
737
+ path: void 0,
738
+ receivedFirstSplice: false
739
+ };
740
+ try {
741
+ const [item] = array.splice(fromIndex, 1);
742
+ const adjustedTarget = toIndex > fromIndex ? toIndex - 1 : toIndex;
743
+ array.splice(adjustedTarget, 0, item);
744
+ } finally {
745
+ activeMoveContext = void 0;
746
+ }
747
+ }
748
+ function processChangeForMove(change) {
749
+ const ctx = activeMoveContext;
750
+ if (!ctx.receivedFirstSplice) {
751
+ ctx.path = change.path;
752
+ ctx.receivedFirstSplice = true;
753
+ return void 0;
754
+ }
755
+ const adjustedToIndex = ctx.toIndex > ctx.fromIndex ? ctx.toIndex - 1 : ctx.toIndex;
756
+ return {
757
+ type: "ArrayMove",
758
+ path: ctx.path,
759
+ fromIndex: ctx.fromIndex,
760
+ toIndex: adjustedToIndex
761
+ };
762
+ }
763
+ function isInMoveContextForArray(array) {
764
+ return activeMoveContext !== void 0 && activeMoveContext.array === array;
765
+ }
766
+ function captureChangeSnapshots(change) {
767
+ if (change.type === DeepChangeType.ArraySplice && change.addedValues.length > 0) {
768
+ const snapshots = change.addedValues.map((v) => isTreeNode(v) ? getSnapshot(v) : v);
769
+ return { ...change, addedValues: snapshots };
770
+ } else if (change.type === DeepChangeType.ArrayUpdate) {
771
+ const snapshot = isTreeNode(change.newValue) ? getSnapshot(change.newValue) : change.newValue;
772
+ return { ...change, newValue: snapshot };
773
+ } else if (change.type === DeepChangeType.ObjectAdd || change.type === DeepChangeType.ObjectUpdate) {
774
+ const snapshot = isTreeNode(change.newValue) ? getSnapshot(change.newValue) : change.newValue;
775
+ return { ...change, newValue: snapshot };
776
+ }
777
+ return change;
778
+ }
779
+ function bindLoroToMobxKeystone({
780
+ loroDoc,
781
+ loroObject,
782
+ mobxKeystoneType
783
+ }) {
784
+ var _a;
785
+ const loroOrigin = `bindLoroToMobxKeystoneTransactionOrigin-${nanoid()}`;
786
+ let applyingLoroChangesToMobxKeystone = 0;
787
+ const bindingContext = {
788
+ loroDoc,
789
+ loroObject,
790
+ mobxKeystoneType,
791
+ loroOrigin,
792
+ boundObject: void 0,
793
+ // not yet created
794
+ get isApplyingLoroChangesToMobxKeystone() {
795
+ return applyingLoroChangesToMobxKeystone > 0;
796
+ }
797
+ };
798
+ const loroJson = convertLoroDataToJson(loroObject);
799
+ let boundObject;
800
+ let hasInitChanges = false;
801
+ const createBoundObject = () => {
802
+ const disposeGlobalListener = onGlobalDeepChange((_target, change) => {
803
+ if (change.isInit) {
804
+ hasInitChanges = true;
805
+ }
806
+ });
807
+ try {
808
+ const result = loroBindingContext.apply(
809
+ () => fromSnapshot(mobxKeystoneType, loroJson),
810
+ bindingContext
811
+ );
812
+ loroBindingContext.set(result, { ...bindingContext, boundObject: result });
813
+ return result;
814
+ } finally {
815
+ disposeGlobalListener();
816
+ }
817
+ };
818
+ boundObject = createBoundObject();
819
+ const rootLoroPath = (_a = loroDoc.getPathToContainer(loroObject.id)) != null ? _a : [];
820
+ const loroSubscribeCb = action((eventBatch) => {
821
+ if (eventBatch.origin === loroOrigin) {
822
+ return;
823
+ }
824
+ const newlyInsertedContainers = /* @__PURE__ */ new Set();
825
+ const reconciliationMap = /* @__PURE__ */ new Map();
826
+ const initChanges = [];
827
+ const disposeGlobalListener = onGlobalDeepChange((target, change) => {
828
+ if (change.isInit) {
829
+ initChanges.push({ target, change: captureChangeSnapshots(change) });
830
+ }
831
+ });
832
+ applyingLoroChangesToMobxKeystone++;
833
+ try {
834
+ try {
835
+ for (const event of eventBatch.events) {
836
+ applyLoroEventToMobx(
837
+ event,
838
+ loroDoc,
839
+ boundObject,
840
+ rootLoroPath,
841
+ reconciliationMap,
842
+ newlyInsertedContainers
843
+ );
844
+ }
845
+ } finally {
846
+ disposeGlobalListener();
847
+ }
848
+ if (initChanges.length > 0) {
849
+ loroDoc.setNextCommitOrigin(loroOrigin);
850
+ for (const { target, change } of initChanges) {
851
+ const pathToTarget = getParentToChildPath(boundObject, target);
852
+ if (pathToTarget !== void 0) {
853
+ const changeWithCorrectPath = {
854
+ ...change,
855
+ path: [...pathToTarget, ...change.path]
856
+ };
857
+ applyMobxChangeToLoroObject(changeWithCorrectPath, loroObject);
858
+ }
859
+ }
860
+ loroDoc.commit();
861
+ }
862
+ if (loroObject instanceof LoroMap || loroObject instanceof LoroMovableList) {
863
+ setLoroContainerSnapshot(loroObject, getSnapshot(boundObject));
864
+ }
865
+ } finally {
866
+ applyingLoroChangesToMobxKeystone--;
867
+ }
868
+ });
869
+ const loroUnsubscribe = loroDoc.subscribe(loroSubscribeCb);
870
+ let pendingChanges = [];
871
+ const disposeOnDeepChange = onDeepChange(boundObject, (change) => {
872
+ if (bindingContext.isApplyingLoroChangesToMobxKeystone) {
873
+ return;
874
+ }
875
+ if (change.isInit) {
876
+ return;
877
+ }
878
+ if (change.type === DeepChangeType.ArraySplice) {
879
+ const resolved = resolvePath(boundObject, change.path);
880
+ if (resolved.resolved && isInMoveContextForArray(resolved.value)) {
881
+ const moveResult = processChangeForMove(change);
882
+ if (moveResult === void 0) {
883
+ return;
884
+ }
885
+ pendingChanges.push(moveResult);
886
+ return;
887
+ }
888
+ }
889
+ pendingChanges.push(captureChangeSnapshots(change));
890
+ });
891
+ const disposeOnSnapshot = onSnapshot(boundObject, () => {
892
+ if (pendingChanges.length === 0) {
893
+ return;
894
+ }
895
+ const changesToApply = pendingChanges;
896
+ pendingChanges = [];
897
+ if (bindingContext.isApplyingLoroChangesToMobxKeystone) {
898
+ return;
899
+ }
900
+ loroDoc.setNextCommitOrigin(loroOrigin);
901
+ for (const change of changesToApply) {
902
+ applyMobxChangeToLoroObject(change, loroObject);
903
+ }
904
+ loroDoc.commit();
905
+ if (loroObject instanceof LoroMap || loroObject instanceof LoroMovableList) {
906
+ setLoroContainerSnapshot(loroObject, getSnapshot(boundObject));
907
+ }
908
+ getOrCreateLoroCollectionAtom(loroObject).reportChanged();
909
+ });
910
+ const finalSnapshot = getSnapshot(boundObject);
911
+ if (hasInitChanges) {
912
+ loroDoc.setNextCommitOrigin(loroOrigin);
913
+ if (loroObject instanceof LoroMap) {
914
+ applyJsonObjectToLoroMap(loroObject, finalSnapshot, { mode: "merge" });
915
+ } else if (loroObject instanceof LoroMovableList) {
916
+ applyJsonArrayToLoroMovableList(loroObject, finalSnapshot, { mode: "merge" });
917
+ } else if (loroObject instanceof LoroText) {
918
+ const snapshot = finalSnapshot;
919
+ if (snapshot.$modelType === loroTextModelId) {
920
+ if (loroObject.length > 0) {
921
+ loroObject.delete(0, loroObject.length);
922
+ }
923
+ const deltas = extractTextDeltaFromSnapshot(snapshot.deltaList);
924
+ if (deltas.length > 0) {
925
+ applyDeltaToLoroText(loroObject, deltas);
926
+ }
927
+ }
928
+ }
929
+ loroDoc.commit();
930
+ }
931
+ if (loroObject instanceof LoroMap || loroObject instanceof LoroMovableList) {
932
+ setLoroContainerSnapshot(loroObject, finalSnapshot);
933
+ }
934
+ const dispose = () => {
935
+ loroUnsubscribe();
936
+ disposeOnDeepChange();
937
+ disposeOnSnapshot();
938
+ };
939
+ return {
940
+ boundObject,
941
+ dispose,
942
+ loroOrigin
943
+ };
944
+ }
945
+ export {
946
+ LoroTextModel,
947
+ MobxKeystoneLoroError,
948
+ applyJsonArrayToLoroMovableList,
949
+ applyJsonObjectToLoroMap,
950
+ bindLoroToMobxKeystone,
951
+ convertJsonToLoroData,
952
+ isLoroTextModelSnapshot,
953
+ loroBindingContext,
954
+ loroTextModelType,
955
+ moveWithinArray
956
+ };
957
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9ieC1rZXlzdG9uZS1sb3JvLmVzbS5tanMiLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9uYW5vaWQvaW5kZXguYnJvd3Nlci5qcyIsIi4uL3NyYy91dGlscy9nZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbS50cyIsIi4uL3NyYy91dGlscy9lcnJvci50cyIsIi4uL3NyYy9iaW5kaW5nL2xvcm9CaW5kaW5nQ29udGV4dC50cyIsIi4uL3NyYy9iaW5kaW5nL3Jlc29sdmVMb3JvUGF0aC50cyIsIi4uL3NyYy9iaW5kaW5nL0xvcm9UZXh0TW9kZWwudHMiLCIuLi9zcmMvYmluZGluZy9jb252ZXJ0TG9yb0RhdGFUb0pzb24udHMiLCIuLi9zcmMvYmluZGluZy9hcHBseUxvcm9FdmVudFRvTW9ieC50cyIsIi4uL3NyYy91dGlscy9pc0JpbmRhYmxlTG9yb0NvbnRhaW5lci50cyIsIi4uL3NyYy9iaW5kaW5nL2xvcm9TbmFwc2hvdFRyYWNraW5nLnRzIiwiLi4vc3JjL2JpbmRpbmcvY29udmVydEpzb25Ub0xvcm9EYXRhLnRzIiwiLi4vc3JjL2JpbmRpbmcvYXBwbHlNb2J4Q2hhbmdlVG9Mb3JvT2JqZWN0LnRzIiwiLi4vc3JjL2JpbmRpbmcvbW92ZVdpdGhpbkFycmF5LnRzIiwiLi4vc3JjL2JpbmRpbmcvYmluZExvcm9Ub01vYnhLZXlzdG9uZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB1cmxBbHBoYWJldCB9IGZyb20gJy4vdXJsLWFscGhhYmV0L2luZGV4LmpzJ1xubGV0IHJhbmRvbSA9IGJ5dGVzID0+IGNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoYnl0ZXMpKVxubGV0IGN1c3RvbVJhbmRvbSA9IChhbHBoYWJldCwgZGVmYXVsdFNpemUsIGdldFJhbmRvbSkgPT4ge1xuICBsZXQgbWFzayA9ICgyIDw8IChNYXRoLmxvZyhhbHBoYWJldC5sZW5ndGggLSAxKSAvIE1hdGguTE4yKSkgLSAxXG4gIGxldCBzdGVwID0gLX4oKDEuNiAqIG1hc2sgKiBkZWZhdWx0U2l6ZSkgLyBhbHBoYWJldC5sZW5ndGgpXG4gIHJldHVybiAoc2l6ZSA9IGRlZmF1bHRTaXplKSA9PiB7XG4gICAgbGV0IGlkID0gJydcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgbGV0IGJ5dGVzID0gZ2V0UmFuZG9tKHN0ZXApXG4gICAgICBsZXQgaiA9IHN0ZXAgfCAwXG4gICAgICB3aGlsZSAoai0tKSB7XG4gICAgICAgIGlkICs9IGFscGhhYmV0W2J5dGVzW2pdICYgbWFza10gfHwgJydcbiAgICAgICAgaWYgKGlkLmxlbmd0aCA9PT0gc2l6ZSkgcmV0dXJuIGlkXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5sZXQgY3VzdG9tQWxwaGFiZXQgPSAoYWxwaGFiZXQsIHNpemUgPSAyMSkgPT5cbiAgY3VzdG9tUmFuZG9tKGFscGhhYmV0LCBzaXplLCByYW5kb20pXG5sZXQgbmFub2lkID0gKHNpemUgPSAyMSkgPT5cbiAgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDhBcnJheShzaXplKSkucmVkdWNlKChpZCwgYnl0ZSkgPT4ge1xuICAgIGJ5dGUgJj0gNjNcbiAgICBpZiAoYnl0ZSA8IDM2KSB7XG4gICAgICBpZCArPSBieXRlLnRvU3RyaW5nKDM2KVxuICAgIH0gZWxzZSBpZiAoYnl0ZSA8IDYyKSB7XG4gICAgICBpZCArPSAoYnl0ZSAtIDI2KS50b1N0cmluZygzNikudG9VcHBlckNhc2UoKVxuICAgIH0gZWxzZSBpZiAoYnl0ZSA+IDYyKSB7XG4gICAgICBpZCArPSAnLSdcbiAgICB9IGVsc2Uge1xuICAgICAgaWQgKz0gJ18nXG4gICAgfVxuICAgIHJldHVybiBpZFxuICB9LCAnJylcbmV4cG9ydCB7IG5hbm9pZCwgY3VzdG9tQWxwaGFiZXQsIGN1c3RvbVJhbmRvbSwgdXJsQWxwaGFiZXQsIHJhbmRvbSB9XG4iLCJpbXBvcnQgeyBjcmVhdGVBdG9tLCB0eXBlIElBdG9tIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHR5cGUgeyBCaW5kYWJsZUxvcm9Db250YWluZXIgfSBmcm9tIFwiLi9pc0JpbmRhYmxlTG9yb0NvbnRhaW5lclwiXG5cbmNvbnN0IGF0b21NYXAgPSBuZXcgV2Vha01hcDxCaW5kYWJsZUxvcm9Db250YWluZXIsIElBdG9tPigpXG5cbi8qKlxuICogR2V0cyBvciBjcmVhdGVzIGEgTW9iWCBhdG9tIGZvciBhIExvcm8gY29sbGVjdGlvbi5cbiAqIFRoaXMgaXMgdXNlZCB0byB0cmFjayByZWFjdGl2aXR5IGZvciBjb21wdXRlZCBwcm9wZXJ0aWVzIHRoYXQgcmVhZCBmcm9tIExvcm8gY29udGFpbmVycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tKGNvbGxlY3Rpb246IEJpbmRhYmxlTG9yb0NvbnRhaW5lcik6IElBdG9tIHtcbiAgbGV0IGF0b20gPSBhdG9tTWFwLmdldChjb2xsZWN0aW9uKVxuICBpZiAoIWF0b20pIHtcbiAgICBhdG9tID0gY3JlYXRlQXRvbShgbG9yb0NvbGxlY3Rpb25BdG9tYClcbiAgICBhdG9tTWFwLnNldChjb2xsZWN0aW9uLCBhdG9tKVxuICB9XG4gIHJldHVybiBhdG9tXG59XG4iLCJleHBvcnQgY2xhc3MgTW9ieEtleXN0b25lTG9yb0Vycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZykge1xuICAgIHN1cGVyKG1zZylcblxuICAgIC8vIFNldCB0aGUgcHJvdG90eXBlIGV4cGxpY2l0bHkgZm9yIGJldHRlciBpbnN0YW5jZW9mIHN1cHBvcnRcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgTW9ieEtleXN0b25lTG9yb0Vycm9yLnByb3RvdHlwZSlcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZmFpbHVyZShtZXNzYWdlOiBzdHJpbmcpOiBuZXZlciB7XG4gIHRocm93IG5ldyBNb2J4S2V5c3RvbmVMb3JvRXJyb3IobWVzc2FnZSlcbn1cbiIsImltcG9ydCB0eXBlIHsgTG9yb0RvYyB9IGZyb20gXCJsb3JvLWNyZHRcIlxuaW1wb3J0IHsgdHlwZSBBbnlUeXBlLCBjcmVhdGVDb250ZXh0IH0gZnJvbSBcIm1vYngta2V5c3RvbmVcIlxuaW1wb3J0IHR5cGUgeyBCaW5kYWJsZUxvcm9Db250YWluZXIgfSBmcm9tIFwiLi4vdXRpbHMvaXNCaW5kYWJsZUxvcm9Db250YWluZXJcIlxuXG4vKipcbiAqIENvbnRleHQgZm9yIHRoZSBMb3JvIGJpbmRpbmcsIHByb3ZpZGluZyBhY2Nlc3MgdG8gdGhlIExvcm8gZG9jdW1lbnRcbiAqIGFuZCBiaW5kaW5nIHN0YXRlIGZyb20gd2l0aGluIG1vYngta2V5c3RvbmUgbW9kZWxzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExvcm9CaW5kaW5nQ29udGV4dCB7XG4gIC8qKlxuICAgKiBUaGUgTG9ybyBkb2N1bWVudCBiZWluZyBib3VuZC5cbiAgICovXG4gIGxvcm9Eb2M6IExvcm9Eb2NcblxuICAvKipcbiAgICogVGhlIHJvb3QgTG9ybyBvYmplY3QgYmVpbmcgYm91bmQuXG4gICAqL1xuICBsb3JvT2JqZWN0OiBCaW5kYWJsZUxvcm9Db250YWluZXJcblxuICAvKipcbiAgICogVGhlIG1vYngta2V5c3RvbmUgbW9kZWwgdHlwZSBiZWluZyB1c2VkLlxuICAgKi9cbiAgbW9ieEtleXN0b25lVHlwZTogQW55VHlwZVxuXG4gIC8qKlxuICAgKiBTdHJpbmcgdXNlZCBhcyBvcmlnaW4gZm9yIExvcm8gdHJhbnNhY3Rpb25zIHRvIGlkZW50aWZ5IGNoYW5nZXNcbiAgICogY29taW5nIGZyb20gbW9ieC1rZXlzdG9uZS5cbiAgICovXG4gIGxvcm9PcmlnaW46IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBUaGUgYm91bmQgbW9ieC1rZXlzdG9uZSBvYmplY3QgKG9uY2UgY3JlYXRlZCkuXG4gICAqL1xuICBib3VuZE9iamVjdDogdW5rbm93blxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGNoYW5nZXMgYXJlIGN1cnJlbnRseSBiZWluZyBhcHBsaWVkIGZyb20gTG9ybyB0byBtb2J4LWtleXN0b25lLlxuICAgKiBVc2VkIHRvIHByZXZlbnQgaW5maW5pdGUgbG9vcHMuXG4gICAqL1xuICBpc0FwcGx5aW5nTG9yb0NoYW5nZXNUb01vYnhLZXlzdG9uZTogYm9vbGVhblxufVxuXG4vKipcbiAqIENvbnRleHQgZm9yIGFjY2Vzc2luZyB0aGUgTG9ybyBiaW5kaW5nIGZyb20gd2l0aGluIG1vYngta2V5c3RvbmUgbW9kZWxzLlxuICovXG5leHBvcnQgY29uc3QgbG9yb0JpbmRpbmdDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxMb3JvQmluZGluZ0NvbnRleHQgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZClcbiIsImltcG9ydCB7IExvcm9NYXAsIExvcm9Nb3ZhYmxlTGlzdCB9IGZyb20gXCJsb3JvLWNyZHRcIlxuaW1wb3J0IHR5cGUgeyBQYXRoIH0gZnJvbSBcIm1vYngta2V5c3RvbmVcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlscy9lcnJvclwiXG5pbXBvcnQgeyBnZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbSB9IGZyb20gXCIuLi91dGlscy9nZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbVwiXG5pbXBvcnQgdHlwZSB7IEJpbmRhYmxlTG9yb0NvbnRhaW5lciB9IGZyb20gXCIuLi91dGlscy9pc0JpbmRhYmxlTG9yb0NvbnRhaW5lclwiXG5cbi8qKlxuICogUmVzb2x2ZXMgYSBwYXRoIHdpdGhpbiBhIExvcm8gb2JqZWN0IHN0cnVjdHVyZS5cbiAqIFJldHVybnMgdGhlIExvcm8gY29udGFpbmVyIGF0IHRoZSBzcGVjaWZpZWQgcGF0aC5cbiAqXG4gKiBAcGFyYW0gbG9yb09iamVjdCBUaGUgcm9vdCBMb3JvIG9iamVjdFxuICogQHBhcmFtIHBhdGggQXJyYXkgb2Yga2V5cy9pbmRpY2VzIHRvIHRyYXZlcnNlXG4gKiBAcmV0dXJucyBUaGUgTG9ybyBjb250YWluZXIgYXQgdGhlIHBhdGhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVMb3JvUGF0aChsb3JvT2JqZWN0OiBCaW5kYWJsZUxvcm9Db250YWluZXIsIHBhdGg6IFBhdGgpOiB1bmtub3duIHtcbiAgbGV0IGN1cnJlbnRMb3JvT2JqZWN0OiB1bmtub3duID0gbG9yb09iamVjdFxuXG4gIHBhdGguZm9yRWFjaCgocGF0aFBhcnQsIGkpID0+IHtcbiAgICBpZiAoY3VycmVudExvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTWFwKSB7XG4gICAgICBnZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbShjdXJyZW50TG9yb09iamVjdCkucmVwb3J0T2JzZXJ2ZWQoKVxuICAgICAgY29uc3Qga2V5ID0gU3RyaW5nKHBhdGhQYXJ0KVxuICAgICAgY3VycmVudExvcm9PYmplY3QgPSBjdXJyZW50TG9yb09iamVjdC5nZXQoa2V5KVxuICAgIH0gZWxzZSBpZiAoY3VycmVudExvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICAgIGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tKGN1cnJlbnRMb3JvT2JqZWN0KS5yZXBvcnRPYnNlcnZlZCgpXG4gICAgICBjb25zdCBrZXkgPSBOdW1iZXIocGF0aFBhcnQpXG4gICAgICBjdXJyZW50TG9yb09iamVjdCA9IGN1cnJlbnRMb3JvT2JqZWN0LmdldChrZXkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IGZhaWx1cmUoXG4gICAgICAgIGBMb3JvTWFwIG9yIExvcm9Nb3ZhYmxlTGlzdCB3YXMgZXhwZWN0ZWQgYXQgcGF0aCAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIHBhdGguc2xpY2UoMCwgaSlcbiAgICAgICAgKX0gaW4gb3JkZXIgdG8gcmVzb2x2ZSBwYXRoICR7SlNPTi5zdHJpbmdpZnkocGF0aCl9LCBidXQgZ290ICR7Y3VycmVudExvcm9PYmplY3R9IGluc3RlYWRgXG4gICAgICApXG4gICAgfVxuICB9KVxuXG4gIHJldHVybiBjdXJyZW50TG9yb09iamVjdFxufVxuIiwiaW1wb3J0IHsgdHlwZSBEZWx0YSwgTG9yb1RleHQgfSBmcm9tIFwibG9yby1jcmR0XCJcclxuaW1wb3J0IHsgY29tcHV0ZWQsIGNyZWF0ZUF0b20gfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7XHJcbiAgZnJvemVuLFxyXG4gIGdldFBhcmVudFRvQ2hpbGRQYXRoLFxyXG4gIGdldFNuYXBzaG90TW9kZWxUeXBlLFxyXG4gIE1vZGVsLFxyXG4gIG1vZGVsLFxyXG4gIG1vZGVsQWN0aW9uLFxyXG4gIHR5cGUgU25hcHNob3RPdXRPZixcclxuICB0UHJvcCxcclxuICB0eXBlcyxcclxufSBmcm9tIFwibW9ieC1rZXlzdG9uZVwiXHJcbmltcG9ydCB7IGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tIH0gZnJvbSBcIi4uL3V0aWxzL2dldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tXCJcclxuaW1wb3J0IHsgbG9yb0JpbmRpbmdDb250ZXh0IH0gZnJvbSBcIi4vbG9yb0JpbmRpbmdDb250ZXh0XCJcclxuaW1wb3J0IHsgcmVzb2x2ZUxvcm9QYXRoIH0gZnJvbSBcIi4vcmVzb2x2ZUxvcm9QYXRoXCJcclxuXHJcbmV4cG9ydCBjb25zdCBsb3JvVGV4dE1vZGVsSWQgPSBcIm1vYngta2V5c3RvbmUtbG9yby9Mb3JvVGV4dE1vZGVsXCJcclxuXHJcbi8qKlxyXG4gKiBUeXBlIGZvciB0aGUgZGVsdGEgc3RvcmVkIGluIHRoZSBtb2RlbC5cclxuICogVXNlcyBRdWlsbCBkZWx0YSBmb3JtYXQ6IGFycmF5IG9mIG9wZXJhdGlvbnMgd2l0aCBpbnNlcnQsIGRlbGV0ZSwgcmV0YWluLlxyXG4gKi9cclxuZXhwb3J0IHR5cGUgTG9yb1RleHREZWx0YUxpc3QgPSBEZWx0YTxzdHJpbmc+W11cclxuXHJcbi8qKlxyXG4gKiBBIG1vYngta2V5c3RvbmUgbW9kZWwgcmVwcmVzZW50aW5nIExvcm8gcmljaCB0ZXh0LlxyXG4gKiBUaGlzIG1vZGVsIHN0b3JlcyB0aGUgY3VycmVudCBkZWx0YSBzdGF0ZSAoUXVpbGwgZm9ybWF0KSBhbmQgc3luY3Mgd2l0aCBMb3JvVGV4dC5cclxuICovXHJcbkBtb2RlbChsb3JvVGV4dE1vZGVsSWQpXHJcbmV4cG9ydCBjbGFzcyBMb3JvVGV4dE1vZGVsIGV4dGVuZHMgTW9kZWwoe1xyXG4gIC8qKlxyXG4gICAqIFRoZSBjdXJyZW50IGRlbHRhIHJlcHJlc2VudGluZyB0aGUgcmljaCB0ZXh0IGNvbnRlbnQuXHJcbiAgICogVXNlcyBRdWlsbCBkZWx0YSBmb3JtYXQuXHJcbiAgICovXHJcbiAgZGVsdGFMaXN0OiB0UHJvcCh0eXBlcy5mcm96ZW4odHlwZXMudW5jaGVja2VkPExvcm9UZXh0RGVsdGFMaXN0PigpKSwgKCkgPT4gZnJvemVuKFtdKSksXHJcbn0pIHtcclxuICAvKipcclxuICAgKiBDcmVhdGVzIGEgTG9yb1RleHRNb2RlbCB3aXRoIGluaXRpYWwgdGV4dCBjb250ZW50LlxyXG4gICAqL1xyXG4gIHN0YXRpYyB3aXRoVGV4dCh0ZXh0OiBzdHJpbmcpOiBMb3JvVGV4dE1vZGVsIHtcclxuICAgIHJldHVybiBuZXcgTG9yb1RleHRNb2RlbCh7XHJcbiAgICAgIGRlbHRhTGlzdDogZnJvemVuKFt7IGluc2VydDogdGV4dCB9XSksXHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhIExvcm9UZXh0TW9kZWwgd2l0aCBpbml0aWFsIGRlbHRhLlxyXG4gICAqL1xyXG4gIHN0YXRpYyB3aXRoRGVsdGEoZGVsdGE6IExvcm9UZXh0RGVsdGFMaXN0KTogTG9yb1RleHRNb2RlbCB7XHJcbiAgICByZXR1cm4gbmV3IExvcm9UZXh0TW9kZWwoe1xyXG4gICAgICBkZWx0YUxpc3Q6IGZyb3plbihkZWx0YSksXHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXRvbSB0aGF0IGdldHMgY2hhbmdlZCB3aGVuIHRoZSBhc3NvY2lhdGVkIExvcm8gdGV4dCBjaGFuZ2VzLlxyXG4gICAqL1xyXG4gIGxvcm9UZXh0Q2hhbmdlZEF0b20gPSBjcmVhdGVBdG9tKFwibG9yb1RleHRDaGFuZ2VkQXRvbVwiKVxyXG5cclxuICAvKipcclxuICAgKiBUaGUgTG9yb1RleHQgb2JqZWN0IHJlcHJlc2VudGVkIGJ5IHRoaXMgbW9ieC1rZXlzdG9uZSBub2RlLCBpZiBib3VuZC5cclxuICAgKiBSZXR1cm5zIHVuZGVmaW5lZCB3aGVuIHRoZSBtb2RlbCBpcyBub3QgcGFydCBvZiBhIGJvdW5kIG9iamVjdCB0cmVlLlxyXG4gICAqL1xyXG4gIEBjb21wdXRlZFxyXG4gIGdldCBsb3JvVGV4dCgpOiBMb3JvVGV4dCB8IHVuZGVmaW5lZCB7XHJcbiAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIGEgYmluZGluZyBjb250ZXh0IGZpcnN0IC0gcmV0dXJuIHVuZGVmaW5lZCBpZiBub3QgYm91bmRcclxuICAgIGNvbnN0IGN0eCA9IGxvcm9CaW5kaW5nQ29udGV4dC5nZXQodGhpcylcclxuICAgIGlmIChjdHg/LmJvdW5kT2JqZWN0ID09IG51bGwpIHtcclxuICAgICAgcmV0dXJuIHVuZGVmaW5lZFxyXG4gICAgfVxyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHBhdGggPSBnZXRQYXJlbnRUb0NoaWxkUGF0aChjdHguYm91bmRPYmplY3QsIHRoaXMpXHJcbiAgICAgIGlmICghcGF0aCkge1xyXG4gICAgICAgIHJldHVybiB1bmRlZmluZWRcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gSWYgdGhpcyBtb2RlbCBJUyB0aGUgYm91bmQgb2JqZWN0LCB0aGUgbG9yb09iamVjdCBpcyB0aGUgTG9yb1RleHRcclxuICAgICAgaWYgKHBhdGgubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgY29uc3QgbG9yb09iamVjdCA9IGN0eC5sb3JvT2JqZWN0XHJcbiAgICAgICAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvVGV4dCkge1xyXG4gICAgICAgICAgZ2V0T3JDcmVhdGVMb3JvQ29sbGVjdGlvbkF0b20obG9yb09iamVjdCkucmVwb3J0T2JzZXJ2ZWQoKVxyXG4gICAgICAgICAgcmV0dXJuIGxvcm9PYmplY3RcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZFxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBPdGhlcndpc2UgcmVzb2x2ZSB0aGUgcGF0aFxyXG4gICAgICBjb25zdCBsb3JvT2JqZWN0ID0gcmVzb2x2ZUxvcm9QYXRoKGN0eC5sb3JvT2JqZWN0LCBwYXRoKVxyXG5cclxuICAgICAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvVGV4dCkge1xyXG4gICAgICAgIGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tKGxvcm9PYmplY3QpLnJlcG9ydE9ic2VydmVkKClcclxuICAgICAgICByZXR1cm4gbG9yb09iamVjdFxyXG4gICAgICB9XHJcbiAgICB9IGNhdGNoIHtcclxuICAgICAgLy8gUGF0aCByZXNvbHV0aW9uIGZhaWxlZCAtIHJldHVybiB1bmRlZmluZWRcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdW5kZWZpbmVkXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBwbGFpbiB0ZXh0IGNvbnRlbnQuXHJcbiAgICogVGhpcyBhbHdheXMgdXNlcyB0aGUgc3RvcmVkIGRlbHRhLCB3aGljaCBpcyBrZXB0IGluIHN5bmMgd2l0aCBMb3JvLlxyXG4gICAqL1xyXG4gIEBjb21wdXRlZFxyXG4gIGdldCB0ZXh0KCk6IHN0cmluZyB7XHJcbiAgICB0aGlzLmxvcm9UZXh0Q2hhbmdlZEF0b20ucmVwb3J0T2JzZXJ2ZWQoKVxyXG5cclxuICAgIC8vIEFsd2F5cyBjb21wdXRlIGZyb20gZGVsdGEgLSBpdCdzIHRoZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIHRoaXMgbW9kZWxcclxuICAgIC8vIFRoZSBkZWx0YSBpcyBrZXB0IGluIHN5bmMgd2l0aCBMb3JvIHZpYSBwYXRjaGVzXHJcbiAgICByZXR1cm4gdGhpcy5kZWx0YVRvVGV4dCh0aGlzLmRlbHRhTGlzdC5kYXRhKVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgY3VycmVudCBkZWx0YSAoUXVpbGwgZm9ybWF0KS5cclxuICAgKi9cclxuICBAY29tcHV0ZWRcclxuICBnZXQgY3VycmVudERlbHRhKCk6IExvcm9UZXh0RGVsdGFMaXN0IHtcclxuICAgIHRoaXMubG9yb1RleHRDaGFuZ2VkQXRvbS5yZXBvcnRPYnNlcnZlZCgpXHJcblxyXG4gICAgLy8gVHJ5IHRvIGdldCBmcm9tIGJvdW5kIExvcm9UZXh0IGZpcnN0XHJcbiAgICBjb25zdCBsb3JvVGV4dCA9IHRoaXMubG9yb1RleHRcclxuICAgIGlmIChsb3JvVGV4dCkge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIHJldHVybiBsb3JvVGV4dC50b0RlbHRhKClcclxuICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgLy8gZmFsbCBiYWNrIHRvIHN0b3JlZCBkZWx0YVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuZGVsdGFMaXN0LmRhdGFcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnZlcnRzIGRlbHRhIHRvIHBsYWluIHRleHQuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBkZWx0YVRvVGV4dChkZWx0YTogTG9yb1RleHREZWx0YUxpc3QpOiBzdHJpbmcge1xyXG4gICAgbGV0IHJlc3VsdCA9IFwiXCJcclxuICAgIGZvciAoY29uc3Qgb3Agb2YgZGVsdGEpIHtcclxuICAgICAgaWYgKFwiaW5zZXJ0XCIgaW4gb3AgJiYgdHlwZW9mIG9wLmluc2VydCA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgIHJlc3VsdCArPSBvcC5pbnNlcnRcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlc3VsdFxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgZGVsdGEuXHJcbiAgICovXHJcbiAgQG1vZGVsQWN0aW9uXHJcbiAgc2V0RGVsdGEoZGVsdGE6IExvcm9UZXh0RGVsdGFMaXN0KTogdm9pZCB7XHJcbiAgICB0aGlzLmRlbHRhTGlzdCA9IGZyb3plbihkZWx0YSlcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluc2VydHMgdGV4dCBhdCB0aGUgc3BlY2lmaWVkIHBvc2l0aW9uLlxyXG4gICAqL1xyXG4gIEBtb2RlbEFjdGlvblxyXG4gIGluc2VydFRleHQoaW5kZXg6IG51bWJlciwgdGV4dDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBsb3JvVGV4dCA9IHRoaXMubG9yb1RleHRcclxuICAgIGlmIChsb3JvVGV4dCkge1xyXG4gICAgICBsb3JvVGV4dC5pbnNlcnQoaW5kZXgsIHRleHQpXHJcbiAgICAgIC8vIFRoZSBiaW5kaW5nIHdpbGwgaGFuZGxlIHN5bmNpbmcgYmFja1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gRmFsbGJhY2s6IG1vZGlmeSBkZWx0YSBkaXJlY3RseVxyXG4gICAgICBjb25zdCBjdXJyZW50VGV4dCA9IHRoaXMudGV4dFxyXG4gICAgICBjb25zdCBuZXdUZXh0ID0gY3VycmVudFRleHQuc2xpY2UoMCwgaW5kZXgpICsgdGV4dCArIGN1cnJlbnRUZXh0LnNsaWNlKGluZGV4KVxyXG4gICAgICB0aGlzLmRlbHRhTGlzdCA9IGZyb3plbihbeyBpbnNlcnQ6IG5ld1RleHQgfV0pXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEZWxldGVzIHRleHQgYXQgdGhlIHNwZWNpZmllZCByYW5nZS5cclxuICAgKi9cclxuICBAbW9kZWxBY3Rpb25cclxuICBkZWxldGVUZXh0KGluZGV4OiBudW1iZXIsIGxlbmd0aDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBjb25zdCBsb3JvVGV4dCA9IHRoaXMubG9yb1RleHRcclxuICAgIGlmIChsb3JvVGV4dCkge1xyXG4gICAgICBsb3JvVGV4dC5kZWxldGUoaW5kZXgsIGxlbmd0aClcclxuICAgICAgLy8gVGhlIGJpbmRpbmcgd2lsbCBoYW5kbGUgc3luY2luZyBiYWNrXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBGYWxsYmFjazogbW9kaWZ5IGRlbHRhIGRpcmVjdGx5XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRUZXh0ID0gdGhpcy50ZXh0XHJcbiAgICAgIGNvbnN0IG5ld1RleHQgPSBjdXJyZW50VGV4dC5zbGljZSgwLCBpbmRleCkgKyBjdXJyZW50VGV4dC5zbGljZShpbmRleCArIGxlbmd0aClcclxuICAgICAgdGhpcy5kZWx0YUxpc3QgPSBmcm96ZW4oW3sgaW5zZXJ0OiBuZXdUZXh0IH1dKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW50ZXJuYWwgYWN0aW9uIHRvIHVwZGF0ZSBkZWx0YSBmcm9tIExvcm8gc3luYy5cclxuICAgKiBAaW50ZXJuYWxcclxuICAgKi9cclxuICBAbW9kZWxBY3Rpb25cclxuICBfdXBkYXRlRGVsdGFGcm9tTG9ybyhkZWx0YTogTG9yb1RleHREZWx0YUxpc3QpOiB2b2lkIHtcclxuICAgIHRoaXMuZGVsdGFMaXN0ID0gZnJvemVuKGRlbHRhKVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFR5cGUgZm9yIExvcm9UZXh0TW9kZWwgZm9yIHVzZSB3aXRoIHRQcm9wLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGxvcm9UZXh0TW9kZWxUeXBlID0gdHlwZXMubW9kZWwoTG9yb1RleHRNb2RlbClcclxuXHJcbi8qKlxyXG4gKiBDaGVja3MgaWYgYSBzbmFwc2hvdCBpcyBhIExvcm9UZXh0TW9kZWwgc25hcHNob3QuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaXNMb3JvVGV4dE1vZGVsU25hcHNob3QodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBTbmFwc2hvdE91dE9mPExvcm9UZXh0TW9kZWw+IHtcclxuICByZXR1cm4gZ2V0U25hcHNob3RNb2RlbFR5cGUodmFsdWUpID09PSBsb3JvVGV4dE1vZGVsSWRcclxufVxyXG4iLCJpbXBvcnQgeyBpc0NvbnRhaW5lciwgTG9yb01hcCwgTG9yb01vdmFibGVMaXN0LCBMb3JvVGV4dCB9IGZyb20gXCJsb3JvLWNyZHRcIlxuaW1wb3J0IHsgbW9kZWxTbmFwc2hvdE91dFdpdGhNZXRhZGF0YSwgdG9Gcm96ZW5TbmFwc2hvdCB9IGZyb20gXCJtb2J4LWtleXN0b25lXCJcbmltcG9ydCB0eXBlIHsgUGxhaW5WYWx1ZSB9IGZyb20gXCIuLi9wbGFpblR5cGVzXCJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHMvZXJyb3JcIlxuaW1wb3J0IHsgdHlwZSBCaW5kYWJsZUxvcm9Db250YWluZXIgfSBmcm9tIFwiLi4vdXRpbHMvaXNCaW5kYWJsZUxvcm9Db250YWluZXJcIlxuaW1wb3J0IHsgTG9yb1RleHRNb2RlbCB9IGZyb20gXCIuL0xvcm9UZXh0TW9kZWxcIlxuXG50eXBlIExvcm9WYWx1ZSA9IEJpbmRhYmxlTG9yb0NvbnRhaW5lciB8IFBsYWluVmFsdWVcblxuLyoqXG4gKiBDb252ZXJ0cyBMb3JvIGRhdGEgdG8gSlNPTi1jb21wYXRpYmxlIGZvcm1hdCBmb3IgbW9ieC1rZXlzdG9uZSBzbmFwc2hvdHMuXG4gKlxuICogQHBhcmFtIHZhbHVlIFRoZSBMb3JvIHZhbHVlIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIEpTT04tY29tcGF0aWJsZSB2YWx1ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29udmVydExvcm9EYXRhVG9Kc29uKHZhbHVlOiBMb3JvVmFsdWUpOiBQbGFpblZhbHVlIHtcbiAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIpIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwidW5kZWZpbmVkIHZhbHVlcyBhcmUgbm90IHN1cHBvcnRlZCBieSBMb3JvXCIpXG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlIGFzIFBsYWluVmFsdWVcbiAgfVxuXG4gIGlmIChpc0NvbnRhaW5lcih2YWx1ZSkpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMb3JvTWFwKSB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIFBsYWluVmFsdWU+ID0ge31cbiAgICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIHZhbHVlLmVudHJpZXMoKSkge1xuICAgICAgICByZXN1bHRba10gPSBjb252ZXJ0TG9yb0RhdGFUb0pzb24odiBhcyBMb3JvVmFsdWUpXG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSB7XG4gICAgICBjb25zdCByZXN1bHQ6IFBsYWluVmFsdWVbXSA9IFtdXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGNvbnZlcnRMb3JvRGF0YVRvSnNvbih2YWx1ZS5nZXQoaSkgYXMgTG9yb1ZhbHVlKSlcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG5cbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMb3JvVGV4dCkge1xuICAgICAgY29uc3QgZGVsdGFzID0gdmFsdWUudG9EZWx0YSgpXG4gICAgICAvLyBSZXR1cm4gYSBMb3JvVGV4dE1vZGVsLWNvbXBhdGlibGUgc25hcHNob3RcbiAgICAgIHJldHVybiBtb2RlbFNuYXBzaG90T3V0V2l0aE1ldGFkYXRhKExvcm9UZXh0TW9kZWwsIHtcbiAgICAgICAgZGVsdGFMaXN0OiB0b0Zyb3plblNuYXBzaG90KGRlbHRhcyksXG4gICAgICB9KSBhcyB1bmtub3duIGFzIFBsYWluVmFsdWVcbiAgICB9XG5cbiAgICB0aHJvdyBmYWlsdXJlKGB1bnN1cHBvcnRlZCBiaW5kYWJsZSBMb3JvIGNvbnRhaW5lciB0eXBlYClcbiAgfVxuXG4gIC8vIFBsYWluIG9iamVjdCBvciBhcnJheVxuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWUubWFwKChpdGVtKSA9PiBjb252ZXJ0TG9yb0RhdGFUb0pzb24oaXRlbSBhcyBMb3JvVmFsdWUpKVxuICB9XG5cbiAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBQbGFpblZhbHVlPiA9IHt9XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHZhbHVlKSkge1xuICAgIHJlc3VsdFtrXSA9IGNvbnZlcnRMb3JvRGF0YVRvSnNvbih2IGFzIExvcm9WYWx1ZSlcbiAgfVxuXG4gIHJldHVybiByZXN1bHRcbn1cbiIsImltcG9ydCB0eXBlIHsgQ29udGFpbmVySUQsIExpc3REaWZmLCBMb3JvRG9jLCBMb3JvRXZlbnQsIE1hcERpZmYgfSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IGlzQ29udGFpbmVyLCBMb3JvTWFwLCBMb3JvTW92YWJsZUxpc3QsIExvcm9UZXh0IH0gZnJvbSBcImxvcm8tY3JkdFwiXG5pbXBvcnQgeyByZW1vdmUgfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQge1xuICBGcm96ZW4sXG4gIGZyb21TbmFwc2hvdCxcbiAgZnJvemVuLFxuICBnZXRTbmFwc2hvdE1vZGVsSWQsXG4gIGlzRGF0YU1vZGVsLFxuICBpc0Zyb3plblNuYXBzaG90LFxuICBpc01vZGVsLFxuICBtb2RlbElkS2V5LFxuICBQYXRoLFxuICByZXNvbHZlUGF0aCxcbiAgcnVuVW5wcm90ZWN0ZWQsXG59IGZyb20gXCJtb2J4LWtleXN0b25lXCJcbmltcG9ydCB0eXBlIHsgUGxhaW5WYWx1ZSB9IGZyb20gXCIuLi9wbGFpblR5cGVzXCJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHMvZXJyb3JcIlxuaW1wb3J0IHsgY29udmVydExvcm9EYXRhVG9Kc29uIH0gZnJvbSBcIi4vY29udmVydExvcm9EYXRhVG9Kc29uXCJcblxuLy8gUmVwcmVzZW50cyB0aGUgbWFwIG9mIHBvdGVudGlhbCBvYmplY3RzIHRvIHJlY29uY2lsZSAoSUQgLT4gT2JqZWN0KVxuZXhwb3J0IHR5cGUgUmVjb25jaWxpYXRpb25NYXAgPSBNYXA8c3RyaW5nLCBvYmplY3Q+XG5cbi8qKlxuICogQXBwbGllcyBhIExvcm8gZXZlbnQgZGlyZWN0bHkgdG8gdGhlIE1vYlggbW9kZWwgdHJlZSB1c2luZyBwcm9wZXIgbXV0YXRpb25zXG4gKiAoc3BsaWNlIGZvciBhcnJheXMsIHByb3BlcnR5IGFzc2lnbm1lbnQgZm9yIG9iamVjdHMpLlxuICogVGhpcyBpcyBtb3JlIGVmZmljaWVudCB0aGFuIGNvbnZlcnRpbmcgdG8gcGF0Y2hlcyBmaXJzdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5TG9yb0V2ZW50VG9Nb2J4KFxuICBldmVudDogTG9yb0V2ZW50LFxuICBsb3JvRG9jOiBMb3JvRG9jLFxuICBib3VuZE9iamVjdDogb2JqZWN0LFxuICByb290UGF0aDogUGF0aCxcbiAgcmVjb25jaWxpYXRpb25NYXA6IFJlY29uY2lsaWF0aW9uTWFwLFxuICBuZXdseUluc2VydGVkQ29udGFpbmVyczogU2V0PENvbnRhaW5lcklEPlxuKTogdm9pZCB7XG4gIC8vIFNraXAgZXZlbnRzIGZvciBjb250YWluZXJzIHRoYXQgd2VyZSBqdXN0IGluc2VydGVkIGFzIHBhcnQgb2YgYW5vdGhlciBjb250YWluZXJcbiAgLy8gVGhlaXIgY29udGVudCBpcyBhbHJlYWR5IGluY2x1ZGVkIGluIHRoZSBwYXJlbnQncyBjb252ZXJ0TG9yb0RhdGFUb0pzb24gY2FsbFxuICBpZiAobmV3bHlJbnNlcnRlZENvbnRhaW5lcnMuaGFzKGV2ZW50LnRhcmdldCkpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIFJlc29sdmUgdGhlIHBhdGggcmVsYXRpdmUgdG8gdGhlIHJvb3RcbiAgY29uc3QgZXZlbnRQYXRoID0gbG9yb0RvYy5nZXRQYXRoVG9Db250YWluZXIoZXZlbnQudGFyZ2V0KVxuICBpZiAoIWV2ZW50UGF0aCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgLy8gU3RyaXAgdGhlIHJvb3QgcGF0aCB0byBnZXQgcmVsYXRpdmUgcGF0aFxuICBjb25zdCByZWxhdGl2ZVBhdGggPSByZXNvbHZlRXZlbnRQYXRoKGV2ZW50UGF0aCwgcm9vdFBhdGgpXG4gIGlmIChyZWxhdGl2ZVBhdGggPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgY29uc3QgeyB2YWx1ZTogdGFyZ2V0IH0gPSByZXNvbHZlUGF0aChib3VuZE9iamVjdCwgcmVsYXRpdmVQYXRoKVxuXG4gIGlmICghdGFyZ2V0KSB7XG4gICAgdGhyb3cgZmFpbHVyZShgY2Fubm90IHJlc29sdmUgcGF0aCAke0pTT04uc3RyaW5naWZ5KHJlbGF0aXZlUGF0aCl9YClcbiAgfVxuXG4gIC8vIFdyYXAgaW4gcnVuVW5wcm90ZWN0ZWQgc2luY2Ugd2UncmUgbW9kaWZ5aW5nIHRoZSB0cmVlIGZyb20gb3V0c2lkZSBhIG1vZGVsIGFjdGlvblxuICBydW5VbnByb3RlY3RlZCgoKSA9PiB7XG4gICAgY29uc3QgZGlmZiA9IGV2ZW50LmRpZmZcbiAgICBpZiAoZGlmZi50eXBlID09PSBcIm1hcFwiKSB7XG4gICAgICBhcHBseU1hcEV2ZW50VG9Nb2J4KGRpZmYsIGxvcm9Eb2MsIGV2ZW50LnRhcmdldCwgdGFyZ2V0LCByZWNvbmNpbGlhdGlvbk1hcClcbiAgICB9IGVsc2UgaWYgKGRpZmYudHlwZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgIGFwcGx5TGlzdEV2ZW50VG9Nb2J4KFxuICAgICAgICBkaWZmLFxuICAgICAgICBsb3JvRG9jLFxuICAgICAgICBldmVudC50YXJnZXQsXG4gICAgICAgIHRhcmdldCxcbiAgICAgICAgcmVjb25jaWxpYXRpb25NYXAsXG4gICAgICAgIG5ld2x5SW5zZXJ0ZWRDb250YWluZXJzXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChkaWZmLnR5cGUgPT09IFwidGV4dFwiKSB7XG4gICAgICBhcHBseVRleHRFdmVudFRvTW9ieChsb3JvRG9jLCBldmVudC50YXJnZXQsIHRhcmdldClcbiAgICB9XG4gIH0pXG59XG5cbmZ1bmN0aW9uIHByb2Nlc3NEZWxldGVkVmFsdWUodmFsOiB1bmtub3duLCByZWNvbmNpbGlhdGlvbk1hcDogUmVjb25jaWxpYXRpb25NYXApIHtcbiAgLy8gSGFuZGxlIGJvdGggTW9kZWwgYW5kIERhdGFNb2RlbCBpbnN0YW5jZXNcbiAgaWYgKGlzTW9kZWwodmFsKSB8fCBpc0RhdGFNb2RlbCh2YWwpKSB7XG4gICAgY29uc3QgaWQgPSBtb2RlbElkS2V5IGluIHZhbCA/IHZhbFttb2RlbElkS2V5XSA6IHVuZGVmaW5lZFxuICAgIGlmIChpZCkge1xuICAgICAgcmVjb25jaWxpYXRpb25NYXAuc2V0KGlkLCB2YWwpXG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHJldml2ZVZhbHVlKGpzb25WYWx1ZTogdW5rbm93biwgcmVjb25jaWxpYXRpb25NYXA6IFJlY29uY2lsaWF0aW9uTWFwKTogdW5rbm93biB7XG4gIC8vIEhhbmRsZSBwcmltaXRpdmVzXG4gIGlmIChqc29uVmFsdWUgPT09IG51bGwgfHwgdHlwZW9mIGpzb25WYWx1ZSAhPT0gXCJvYmplY3RcIikge1xuICAgIHJldHVybiBqc29uVmFsdWVcbiAgfVxuXG4gIC8vIEhhbmRsZSBmcm96ZW5cbiAgaWYgKGlzRnJvemVuU25hcHNob3QoanNvblZhbHVlKSkge1xuICAgIHJldHVybiBmcm96ZW4oanNvblZhbHVlLmRhdGEpXG4gIH1cblxuICAvLyBJZiB3ZSBoYXZlIGEgcmVjb25jaWxpYXRpb24gbWFwIGFuZCB0aGUgdmFsdWUgbG9va3MgbGlrZSBhIG1vZGVsIHdpdGggYW4gSUQsIGNoZWNrIGlmIHdlIGhhdmUgaXRcbiAgaWYgKHJlY29uY2lsaWF0aW9uTWFwKSB7XG4gICAgY29uc3QgbW9kZWxJZCA9IGdldFNuYXBzaG90TW9kZWxJZChqc29uVmFsdWUpXG4gICAgaWYgKG1vZGVsSWQpIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nID0gcmVjb25jaWxpYXRpb25NYXAuZ2V0KG1vZGVsSWQpXG4gICAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgICAgcmVjb25jaWxpYXRpb25NYXAuZGVsZXRlKG1vZGVsSWQpXG4gICAgICAgIHJldHVybiBleGlzdGluZ1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmcm9tU25hcHNob3QoanNvblZhbHVlKVxufVxuXG5mdW5jdGlvbiBhcHBseU1hcEV2ZW50VG9Nb2J4KFxuICBkaWZmOiBNYXBEaWZmLFxuICBsb3JvRG9jOiBMb3JvRG9jLFxuICBjb250YWluZXJUYXJnZXQ6IENvbnRhaW5lcklELFxuICB0YXJnZXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICByZWNvbmNpbGlhdGlvbk1hcDogUmVjb25jaWxpYXRpb25NYXBcbik6IHZvaWQge1xuICBjb25zdCBjb250YWluZXIgPSBsb3JvRG9jLmdldENvbnRhaW5lckJ5SWQoY29udGFpbmVyVGFyZ2V0KVxuXG4gIGlmICghY29udGFpbmVyIHx8ICEoY29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01hcCkpIHtcbiAgICB0aHJvdyBmYWlsdXJlKGAke2NvbnRhaW5lclRhcmdldH0gd2FzIG5vdCBhIExvcm8gbWFwYClcbiAgfVxuXG4gIC8vIFByb2Nlc3MgYWRkaXRpb25zIGFuZCB1cGRhdGVzIGZyb20gZGlmZi51cGRhdGVkXG4gIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGRpZmYudXBkYXRlZCkpIHtcbiAgICBjb25zdCBsb3JvVmFsdWUgPSBjb250YWluZXIuZ2V0KGtleSlcblxuICAgIGlmIChsb3JvVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gS2V5IHdhcyBkZWxldGVkIChMb3JvIHJldHVybnMgdW5kZWZpbmVkIGZvciBkZWxldGVkIGtleXMpXG4gICAgICBpZiAoa2V5IGluIHRhcmdldCkge1xuICAgICAgICBwcm9jZXNzRGVsZXRlZFZhbHVlKHRhcmdldFtrZXldLCByZWNvbmNpbGlhdGlvbk1hcClcbiAgICAgICAgLy8gVXNlIE1vYlgncyByZW1vdmUgdG8gcHJvcGVybHkgZGVsZXRlIHRoZSBrZXkgZnJvbSB0aGUgb2JzZXJ2YWJsZSBvYmplY3RcbiAgICAgICAgaWYgKGlzTW9kZWwodGFyZ2V0KSkge1xuICAgICAgICAgIHJlbW92ZSh0YXJnZXQuJCwga2V5KVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlbW92ZSh0YXJnZXQsIGtleSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBLZXkgd2FzIGFkZGVkIG9yIHVwZGF0ZWRcbiAgICAgIGlmIChrZXkgaW4gdGFyZ2V0KSB7XG4gICAgICAgIHByb2Nlc3NEZWxldGVkVmFsdWUodGFyZ2V0W2tleV0sIHJlY29uY2lsaWF0aW9uTWFwKVxuICAgICAgfVxuICAgICAgY29uc3QganNvblZhbHVlID0gY29udmVydExvcm9EYXRhVG9Kc29uKGxvcm9WYWx1ZSBhcyBQbGFpblZhbHVlKVxuICAgICAgdGFyZ2V0W2tleV0gPSByZXZpdmVWYWx1ZShqc29uVmFsdWUsIHJlY29uY2lsaWF0aW9uTWFwKVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBhcHBseUxpc3RFdmVudFRvTW9ieChcbiAgZGlmZjogTGlzdERpZmYsXG4gIGxvcm9Eb2M6IExvcm9Eb2MsXG4gIGNvbnRhaW5lclRhcmdldDogQ29udGFpbmVySUQsXG4gIHRhcmdldDogdW5rbm93bltdLFxuICByZWNvbmNpbGlhdGlvbk1hcDogUmVjb25jaWxpYXRpb25NYXAsXG4gIG5ld2x5SW5zZXJ0ZWRDb250YWluZXJzOiBTZXQ8Q29udGFpbmVySUQ+XG4pOiB2b2lkIHtcbiAgY29uc3QgY29udGFpbmVyID0gbG9yb0RvYy5nZXRDb250YWluZXJCeUlkKGNvbnRhaW5lclRhcmdldClcblxuICBpZiAoIWNvbnRhaW5lciB8fCAhKGNvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9Nb3ZhYmxlTGlzdCkpIHtcbiAgICB0aHJvdyBmYWlsdXJlKGAke2NvbnRhaW5lclRhcmdldH0gd2FzIG5vdCBhIExvcm8gbW92YWJsZSBsaXN0YClcbiAgfVxuXG4gIC8vIFByb2Nlc3MgZGVsdGEgb3BlcmF0aW9ucyBpbiBvcmRlclxuICBsZXQgY3VycmVudEluZGV4ID0gMFxuXG4gIGZvciAoY29uc3QgY2hhbmdlIG9mIGRpZmYuZGlmZikge1xuICAgIGlmIChjaGFuZ2UucmV0YWluKSB7XG4gICAgICBjdXJyZW50SW5kZXggKz0gY2hhbmdlLnJldGFpblxuICAgIH1cblxuICAgIGlmIChjaGFuZ2UuZGVsZXRlKSB7XG4gICAgICAvLyBDYXB0dXJlIGRlbGV0ZWQgaXRlbXMgZm9yIHJlY29uY2lsaWF0aW9uXG4gICAgICBjb25zdCBkZWxldGVkSXRlbXMgPSB0YXJnZXQuc2xpY2UoY3VycmVudEluZGV4LCBjdXJyZW50SW5kZXggKyBjaGFuZ2UuZGVsZXRlKVxuICAgICAgZGVsZXRlZEl0ZW1zLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgcHJvY2Vzc0RlbGV0ZWRWYWx1ZShpdGVtLCByZWNvbmNpbGlhdGlvbk1hcClcbiAgICAgIH0pXG5cbiAgICAgIC8vIERlbGV0ZSBpdGVtcyBhdCBjdXJyZW50IHBvc2l0aW9uXG4gICAgICB0YXJnZXQuc3BsaWNlKGN1cnJlbnRJbmRleCwgY2hhbmdlLmRlbGV0ZSlcbiAgICB9XG5cbiAgICBpZiAoY2hhbmdlLmluc2VydCkge1xuICAgICAgLy8gSW5zZXJ0IGl0ZW1zIGF0IGN1cnJlbnQgcG9zaXRpb25cbiAgICAgIGNvbnN0IGluc2VydGVkSXRlbXMgPSBjaGFuZ2UuaW5zZXJ0XG4gICAgICBjb25zdCB2YWx1ZXMgPSBpbnNlcnRlZEl0ZW1zLm1hcCgobG9yb1ZhbHVlKSA9PiB7XG4gICAgICAgIC8vIFRyYWNrIGNvbnRhaW5lciBJRHMgdG8gYXZvaWQgZG91YmxlLXByb2Nlc3NpbmcgdGhlaXIgZXZlbnRzXG4gICAgICAgIC8vIFdoZW4gYSBjb250YWluZXIgd2l0aCBkYXRhIGlzIGluc2VydGVkLCBMb3JvIGZpcmVzIGV2ZW50cyBmb3IgYm90aFxuICAgICAgICAvLyB0aGUgY29udGFpbmVyIGluc2VydCBhbmQgdGhlIGNvbnRhaW5lcidzIGNvbnRlbnQsIGJ1dCB0aGUgY29udGVudFxuICAgICAgICAvLyBpcyBhbHJlYWR5IGluY2x1ZGVkIGluIGNvbnZlcnRMb3JvRGF0YVRvSnNvblxuICAgICAgICBpZiAoaXNDb250YWluZXIobG9yb1ZhbHVlKSkge1xuICAgICAgICAgIG5ld2x5SW5zZXJ0ZWRDb250YWluZXJzLmFkZChsb3JvVmFsdWUuaWQpXG4gICAgICAgICAgLy8gQWxzbyByZWN1cnNpdmVseSB0cmFjayBhbnkgbmVzdGVkIGNvbnRhaW5lcnNcbiAgICAgICAgICBjb2xsZWN0TmVzdGVkQ29udGFpbmVySWRzKGxvcm9WYWx1ZSwgbmV3bHlJbnNlcnRlZENvbnRhaW5lcnMpXG4gICAgICAgIH1cbiAgICAgICAgY29uc3QganNvblZhbHVlID0gY29udmVydExvcm9EYXRhVG9Kc29uKGxvcm9WYWx1ZSBhcyBQbGFpblZhbHVlKVxuICAgICAgICByZXR1cm4gcmV2aXZlVmFsdWUoanNvblZhbHVlLCByZWNvbmNpbGlhdGlvbk1hcClcbiAgICAgIH0pXG5cbiAgICAgIHRhcmdldC5zcGxpY2UoY3VycmVudEluZGV4LCAwLCAuLi52YWx1ZXMpXG4gICAgICBjdXJyZW50SW5kZXggKz0gdmFsdWVzLmxlbmd0aFxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBhcHBseVRleHRFdmVudFRvTW9ieChcbiAgbG9yb0RvYzogTG9yb0RvYyxcbiAgY29udGFpbmVyVGFyZ2V0OiBDb250YWluZXJJRCxcbiAgdGFyZ2V0OiB7IGRlbHRhTGlzdD86IEZyb3plbjx1bmtub3duW10+IH1cbik6IHZvaWQge1xuICBjb25zdCBjb250YWluZXIgPSBsb3JvRG9jLmdldENvbnRhaW5lckJ5SWQoY29udGFpbmVyVGFyZ2V0KVxuXG4gIGlmICghY29udGFpbmVyIHx8ICEoY29udGFpbmVyIGluc3RhbmNlb2YgTG9yb1RleHQpKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgJHtjb250YWluZXJUYXJnZXR9IHdhcyBub3QgYSBMb3JvIHRleHQgY29udGFpbmVyYClcbiAgfVxuXG4gIC8vIExvcm9UZXh0TW9kZWwgaGFzIGRlbHRhTGlzdCBhcyBhIHNpbmdsZSBGcm96ZW48TG9yb1RleHREZWx0YUxpc3Q+LCBub3QgYW4gYXJyYXlcbiAgLy8gUmVwbGFjZSBpdCB3aXRoIHRoZSBjdXJyZW50IGRlbHRhIGZyb20gdGhlIExvcm9UZXh0XG4gIGlmICghKFwiZGVsdGFMaXN0XCIgaW4gdGFyZ2V0KSkge1xuICAgIHRocm93IGZhaWx1cmUoXCJ0YXJnZXQgZG9lcyBub3QgaGF2ZSBhIGRlbHRhTGlzdCBwcm9wZXJ0eSAtIGV4cGVjdGVkIExvcm9UZXh0TW9kZWxcIilcbiAgfVxuICB0YXJnZXQuZGVsdGFMaXN0ID0gZnJvemVuKGNvbnRhaW5lci50b0RlbHRhKCkpXG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgY29sbGVjdHMgYWxsIGNvbnRhaW5lciBJRHMgZnJvbSBhIExvcm8gY29udGFpbmVyLlxuICogVGhpcyBpcyB1c2VkIHRvIHRyYWNrIGNvbnRhaW5lcnMgdGhhdCBoYXZlIGJlZW4gaW5zZXJ0ZWQgYW5kIHNob3VsZCBub3RcbiAqIGhhdmUgdGhlaXIgZXZlbnRzIHByb2Nlc3NlZCBhZ2FpbiAoc2luY2UgdGhlaXIgY29udGVudCB3YXMgYWxyZWFkeSBpbmNsdWRlZFxuICogaW4gdGhlIHBhcmVudCdzIGNvbnZlcnRMb3JvRGF0YVRvSnNvbiBjYWxsKS5cbiAqL1xuZnVuY3Rpb24gY29sbGVjdE5lc3RlZENvbnRhaW5lcklkcyhjb250YWluZXI6IHVua25vd24sIGNvbnRhaW5lcklkczogU2V0PENvbnRhaW5lcklEPik6IHZvaWQge1xuICBpZiAoIWlzQ29udGFpbmVyKGNvbnRhaW5lcikpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIEFkZCB0aGlzIGNvbnRhaW5lcidzIElEXG4gIGNvbnRhaW5lcklkcy5hZGQoY29udGFpbmVyLmlkKVxuXG4gIC8vIEhhbmRsZSBMb3JvTWFwIC0gaXRlcmF0ZSBvdmVyIHZhbHVlc1xuICBpZiAoY29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01hcCkge1xuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGNvbnRhaW5lci50b0pTT04oKSkpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udGFpbmVyLmdldChrZXkpXG4gICAgICBjb2xsZWN0TmVzdGVkQ29udGFpbmVySWRzKHZhbHVlLCBjb250YWluZXJJZHMpXG4gICAgfVxuICB9XG5cbiAgLy8gSGFuZGxlIExvcm9Nb3ZhYmxlTGlzdCAtIGl0ZXJhdGUgb3ZlciBpdGVtc1xuICBpZiAoY29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb250YWluZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbGxlY3ROZXN0ZWRDb250YWluZXJJZHMoY29udGFpbmVyLmdldChpKSwgY29udGFpbmVySWRzKVxuICAgIH1cbiAgfVxuXG4gIC8vIExvcm9UZXh0IGRvZXNuJ3QgY29udGFpbiBuZXN0ZWQgY29udGFpbmVyc1xufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBwYXRoIGZyb20gYSBMb3JvIGV2ZW50IHRvIGEgbW9ieC1rZXlzdG9uZSBwYXRoLlxuICogVGhlIGV2ZW50IHBhdGggaXMgdGhlIHBhdGggZnJvbSB0aGUgZG9jIHJvb3QgdG8gdGhlIGNvbnRhaW5lciB0aGF0IGVtaXR0ZWQgdGhlIGV2ZW50LlxuICogV2UgbmVlZCB0byBzdHJpcCB0aGUgcGF0aCBvZiBvdXIgcm9vdCBjb250YWluZXIgdG8gZ2V0IGEgcGF0aCByZWxhdGl2ZSB0byBvdXIgYm91bmQgb2JqZWN0LlxuICovXG5mdW5jdGlvbiByZXNvbHZlRXZlbnRQYXRoKGV2ZW50UGF0aDogUGF0aCwgcm9vdFBhdGg6IFBhdGgpOiBQYXRoIHwgdW5kZWZpbmVkIHtcbiAgaWYgKGV2ZW50UGF0aC5sZW5ndGggPCByb290UGF0aC5sZW5ndGgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHJvb3RQYXRoLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGV2ZW50UGF0aFtpXSAhPT0gcm9vdFBhdGhbaV0pIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZXZlbnRQYXRoLnNsaWNlKHJvb3RQYXRoLmxlbmd0aCkgYXMgUGF0aFxufVxuIiwiaW1wb3J0IHsgTG9yb01hcCwgTG9yb01vdmFibGVMaXN0LCBMb3JvVGV4dCB9IGZyb20gXCJsb3JvLWNyZHRcIlxuXG4vKipcbiAqIEEgYmluZGFibGUgTG9ybyBjb250YWluZXIgKE1hcCwgTW92YWJsZUxpc3QsIG9yIFRleHQpLlxuICovXG5leHBvcnQgdHlwZSBCaW5kYWJsZUxvcm9Db250YWluZXIgPSBMb3JvTWFwIHwgTG9yb01vdmFibGVMaXN0IHwgTG9yb1RleHRcblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhIGJpbmRhYmxlIExvcm8gY29udGFpbmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNCaW5kYWJsZUxvcm9Db250YWluZXIodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBCaW5kYWJsZUxvcm9Db250YWluZXIge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBMb3JvTWFwIHx8IHZhbHVlIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0IHx8IHZhbHVlIGluc3RhbmNlb2YgTG9yb1RleHRcbn1cbiIsImltcG9ydCB0eXBlIHsgTG9yb01hcCwgTG9yb01vdmFibGVMaXN0IH0gZnJvbSBcImxvcm8tY3JkdFwiXG5cbnR5cGUgTG9yb0NvbnRhaW5lciA9IExvcm9NYXAgfCBMb3JvTW92YWJsZUxpc3RcblxuLyoqXG4gKiBXZWFrTWFwIHRoYXQgdHJhY2tzIHdoaWNoIHNuYXBzaG90IGVhY2ggTG9ybyBjb250YWluZXIgd2FzIGxhc3Qgc3luY2VkIGZyb20uXG4gKiBUaGlzIGlzIHVzZWQgZHVyaW5nIHJlY29uY2lsaWF0aW9uIHRvIHNraXAgY29udGFpbmVycyB0aGF0IGFyZSBhbHJlYWR5IHVwLXRvLWRhdGUuXG4gKlxuICogVGhlIGtleSBpcyB0aGUgTG9ybyBjb250YWluZXIgKExvcm9NYXAgb3IgTG9yb01vdmFibGVMaXN0KS5cbiAqIFRoZSB2YWx1ZSBpcyB0aGUgc25hcHNob3QgKHBsYWluIG9iamVjdCBvciBhcnJheSkgdGhhdCB3YXMgbGFzdCBzeW5jZWQgdG8gaXQuXG4gKi9cbmV4cG9ydCBjb25zdCBsb3JvQ29udGFpbmVyVG9TbmFwc2hvdCA9IG5ldyBXZWFrTWFwPExvcm9Db250YWluZXIsIHVua25vd24+KClcblxuLyoqXG4gKiBVcGRhdGVzIHRoZSBzbmFwc2hvdCB0cmFja2luZyBmb3IgYSBMb3JvIGNvbnRhaW5lci5cbiAqIENhbGwgdGhpcyBhZnRlciBzeW5jaW5nIGEgc25hcHNob3QgdG8gYSBMb3JvIGNvbnRhaW5lci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldExvcm9Db250YWluZXJTbmFwc2hvdChjb250YWluZXI6IExvcm9Db250YWluZXIsIHNuYXBzaG90OiB1bmtub3duKTogdm9pZCB7XG4gIGxvcm9Db250YWluZXJUb1NuYXBzaG90LnNldChjb250YWluZXIsIHNuYXBzaG90KVxufVxuXG4vKipcbiAqIEdldHMgdGhlIGxhc3Qgc3luY2VkIHNuYXBzaG90IGZvciBhIExvcm8gY29udGFpbmVyLlxuICogUmV0dXJucyB1bmRlZmluZWQgaWYgdGhlIGNvbnRhaW5lciBoYXMgbmV2ZXIgYmVlbiBzeW5jZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb3JvQ29udGFpbmVyU25hcHNob3QoY29udGFpbmVyOiBMb3JvQ29udGFpbmVyKTogdW5rbm93biB7XG4gIHJldHVybiBsb3JvQ29udGFpbmVyVG9TbmFwc2hvdC5nZXQoY29udGFpbmVyKVxufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIExvcm8gY29udGFpbmVyIGlzIHVwLXRvLWRhdGUgd2l0aCB0aGUgZ2l2ZW4gc25hcHNob3QuXG4gKiBVc2VzIHJlZmVyZW5jZSBlcXVhbGl0eSB0byBjaGVjayBpZiB0aGUgc25hcHNob3QgaXMgdGhlIHNhbWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0xvcm9Db250YWluZXJVcFRvRGF0ZShjb250YWluZXI6IExvcm9Db250YWluZXIsIHNuYXBzaG90OiB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiBsb3JvQ29udGFpbmVyVG9TbmFwc2hvdC5nZXQoY29udGFpbmVyKSA9PT0gc25hcHNob3Rcbn1cbiIsImltcG9ydCB0eXBlIHsgRGVsdGEgfSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IExvcm9NYXAsIExvcm9Nb3ZhYmxlTGlzdCwgTG9yb1RleHQgfSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IGZyb3plbktleSwgaXNGcm96ZW5TbmFwc2hvdCB9IGZyb20gXCJtb2J4LWtleXN0b25lXCJcbmltcG9ydCB0eXBlIHsgUGxhaW5BcnJheSwgUGxhaW5PYmplY3QsIFBsYWluUHJpbWl0aXZlLCBQbGFpblZhbHVlIH0gZnJvbSBcIi4uL3BsYWluVHlwZXNcIlxuaW1wb3J0IHtcbiAgdHlwZSBCaW5kYWJsZUxvcm9Db250YWluZXIsXG4gIGlzQmluZGFibGVMb3JvQ29udGFpbmVyLFxufSBmcm9tIFwiLi4vdXRpbHMvaXNCaW5kYWJsZUxvcm9Db250YWluZXJcIlxuaW1wb3J0IHsgaXNMb3JvVGV4dE1vZGVsU25hcHNob3QgfSBmcm9tIFwiLi9Mb3JvVGV4dE1vZGVsXCJcbmltcG9ydCB7IGlzTG9yb0NvbnRhaW5lclVwVG9EYXRlLCBzZXRMb3JvQ29udGFpbmVyU25hcHNob3QgfSBmcm9tIFwiLi9sb3JvU25hcHNob3RUcmFja2luZ1wiXG5cbnR5cGUgTG9yb1ZhbHVlID0gQmluZGFibGVMb3JvQ29udGFpbmVyIHwgUGxhaW5WYWx1ZVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGFwcGx5aW5nIEpTT04gZGF0YSB0byBMb3JvIGRhdGEgc3RydWN0dXJlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBseUpzb25Ub0xvcm9PcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBtb2RlIHRvIHVzZSB3aGVuIGFwcGx5aW5nIEpTT04gZGF0YSB0byBMb3JvIGRhdGEgc3RydWN0dXJlcy5cbiAgICogLSBgYWRkYDogQ3JlYXRlcyBuZXcgTG9ybyBjb250YWluZXJzIGZvciBvYmplY3RzL2FycmF5cyAoZGVmYXVsdCwgYmFja3dhcmRzIGNvbXBhdGlibGUpXG4gICAqIC0gYG1lcmdlYDogUmVjdXJzaXZlbHkgbWVyZ2VzIHZhbHVlcywgcHJlc2VydmluZyBleGlzdGluZyBjb250YWluZXIgcmVmZXJlbmNlcyB3aGVyZSBwb3NzaWJsZVxuICAgKi9cbiAgbW9kZT86IFwiYWRkXCIgfCBcIm1lcmdlXCJcbn1cblxuZnVuY3Rpb24gaXNQbGFpblByaW1pdGl2ZSh2OiBQbGFpblZhbHVlKTogdiBpcyBQbGFpblByaW1pdGl2ZSB7XG4gIGNvbnN0IHQgPSB0eXBlb2YgdlxuICByZXR1cm4gdCA9PT0gXCJzdHJpbmdcIiB8fCB0ID09PSBcIm51bWJlclwiIHx8IHQgPT09IFwiYm9vbGVhblwiIHx8IHYgPT09IG51bGwgfHwgdiA9PT0gdW5kZWZpbmVkXG59XG5cbmZ1bmN0aW9uIGlzUGxhaW5BcnJheSh2OiBQbGFpblZhbHVlKTogdiBpcyBQbGFpbkFycmF5IHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodilcbn1cblxuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2OiBQbGFpblZhbHVlKTogdiBpcyBQbGFpbk9iamVjdCB7XG4gIHJldHVybiB0eXBlb2YgdiA9PT0gXCJvYmplY3RcIiAmJiB2ICE9PSBudWxsICYmICFBcnJheS5pc0FycmF5KHYpXG59XG5cbi8qKlxuICogRXh0cmFjdHMgZGVsdGEgYXJyYXkgZnJvbSBhIExvcm9UZXh0TW9kZWwgc25hcHNob3QncyBkZWx0YSBmaWVsZC5cbiAqIFRoZSBkZWx0YSBmaWVsZCBpcyBhIGZyb3plbiBEZWx0YTxzdHJpbmc+W10gKGFycmF5IG9mIGRlbHRhIG9wZXJhdGlvbnMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdFRleHREZWx0YUZyb21TbmFwc2hvdChkZWx0YTogdW5rbm93bik6IERlbHRhPHN0cmluZz5bXSB7XG4gIC8vIFRoZSBkZWx0YSBmaWVsZCBpcyBmcm96ZW4sIHNvIHdlIG5lZWQgdG8gZXh0cmFjdCBpdFxuICBpZiAoaXNGcm96ZW5TbmFwc2hvdDxEZWx0YTxzdHJpbmc+W10+KGRlbHRhKSkge1xuICAgIGNvbnN0IGRhdGEgPSBkZWx0YS5kYXRhXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgIHJldHVybiBkYXRhXG4gICAgfVxuICB9XG5cbiAgLy8gSGFuZGxlIHBsYWluIGRlbHRhIGFycmF5IChub3Qgd3JhcHBlZCBpbiBmcm96ZW4pXG4gIGlmIChBcnJheS5pc0FycmF5KGRlbHRhKSkge1xuICAgIHJldHVybiBkZWx0YSBhcyBEZWx0YTxzdHJpbmc+W11cbiAgfVxuXG4gIHJldHVybiBbXVxufVxuXG4vKipcbiAqIEFwcGxpZXMgZGVsdGEgb3BlcmF0aW9ucyB0byBhIExvcm9UZXh0IHVzaW5nIGluc2VydC9tYXJrIEFQSXMuXG4gKiBUaGlzIHdvcmtzIG9uIGJvdGggYXR0YWNoZWQgYW5kIGRldGFjaGVkIGNvbnRhaW5lcnMuXG4gKlxuICogU3RyYXRlZ3k6IEluc2VydCBhbGwgdGV4dCBmaXJzdCwgdGhlbiBhcHBseSBtYXJrcy4gVGhpcyBhdm9pZHMgbWFyayBpbmhlcml0YW5jZVxuICogaXNzdWVzIHdoZW4gaW5zZXJ0aW5nIGF0IHRoZSBib3VuZGFyeSBvZiBhIG1hcmtlZCByZWdpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseURlbHRhVG9Mb3JvVGV4dCh0ZXh0OiBMb3JvVGV4dCwgZGVsdGFzOiBEZWx0YTxzdHJpbmc+W10pOiB2b2lkIHtcbiAgLy8gUGhhc2UgMTogSW5zZXJ0IGFsbCB0ZXh0IGNvbnRlbnRcbiAgbGV0IHBvc2l0aW9uID0gMFxuICBjb25zdCBtYXJrT3BlcmF0aW9uczogQXJyYXk8e1xuICAgIHN0YXJ0OiBudW1iZXJcbiAgICBlbmQ6IG51bWJlclxuICAgIGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gIH0+ID0gW11cblxuICBmb3IgKGNvbnN0IGRlbHRhIG9mIGRlbHRhcykge1xuICAgIGlmIChkZWx0YS5pbnNlcnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgY29udGVudCA9IGRlbHRhLmluc2VydFxuICAgICAgdGV4dC5pbnNlcnQocG9zaXRpb24sIGNvbnRlbnQpXG5cbiAgICAgIC8vIENvbGxlY3QgbWFyayBvcGVyYXRpb25zIHRvIGFwcGx5IGxhdGVyXG4gICAgICBpZiAoZGVsdGEuYXR0cmlidXRlcyAmJiBPYmplY3Qua2V5cyhkZWx0YS5hdHRyaWJ1dGVzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIG1hcmtPcGVyYXRpb25zLnB1c2goe1xuICAgICAgICAgIHN0YXJ0OiBwb3NpdGlvbixcbiAgICAgICAgICBlbmQ6IHBvc2l0aW9uICsgY29udGVudC5sZW5ndGgsXG4gICAgICAgICAgYXR0cmlidXRlczogZGVsdGEuYXR0cmlidXRlcyxcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgcG9zaXRpb24gKz0gY29udGVudC5sZW5ndGhcbiAgICB9IGVsc2UgaWYgKGRlbHRhLnJldGFpbikge1xuICAgICAgcG9zaXRpb24gKz0gZGVsdGEucmV0YWluXG4gICAgfSBlbHNlIGlmIChkZWx0YS5kZWxldGUpIHtcbiAgICAgIHRleHQuZGVsZXRlKHBvc2l0aW9uLCBkZWx0YS5kZWxldGUpXG4gICAgfVxuICB9XG5cbiAgLy8gUGhhc2UgMjogQXBwbHkgYWxsIG1hcmtzIGFmdGVyIHRleHQgaXMgaW5zZXJ0ZWRcbiAgZm9yIChjb25zdCBvcCBvZiBtYXJrT3BlcmF0aW9ucykge1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9wLmF0dHJpYnV0ZXMpKSB7XG4gICAgICB0ZXh0Lm1hcmsoeyBzdGFydDogb3Auc3RhcnQsIGVuZDogb3AuZW5kIH0sIGtleSwgdmFsdWUpXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29udmVydHMgYSBwbGFpbiB2YWx1ZSB0byBhIExvcm8gZGF0YSBzdHJ1Y3R1cmUuXG4gKiBPYmplY3RzIGFyZSBjb252ZXJ0ZWQgdG8gTG9yb01hcHMsIGFycmF5cyB0byBMb3JvTW92YWJsZUxpc3RzLCBwcmltaXRpdmVzIGFyZSB1bnRvdWNoZWQuXG4gKiBGcm96ZW4gdmFsdWVzIGFyZSBhIHNwZWNpYWwgY2FzZSBhbmQgdGhleSBhcmUga2VwdCBhcyBpbW11dGFibGUgcGxhaW4gdmFsdWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29udmVydEpzb25Ub0xvcm9EYXRhKHY6IFBsYWluVmFsdWUpOiBMb3JvVmFsdWUge1xuICBpZiAoaXNQbGFpblByaW1pdGl2ZSh2KSkge1xuICAgIHJldHVybiB2XG4gIH1cblxuICBpZiAoaXNQbGFpbkFycmF5KHYpKSB7XG4gICAgY29uc3QgbGlzdCA9IG5ldyBMb3JvTW92YWJsZUxpc3QoKVxuICAgIGFwcGx5SnNvbkFycmF5VG9Mb3JvTW92YWJsZUxpc3QobGlzdCwgdilcbiAgICByZXR1cm4gbGlzdFxuICB9XG5cbiAgaWYgKGlzUGxhaW5PYmplY3QodikpIHtcbiAgICBpZiAodltmcm96ZW5LZXldID09PSB0cnVlKSB7XG4gICAgICAvLyBmcm96ZW4gdmFsdWUgd2l0aCBleHBsaWNpdCAkZnJvemVuIG1hcmtlciAoc2hvdWxkbid0IHJlYWNoIGhlcmUgYWZ0ZXIgYWJvdmUgY2hlY2spXG4gICAgICByZXR1cm4gdlxuICAgIH1cblxuICAgIGlmIChpc0xvcm9UZXh0TW9kZWxTbmFwc2hvdCh2KSkge1xuICAgICAgY29uc3QgdGV4dCA9IG5ldyBMb3JvVGV4dCgpXG4gICAgICAvLyBFeHRyYWN0IGRlbHRhIGZyb20gdGhlIHNuYXBzaG90IGFuZCBhcHBseSB1c2luZyBpbnNlcnQvbWFyayBBUElzXG4gICAgICAvLyAoYXBwbHlEZWx0YSBkb2Vzbid0IHdvcmsgb24gZGV0YWNoZWQgY29udGFpbmVycywgYnV0IGluc2VydC9tYXJrIGRvKVxuICAgICAgY29uc3QgZGVsdGFzID0gZXh0cmFjdFRleHREZWx0YUZyb21TbmFwc2hvdCh2LmRlbHRhTGlzdClcbiAgICAgIGlmIChkZWx0YXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhcHBseURlbHRhVG9Mb3JvVGV4dCh0ZXh0LCBkZWx0YXMpXG4gICAgICB9XG4gICAgICByZXR1cm4gdGV4dFxuICAgIH1cblxuICAgIGNvbnN0IG1hcCA9IG5ldyBMb3JvTWFwKClcbiAgICBhcHBseUpzb25PYmplY3RUb0xvcm9NYXAobWFwLCB2KVxuICAgIHJldHVybiBtYXBcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgdmFsdWUgdHlwZTogJHt2fWApXG59XG5cbi8qKlxuICogQXBwbGllcyBhIEpTT04gYXJyYXkgdG8gYSBMb3JvTW92YWJsZUxpc3QsIHVzaW5nIGNvbnZlcnRKc29uVG9Mb3JvRGF0YSB0byBjb252ZXJ0IHRoZSB2YWx1ZXMuXG4gKlxuICogQHBhcmFtIGRlc3QgVGhlIGRlc3RpbmF0aW9uIExvcm9Nb3ZhYmxlTGlzdC5cbiAqIEBwYXJhbSBzb3VyY2UgVGhlIHNvdXJjZSBKU09OIGFycmF5LlxuICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucyBmb3IgYXBwbHlpbmcgdGhlIEpTT04gZGF0YS5cbiAqL1xuZXhwb3J0IGNvbnN0IGFwcGx5SnNvbkFycmF5VG9Mb3JvTW92YWJsZUxpc3QgPSAoXG4gIGRlc3Q6IExvcm9Nb3ZhYmxlTGlzdCxcbiAgc291cmNlOiBQbGFpbkFycmF5LFxuICBvcHRpb25zOiBBcHBseUpzb25Ub0xvcm9PcHRpb25zID0ge31cbikgPT4ge1xuICBjb25zdCB7IG1vZGUgPSBcImFkZFwiIH0gPSBvcHRpb25zXG5cbiAgaWYgKG1vZGUgPT09IFwiYWRkXCIpIHtcbiAgICAvLyBBZGQgbW9kZToganVzdCBwdXNoIGFsbCBpdGVtcyB0byB0aGUgZW5kXG4gICAgZm9yIChjb25zdCBpdGVtIG9mIHNvdXJjZSkge1xuICAgICAgY29uc3QgY29udmVydGVkID0gY29udmVydEpzb25Ub0xvcm9EYXRhKGl0ZW0pXG4gICAgICBpZiAoaXNCaW5kYWJsZUxvcm9Db250YWluZXIoY29udmVydGVkKSkge1xuICAgICAgICBkZXN0LnB1c2hDb250YWluZXIoY29udmVydGVkKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGVzdC5wdXNoKGNvbnZlcnRlZClcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuXG4gIH1cblxuICAvLyBNZXJnZSBtb2RlOiByZWN1cnNpdmVseSBtZXJnZSB2YWx1ZXMsIHByZXNlcnZpbmcgZXhpc3RpbmcgY29udGFpbmVyIHJlZmVyZW5jZXNcbiAgLy8gSW4gbWVyZ2UgbW9kZSwgY2hlY2sgaWYgdGhlIGNvbnRhaW5lciBpcyBhbHJlYWR5IHVwLXRvLWRhdGUgd2l0aCB0aGlzIHNuYXBzaG90XG4gIGlmIChpc0xvcm9Db250YWluZXJVcFRvRGF0ZShkZXN0LCBzb3VyY2UpKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICAvLyBSZW1vdmUgZXh0cmEgaXRlbXMgZnJvbSB0aGUgZW5kXG4gIGNvbnN0IGRlc3RMZW4gPSBkZXN0Lmxlbmd0aFxuICBjb25zdCBzcmNMZW4gPSBzb3VyY2UubGVuZ3RoXG4gIGlmIChkZXN0TGVuID4gc3JjTGVuKSB7XG4gICAgZGVzdC5kZWxldGUoc3JjTGVuLCBkZXN0TGVuIC0gc3JjTGVuKVxuICB9XG5cbiAgLy8gVXBkYXRlIGV4aXN0aW5nIGl0ZW1zXG4gIGNvbnN0IG1pbkxlbiA9IE1hdGgubWluKGRlc3RMZW4sIHNyY0xlbilcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBtaW5MZW47IGkrKykge1xuICAgIGNvbnN0IHNyY0l0ZW0gPSBzb3VyY2VbaV1cbiAgICBjb25zdCBkZXN0SXRlbSA9IGRlc3QuZ2V0KGkpXG5cbiAgICAvLyBJZiBib3RoIGFyZSBvYmplY3RzLCBtZXJnZSByZWN1cnNpdmVseVxuICAgIGlmIChpc1BsYWluT2JqZWN0KHNyY0l0ZW0pICYmIGRlc3RJdGVtIGluc3RhbmNlb2YgTG9yb01hcCkge1xuICAgICAgYXBwbHlKc29uT2JqZWN0VG9Mb3JvTWFwKGRlc3RJdGVtLCBzcmNJdGVtLCBvcHRpb25zKVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICAvLyBJZiBib3RoIGFyZSBhcnJheXMsIG1lcmdlIHJlY3Vyc2l2ZWx5XG4gICAgaWYgKGlzUGxhaW5BcnJheShzcmNJdGVtKSAmJiBkZXN0SXRlbSBpbnN0YW5jZW9mIExvcm9Nb3ZhYmxlTGlzdCkge1xuICAgICAgYXBwbHlKc29uQXJyYXlUb0xvcm9Nb3ZhYmxlTGlzdChkZXN0SXRlbSwgc3JjSXRlbSwgb3B0aW9ucylcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgLy8gU2tpcCBpZiBwcmltaXRpdmUgdmFsdWUgaXMgdW5jaGFuZ2VkIChvcHRpbWl6YXRpb24pXG4gICAgaWYgKGlzUGxhaW5QcmltaXRpdmUoc3JjSXRlbSkgJiYgZGVzdEl0ZW0gPT09IHNyY0l0ZW0pIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgLy8gT3RoZXJ3aXNlLCByZXBsYWNlIHRoZSBpdGVtXG4gICAgZGVzdC5kZWxldGUoaSwgMSlcbiAgICBjb25zdCBjb252ZXJ0ZWQgPSBjb252ZXJ0SnNvblRvTG9yb0RhdGEoc3JjSXRlbSlcbiAgICBpZiAoaXNCaW5kYWJsZUxvcm9Db250YWluZXIoY29udmVydGVkKSkge1xuICAgICAgZGVzdC5pbnNlcnRDb250YWluZXIoaSwgY29udmVydGVkKVxuICAgIH0gZWxzZSB7XG4gICAgICBkZXN0Lmluc2VydChpLCBjb252ZXJ0ZWQpXG4gICAgfVxuICB9XG5cbiAgLy8gQWRkIG5ldyBpdGVtcyBhdCB0aGUgZW5kXG4gIGZvciAobGV0IGkgPSBkZXN0TGVuOyBpIDwgc3JjTGVuOyBpKyspIHtcbiAgICBjb25zdCBjb252ZXJ0ZWQgPSBjb252ZXJ0SnNvblRvTG9yb0RhdGEoc291cmNlW2ldKVxuICAgIGlmIChpc0JpbmRhYmxlTG9yb0NvbnRhaW5lcihjb252ZXJ0ZWQpKSB7XG4gICAgICBkZXN0LnB1c2hDb250YWluZXIoY29udmVydGVkKVxuICAgIH0gZWxzZSB7XG4gICAgICBkZXN0LnB1c2goY29udmVydGVkKVxuICAgIH1cbiAgfVxuXG4gIC8vIFVwZGF0ZSBzbmFwc2hvdCB0cmFja2luZyBhZnRlciBzdWNjZXNzZnVsIG1lcmdlXG4gIHNldExvcm9Db250YWluZXJTbmFwc2hvdChkZXN0LCBzb3VyY2UpXG59XG5cbi8qKlxuICogQXBwbGllcyBhIEpTT04gb2JqZWN0IHRvIGEgTG9yb01hcCwgdXNpbmcgY29udmVydEpzb25Ub0xvcm9EYXRhIHRvIGNvbnZlcnQgdGhlIHZhbHVlcy5cbiAqXG4gKiBAcGFyYW0gZGVzdCBUaGUgZGVzdGluYXRpb24gTG9yb01hcC5cbiAqIEBwYXJhbSBzb3VyY2UgVGhlIHNvdXJjZSBKU09OIG9iamVjdC5cbiAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnMgZm9yIGFwcGx5aW5nIHRoZSBKU09OIGRhdGEuXG4gKi9cbmV4cG9ydCBjb25zdCBhcHBseUpzb25PYmplY3RUb0xvcm9NYXAgPSAoXG4gIGRlc3Q6IExvcm9NYXAsXG4gIHNvdXJjZTogUGxhaW5PYmplY3QsXG4gIG9wdGlvbnM6IEFwcGx5SnNvblRvTG9yb09wdGlvbnMgPSB7fVxuKSA9PiB7XG4gIGNvbnN0IHsgbW9kZSA9IFwiYWRkXCIgfSA9IG9wdGlvbnNcblxuICBpZiAobW9kZSA9PT0gXCJhZGRcIikge1xuICAgIC8vIEFkZCBtb2RlOiBqdXN0IHNldCBhbGwgdmFsdWVzXG4gICAgZm9yIChjb25zdCBrIG9mIE9iamVjdC5rZXlzKHNvdXJjZSkpIHtcbiAgICAgIGNvbnN0IHYgPSBzb3VyY2Vba11cbiAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgY29udmVydGVkID0gY29udmVydEpzb25Ub0xvcm9EYXRhKHYpXG4gICAgICAgIGlmIChpc0JpbmRhYmxlTG9yb0NvbnRhaW5lcihjb252ZXJ0ZWQpKSB7XG4gICAgICAgICAgZGVzdC5zZXRDb250YWluZXIoaywgY29udmVydGVkKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlc3Quc2V0KGssIGNvbnZlcnRlZClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIE1lcmdlIG1vZGU6IHJlY3Vyc2l2ZWx5IG1lcmdlIHZhbHVlcywgcHJlc2VydmluZyBleGlzdGluZyBjb250YWluZXIgcmVmZXJlbmNlc1xuICAvLyBJbiBtZXJnZSBtb2RlLCBjaGVjayBpZiB0aGUgY29udGFpbmVyIGlzIGFscmVhZHkgdXAtdG8tZGF0ZSB3aXRoIHRoaXMgc25hcHNob3RcbiAgaWYgKGlzTG9yb0NvbnRhaW5lclVwVG9EYXRlKGRlc3QsIHNvdXJjZSkpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIERlbGV0ZSBrZXlzIHRoYXQgYXJlIG5vdCBwcmVzZW50IGluIHNvdXJjZSAob3IgaGF2ZSB1bmRlZmluZWQgdmFsdWUpXG4gIGNvbnN0IHNvdXJjZUtleXNXaXRoVmFsdWVzID0gbmV3IFNldChPYmplY3Qua2V5cyhzb3VyY2UpLmZpbHRlcigoaykgPT4gc291cmNlW2tdICE9PSB1bmRlZmluZWQpKVxuICBmb3IgKGNvbnN0IGtleSBvZiBkZXN0LmtleXMoKSkge1xuICAgIGlmICghc291cmNlS2V5c1dpdGhWYWx1ZXMuaGFzKGtleSkpIHtcbiAgICAgIGRlc3QuZGVsZXRlKGtleSlcbiAgICB9XG4gIH1cblxuICBmb3IgKGNvbnN0IGsgb2YgT2JqZWN0LmtleXMoc291cmNlKSkge1xuICAgIGNvbnN0IHYgPSBzb3VyY2Vba11cbiAgICAvLyBTa2lwIHVuZGVmaW5lZCB2YWx1ZXMgLSBMb3JvIG1hcHMgY2Fubm90IHN0b3JlIHVuZGVmaW5lZFxuICAgIGlmICh2ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgY29uc3QgZXhpc3RpbmcgPSBkZXN0LmdldChrKVxuXG4gICAgLy8gSWYgc291cmNlIGlzIGFuIG9iamVjdCBhbmQgZGVzdCBoYXMgYSBMb3JvTWFwLCBtZXJnZSByZWN1cnNpdmVseVxuICAgIGlmIChpc1BsYWluT2JqZWN0KHYpICYmIGV4aXN0aW5nIGluc3RhbmNlb2YgTG9yb01hcCkge1xuICAgICAgYXBwbHlKc29uT2JqZWN0VG9Mb3JvTWFwKGV4aXN0aW5nLCB2LCBvcHRpb25zKVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICAvLyBJZiBzb3VyY2UgaXMgYW4gYXJyYXkgYW5kIGRlc3QgaGFzIGEgTG9yb01vdmFibGVMaXN0LCBtZXJnZSByZWN1cnNpdmVseVxuICAgIGlmIChpc1BsYWluQXJyYXkodikgJiYgZXhpc3RpbmcgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICAgIGFwcGx5SnNvbkFycmF5VG9Mb3JvTW92YWJsZUxpc3QoZXhpc3RpbmcsIHYsIG9wdGlvbnMpXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIC8vIFNraXAgaWYgcHJpbWl0aXZlIHZhbHVlIGlzIHVuY2hhbmdlZCAob3B0aW1pemF0aW9uKVxuICAgIGlmIChpc1BsYWluUHJpbWl0aXZlKHYpICYmIGV4aXN0aW5nID09PSB2KSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIC8vIE90aGVyd2lzZSwgY29udmVydCBhbmQgc2V0IHRoZSB2YWx1ZSAodGhpcyBjcmVhdGVzIG5ldyBjb250YWluZXJzIGlmIG5lZWRlZClcbiAgICBjb25zdCBjb252ZXJ0ZWQgPSBjb252ZXJ0SnNvblRvTG9yb0RhdGEodilcbiAgICBpZiAoaXNCaW5kYWJsZUxvcm9Db250YWluZXIoY29udmVydGVkKSkge1xuICAgICAgZGVzdC5zZXRDb250YWluZXIoaywgY29udmVydGVkKVxuICAgIH0gZWxzZSB7XG4gICAgICBkZXN0LnNldChrLCBjb252ZXJ0ZWQpXG4gICAgfVxuICB9XG5cbiAgLy8gVXBkYXRlIHNuYXBzaG90IHRyYWNraW5nIGFmdGVyIHN1Y2Nlc3NmdWwgbWVyZ2VcbiAgc2V0TG9yb0NvbnRhaW5lclNuYXBzaG90KGRlc3QsIHNvdXJjZSlcbn1cbiIsImltcG9ydCB7IExvcm9NYXAsIExvcm9Nb3ZhYmxlTGlzdCwgTG9yb1RleHQgfSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IERlZXBDaGFuZ2UsIERlZXBDaGFuZ2VUeXBlIH0gZnJvbSBcIm1vYngta2V5c3RvbmVcIlxuaW1wb3J0IHR5cGUgeyBQbGFpblZhbHVlIH0gZnJvbSBcIi4uL3BsYWluVHlwZXNcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlscy9lcnJvclwiXG5pbXBvcnQgdHlwZSB7IEJpbmRhYmxlTG9yb0NvbnRhaW5lciB9IGZyb20gXCIuLi91dGlscy9pc0JpbmRhYmxlTG9yb0NvbnRhaW5lclwiXG5pbXBvcnQge1xuICBhcHBseURlbHRhVG9Mb3JvVGV4dCxcbiAgY29udmVydEpzb25Ub0xvcm9EYXRhLFxuICBleHRyYWN0VGV4dERlbHRhRnJvbVNuYXBzaG90LFxufSBmcm9tIFwiLi9jb252ZXJ0SnNvblRvTG9yb0RhdGFcIlxuaW1wb3J0IHsgaXNMb3JvVGV4dE1vZGVsU25hcHNob3QgfSBmcm9tIFwiLi9Mb3JvVGV4dE1vZGVsXCJcbmltcG9ydCB0eXBlIHsgQXJyYXlNb3ZlQ2hhbmdlIH0gZnJvbSBcIi4vbW92ZVdpdGhpbkFycmF5XCJcbmltcG9ydCB7IHJlc29sdmVMb3JvUGF0aCB9IGZyb20gXCIuL3Jlc29sdmVMb3JvUGF0aFwiXG5cbi8qKlxuICogQ29udmVydHMgYSBzbmFwc2hvdCB2YWx1ZSB0byBhIExvcm8tY29tcGF0aWJsZSB2YWx1ZS5cbiAqIE5vdGU6IEFsbCB2YWx1ZXMgcGFzc2VkIGhlcmUgYXJlIGFscmVhZHkgc25hcHNob3RzIChjYXB0dXJlZCBhdCBjaGFuZ2UgdGltZSkuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRWYWx1ZSh2OiB1bmtub3duKTogdW5rbm93biB7XG4gIC8vIEhhbmRsZSBwcmltaXRpdmVzIGRpcmVjdGx5XG4gIGlmICh2ID09PSBudWxsIHx8IHYgPT09IHVuZGVmaW5lZCB8fCB0eXBlb2YgdiAhPT0gXCJvYmplY3RcIikge1xuICAgIHJldHVybiB2XG4gIH1cbiAgLy8gSGFuZGxlIHBsYWluIGFycmF5cyAtIHVzZWQgZm9yIGVtcHR5IGFycmF5IGluaXRcbiAgaWYgKEFycmF5LmlzQXJyYXkodikgJiYgdi5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmV3IExvcm9Nb3ZhYmxlTGlzdCgpXG4gIH1cbiAgLy8gSGFuZGxlIExvcm9UZXh0TW9kZWwgc25hcHNob3Qgc3BlY2lhbGx5IC0gd2UgbmVlZCB0byByZXR1cm4gaXQgYXMtaXNcbiAgLy8gc28gdGhlIGNhbGxlciBjYW4gaGFuZGxlIGNyZWF0aW5nIHRoZSBMb3JvVGV4dCBjb250YWluZXIgcHJvcGVybHlcbiAgaWYgKGlzTG9yb1RleHRNb2RlbFNuYXBzaG90KHYpKSB7XG4gICAgcmV0dXJuIHZcbiAgfVxuICAvLyBWYWx1ZSBpcyBhbHJlYWR5IGEgc25hcHNob3QsIGNvbnZlcnQgdG8gTG9ybyBkYXRhXG4gIHJldHVybiBjb252ZXJ0SnNvblRvTG9yb0RhdGEodiBhcyBQbGFpblZhbHVlKVxufVxuXG4vKipcbiAqIEluc2VydHMgYSB2YWx1ZSBpbnRvIGEgTG9yb01vdmFibGVMaXN0IGF0IHRoZSBnaXZlbiBpbmRleC5cbiAqL1xuZnVuY3Rpb24gaW5zZXJ0SW50b0xpc3QobGlzdDogTG9yb01vdmFibGVMaXN0LCBpbmRleDogbnVtYmVyLCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMb3JvTWFwIHx8IHZhbHVlIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0IHx8IHZhbHVlIGluc3RhbmNlb2YgTG9yb1RleHQpIHtcbiAgICBsaXN0Lmluc2VydENvbnRhaW5lcihpbmRleCwgdmFsdWUpXG4gIH0gZWxzZSBpZiAoaXNMb3JvVGV4dE1vZGVsU25hcHNob3QodmFsdWUpKSB7XG4gICAgY29uc3QgYXR0YWNoZWRUZXh0ID0gbGlzdC5pbnNlcnRDb250YWluZXIoaW5kZXgsIG5ldyBMb3JvVGV4dCgpKVxuICAgIGNvbnN0IGRlbHRhcyA9IGV4dHJhY3RUZXh0RGVsdGFGcm9tU25hcHNob3QoKHZhbHVlIGFzIGFueSkuZGVsdGFMaXN0KVxuICAgIGlmIChkZWx0YXMubGVuZ3RoID4gMCkge1xuICAgICAgYXBwbHlEZWx0YVRvTG9yb1RleHQoYXR0YWNoZWRUZXh0LCBkZWx0YXMpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGxpc3QuaW5zZXJ0KGluZGV4LCB2YWx1ZSlcbiAgfVxufVxuXG4vKipcbiAqIFNldHMgYSB2YWx1ZSBpbiBhIExvcm9NYXAgYXQgdGhlIGdpdmVuIGtleS5cbiAqL1xuZnVuY3Rpb24gc2V0SW5NYXAobWFwOiBMb3JvTWFwLCBrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiB2b2lkIHtcbiAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICBtYXAuZGVsZXRlKGtleSlcbiAgfSBlbHNlIGlmIChcbiAgICB2YWx1ZSBpbnN0YW5jZW9mIExvcm9NYXAgfHxcbiAgICB2YWx1ZSBpbnN0YW5jZW9mIExvcm9Nb3ZhYmxlTGlzdCB8fFxuICAgIHZhbHVlIGluc3RhbmNlb2YgTG9yb1RleHRcbiAgKSB7XG4gICAgbWFwLnNldENvbnRhaW5lcihrZXksIHZhbHVlKVxuICB9IGVsc2UgaWYgKGlzTG9yb1RleHRNb2RlbFNuYXBzaG90KHZhbHVlKSkge1xuICAgIGNvbnN0IGF0dGFjaGVkVGV4dCA9IG1hcC5zZXRDb250YWluZXIoa2V5LCBuZXcgTG9yb1RleHQoKSlcbiAgICBjb25zdCBkZWx0YXMgPSBleHRyYWN0VGV4dERlbHRhRnJvbVNuYXBzaG90KCh2YWx1ZSBhcyBhbnkpLmRlbHRhTGlzdClcbiAgICBpZiAoZGVsdGFzLmxlbmd0aCA+IDApIHtcbiAgICAgIGFwcGx5RGVsdGFUb0xvcm9UZXh0KGF0dGFjaGVkVGV4dCwgZGVsdGFzKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBtYXAuc2V0KGtleSwgdmFsdWUpXG4gIH1cbn1cblxuLyoqXG4gKiBBcHBsaWVzIGEgTW9iWCBEZWVwQ2hhbmdlIG9yIGFuIEFycmF5TW92ZUNoYW5nZSB0byBhIExvcm8gb2JqZWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlNb2J4Q2hhbmdlVG9Mb3JvT2JqZWN0KFxuICBjaGFuZ2U6IERlZXBDaGFuZ2UgfCBBcnJheU1vdmVDaGFuZ2UsXG4gIGxvcm9PYmplY3Q6IEJpbmRhYmxlTG9yb0NvbnRhaW5lclxuKTogdm9pZCB7XG4gIGNvbnN0IGxvcm9Db250YWluZXIgPSByZXNvbHZlTG9yb1BhdGgobG9yb09iamVjdCwgY2hhbmdlLnBhdGgpXG5cbiAgLy8gSWYgY29udGFpbmVyIGRvZXNuJ3QgZXhpc3QgYXQgdGhpcyBwYXRoLCB0aHJvdyBhbiBlcnJvclxuICBpZiAoIWxvcm9Db250YWluZXIpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFxuICAgICAgYGNhbm5vdCBhcHBseSBjaGFuZ2UgdG8gbWlzc2luZyBMb3JvIGNvbnRhaW5lciBhdCBwYXRoOiAke0pTT04uc3RyaW5naWZ5KGNoYW5nZS5wYXRoKX1gXG4gICAgKVxuICB9XG5cbiAgc3dpdGNoIChjaGFuZ2UudHlwZSkge1xuICAgIGNhc2UgXCJBcnJheU1vdmVcIjoge1xuICAgICAgaWYgKCEobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9Nb3ZhYmxlTGlzdCkpIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShgQXJyYXlNb3ZlIGNoYW5nZSByZXF1aXJlcyBhIExvcm9Nb3ZhYmxlTGlzdCBjb250YWluZXJgKVxuICAgICAgfVxuICAgICAgbG9yb0NvbnRhaW5lci5tb3ZlKGNoYW5nZS5mcm9tSW5kZXgsIGNoYW5nZS50b0luZGV4KVxuICAgICAgYnJlYWtcbiAgICB9XG5cbiAgICBjYXNlIERlZXBDaGFuZ2VUeXBlLkFycmF5U3BsaWNlOiB7XG4gICAgICBpZiAoIShsb3JvQ29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSkge1xuICAgICAgICB0aHJvdyBmYWlsdXJlKGBBcnJheVNwbGljZSBjaGFuZ2UgcmVxdWlyZXMgYSBMb3JvTW92YWJsZUxpc3QgY29udGFpbmVyYClcbiAgICAgIH1cbiAgICAgIGlmIChjaGFuZ2UucmVtb3ZlZFZhbHVlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGxvcm9Db250YWluZXIuZGVsZXRlKGNoYW5nZS5pbmRleCwgY2hhbmdlLnJlbW92ZWRWYWx1ZXMubGVuZ3RoKVxuICAgICAgfVxuICAgICAgaWYgKGNoYW5nZS5hZGRlZFZhbHVlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlc1RvSW5zZXJ0ID0gY2hhbmdlLmFkZGVkVmFsdWVzLm1hcChjb252ZXJ0VmFsdWUpXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmFsdWVzVG9JbnNlcnQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpbnNlcnRJbnRvTGlzdChsb3JvQ29udGFpbmVyLCBjaGFuZ2UuaW5kZXggKyBpLCB2YWx1ZXNUb0luc2VydFtpXSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYnJlYWtcbiAgICB9XG5cbiAgICBjYXNlIERlZXBDaGFuZ2VUeXBlLkFycmF5VXBkYXRlOiB7XG4gICAgICBpZiAoIShsb3JvQ29udGFpbmVyIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSkge1xuICAgICAgICB0aHJvdyBmYWlsdXJlKGBBcnJheVVwZGF0ZSBjaGFuZ2UgcmVxdWlyZXMgYSBMb3JvTW92YWJsZUxpc3QgY29udGFpbmVyYClcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbnZlcnRlZCA9IGNvbnZlcnRWYWx1ZShjaGFuZ2UubmV3VmFsdWUpXG4gICAgICBpZiAoXG4gICAgICAgIGNvbnZlcnRlZCBpbnN0YW5jZW9mIExvcm9NYXAgfHxcbiAgICAgICAgY29udmVydGVkIGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0IHx8XG4gICAgICAgIGNvbnZlcnRlZCBpbnN0YW5jZW9mIExvcm9UZXh0XG4gICAgICApIHtcbiAgICAgICAgbG9yb0NvbnRhaW5lci5zZXRDb250YWluZXIoY2hhbmdlLmluZGV4LCBjb252ZXJ0ZWQpXG4gICAgICB9IGVsc2UgaWYgKGlzTG9yb1RleHRNb2RlbFNuYXBzaG90KGNvbnZlcnRlZCkpIHtcbiAgICAgICAgY29uc3QgYXR0YWNoZWRUZXh0ID0gbG9yb0NvbnRhaW5lci5zZXRDb250YWluZXIoY2hhbmdlLmluZGV4LCBuZXcgTG9yb1RleHQoKSlcbiAgICAgICAgY29uc3QgZGVsdGFzID0gZXh0cmFjdFRleHREZWx0YUZyb21TbmFwc2hvdCgoY29udmVydGVkIGFzIGFueSkuZGVsdGFMaXN0KVxuICAgICAgICBpZiAoZGVsdGFzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBhcHBseURlbHRhVG9Mb3JvVGV4dChhdHRhY2hlZFRleHQsIGRlbHRhcylcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9yb0NvbnRhaW5lci5zZXQoY2hhbmdlLmluZGV4LCBjb252ZXJ0ZWQpXG4gICAgICB9XG4gICAgICBicmVha1xuICAgIH1cblxuICAgIGNhc2UgRGVlcENoYW5nZVR5cGUuT2JqZWN0QWRkOlxuICAgIGNhc2UgRGVlcENoYW5nZVR5cGUuT2JqZWN0VXBkYXRlOiB7XG4gICAgICBpZiAobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9UZXh0KSB7XG4gICAgICAgIC8vIEhhbmRsZSBjaGFuZ2VzIHRvIExvcm9UZXh0IHByb3BlcnRpZXMgKG1haW5seSBkZWx0YUxpc3QpXG4gICAgICAgIGlmIChjaGFuZ2Uua2V5ID09PSBcImRlbHRhTGlzdFwiKSB7XG4gICAgICAgICAgLy8gY2hhbmdlLm5ld1ZhbHVlIGlzIGFscmVhZHkgYSBzbmFwc2hvdCAoY2FwdHVyZWQgYXQgY2hhbmdlIHRpbWUpXG4gICAgICAgICAgY29uc3QgZGVsdGFzID0gZXh0cmFjdFRleHREZWx0YUZyb21TbmFwc2hvdChjaGFuZ2UubmV3VmFsdWUpXG4gICAgICAgICAgaWYgKGxvcm9Db250YWluZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgbG9yb0NvbnRhaW5lci5kZWxldGUoMCwgbG9yb0NvbnRhaW5lci5sZW5ndGgpXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChkZWx0YXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgYXBwbHlEZWx0YVRvTG9yb1RleHQobG9yb0NvbnRhaW5lciwgZGVsdGFzKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBpZ25vcmUgb3RoZXIgcHJvcGVydHkgY2hhbmdlcyBvbiBMb3JvVGV4dCBhcyB0aGV5J3JlIG5vdCBzeW5jZWRcbiAgICAgIH0gZWxzZSBpZiAobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9NYXApIHtcbiAgICAgICAgY29uc3QgY29udmVydGVkID0gY29udmVydFZhbHVlKGNoYW5nZS5uZXdWYWx1ZSlcbiAgICAgICAgc2V0SW5NYXAobG9yb0NvbnRhaW5lciwgY2hhbmdlLmtleSwgY29udmVydGVkKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShgT2JqZWN0QWRkL09iamVjdFVwZGF0ZSBjaGFuZ2UgcmVxdWlyZXMgYSBMb3JvTWFwIG9yIExvcm9UZXh0IGNvbnRhaW5lcmApXG4gICAgICB9XG4gICAgICBicmVha1xuICAgIH1cblxuICAgIGNhc2UgRGVlcENoYW5nZVR5cGUuT2JqZWN0UmVtb3ZlOiB7XG4gICAgICBpZiAobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9UZXh0KSB7XG4gICAgICAgIC8vIGlnbm9yZSByZW1vdmVzIG9uIExvcm9UZXh0IHByb3BlcnRpZXNcbiAgICAgIH0gZWxzZSBpZiAobG9yb0NvbnRhaW5lciBpbnN0YW5jZW9mIExvcm9NYXApIHtcbiAgICAgICAgbG9yb0NvbnRhaW5lci5kZWxldGUoY2hhbmdlLmtleSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGZhaWx1cmUoYE9iamVjdFJlbW92ZSBjaGFuZ2UgcmVxdWlyZXMgYSBMb3JvTWFwIG9yIExvcm9UZXh0IGNvbnRhaW5lcmApXG4gICAgICB9XG4gICAgICBicmVha1xuICAgIH1cblxuICAgIGRlZmF1bHQ6IHtcbiAgICAgIC8vIEV4aGF1c3RpdmUgY2hlY2sgLSBUeXBlU2NyaXB0IHdpbGwgZXJyb3IgaWYgd2UgbWlzcyBhIGNhc2VcbiAgICAgIGNvbnN0IF9leGhhdXN0aXZlQ2hlY2s6IG5ldmVyID0gY2hhbmdlXG4gICAgICB0aHJvdyBmYWlsdXJlKGB1bnN1cHBvcnRlZCBjaGFuZ2UgdHlwZTogJHsoX2V4aGF1c3RpdmVDaGVjayBhcyBhbnkpLnR5cGV9YClcbiAgICB9XG4gIH1cbn1cbiIsImltcG9ydCB7IERlZXBDaGFuZ2UgfSBmcm9tIFwibW9ieC1rZXlzdG9uZVwiXG5cbi8qKlxuICogU3ludGhldGljIGNoYW5nZSB0eXBlIGZvciBhcnJheSBtb3Zlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcnJheU1vdmVDaGFuZ2Uge1xuICB0eXBlOiBcIkFycmF5TW92ZVwiXG4gIHBhdGg6IHJlYWRvbmx5IChzdHJpbmcgfCBudW1iZXIpW11cbiAgZnJvbUluZGV4OiBudW1iZXJcbiAgdG9JbmRleDogbnVtYmVyXG59XG5cbi8qKlxuICogVHJhY2tzIHRoZSBjdXJyZW50bHkgYWN0aXZlIG1vdmUgb3BlcmF0aW9uLlxuICogV2hlbiBzZXQsIHRoZSBuZXh0IHR3byBzcGxpY2Ugb3BlcmF0aW9ucyBvbiB0aGlzIGFycmF5IGFyZSBpbnRlcmNlcHRlZC5cbiAqL1xubGV0IGFjdGl2ZU1vdmVDb250ZXh0OlxuICB8IHtcbiAgICAgIGFycmF5OiB1bmtub3duW11cbiAgICAgIGZyb21JbmRleDogbnVtYmVyXG4gICAgICB0b0luZGV4OiBudW1iZXJcbiAgICAgIHBhdGg6IHJlYWRvbmx5IChzdHJpbmcgfCBudW1iZXIpW10gfCB1bmRlZmluZWQgLy8gQ2FwdHVyZWQgZnJvbSBmaXJzdCBzcGxpY2VcbiAgICAgIHJlY2VpdmVkRmlyc3RTcGxpY2U6IGJvb2xlYW5cbiAgICB9XG4gIHwgdW5kZWZpbmVkXG5cbi8qKlxuICogTW92ZXMgYW4gaXRlbSB3aXRoaW4gYW4gYXJyYXkgZnJvbSBvbmUgaW5kZXggdG8gYW5vdGhlci5cbiAqXG4gKiBXaGVuIHVzZWQgb24gYSBtb2J4LWtleXN0b25lIGFycmF5IGJvdW5kIHRvIGEgTG9ybyBtb3ZhYmxlIGxpc3QsXG4gKiB0aGlzIHRyYW5zbGF0ZXMgdG8gYSBuYXRpdmUgTG9ybyBtb3ZlIG9wZXJhdGlvbiBmb3Igb3B0aW1hbCBDUkRUIG1lcmdpbmcuXG4gKlxuICogRm9yIHVuYm91bmQgYXJyYXlzLCBwZXJmb3JtcyBhIHN0YW5kYXJkIHNwbGljZS1iYXNlZCBtb3ZlLlxuICpcbiAqIEBwYXJhbSBhcnJheSBUaGUgYXJyYXkgdG8gbW92ZSB3aXRoaW5cbiAqIEBwYXJhbSBmcm9tSW5kZXggVGhlIGluZGV4IG9mIHRoZSBpdGVtIHRvIG1vdmVcbiAqIEBwYXJhbSB0b0luZGV4IFRoZSB0YXJnZXQgaW5kZXggdG8gbW92ZSB0aGUgaXRlbSB0b1xuICovXG5leHBvcnQgZnVuY3Rpb24gbW92ZVdpdGhpbkFycmF5PFQ+KGFycmF5OiBUW10sIGZyb21JbmRleDogbnVtYmVyLCB0b0luZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgLy8gVmFsaWRhdGUgaW5kaWNlc1xuICBpZiAoZnJvbUluZGV4IDwgMCB8fCBmcm9tSW5kZXggPj0gYXJyYXkubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBmcm9tSW5kZXggJHtmcm9tSW5kZXh9IGlzIG91dCBvZiBib3VuZHMgKGFycmF5IGxlbmd0aDogJHthcnJheS5sZW5ndGh9KWApXG4gIH1cbiAgaWYgKHRvSW5kZXggPCAwIHx8IHRvSW5kZXggPiBhcnJheS5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHRvSW5kZXggJHt0b0luZGV4fSBpcyBvdXQgb2YgYm91bmRzIChhcnJheSBsZW5ndGg6ICR7YXJyYXkubGVuZ3RofSlgKVxuICB9XG4gIGlmIChmcm9tSW5kZXggPT09IHRvSW5kZXgpIHtcbiAgICByZXR1cm4gLy8gTm8tb3BcbiAgfVxuXG4gIC8vIFNldCB1cCB0aGUgbW92ZSBjb250ZXh0IGJlZm9yZSBtdXRhdGlvbnNcbiAgYWN0aXZlTW92ZUNvbnRleHQgPSB7XG4gICAgYXJyYXksXG4gICAgZnJvbUluZGV4LFxuICAgIHRvSW5kZXgsXG4gICAgcGF0aDogdW5kZWZpbmVkLFxuICAgIHJlY2VpdmVkRmlyc3RTcGxpY2U6IGZhbHNlLFxuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBQZXJmb3JtIHRoZSBhY3R1YWwgc3BsaWNlIG9wZXJhdGlvbnNcbiAgICAvLyBUaGlzIHdpbGwgdHJpZ2dlciBvbkRlZXBDaGFuZ2UgZm9yIGVhY2ggc3BsaWNlXG4gICAgY29uc3QgW2l0ZW1dID0gYXJyYXkuc3BsaWNlKGZyb21JbmRleCwgMSlcbiAgICBjb25zdCBhZGp1c3RlZFRhcmdldCA9IHRvSW5kZXggPiBmcm9tSW5kZXggPyB0b0luZGV4IC0gMSA6IHRvSW5kZXhcbiAgICBhcnJheS5zcGxpY2UoYWRqdXN0ZWRUYXJnZXQsIDAsIGl0ZW0pXG4gIH0gZmluYWxseSB7XG4gICAgYWN0aXZlTW92ZUNvbnRleHQgPSB1bmRlZmluZWRcbiAgfVxufVxuXG4vKipcbiAqIENoZWNrIGlmIGEgY2hhbmdlIGlzIHBhcnQgb2YgYW4gYWN0aXZlIG1vdmUgb3BlcmF0aW9uIGFuZCBwcm9jZXNzIGl0LlxuICogVGhpcyBpcyBjYWxsZWQgZm9yIEFycmF5U3BsaWNlIGNoYW5nZXMgb24gdGhlIHRhcmdldCBhcnJheS5cbiAqXG4gKiBAcGFyYW0gY2hhbmdlIFRoZSBkZWVwIGNoYW5nZSAobXVzdCBiZSBBcnJheVNwbGljZSB0eXBlKVxuICogQHJldHVybnMgVGhlIEFycmF5TW92ZUNoYW5nZSBpZiB0aGUgbW92ZSBpcyBjb21wbGV0ZSAoc2Vjb25kIHNwbGljZSksXG4gKiAgICAgICAgICB1bmRlZmluZWQgaWYgaW50ZXJjZXB0ZWQgYnV0IG5vdCBjb21wbGV0ZSAoZmlyc3Qgc3BsaWNlKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0NoYW5nZUZvck1vdmUoY2hhbmdlOiBEZWVwQ2hhbmdlKTogQXJyYXlNb3ZlQ2hhbmdlIHwgdW5kZWZpbmVkIHtcbiAgLy8gV2Uga25vdyB3ZSdyZSBpbiBhIG1vdmUgY29udGV4dCBhbmQgdGhpcyBpcyBhbiBBcnJheVNwbGljZSBvbiB0aGUgdGFyZ2V0IGFycmF5XG4gIGNvbnN0IGN0eCA9IGFjdGl2ZU1vdmVDb250ZXh0IVxuXG4gIGlmICghY3R4LnJlY2VpdmVkRmlyc3RTcGxpY2UpIHtcbiAgICAvLyBGaXJzdCBzcGxpY2UgLSBjYXB0dXJlIHRoZSBwYXRoIGFuZCBtYXJrIGFzIHJlY2VpdmVkXG4gICAgY3R4LnBhdGggPSBjaGFuZ2UucGF0aFxuICAgIGN0eC5yZWNlaXZlZEZpcnN0U3BsaWNlID0gdHJ1ZVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfVxuXG4gIC8vIFNlY29uZCBzcGxpY2UgLSB0aGUgbW92ZSBpcyBjb21wbGV0ZS5cbiAgLy8gTm90ZTogV2UgYWRqdXN0IHRvSW5kZXggaGVyZSBmb3IgTG9ybydzIG1vdmUoKSBzZW1hbnRpY3MsIHdoaWNoIGV4cGVjdHNcbiAgLy8gdGhlIHRhcmdldCBwb3NpdGlvbiBhZnRlciByZW1vdmFsLiBUaGlzIGlzIGludGVudGlvbmFsbHkgc2VwYXJhdGUgZnJvbVxuICAvLyB0aGUgYWRqdXN0bWVudCBvbiBsaW5lIDY0LCB3aGljaCBpcyBmb3IgdGhlIHNwbGljZSBvcGVyYXRpb24gb24gdGhlIE1vYlggYXJyYXkuXG4gIC8vIEJvdGggYWRqdXN0bWVudHMgYXJlIG5lZWRlZCBiZWNhdXNlOlxuICAvLyAtIExpbmUgNjQ6IHNwbGljZSgpIGluc2VydHMgYXQgYSBwb3NpdGlvbiBpbiB0aGUgYWxyZWFkeS1zaG9ydGVuZWQgYXJyYXlcbiAgLy8gLSBIZXJlOiBMb3JvJ3MgbW92ZShmcm9tLCB0bykgYWxzbyBleHBlY3RzIGB0b2AgYXMgdGhlIHBvc2l0aW9uIGFmdGVyIHJlbW92YWxcbiAgY29uc3QgYWRqdXN0ZWRUb0luZGV4ID0gY3R4LnRvSW5kZXggPiBjdHguZnJvbUluZGV4ID8gY3R4LnRvSW5kZXggLSAxIDogY3R4LnRvSW5kZXhcblxuICByZXR1cm4ge1xuICAgIHR5cGU6IFwiQXJyYXlNb3ZlXCIsXG4gICAgcGF0aDogY3R4LnBhdGghLFxuICAgIGZyb21JbmRleDogY3R4LmZyb21JbmRleCxcbiAgICB0b0luZGV4OiBhZGp1c3RlZFRvSW5kZXgsXG4gIH1cbn1cblxuLyoqXG4gKiBDaGVjayBpZiB3ZSdyZSBjdXJyZW50bHkgaW4gYSBtb3ZlIGNvbnRleHQgZm9yIGEgc3BlY2lmaWMgYXJyYXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0luTW92ZUNvbnRleHRGb3JBcnJheShhcnJheTogdW5rbm93bltdKTogYm9vbGVhbiB7XG4gIHJldHVybiBhY3RpdmVNb3ZlQ29udGV4dCAhPT0gdW5kZWZpbmVkICYmIGFjdGl2ZU1vdmVDb250ZXh0LmFycmF5ID09PSBhcnJheVxufVxuIiwiaW1wb3J0IHtcbiAgdHlwZSBDb250YWluZXJJRCxcbiAgdHlwZSBMb3JvRG9jLFxuICB0eXBlIExvcm9FdmVudEJhdGNoLFxuICBMb3JvTWFwLFxuICBMb3JvTW92YWJsZUxpc3QsXG4gIExvcm9UZXh0LFxufSBmcm9tIFwibG9yby1jcmR0XCJcbmltcG9ydCB7IGFjdGlvbiB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7XG4gIEFueURhdGFNb2RlbCxcbiAgQW55TW9kZWwsXG4gIEFueVN0YW5kYXJkVHlwZSxcbiAgRGVlcENoYW5nZSxcbiAgRGVlcENoYW5nZVR5cGUsXG4gIGZyb21TbmFwc2hvdCxcbiAgZ2V0UGFyZW50VG9DaGlsZFBhdGgsXG4gIGdldFNuYXBzaG90LFxuICBpc1RyZWVOb2RlLFxuICBNb2RlbENsYXNzLFxuICBvbkRlZXBDaGFuZ2UsXG4gIG9uR2xvYmFsRGVlcENoYW5nZSxcbiAgb25TbmFwc2hvdCxcbiAgcmVzb2x2ZVBhdGgsXG4gIFNuYXBzaG90T3V0T2YsXG4gIFR5cGVUb0RhdGEsXG59IGZyb20gXCJtb2J4LWtleXN0b25lXCJcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gXCJuYW5vaWRcIlxuaW1wb3J0IHR5cGUgeyBQbGFpbkFycmF5LCBQbGFpbk9iamVjdCB9IGZyb20gXCIuLi9wbGFpblR5cGVzXCJcbmltcG9ydCB7IGdldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tIH0gZnJvbSBcIi4uL3V0aWxzL2dldE9yQ3JlYXRlTG9yb0NvbGxlY3Rpb25BdG9tXCJcbmltcG9ydCB0eXBlIHsgQmluZGFibGVMb3JvQ29udGFpbmVyIH0gZnJvbSBcIi4uL3V0aWxzL2lzQmluZGFibGVMb3JvQ29udGFpbmVyXCJcblxuaW1wb3J0IHsgYXBwbHlMb3JvRXZlbnRUb01vYngsIFJlY29uY2lsaWF0aW9uTWFwIH0gZnJvbSBcIi4vYXBwbHlMb3JvRXZlbnRUb01vYnhcIlxuaW1wb3J0IHsgYXBwbHlNb2J4Q2hhbmdlVG9Mb3JvT2JqZWN0IH0gZnJvbSBcIi4vYXBwbHlNb2J4Q2hhbmdlVG9Mb3JvT2JqZWN0XCJcbmltcG9ydCB7XG4gIGFwcGx5RGVsdGFUb0xvcm9UZXh0LFxuICBhcHBseUpzb25BcnJheVRvTG9yb01vdmFibGVMaXN0LFxuICBhcHBseUpzb25PYmplY3RUb0xvcm9NYXAsXG4gIGV4dHJhY3RUZXh0RGVsdGFGcm9tU25hcHNob3QsXG59IGZyb20gXCIuL2NvbnZlcnRKc29uVG9Mb3JvRGF0YVwiXG5pbXBvcnQgeyBjb252ZXJ0TG9yb0RhdGFUb0pzb24gfSBmcm9tIFwiLi9jb252ZXJ0TG9yb0RhdGFUb0pzb25cIlxuaW1wb3J0IHsgbG9yb1RleHRNb2RlbElkIH0gZnJvbSBcIi4vTG9yb1RleHRNb2RlbFwiXG5pbXBvcnQgeyB0eXBlIExvcm9CaW5kaW5nQ29udGV4dCwgbG9yb0JpbmRpbmdDb250ZXh0IH0gZnJvbSBcIi4vbG9yb0JpbmRpbmdDb250ZXh0XCJcbmltcG9ydCB7IHNldExvcm9Db250YWluZXJTbmFwc2hvdCB9IGZyb20gXCIuL2xvcm9TbmFwc2hvdFRyYWNraW5nXCJcbmltcG9ydCB7XG4gIHR5cGUgQXJyYXlNb3ZlQ2hhbmdlLFxuICBpc0luTW92ZUNvbnRleHRGb3JBcnJheSxcbiAgcHJvY2Vzc0NoYW5nZUZvck1vdmUsXG59IGZyb20gXCIuL21vdmVXaXRoaW5BcnJheVwiXG5cbi8qKlxuICogQ2FwdHVyZXMgc25hcHNob3RzIG9mIHRyZWUgbm9kZXMgaW4gYSBEZWVwQ2hhbmdlLlxuICogVGhpcyBlbnN1cmVzIHZhbHVlcyBhcmUgY2FwdHVyZWQgYXQgY2hhbmdlIHRpbWUsIG5vdCBhdCBhcHBseSB0aW1lLFxuICogcHJldmVudGluZyBpc3N1ZXMgd2hlbiB2YWx1ZXMgYXJlIG11dGF0ZWQgYWZ0ZXIgYmVpbmcgYWRkZWQgdG8gYSBjb2xsZWN0aW9uLlxuICovXG5mdW5jdGlvbiBjYXB0dXJlQ2hhbmdlU25hcHNob3RzKGNoYW5nZTogRGVlcENoYW5nZSk6IERlZXBDaGFuZ2Uge1xuICBpZiAoY2hhbmdlLnR5cGUgPT09IERlZXBDaGFuZ2VUeXBlLkFycmF5U3BsaWNlICYmIGNoYW5nZS5hZGRlZFZhbHVlcy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3Qgc25hcHNob3RzID0gY2hhbmdlLmFkZGVkVmFsdWVzLm1hcCgodikgPT4gKGlzVHJlZU5vZGUodikgPyBnZXRTbmFwc2hvdCh2KSA6IHYpKVxuICAgIHJldHVybiB7IC4uLmNoYW5nZSwgYWRkZWRWYWx1ZXM6IHNuYXBzaG90cyB9XG4gIH0gZWxzZSBpZiAoY2hhbmdlLnR5cGUgPT09IERlZXBDaGFuZ2VUeXBlLkFycmF5VXBkYXRlKSB7XG4gICAgY29uc3Qgc25hcHNob3QgPSBpc1RyZWVOb2RlKGNoYW5nZS5uZXdWYWx1ZSkgPyBnZXRTbmFwc2hvdChjaGFuZ2UubmV3VmFsdWUpIDogY2hhbmdlLm5ld1ZhbHVlXG4gICAgcmV0dXJuIHsgLi4uY2hhbmdlLCBuZXdWYWx1ZTogc25hcHNob3QgfVxuICB9IGVsc2UgaWYgKFxuICAgIGNoYW5nZS50eXBlID09PSBEZWVwQ2hhbmdlVHlwZS5PYmplY3RBZGQgfHxcbiAgICBjaGFuZ2UudHlwZSA9PT0gRGVlcENoYW5nZVR5cGUuT2JqZWN0VXBkYXRlXG4gICkge1xuICAgIGNvbnN0IHNuYXBzaG90ID0gaXNUcmVlTm9kZShjaGFuZ2UubmV3VmFsdWUpID8gZ2V0U25hcHNob3QoY2hhbmdlLm5ld1ZhbHVlKSA6IGNoYW5nZS5uZXdWYWx1ZVxuICAgIHJldHVybiB7IC4uLmNoYW5nZSwgbmV3VmFsdWU6IHNuYXBzaG90IH1cbiAgfVxuICByZXR1cm4gY2hhbmdlXG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGJpZGlyZWN0aW9uYWwgYmluZGluZyBiZXR3ZWVuIGEgTG9ybyBkYXRhIHN0cnVjdHVyZSBhbmQgYSBtb2J4LWtleXN0b25lIG1vZGVsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYmluZExvcm9Ub01vYnhLZXlzdG9uZTxcbiAgVFR5cGUgZXh0ZW5kcyBBbnlTdGFuZGFyZFR5cGUgfCBNb2RlbENsYXNzPEFueU1vZGVsPiB8IE1vZGVsQ2xhc3M8QW55RGF0YU1vZGVsPixcbj4oe1xuICBsb3JvRG9jLFxuICBsb3JvT2JqZWN0LFxuICBtb2J4S2V5c3RvbmVUeXBlLFxufToge1xuICAvKipcbiAgICogVGhlIExvcm8gZG9jdW1lbnQuXG4gICAqL1xuICBsb3JvRG9jOiBMb3JvRG9jXG4gIC8qKlxuICAgKiBUaGUgYm91bmQgTG9ybyBkYXRhIHN0cnVjdHVyZS5cbiAgICovXG4gIGxvcm9PYmplY3Q6IEJpbmRhYmxlTG9yb0NvbnRhaW5lclxuICAvKipcbiAgICogVGhlIG1vYngta2V5c3RvbmUgbW9kZWwgdHlwZS5cbiAgICovXG4gIG1vYnhLZXlzdG9uZVR5cGU6IFRUeXBlXG59KToge1xuICAvKipcbiAgICogVGhlIGJvdW5kIG1vYngta2V5c3RvbmUgaW5zdGFuY2UuXG4gICAqL1xuICBib3VuZE9iamVjdDogVHlwZVRvRGF0YTxUVHlwZT5cbiAgLyoqXG4gICAqIERpc3Bvc2VzIHRoZSBiaW5kaW5nLlxuICAgKi9cbiAgZGlzcG9zZTogKCkgPT4gdm9pZFxuICAvKipcbiAgICogVGhlIExvcm8gb3JpZ2luIHN0cmluZyB1c2VkIGZvciBiaW5kaW5nIHRyYW5zYWN0aW9ucy5cbiAgICovXG4gIGxvcm9PcmlnaW46IHN0cmluZ1xufSB7XG4gIGNvbnN0IGxvcm9PcmlnaW4gPSBgYmluZExvcm9Ub01vYnhLZXlzdG9uZVRyYW5zYWN0aW9uT3JpZ2luLSR7bmFub2lkKCl9YFxuXG4gIGxldCBhcHBseWluZ0xvcm9DaGFuZ2VzVG9Nb2J4S2V5c3RvbmUgPSAwXG5cbiAgY29uc3QgYmluZGluZ0NvbnRleHQ6IExvcm9CaW5kaW5nQ29udGV4dCA9IHtcbiAgICBsb3JvRG9jLFxuICAgIGxvcm9PYmplY3QsXG4gICAgbW9ieEtleXN0b25lVHlwZSxcbiAgICBsb3JvT3JpZ2luLFxuICAgIGJvdW5kT2JqZWN0OiB1bmRlZmluZWQsIC8vIG5vdCB5ZXQgY3JlYXRlZFxuXG4gICAgZ2V0IGlzQXBwbHlpbmdMb3JvQ2hhbmdlc1RvTW9ieEtleXN0b25lKCkge1xuICAgICAgcmV0dXJuIGFwcGx5aW5nTG9yb0NoYW5nZXNUb01vYnhLZXlzdG9uZSA+IDBcbiAgICB9LFxuICB9XG5cbiAgY29uc3QgbG9yb0pzb24gPSBjb252ZXJ0TG9yb0RhdGFUb0pzb24obG9yb09iamVjdCkgYXMgU25hcHNob3RPdXRPZjxUeXBlVG9EYXRhPFRUeXBlPj5cblxuICBsZXQgYm91bmRPYmplY3Q6IFR5cGVUb0RhdGE8VFR5cGU+XG5cbiAgLy8gVHJhY2sgaWYgYW55IGluaXQgY2hhbmdlcyBvY2N1cnJlZCBkdXJpbmcgZnJvbVNuYXBzaG90XG4gIC8vIElmIHRoZXkgZGlkLCB3ZSBuZWVkIHRvIHN5bmMgdGhlIG1vZGVsIHNuYXBzaG90IHRvIHRoZSBDUkRUXG4gIGxldCBoYXNJbml0Q2hhbmdlcyA9IGZhbHNlXG5cbiAgY29uc3QgY3JlYXRlQm91bmRPYmplY3QgPSAoKSA9PiB7XG4gICAgLy8gU2V0IHVwIGEgdGVtcG9yYXJ5IGdsb2JhbCBsaXN0ZW5lciB0byBkZXRlY3QgaW5pdCBjaGFuZ2VzIGR1cmluZyBmcm9tU25hcHNob3RcbiAgICBjb25zdCBkaXNwb3NlR2xvYmFsTGlzdGVuZXIgPSBvbkdsb2JhbERlZXBDaGFuZ2UoKF90YXJnZXQsIGNoYW5nZSkgPT4ge1xuICAgICAgaWYgKGNoYW5nZS5pc0luaXQpIHtcbiAgICAgICAgaGFzSW5pdENoYW5nZXMgPSB0cnVlXG4gICAgICB9XG4gICAgfSlcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBsb3JvQmluZGluZ0NvbnRleHQuYXBwbHkoXG4gICAgICAgICgpID0+IGZyb21TbmFwc2hvdChtb2J4S2V5c3RvbmVUeXBlLCBsb3JvSnNvbiksXG4gICAgICAgIGJpbmRpbmdDb250ZXh0XG4gICAgICApXG4gICAgICBsb3JvQmluZGluZ0NvbnRleHQuc2V0KHJlc3VsdCwgeyAuLi5iaW5kaW5nQ29udGV4dCwgYm91bmRPYmplY3Q6IHJlc3VsdCB9KVxuICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH0gZmluYWxseSB7XG4gICAgICBkaXNwb3NlR2xvYmFsTGlzdGVuZXIoKVxuICAgIH1cbiAgfVxuXG4gIGJvdW5kT2JqZWN0ID0gY3JlYXRlQm91bmRPYmplY3QoKVxuXG4gIC8vIEdldCB0aGUgcGF0aCB0byB0aGUgcm9vdCBMb3JvIG9iamVjdCBmb3IgcGF0aCByZXNvbHV0aW9uXG4gIGNvbnN0IHJvb3RMb3JvUGF0aCA9IGxvcm9Eb2MuZ2V0UGF0aFRvQ29udGFpbmVyKGxvcm9PYmplY3QuaWQpID8/IFtdXG5cbiAgLy8gYmluZCBhbnkgY2hhbmdlcyBmcm9tIExvcm8gdG8gbW9ieC1rZXlzdG9uZVxuICBjb25zdCBsb3JvU3Vic2NyaWJlQ2IgPSBhY3Rpb24oKGV2ZW50QmF0Y2g6IExvcm9FdmVudEJhdGNoKSA9PiB7XG4gICAgLy8gU2tpcCBjaGFuZ2VzIHRoYXQgb3JpZ2luYXRlZCBmcm9tIHRoaXMgYmluZGluZ1xuICAgIGlmIChldmVudEJhdGNoLm9yaWdpbiA9PT0gbG9yb09yaWdpbikge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gVHJhY2sgbmV3bHkgaW5zZXJ0ZWQgY29udGFpbmVycyB0byBhdm9pZCBkb3VibGUtcHJvY2Vzc2luZyB0aGVpciBldmVudHNcbiAgICBjb25zdCBuZXdseUluc2VydGVkQ29udGFpbmVycyA9IG5ldyBTZXQ8Q29udGFpbmVySUQ+KClcblxuICAgIC8vIENyZWF0ZSBhIG1hcCB0byBzdG9yZSByZWNvbmNpbGlhdGlvbiBkYXRhIGZvciB0aGlzIGJhdGNoXG4gICAgY29uc3QgcmVjb25jaWxpYXRpb25NYXA6IFJlY29uY2lsaWF0aW9uTWFwID0gbmV3IE1hcCgpXG5cbiAgICAvLyBDb2xsZWN0IGluaXQgY2hhbmdlcyB0aGF0IG9jY3VyIGR1cmluZyBldmVudCBhcHBsaWNhdGlvblxuICAgIC8vIChlLmcuLCBmcm9tU25hcHNob3QgY2FsbHMgdGhhdCB0cmlnZ2VyIG9uSW5pdCBob29rcylcbiAgICAvLyBXZSBzdG9yZSBib3RoIHRhcmdldCBhbmQgY2hhbmdlIHNvIHdlIGNhbiBjb21wdXRlIHRoZSBjb3JyZWN0IHBhdGggbGF0ZXJcbiAgICAvLyBTbmFwc2hvdHMgYXJlIGNhcHR1cmVkIGltbWVkaWF0ZWx5IHRvIHByZXNlcnZlIHZhbHVlcyBhdCBpbml0IHRpbWVcbiAgICBjb25zdCBpbml0Q2hhbmdlczogeyB0YXJnZXQ6IG9iamVjdDsgY2hhbmdlOiBEZWVwQ2hhbmdlIH1bXSA9IFtdXG4gICAgY29uc3QgZGlzcG9zZUdsb2JhbExpc3RlbmVyID0gb25HbG9iYWxEZWVwQ2hhbmdlKCh0YXJnZXQsIGNoYW5nZSkgPT4ge1xuICAgICAgaWYgKGNoYW5nZS5pc0luaXQpIHtcbiAgICAgICAgaW5pdENoYW5nZXMucHVzaCh7IHRhcmdldCwgY2hhbmdlOiBjYXB0dXJlQ2hhbmdlU25hcHNob3RzKGNoYW5nZSkgfSlcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgYXBwbHlpbmdMb3JvQ2hhbmdlc1RvTW9ieEtleXN0b25lKytcbiAgICB0cnkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZm9yIChjb25zdCBldmVudCBvZiBldmVudEJhdGNoLmV2ZW50cykge1xuICAgICAgICAgIGFwcGx5TG9yb0V2ZW50VG9Nb2J4KFxuICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICBsb3JvRG9jLFxuICAgICAgICAgICAgYm91bmRPYmplY3QsXG4gICAgICAgICAgICByb290TG9yb1BhdGgsXG4gICAgICAgICAgICByZWNvbmNpbGlhdGlvbk1hcCxcbiAgICAgICAgICAgIG5ld2x5SW5zZXJ0ZWRDb250YWluZXJzXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBkaXNwb3NlR2xvYmFsTGlzdGVuZXIoKVxuICAgICAgfVxuXG4gICAgICAvLyBTeW5jIGJhY2sgYW55IGluaXQtdGltZSBtdXRhdGlvbnMgZnJvbSBmcm9tU25hcHNob3QgY2FsbHNcbiAgICAgIC8vIChlLmcuLCBvbkluaXQgaG9va3MgdGhhdCBtb2RpZnkgdGhlIG1vZGVsKVxuICAgICAgLy8gVGhpcyBpcyBuZWVkZWQgYmVjYXVzZSBpbml0IGNoYW5nZXMgZHVyaW5nIExvcm8gZXZlbnQgaGFuZGxpbmcgYXJlIG5vdFxuICAgICAgLy8gY2FwdHVyZWQgYnkgdGhlIG1haW4gb25EZWVwQ2hhbmdlIChpdCBza2lwcyBjaGFuZ2VzIHdoZW4gYXBwbHlpbmdMb3JvQ2hhbmdlc1RvTW9ieEtleXN0b25lID4gMClcbiAgICAgIGlmIChpbml0Q2hhbmdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGxvcm9Eb2Muc2V0TmV4dENvbW1pdE9yaWdpbihsb3JvT3JpZ2luKVxuXG4gICAgICAgIGZvciAoY29uc3QgeyB0YXJnZXQsIGNoYW5nZSB9IG9mIGluaXRDaGFuZ2VzKSB7XG4gICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgcGF0aCBmcm9tIGJvdW5kT2JqZWN0IHRvIHRoZSB0YXJnZXRcbiAgICAgICAgICBjb25zdCBwYXRoVG9UYXJnZXQgPSBnZXRQYXJlbnRUb0NoaWxkUGF0aChib3VuZE9iamVjdCwgdGFyZ2V0KVxuICAgICAgICAgIGlmIChwYXRoVG9UYXJnZXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IGNoYW5nZSB3aXRoIHRoZSBjb3JyZWN0IHBhdGggZnJvbSB0aGUgcm9vdFxuICAgICAgICAgICAgY29uc3QgY2hhbmdlV2l0aENvcnJlY3RQYXRoOiBEZWVwQ2hhbmdlID0ge1xuICAgICAgICAgICAgICAuLi5jaGFuZ2UsXG4gICAgICAgICAgICAgIHBhdGg6IFsuLi5wYXRoVG9UYXJnZXQsIC4uLmNoYW5nZS5wYXRoXSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFwcGx5TW9ieENoYW5nZVRvTG9yb09iamVjdChjaGFuZ2VXaXRoQ29ycmVjdFBhdGgsIGxvcm9PYmplY3QpXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbG9yb0RvYy5jb21taXQoKVxuICAgICAgfVxuXG4gICAgICAvLyBVcGRhdGUgc25hcHNob3QgdHJhY2tpbmc6IHRoZSBMb3JvIGNvbnRhaW5lciBpcyBub3cgaW4gc3luYyB3aXRoIHRoZSBjdXJyZW50IE1vYlggc25hcHNob3RcbiAgICAgIC8vIFRoaXMgZW5hYmxlcyB0aGUgbWVyZ2Ugb3B0aW1pemF0aW9uIHRvIHNraXAgdW5jaGFuZ2VkIHN1YnRyZWVzIGR1cmluZyByZWNvbmNpbGlhdGlvblxuICAgICAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTWFwIHx8IGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICAgICAgc2V0TG9yb0NvbnRhaW5lclNuYXBzaG90KGxvcm9PYmplY3QsIGdldFNuYXBzaG90KGJvdW5kT2JqZWN0KSlcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXBwbHlpbmdMb3JvQ2hhbmdlc1RvTW9ieEtleXN0b25lLS1cbiAgICB9XG4gIH0pXG4gIGNvbnN0IGxvcm9VbnN1YnNjcmliZSA9IGxvcm9Eb2Muc3Vic2NyaWJlKGxvcm9TdWJzY3JpYmVDYilcblxuICAvLyBiaW5kIGFueSBjaGFuZ2VzIGZyb20gbW9ieC1rZXlzdG9uZSB0byBMb3JvXG4gIC8vIENvbGxlY3QgY2hhbmdlcyBkdXJpbmcgYW4gYWN0aW9uIGFuZCBhcHBseSB0aGVtIGFmdGVyIHRoZSBhY3Rpb24gY29tcGxldGVzXG4gIGxldCBwZW5kaW5nQ2hhbmdlczogKERlZXBDaGFuZ2UgfCBBcnJheU1vdmVDaGFuZ2UpW10gPSBbXVxuXG4gIGNvbnN0IGRpc3Bvc2VPbkRlZXBDaGFuZ2UgPSBvbkRlZXBDaGFuZ2UoYm91bmRPYmplY3QsIChjaGFuZ2UpID0+IHtcbiAgICAvLyBTa2lwIGlmIHdlJ3JlIGN1cnJlbnRseSBhcHBseWluZyBMb3JvIGNoYW5nZXMgdG8gTW9iWFxuICAgIGlmIChiaW5kaW5nQ29udGV4dC5pc0FwcGx5aW5nTG9yb0NoYW5nZXNUb01vYnhLZXlzdG9uZSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gU2tpcCBpbml0IGNoYW5nZXMgLSB0aGV5IGFyZSBoYW5kbGVkIGJ5IHRoZSBnZXRTbmFwc2hvdCArIG1lcmdlIGF0IHRoZSBlbmQgb2YgYmluZGluZ1xuICAgIGlmIChjaGFuZ2UuaXNJbml0KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB0aGlzIGlzIHBhcnQgb2YgYSBtb3ZlV2l0aGluQXJyYXkgb3BlcmF0aW9uXG4gICAgaWYgKGNoYW5nZS50eXBlID09PSBEZWVwQ2hhbmdlVHlwZS5BcnJheVNwbGljZSkge1xuICAgICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlUGF0aChib3VuZE9iamVjdCwgY2hhbmdlLnBhdGgpXG4gICAgICBpZiAocmVzb2x2ZWQucmVzb2x2ZWQgJiYgaXNJbk1vdmVDb250ZXh0Rm9yQXJyYXkocmVzb2x2ZWQudmFsdWUgYXMgdW5rbm93bltdKSkge1xuICAgICAgICBjb25zdCBtb3ZlUmVzdWx0ID0gcHJvY2Vzc0NoYW5nZUZvck1vdmUoY2hhbmdlKVxuXG4gICAgICAgIGlmIChtb3ZlUmVzdWx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAvLyBJbnRlcmNlcHRlZCBidXQgbW92ZSBub3QgY29tcGxldGUgLSBza2lwIHRoaXMgY2hhbmdlXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICAvLyBNb3ZlIGNvbXBsZXRlIC0gYWRkIHRoZSBtb3ZlIGNoYW5nZSBpbnN0ZWFkXG4gICAgICAgIHBlbmRpbmdDaGFuZ2VzLnB1c2gobW92ZVJlc3VsdClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2FwdHVyZSBzbmFwc2hvdHMgbm93IGJlZm9yZSB0aGUgdmFsdWVzIGNhbiBiZSBtdXRhdGVkIHdpdGhpbiB0aGUgc2FtZSB0cmFuc2FjdGlvbi5cbiAgICAvLyBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIGNoYW5nZXMgYXJlIGNvbGxlY3RlZCBhbmQgYXBwbGllZCBhZnRlciB0aGUgYWN0aW9uIGNvbXBsZXRlcyxcbiAgICAvLyBieSB3aGljaCB0aW1lIHRoZSBvcmlnaW5hbCB2YWx1ZXMgbWF5IGhhdmUgYmVlbiBtb2RpZmllZC5cbiAgICAvLyBFeGFtcGxlOiBgb2JqLml0ZW1zID0gW2EsIGJdOyBvYmouaXRlbXMuc3BsaWNlKDAsIDEpYCAtIHdpdGhvdXQgZWFybHkgY2FwdHVyZSxcbiAgICAvLyB0aGUgT2JqZWN0VXBkYXRlIGZvciBgaXRlbXNgIHdvdWxkIGdldCB0aGUgcG9zdC1zcGxpY2UgYXJyYXkgc3RhdGUuXG4gICAgcGVuZGluZ0NoYW5nZXMucHVzaChjYXB0dXJlQ2hhbmdlU25hcHNob3RzKGNoYW5nZSkpXG4gIH0pXG5cbiAgLy8gQXBwbHkgY29sbGVjdGVkIGNoYW5nZXMgd2hlbiBzbmFwc2hvdCBjaGFuZ2VzIChpLmUuLCBhZnRlciBhY3Rpb24gY29tcGxldGVzKVxuICAvLyBBbHNvIG5vdGlmeSB0aGF0IHRoZSBsb3JvIGNvbnRhaW5lciBhdG9tcyBoYXZlIGJlZW4gdXBkYXRlZFxuICBjb25zdCBkaXNwb3NlT25TbmFwc2hvdCA9IG9uU25hcHNob3QoYm91bmRPYmplY3QsICgpID0+IHtcbiAgICBpZiAocGVuZGluZ0NoYW5nZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBjaGFuZ2VzVG9BcHBseSA9IHBlbmRpbmdDaGFuZ2VzXG4gICAgcGVuZGluZ0NoYW5nZXMgPSBbXVxuXG4gICAgLy8gU2tpcCBpZiB3ZSdyZSBjdXJyZW50bHkgYXBwbHlpbmcgTG9ybyBjaGFuZ2VzIHRvIE1vYlhcbiAgICBpZiAoYmluZGluZ0NvbnRleHQuaXNBcHBseWluZ0xvcm9DaGFuZ2VzVG9Nb2J4S2V5c3RvbmUpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGxvcm9Eb2Muc2V0TmV4dENvbW1pdE9yaWdpbihsb3JvT3JpZ2luKVxuXG4gICAgLy8gQXBwbHkgYWxsIGNoYW5nZXMgZGlyZWN0bHkgdG8gTG9yb1xuICAgIGZvciAoY29uc3QgY2hhbmdlIG9mIGNoYW5nZXNUb0FwcGx5KSB7XG4gICAgICBhcHBseU1vYnhDaGFuZ2VUb0xvcm9PYmplY3QoY2hhbmdlLCBsb3JvT2JqZWN0KVxuICAgIH1cblxuICAgIGxvcm9Eb2MuY29tbWl0KClcblxuICAgIC8vIFVwZGF0ZSBzbmFwc2hvdCB0cmFja2luZzogdGhlIExvcm8gY29udGFpbmVyIGlzIG5vdyBpbiBzeW5jIHdpdGggdGhlIGN1cnJlbnQgTW9iWCBzbmFwc2hvdFxuICAgIGlmIChsb3JvT2JqZWN0IGluc3RhbmNlb2YgTG9yb01hcCB8fCBsb3JvT2JqZWN0IGluc3RhbmNlb2YgTG9yb01vdmFibGVMaXN0KSB7XG4gICAgICBzZXRMb3JvQ29udGFpbmVyU25hcHNob3QobG9yb09iamVjdCwgZ2V0U25hcHNob3QoYm91bmRPYmplY3QpKVxuICAgIH1cblxuICAgIC8vIE5vdGlmeSBNb2JYIHRoYXQgdGhlIExvcm8gY29udGFpbmVyIGhhcyBiZWVuIHVwZGF0ZWRcbiAgICBnZXRPckNyZWF0ZUxvcm9Db2xsZWN0aW9uQXRvbShsb3JvT2JqZWN0KS5yZXBvcnRDaGFuZ2VkKClcbiAgfSlcblxuICAvLyBTeW5jIHRoZSBtb2RlbCBzbmFwc2hvdCB0byB0aGUgQ1JEVCBpZiBhbnkgaW5pdCBjaGFuZ2VzIG9jY3VycmVkLlxuICAvLyBJbml0IGNoYW5nZXMgaW5jbHVkZTogZGVmYXVsdHMgYmVpbmcgYXBwbGllZCwgb25Jbml0IGhvb2tzIG11dGF0aW5nIHRoZSBtb2RlbC5cbiAgLy8gVGhpcyBpcyBhbiBvcHRpbWl6YXRpb246IGlmIG5vIGluaXQgY2hhbmdlcyBvY2N1cnJlZCwgd2Ugc2tpcCB0aGUgc3luYyBlbnRpcmVseS5cbiAgY29uc3QgZmluYWxTbmFwc2hvdCA9IGdldFNuYXBzaG90KGJvdW5kT2JqZWN0KVxuXG4gIGlmIChoYXNJbml0Q2hhbmdlcykge1xuICAgIGxvcm9Eb2Muc2V0TmV4dENvbW1pdE9yaWdpbihsb3JvT3JpZ2luKVxuXG4gICAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTWFwKSB7XG4gICAgICBhcHBseUpzb25PYmplY3RUb0xvcm9NYXAobG9yb09iamVjdCwgZmluYWxTbmFwc2hvdCBhcyBQbGFpbk9iamVjdCwgeyBtb2RlOiBcIm1lcmdlXCIgfSlcbiAgICB9IGVsc2UgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICAgIGFwcGx5SnNvbkFycmF5VG9Mb3JvTW92YWJsZUxpc3QobG9yb09iamVjdCwgZmluYWxTbmFwc2hvdCBhcyBQbGFpbkFycmF5LCB7IG1vZGU6IFwibWVyZ2VcIiB9KVxuICAgIH0gZWxzZSBpZiAobG9yb09iamVjdCBpbnN0YW5jZW9mIExvcm9UZXh0KSB7XG4gICAgICAvLyBGb3IgTG9yb1RleHQsIHdlIG5lZWQgdG8gaGFuZGxlIExvcm9UZXh0TW9kZWwgc25hcHNob3RcbiAgICAgIGNvbnN0IHNuYXBzaG90ID0gZmluYWxTbmFwc2hvdCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlxuICAgICAgaWYgKHNuYXBzaG90LiRtb2RlbFR5cGUgPT09IGxvcm9UZXh0TW9kZWxJZCkge1xuICAgICAgICAvLyBDbGVhciBleGlzdGluZyBjb250ZW50IGFuZCBhcHBseSBkZWx0YXNcbiAgICAgICAgaWYgKGxvcm9PYmplY3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGxvcm9PYmplY3QuZGVsZXRlKDAsIGxvcm9PYmplY3QubGVuZ3RoKVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGRlbHRhcyA9IGV4dHJhY3RUZXh0RGVsdGFGcm9tU25hcHNob3Qoc25hcHNob3QuZGVsdGFMaXN0KVxuICAgICAgICBpZiAoZGVsdGFzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBhcHBseURlbHRhVG9Mb3JvVGV4dChsb3JvT2JqZWN0LCBkZWx0YXMpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBsb3JvRG9jLmNvbW1pdCgpXG4gIH1cblxuICAvLyBBbHdheXMgdXBkYXRlIHNuYXBzaG90IHRyYWNraW5nIGFmdGVyIGJpbmRpbmcgaW5pdGlhbGl6YXRpb25cbiAgLy8gVGhpcyBlbnN1cmVzIHRoZSBtZXJnZSBvcHRpbWl6YXRpb24gY2FuIHNraXAgdW5jaGFuZ2VkIHN1YnRyZWVzIGluIGZ1dHVyZSByZWNvbmNpbGlhdGlvbnNcbiAgaWYgKGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTWFwIHx8IGxvcm9PYmplY3QgaW5zdGFuY2VvZiBMb3JvTW92YWJsZUxpc3QpIHtcbiAgICBzZXRMb3JvQ29udGFpbmVyU25hcHNob3QobG9yb09iamVjdCwgZmluYWxTbmFwc2hvdClcbiAgfVxuXG4gIGNvbnN0IGRpc3Bvc2UgPSAoKSA9PiB7XG4gICAgbG9yb1Vuc3Vic2NyaWJlKClcbiAgICBkaXNwb3NlT25EZWVwQ2hhbmdlKClcbiAgICBkaXNwb3NlT25TbmFwc2hvdCgpXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGJvdW5kT2JqZWN0LFxuICAgIGRpc3Bvc2UsXG4g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