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