ts2famix 1.4.1 → 2.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/README.md +1 -1
- package/dist/analyze.js +4 -2
- package/dist/analyze_functions/process_functions.js +248 -100
- package/dist/famix2puml.js +1 -0
- package/dist/famix_functions/EntityDictionary.js +661 -155
- package/dist/famix_functions/helpers_creation.js +26 -6
- package/dist/fqn.js +156 -69
- package/dist/lib/famix/src/famix_JSON_exporter.js +1 -0
- package/dist/lib/famix/src/famix_base_element.js +1 -0
- package/dist/lib/famix/src/famix_repository.js +9 -8
- package/dist/lib/famix/src/index.js +1 -0
- package/dist/lib/famix/src/model/famix/access.js +3 -2
- package/dist/lib/famix/src/model/famix/accessor.js +1 -0
- package/dist/lib/famix/src/model/famix/alias.js +2 -1
- package/dist/lib/famix/src/model/famix/arrowFunction.js +17 -0
- package/dist/lib/famix/src/model/famix/behavioral_entity.js +13 -15
- package/dist/lib/famix/src/model/famix/class.js +1 -0
- package/dist/lib/famix/src/model/famix/comment.js +2 -1
- package/dist/lib/famix/src/model/famix/concretisation.js +31 -0
- package/dist/lib/famix/src/model/famix/container_entity.js +7 -6
- package/dist/lib/famix/src/model/famix/decorator.js +2 -1
- package/dist/lib/famix/src/model/famix/entity.js +1 -0
- package/dist/lib/famix/src/model/famix/enum.js +2 -1
- package/dist/lib/famix/src/model/famix/enum_value.js +2 -1
- package/dist/lib/famix/src/model/famix/function.js +1 -0
- package/dist/lib/famix/src/model/famix/implicit_variable.js +1 -0
- package/dist/lib/famix/src/model/famix/import_clause.js +5 -3
- package/dist/lib/famix/src/model/famix/index.js +18 -11
- package/dist/lib/famix/src/model/famix/indexed_file_anchor.js +3 -2
- package/dist/lib/famix/src/model/famix/inheritance.js +3 -2
- package/dist/lib/famix/src/model/famix/interface.js +2 -1
- package/dist/lib/famix/src/model/famix/invocation.js +3 -2
- package/dist/lib/famix/src/model/famix/method.js +2 -1
- package/dist/lib/famix/src/model/famix/module.js +53 -0
- package/dist/lib/famix/src/model/famix/named_entity.js +4 -3
- package/dist/lib/famix/src/model/famix/parameter.js +2 -1
- package/dist/lib/famix/src/model/famix/parameterConcretisation.js +44 -0
- package/dist/lib/famix/src/model/famix/parameter_type.js +22 -1
- package/dist/lib/famix/src/model/famix/parametric_arrow_function.js +31 -0
- package/dist/lib/famix/src/model/famix/parametric_class.js +44 -0
- package/dist/lib/famix/src/model/famix/parametric_function.js +31 -0
- package/dist/lib/famix/src/model/famix/parametric_interface.js +44 -0
- package/dist/lib/famix/src/model/famix/parametric_method.js +31 -0
- package/dist/lib/famix/src/model/famix/primitive_type.js +1 -0
- package/dist/lib/famix/src/model/famix/property.js +91 -9
- package/dist/lib/famix/src/model/famix/reference.js +3 -2
- package/dist/lib/famix/src/model/famix/scoping_entity.js +12 -10
- package/dist/lib/famix/src/model/famix/script_entity.js +1 -2
- package/dist/lib/famix/src/model/famix/source_anchor.js +1 -0
- package/dist/lib/famix/src/model/famix/source_language.js +1 -1
- package/dist/lib/famix/src/model/famix/sourced_entity.js +2 -1
- package/dist/lib/famix/src/model/famix/structural_entity.js +1 -0
- package/dist/lib/famix/src/model/famix/text_anchor.js +1 -0
- package/dist/lib/famix/src/model/famix/type.js +6 -4
- package/dist/lib/famix/src/model/famix/variable.js +1 -0
- package/dist/lib/ts-complex/cyclomatic-service.js +2 -2
- package/dist/ts2famix-cli-wrapper.js +16 -0
- package/dist/ts2famix-cli.js +8 -1
- package/dist/ts2famix-tsconfig.js +1 -0
- package/doc-uml/famix-typescript-model.puml +559 -0
- package/doc-uml/famix-typescript-model.svg +1 -0
- package/jest.config.json +2 -1
- package/package.json +10 -10
- package/src/analyze.ts +22 -21
- package/src/analyze_functions/process_functions.ts +272 -96
- package/src/famix_functions/EntityDictionary.ts +731 -182
- package/src/famix_functions/helpers_creation.ts +28 -2
- package/src/fqn.ts +132 -10
- package/src/lib/famix/src/famix_repository.ts +9 -9
- package/src/lib/famix/src/model/famix/access.ts +2 -2
- package/src/lib/famix/src/model/famix/alias.ts +1 -1
- package/src/lib/famix/src/model/famix/arrowFunction.ts +15 -0
- package/src/lib/famix/src/model/famix/behavioral_entity.ts +12 -19
- package/src/lib/famix/src/model/famix/comment.ts +1 -1
- package/src/lib/famix/src/model/famix/concretisation.ts +42 -0
- package/src/lib/famix/src/model/famix/container_entity.ts +6 -6
- package/src/lib/famix/src/model/famix/decorator.ts +1 -1
- package/src/lib/famix/src/model/famix/enum.ts +1 -1
- package/src/lib/famix/src/model/famix/enum_value.ts +1 -1
- package/src/lib/famix/src/model/famix/import_clause.ts +4 -3
- package/src/lib/famix/src/model/famix/index.ts +8 -5
- package/src/lib/famix/src/model/famix/indexed_file_anchor.ts +2 -2
- package/src/lib/famix/src/model/famix/inheritance.ts +3 -4
- package/src/lib/famix/src/model/famix/interface.ts +1 -1
- package/src/lib/famix/src/model/famix/invocation.ts +2 -2
- package/src/lib/famix/src/model/famix/method.ts +1 -1
- package/src/lib/famix/src/model/famix/module.ts +67 -1
- package/src/lib/famix/src/model/famix/named_entity.ts +3 -3
- package/src/lib/famix/src/model/famix/parameter.ts +1 -1
- package/src/lib/famix/src/model/famix/parameterConcretisation.ts +54 -0
- package/src/lib/famix/src/model/famix/parameter_type.ts +33 -6
- package/src/lib/famix/src/model/famix/parametric_arrow_function.ts +32 -0
- package/src/lib/famix/src/model/famix/parametric_class.ts +49 -0
- package/src/lib/famix/src/model/famix/parametric_function.ts +32 -0
- package/src/lib/famix/src/model/famix/parametric_interface.ts +49 -0
- package/src/lib/famix/src/model/famix/parametric_method.ts +32 -0
- package/src/lib/famix/src/model/famix/property.ts +109 -11
- package/src/lib/famix/src/model/famix/reference.ts +2 -2
- package/src/lib/famix/src/model/famix/scoping_entity.ts +12 -11
- package/src/lib/famix/src/model/famix/script_entity.ts +0 -2
- package/src/lib/famix/src/model/famix/source_language.ts +0 -1
- package/src/lib/famix/src/model/famix/sourced_entity.ts +1 -1
- package/src/lib/famix/src/model/famix/type.ts +5 -4
- package/src/ts2famix-cli-wrapper.ts +17 -0
- package/src/ts2famix-cli.ts +7 -1
- package/tsconfig.json +5 -5
- package/dist/lib/famix/src/model/famix/association.js +0 -36
- package/dist/lib/famix/src/model/famix/namespace.js +0 -24
- package/dist/lib/famix/src/model/famix/parameterizable_class.js +0 -30
- package/dist/lib/famix/src/model/famix/parameterizable_interface.js +0 -30
- package/dist/lib/famix/src/model/famix/parameterized_type.js +0 -36
- package/doc-uml/metamodel-full.svg +0 -1
- package/doc-uml/metamodel.svg +0 -1
- package/plantuml.jar +0 -0
- package/src/lib/famix/src/model/famix/association.ts +0 -44
- package/src/lib/famix/src/model/famix/namespace.ts +0 -28
- package/src/lib/famix/src/model/famix/parameterizable_class.ts +0 -31
- package/src/lib/famix/src/model/famix/parameterizable_interface.ts +0 -31
- package/src/lib/famix/src/model/famix/parameterized_type.ts +0 -40
|
@@ -23,24 +23,36 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.
|
|
26
|
+
exports.currentCC = exports.listOfExportMaps = exports.modules = exports.interfaces = exports.classes = exports.accessMap = exports.methodsAndFunctionsWithId = void 0;
|
|
27
|
+
exports.getModulePath = getModulePath;
|
|
28
|
+
exports.getImplementedOrExtendedInterfaces = getImplementedOrExtendedInterfaces;
|
|
29
|
+
exports.processFiles = processFiles;
|
|
30
|
+
exports.isAmbient = isAmbient;
|
|
31
|
+
exports.isNamespace = isNamespace;
|
|
32
|
+
exports.processAccesses = processAccesses;
|
|
33
|
+
exports.processImportClausesForImportEqualsDeclarations = processImportClausesForImportEqualsDeclarations;
|
|
34
|
+
exports.processImportClausesForModules = processImportClausesForModules;
|
|
35
|
+
exports.processInheritances = processInheritances;
|
|
36
|
+
exports.processInvocations = processInvocations;
|
|
37
|
+
exports.processConcretisations = processConcretisations;
|
|
27
38
|
const ts_morph_1 = require("ts-morph");
|
|
28
39
|
const Famix = __importStar(require("../lib/famix/src/model/famix"));
|
|
29
40
|
const cyclomatic_service_1 = require("../lib/ts-complex/cyclomatic-service");
|
|
30
41
|
const fs = __importStar(require("fs"));
|
|
31
42
|
const analyze_1 = require("../analyze");
|
|
43
|
+
const fqn_1 = require("../fqn");
|
|
32
44
|
exports.methodsAndFunctionsWithId = new Map(); // Maps the Famix method, constructor, getter, setter and function ids to their ts-morph method, constructor, getter, setter or function object
|
|
33
45
|
exports.accessMap = new Map(); // Maps the Famix parameter, variable, property and enum value ids to their ts-morph parameter, variable, property or enum member object
|
|
34
46
|
exports.classes = new Array(); // Array of all the classes of the source files
|
|
35
47
|
exports.interfaces = new Array(); // Array of all the interfaces of the source files
|
|
36
48
|
exports.modules = new Array(); // Array of all the source files which are modules
|
|
37
|
-
exports.
|
|
49
|
+
exports.listOfExportMaps = new Array(); // Array of all the export maps
|
|
38
50
|
/**
|
|
39
51
|
* Checks if the file has any imports or exports to be considered a module
|
|
40
52
|
* @param sourceFile A source file
|
|
41
53
|
* @returns A boolean indicating if the file is a module
|
|
42
54
|
*/
|
|
43
|
-
function
|
|
55
|
+
function isSourceFileAModule(sourceFile) {
|
|
44
56
|
return sourceFile.getImportDeclarations().length > 0 || sourceFile.getExportedDeclarations().size > 0;
|
|
45
57
|
}
|
|
46
58
|
/**
|
|
@@ -63,7 +75,6 @@ function getModulePath(i) {
|
|
|
63
75
|
}
|
|
64
76
|
return path;
|
|
65
77
|
}
|
|
66
|
-
exports.getModulePath = getModulePath;
|
|
67
78
|
/**
|
|
68
79
|
* Gets the interfaces implemented or extended by a class or an interface
|
|
69
80
|
* @param interfaces An array of interfaces
|
|
@@ -90,7 +101,6 @@ function getImplementedOrExtendedInterfaces(interfaces, subClass) {
|
|
|
90
101
|
});
|
|
91
102
|
return implementedOrExtendedInterfaces;
|
|
92
103
|
}
|
|
93
|
-
exports.getImplementedOrExtendedInterfaces = getImplementedOrExtendedInterfaces;
|
|
94
104
|
/**
|
|
95
105
|
* Builds a Famix model for an array of source files
|
|
96
106
|
* @param sourceFiles An array of source files
|
|
@@ -106,17 +116,18 @@ function processFiles(sourceFiles) {
|
|
|
106
116
|
processFile(file);
|
|
107
117
|
});
|
|
108
118
|
}
|
|
109
|
-
exports.processFiles = processFiles;
|
|
110
119
|
/**
|
|
111
120
|
* Builds a Famix model for a source file
|
|
112
121
|
* @param f A source file
|
|
113
122
|
*/
|
|
114
123
|
function processFile(f) {
|
|
115
|
-
const isModule =
|
|
124
|
+
const isModule = isSourceFileAModule(f);
|
|
116
125
|
if (isModule) {
|
|
117
126
|
exports.modules.push(f);
|
|
118
|
-
exports.exportedMap.push(f.getExportedDeclarations());
|
|
119
127
|
}
|
|
128
|
+
const exportMap = f.getExportedDeclarations();
|
|
129
|
+
if (exportMap)
|
|
130
|
+
exports.listOfExportMaps.push(exportMap);
|
|
120
131
|
const fmxFile = analyze_1.entityDictionary.createOrGetFamixFile(f, isModule);
|
|
121
132
|
analyze_1.logger.debug(`processFile: file: ${f.getBaseName()}, fqn = ${fmxFile.getFullyQualifiedName()}`);
|
|
122
133
|
processComments(f, fmxFile);
|
|
@@ -126,25 +137,34 @@ function processFile(f) {
|
|
|
126
137
|
processVariables(f, fmxFile);
|
|
127
138
|
processEnums(f, fmxFile);
|
|
128
139
|
processFunctions(f, fmxFile);
|
|
129
|
-
|
|
140
|
+
processModules(f, fmxFile);
|
|
141
|
+
}
|
|
142
|
+
function isAmbient(node) {
|
|
143
|
+
// An ambient module has the DeclareKeyword modifier.
|
|
144
|
+
return (node.getModifiers()?.some(modifier => modifier.getKind() === ts_morph_1.SyntaxKind.DeclareKeyword)) ?? false;
|
|
145
|
+
}
|
|
146
|
+
function isNamespace(node) {
|
|
147
|
+
// Check if the module declaration has a namespace keyword.
|
|
148
|
+
// This approach uses the getChildren() method to inspect the syntax directly.
|
|
149
|
+
return node.getChildrenOfKind(ts_morph_1.SyntaxKind.NamespaceKeyword).length > 0;
|
|
130
150
|
}
|
|
131
151
|
/**
|
|
132
|
-
* Builds a Famix model for a namespace
|
|
152
|
+
* Builds a Famix model for a module (also namespace)
|
|
133
153
|
* @param m A namespace
|
|
134
|
-
* @returns A Famix.
|
|
135
|
-
*/
|
|
136
|
-
function
|
|
137
|
-
const
|
|
138
|
-
analyze_1.logger.debug(`
|
|
139
|
-
processComments(m,
|
|
140
|
-
processAliases(m,
|
|
141
|
-
processClasses(m,
|
|
142
|
-
processInterfaces(m,
|
|
143
|
-
processVariables(m,
|
|
144
|
-
processEnums(m,
|
|
145
|
-
processFunctions(m,
|
|
146
|
-
|
|
147
|
-
return
|
|
154
|
+
* @returns A Famix.Module representing the module
|
|
155
|
+
*/
|
|
156
|
+
function processModule(m) {
|
|
157
|
+
const fmxModule = analyze_1.entityDictionary.createOrGetFamixModule(m);
|
|
158
|
+
analyze_1.logger.debug(`module: ${m.getName()}, (${m.getType().getText()}), ${fmxModule.getFullyQualifiedName()}`);
|
|
159
|
+
processComments(m, fmxModule);
|
|
160
|
+
processAliases(m, fmxModule);
|
|
161
|
+
processClasses(m, fmxModule);
|
|
162
|
+
processInterfaces(m, fmxModule);
|
|
163
|
+
processVariables(m, fmxModule);
|
|
164
|
+
processEnums(m, fmxModule);
|
|
165
|
+
processFunctions(m, fmxModule);
|
|
166
|
+
processModules(m, fmxModule);
|
|
167
|
+
return fmxModule;
|
|
148
168
|
}
|
|
149
169
|
/**
|
|
150
170
|
* Builds a Famix model for the aliases of a container
|
|
@@ -165,11 +185,34 @@ function processAliases(m, fmxScope) {
|
|
|
165
185
|
*/
|
|
166
186
|
function processClasses(m, fmxScope) {
|
|
167
187
|
analyze_1.logger.debug(`processClasses: ---------- Finding Classes:`);
|
|
168
|
-
m
|
|
188
|
+
const classesInArrowFunctions = getClassesDeclaredInArrowFunctions(m);
|
|
189
|
+
const classes = m.getClasses().concat(classesInArrowFunctions);
|
|
190
|
+
classes.forEach(c => {
|
|
169
191
|
const fmxClass = processClass(c);
|
|
170
192
|
fmxScope.addType(fmxClass);
|
|
171
193
|
});
|
|
172
194
|
}
|
|
195
|
+
function getArrowFunctionClasses(f) {
|
|
196
|
+
const classes = [];
|
|
197
|
+
function findClasses(node) {
|
|
198
|
+
if (node.getKind() === ts_morph_1.SyntaxKind.ClassDeclaration) {
|
|
199
|
+
classes.push(node);
|
|
200
|
+
}
|
|
201
|
+
node.getChildren().forEach(findClasses);
|
|
202
|
+
}
|
|
203
|
+
findClasses(f);
|
|
204
|
+
return classes;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* ts-morph doesn't find classes in arrow functions, so we need to find them manually
|
|
208
|
+
* @param s A source file
|
|
209
|
+
* @returns the ClassDeclaration objects found in arrow functions of the source file
|
|
210
|
+
*/
|
|
211
|
+
function getClassesDeclaredInArrowFunctions(s) {
|
|
212
|
+
const arrowFunctions = s.getDescendantsOfKind(ts_morph_1.SyntaxKind.ArrowFunction);
|
|
213
|
+
const classesInArrowFunctions = arrowFunctions.map(f => getArrowFunctionClasses(f)).flat();
|
|
214
|
+
return classesInArrowFunctions;
|
|
215
|
+
}
|
|
173
216
|
/**
|
|
174
217
|
* Builds a Famix model for the interfaces of a container
|
|
175
218
|
* @param m A container (a source file or a namespace)
|
|
@@ -219,17 +262,24 @@ function processFunctions(m, fmxScope) {
|
|
|
219
262
|
const fmxFunction = processFunction(f);
|
|
220
263
|
fmxScope.addFunction(fmxFunction);
|
|
221
264
|
});
|
|
265
|
+
//find arrow functions
|
|
266
|
+
analyze_1.logger.debug(`Finding Functions:`);
|
|
267
|
+
const arrowFunctions = m.getDescendantsOfKind(ts_morph_1.SyntaxKind.ArrowFunction);
|
|
268
|
+
arrowFunctions.forEach(af => {
|
|
269
|
+
const fmxFunction = processFunction(af);
|
|
270
|
+
fmxScope.addFunction(fmxFunction);
|
|
271
|
+
});
|
|
222
272
|
}
|
|
223
273
|
/**
|
|
224
|
-
* Builds a Famix model for the
|
|
274
|
+
* Builds a Famix model for the modules of a container.
|
|
225
275
|
* @param m A container (a source file or a namespace)
|
|
226
276
|
* @param fmxScope The Famix model of the container
|
|
227
277
|
*/
|
|
228
|
-
function
|
|
229
|
-
analyze_1.logger.debug(`Finding
|
|
278
|
+
function processModules(m, fmxScope) {
|
|
279
|
+
analyze_1.logger.debug(`Finding Modules:`);
|
|
230
280
|
m.getModules().forEach(md => {
|
|
231
|
-
const
|
|
232
|
-
fmxScope.
|
|
281
|
+
const fmxModule = processModule(md);
|
|
282
|
+
fmxScope.addModule(fmxModule);
|
|
233
283
|
});
|
|
234
284
|
}
|
|
235
285
|
/**
|
|
@@ -246,7 +296,7 @@ function processAlias(a) {
|
|
|
246
296
|
/**
|
|
247
297
|
* Builds a Famix model for a class
|
|
248
298
|
* @param c A class
|
|
249
|
-
* @returns A Famix.Class or a Famix.
|
|
299
|
+
* @returns A Famix.Class or a Famix.ParametricClass representing the class
|
|
250
300
|
*/
|
|
251
301
|
function processClass(c) {
|
|
252
302
|
exports.classes.push(c);
|
|
@@ -272,7 +322,7 @@ function processClass(c) {
|
|
|
272
322
|
/**
|
|
273
323
|
* Builds a Famix model for an interface
|
|
274
324
|
* @param i An interface
|
|
275
|
-
* @returns A Famix.Interface or a Famix.
|
|
325
|
+
* @returns A Famix.Interface or a Famix.ParametricInterface representing the interface
|
|
276
326
|
*/
|
|
277
327
|
function processInterface(i) {
|
|
278
328
|
exports.interfaces.push(i);
|
|
@@ -289,7 +339,7 @@ function processInterface(i) {
|
|
|
289
339
|
*/
|
|
290
340
|
function processStructuredType(c, fmxScope) {
|
|
291
341
|
analyze_1.logger.debug(`Finding Properties and Methods:`);
|
|
292
|
-
if (fmxScope instanceof Famix.
|
|
342
|
+
if (fmxScope instanceof Famix.ParametricClass || fmxScope instanceof Famix.ParametricInterface) {
|
|
293
343
|
processTypeParameters(c, fmxScope);
|
|
294
344
|
}
|
|
295
345
|
c.getProperties().forEach(prop => {
|
|
@@ -312,11 +362,12 @@ function processProperty(p) {
|
|
|
312
362
|
analyze_1.logger.debug(` ---> It's a Property${(p instanceof ts_morph_1.PropertySignature) ? "Signature" : "Declaration"}!`);
|
|
313
363
|
const ancestor = p.getFirstAncestorOrThrow();
|
|
314
364
|
analyze_1.logger.debug(` ---> Its first ancestor is a ${ancestor.getKindName()}`);
|
|
365
|
+
// decorators
|
|
315
366
|
if (!(p instanceof ts_morph_1.PropertySignature)) {
|
|
316
367
|
processDecorators(p, fmxProperty);
|
|
317
368
|
// only add access if the p's first ancestor is not a PropertyDeclaration
|
|
318
369
|
if (ancestor.getKindName() !== "PropertyDeclaration") {
|
|
319
|
-
analyze_1.logger.debug(`adding access: ${p.getName()}, (${p.getType().getText()}) Famix ${fmxProperty.getName()}`);
|
|
370
|
+
analyze_1.logger.debug(`adding access to map: ${p.getName()}, (${p.getType().getText()}) Famix ${fmxProperty.getName()} id: ${fmxProperty.id}`);
|
|
320
371
|
exports.accessMap.set(fmxProperty.id, p);
|
|
321
372
|
}
|
|
322
373
|
}
|
|
@@ -329,7 +380,7 @@ function processProperty(p) {
|
|
|
329
380
|
* @returns A Famix.Method or a Famix.Accessor representing the method or the accessor
|
|
330
381
|
*/
|
|
331
382
|
function processMethod(m) {
|
|
332
|
-
const fmxMethod = analyze_1.entityDictionary.
|
|
383
|
+
const fmxMethod = analyze_1.entityDictionary.createOrGetFamixMethod(m, exports.currentCC);
|
|
333
384
|
analyze_1.logger.debug(`Method: ${!(m instanceof ts_morph_1.ConstructorDeclaration) ? m.getName() : "constructor"}, (${m.getType().getText()}), parent: ${m.getParent().getName()}, fqn = ${fmxMethod.getFullyQualifiedName()}`);
|
|
334
385
|
processComments(m, fmxMethod);
|
|
335
386
|
processTypeParameters(m, fmxMethod);
|
|
@@ -353,8 +404,14 @@ function processMethod(m) {
|
|
|
353
404
|
* @returns A Famix.Function representing the function
|
|
354
405
|
*/
|
|
355
406
|
function processFunction(f) {
|
|
356
|
-
|
|
357
|
-
|
|
407
|
+
analyze_1.logger.debug(`Function: ${(f instanceof ts_morph_1.ArrowFunction ? "anonymous" : f.getName() ? f.getName() : "anonymous")}, (${f.getType().getText()}), fqn = ${(0, fqn_1.getFQN)(f)}`);
|
|
408
|
+
let fmxFunction;
|
|
409
|
+
if (f instanceof ts_morph_1.ArrowFunction) {
|
|
410
|
+
fmxFunction = analyze_1.entityDictionary.createFamixArrowFunction(f, exports.currentCC);
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
fmxFunction = analyze_1.entityDictionary.createOrGetFamixFunction(f, exports.currentCC);
|
|
414
|
+
}
|
|
358
415
|
processComments(f, fmxFunction);
|
|
359
416
|
processAliases(f, fmxFunction);
|
|
360
417
|
processTypeParameters(f, fmxFunction);
|
|
@@ -391,8 +448,67 @@ function processParameters(m, fmxScope) {
|
|
|
391
448
|
m.getParameters().forEach(param => {
|
|
392
449
|
const fmxParam = processParameter(param);
|
|
393
450
|
fmxScope.addParameter(fmxParam);
|
|
451
|
+
// Additional handling for Parameter Properties in constructors
|
|
452
|
+
if (m instanceof ts_morph_1.ConstructorDeclaration) {
|
|
453
|
+
// Check if the parameter has any visibility modifier
|
|
454
|
+
if (param.hasModifier(ts_morph_1.SyntaxKind.PrivateKeyword) || param.hasModifier(ts_morph_1.SyntaxKind.PublicKeyword) || param.hasModifier(ts_morph_1.SyntaxKind.ProtectedKeyword) || param.hasModifier(ts_morph_1.SyntaxKind.ReadonlyKeyword)) {
|
|
455
|
+
const classOfConstructor = m.getParent();
|
|
456
|
+
analyze_1.logger.info(`Parameter Property ${param.getName()} in constructor of ${classOfConstructor.getName()}.`);
|
|
457
|
+
// Treat the parameter as a property and add it to the class
|
|
458
|
+
const fmxProperty = processParameterAsProperty(param, classOfConstructor);
|
|
459
|
+
fmxProperty.readOnly = param.hasModifier(ts_morph_1.SyntaxKind.ReadonlyKeyword);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
394
462
|
});
|
|
395
463
|
}
|
|
464
|
+
// This function should create a Famix.Property model from a ParameterDeclaration
|
|
465
|
+
// You'll need to implement it according to your Famix model structure
|
|
466
|
+
function processParameterAsProperty(param, c) {
|
|
467
|
+
// Convert the parameter into a Property
|
|
468
|
+
const propertyRepresentation = convertParameterToPropertyRepresentation(param);
|
|
469
|
+
// Add the property to the class so we can have a PropertyDeclaration object
|
|
470
|
+
c.addProperty(propertyRepresentation);
|
|
471
|
+
const p = c.getProperty(propertyRepresentation.name);
|
|
472
|
+
const fmxProperty = analyze_1.entityDictionary.createFamixProperty(p);
|
|
473
|
+
if (c instanceof ts_morph_1.ClassDeclaration) {
|
|
474
|
+
const fmxClass = analyze_1.entityDictionary.createOrGetFamixClass(c);
|
|
475
|
+
fmxClass.addProperty(fmxProperty);
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
throw new Error("Unexpected type ClassExpression.");
|
|
479
|
+
}
|
|
480
|
+
processComments(p, fmxProperty);
|
|
481
|
+
// remove the property from the class
|
|
482
|
+
p.remove();
|
|
483
|
+
return fmxProperty;
|
|
484
|
+
}
|
|
485
|
+
function convertParameterToPropertyRepresentation(param) {
|
|
486
|
+
// Extract name
|
|
487
|
+
const paramName = param.getName();
|
|
488
|
+
// Extract type
|
|
489
|
+
const paramType = param.getType().getText(param);
|
|
490
|
+
// Determine visibility
|
|
491
|
+
let scope;
|
|
492
|
+
if (param.hasModifier(ts_morph_1.SyntaxKind.PrivateKeyword)) {
|
|
493
|
+
scope = ts_morph_1.Scope.Private;
|
|
494
|
+
}
|
|
495
|
+
else if (param.hasModifier(ts_morph_1.SyntaxKind.ProtectedKeyword)) {
|
|
496
|
+
scope = ts_morph_1.Scope.Protected;
|
|
497
|
+
}
|
|
498
|
+
else if (param.hasModifier(ts_morph_1.SyntaxKind.PublicKeyword)) {
|
|
499
|
+
scope = ts_morph_1.Scope.Public;
|
|
500
|
+
}
|
|
501
|
+
// Determine if readonly
|
|
502
|
+
const isReadonly = param.hasModifier(ts_morph_1.SyntaxKind.ReadonlyKeyword);
|
|
503
|
+
// Create a representation of the property
|
|
504
|
+
const propertyRepresentation = {
|
|
505
|
+
name: paramName,
|
|
506
|
+
type: paramType,
|
|
507
|
+
scope: scope,
|
|
508
|
+
isReadonly: isReadonly,
|
|
509
|
+
};
|
|
510
|
+
return propertyRepresentation;
|
|
511
|
+
}
|
|
396
512
|
/**
|
|
397
513
|
* Builds a Famix model for a parameter
|
|
398
514
|
* @param p A parameter
|
|
@@ -419,7 +535,7 @@ function processTypeParameters(e, fmxScope) {
|
|
|
419
535
|
analyze_1.logger.debug(`Finding Type Parameters:`);
|
|
420
536
|
e.getTypeParameters().forEach(tp => {
|
|
421
537
|
const fmxParam = processTypeParameter(tp);
|
|
422
|
-
fmxScope.
|
|
538
|
+
fmxScope.addGenericParameter(fmxParam);
|
|
423
539
|
});
|
|
424
540
|
}
|
|
425
541
|
/**
|
|
@@ -548,41 +664,40 @@ function processComment(c, fmxScope) {
|
|
|
548
664
|
* @param accessMap A map of parameters, variables, properties and enum members with their id
|
|
549
665
|
*/
|
|
550
666
|
function processAccesses(accessMap) {
|
|
551
|
-
analyze_1.logger.debug(`
|
|
667
|
+
analyze_1.logger.debug(`Creating accesses:`);
|
|
552
668
|
accessMap.forEach((v, id) => {
|
|
553
|
-
analyze_1.logger.debug(`
|
|
554
|
-
try {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
}
|
|
669
|
+
analyze_1.logger.debug(`Accesses to ${v.getName()}`);
|
|
670
|
+
// try {
|
|
671
|
+
const temp_nodes = v.findReferencesAsNodes();
|
|
672
|
+
temp_nodes.forEach(node => processNodeForAccesses(node, id));
|
|
673
|
+
// } catch (error) {
|
|
674
|
+
// logger.error(`> WARNING: got exception "${error}".\nContinuing...`);
|
|
675
|
+
// }
|
|
561
676
|
});
|
|
562
677
|
}
|
|
563
|
-
exports.processAccesses = processAccesses;
|
|
564
678
|
/**
|
|
565
679
|
* Builds a Famix model for an access on a parameter, variable, property or enum member
|
|
566
680
|
* @param n A node
|
|
567
681
|
* @param id An id of a parameter, a variable, a property or an enum member
|
|
568
682
|
*/
|
|
569
683
|
function processNodeForAccesses(n, id) {
|
|
570
|
-
try {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
}
|
|
579
|
-
analyze_1.entityDictionary.createFamixAccess(n, id);
|
|
580
|
-
analyze_1.logger.debug(`processNodeForAccesses: node kind: ${n.getKindName()}, ${n.getText()}, (${n.getType().getText()})`);
|
|
581
|
-
}
|
|
582
|
-
catch (error) {
|
|
583
|
-
analyze_1.logger.error(`> WARNING: got exception ${error}. ScopeDeclaration invalid for ${n.getSymbol().getFullyQualifiedName()}. Continuing...`);
|
|
684
|
+
// try {
|
|
685
|
+
// sometimes node's first ancestor is a PropertyDeclaration, which is not an access
|
|
686
|
+
// see https://github.com/fuhrmanator/FamixTypeScriptImporter/issues/9
|
|
687
|
+
// check for a node whose first ancestor is a property declaration and bail?
|
|
688
|
+
// This may be a bug in ts-morph?
|
|
689
|
+
if (n.getFirstAncestorOrThrow().getKindName() === "PropertyDeclaration") {
|
|
690
|
+
analyze_1.logger.debug(`processNodeForAccesses: node kind: ${n.getKindName()}, ${n.getText()}, (${n.getType().getText()})'s first ancestor is a PropertyDeclaration. Skipping...`);
|
|
691
|
+
return;
|
|
584
692
|
}
|
|
585
|
-
|
|
693
|
+
analyze_1.entityDictionary.createFamixAccess(n, id);
|
|
694
|
+
analyze_1.logger.debug(`processNodeForAccesses: node kind: ${n.getKindName()}, ${n.getText()}, (${n.getType().getText()})`);
|
|
695
|
+
// } catch (error) {
|
|
696
|
+
// logger.error(`> Got exception "${error}".\nScopeDeclaration invalid for "${n.getSymbol().getFullyQualifiedName()}".\nContinuing...`);
|
|
697
|
+
// }
|
|
698
|
+
}
|
|
699
|
+
// exports has name -> Declaration -- the declaration can be used to find the FamixElement
|
|
700
|
+
// handle `import path = require("path")` for example
|
|
586
701
|
function processImportClausesForImportEqualsDeclarations(sourceFiles, exports) {
|
|
587
702
|
analyze_1.logger.info(`Creating import clauses from ImportEqualsDeclarations in source files:`);
|
|
588
703
|
sourceFiles.forEach(sourceFile => {
|
|
@@ -591,41 +706,39 @@ function processImportClausesForImportEqualsDeclarations(sourceFiles, exports) {
|
|
|
591
706
|
// You've found an ImportEqualsDeclaration
|
|
592
707
|
analyze_1.logger.info("Declaration Name:", node.getName());
|
|
593
708
|
analyze_1.logger.info("Module Reference Text:", node.getModuleReference().getText());
|
|
709
|
+
// what's the name of the imported entity?
|
|
710
|
+
// const importedEntity = node.getName();
|
|
594
711
|
// create a famix import clause
|
|
595
712
|
const namedImport = node.getNameNode();
|
|
596
|
-
analyze_1.entityDictionary.
|
|
597
|
-
|
|
713
|
+
analyze_1.entityDictionary.oldCreateFamixImportClause({ importDeclaration: node,
|
|
714
|
+
importerSourceFile: sourceFile,
|
|
598
715
|
moduleSpecifierFilePath: node.getModuleReference().getText(),
|
|
599
716
|
importElement: namedImport,
|
|
600
717
|
isInExports: exports.find(e => e.has(namedImport.getText())) !== undefined,
|
|
601
718
|
isDefaultExport: false });
|
|
719
|
+
// entityDictionary.createFamixImportClause(importedEntity, importingEntity);
|
|
602
720
|
}
|
|
603
721
|
});
|
|
604
722
|
});
|
|
605
723
|
}
|
|
606
|
-
exports.processImportClausesForImportEqualsDeclarations = processImportClausesForImportEqualsDeclarations;
|
|
607
724
|
/**
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
725
|
+
* Builds a Famix model for the import clauses of the source files which are modules
|
|
726
|
+
* @param modules An array of modules
|
|
727
|
+
* @param exports An array of maps of exported declarations
|
|
728
|
+
*/
|
|
612
729
|
function processImportClausesForModules(modules, exports) {
|
|
613
730
|
analyze_1.logger.info(`Creating import clauses from ${modules.length} modules:`);
|
|
614
731
|
modules.forEach(module => {
|
|
732
|
+
const modulePath = module.getFilePath() + module.getBaseName();
|
|
615
733
|
module.getImportDeclarations().forEach(impDecl => {
|
|
616
|
-
analyze_1.logger.
|
|
734
|
+
analyze_1.logger.info(`Importing ${impDecl.getModuleSpecifierValue()} in ${modulePath}`);
|
|
617
735
|
const path = getModulePath(impDecl);
|
|
618
736
|
impDecl.getNamedImports().forEach(namedImport => {
|
|
619
|
-
analyze_1.logger.
|
|
737
|
+
analyze_1.logger.info(`Importing (named) ${namedImport.getName()} from ${impDecl.getModuleSpecifierValue()} in ${modulePath}`);
|
|
620
738
|
const importedEntityName = namedImport.getName();
|
|
621
|
-
let importFoundInExports =
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
importFoundInExports = true;
|
|
625
|
-
}
|
|
626
|
-
});
|
|
627
|
-
analyze_1.entityDictionary.createFamixImportClause({ importDeclaration: impDecl,
|
|
628
|
-
importer: module,
|
|
739
|
+
let importFoundInExports = isInExports(exports, importedEntityName);
|
|
740
|
+
analyze_1.entityDictionary.oldCreateFamixImportClause({ importDeclaration: impDecl,
|
|
741
|
+
importerSourceFile: module,
|
|
629
742
|
moduleSpecifierFilePath: path,
|
|
630
743
|
importElement: namedImport,
|
|
631
744
|
isInExports: importFoundInExports,
|
|
@@ -633,10 +746,10 @@ function processImportClausesForModules(modules, exports) {
|
|
|
633
746
|
});
|
|
634
747
|
const defaultImport = impDecl.getDefaultImport();
|
|
635
748
|
if (defaultImport !== undefined) {
|
|
636
|
-
analyze_1.logger.
|
|
749
|
+
analyze_1.logger.info(`Importing (default) ${defaultImport.getText()} from ${impDecl.getModuleSpecifierValue()} in ${modulePath}`);
|
|
637
750
|
// call with module, impDecl.getModuleSpecifierValue(), path, defaultImport, false, true
|
|
638
|
-
analyze_1.entityDictionary.
|
|
639
|
-
|
|
751
|
+
analyze_1.entityDictionary.oldCreateFamixImportClause({ importDeclaration: impDecl,
|
|
752
|
+
importerSourceFile: module,
|
|
640
753
|
moduleSpecifierFilePath: path,
|
|
641
754
|
importElement: defaultImport,
|
|
642
755
|
isInExports: false,
|
|
@@ -644,9 +757,9 @@ function processImportClausesForModules(modules, exports) {
|
|
|
644
757
|
}
|
|
645
758
|
const namespaceImport = impDecl.getNamespaceImport();
|
|
646
759
|
if (namespaceImport !== undefined) {
|
|
647
|
-
analyze_1.logger.
|
|
648
|
-
analyze_1.entityDictionary.
|
|
649
|
-
|
|
760
|
+
analyze_1.logger.info(`Importing (namespace) ${namespaceImport.getText()} from ${impDecl.getModuleSpecifierValue()} in ${modulePath}`);
|
|
761
|
+
analyze_1.entityDictionary.oldCreateFamixImportClause({ importDeclaration: impDecl,
|
|
762
|
+
importerSourceFile: module,
|
|
650
763
|
moduleSpecifierFilePath: path,
|
|
651
764
|
importElement: namespaceImport,
|
|
652
765
|
isInExports: false,
|
|
@@ -656,12 +769,20 @@ function processImportClausesForModules(modules, exports) {
|
|
|
656
769
|
});
|
|
657
770
|
});
|
|
658
771
|
}
|
|
659
|
-
exports
|
|
772
|
+
function isInExports(exports, importedEntityName) {
|
|
773
|
+
let importFoundInExports = false;
|
|
774
|
+
exports.forEach(e => {
|
|
775
|
+
if (e.has(importedEntityName)) {
|
|
776
|
+
importFoundInExports = true;
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
return importFoundInExports;
|
|
780
|
+
}
|
|
660
781
|
/**
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
782
|
+
* Builds a Famix model for the inheritances of the classes and interfaces of the source files
|
|
783
|
+
* @param classes An array of classes
|
|
784
|
+
* @param interfaces An array of interfaces
|
|
785
|
+
*/
|
|
665
786
|
function processInheritances(classes, interfaces) {
|
|
666
787
|
analyze_1.logger.info(`processInheritances: Creating inheritances:`);
|
|
667
788
|
classes.forEach(cls => {
|
|
@@ -687,7 +808,6 @@ function processInheritances(classes, interfaces) {
|
|
|
687
808
|
});
|
|
688
809
|
});
|
|
689
810
|
}
|
|
690
|
-
exports.processInheritances = processInheritances;
|
|
691
811
|
/**
|
|
692
812
|
* Builds a Famix model for the invocations of the methods and functions of the source files
|
|
693
813
|
* @param methodsAndFunctionsWithId A map of methods and functions with their id
|
|
@@ -695,17 +815,18 @@ exports.processInheritances = processInheritances;
|
|
|
695
815
|
function processInvocations(methodsAndFunctionsWithId) {
|
|
696
816
|
analyze_1.logger.info(`Creating invocations:`);
|
|
697
817
|
methodsAndFunctionsWithId.forEach((m, id) => {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
818
|
+
if (!(m instanceof ts_morph_1.ArrowFunction)) {
|
|
819
|
+
analyze_1.logger.debug(`Invocations to ${(m instanceof ts_morph_1.MethodDeclaration || m instanceof ts_morph_1.GetAccessorDeclaration || m instanceof ts_morph_1.SetAccessorDeclaration || m instanceof ts_morph_1.FunctionDeclaration) ? m.getName() : ((m instanceof ts_morph_1.ConstructorDeclaration) ? 'constructor' : (m.getName() ? m.getName() : 'anonymous'))}`);
|
|
820
|
+
try {
|
|
821
|
+
const temp_nodes = m.findReferencesAsNodes();
|
|
822
|
+
temp_nodes.forEach(node => processNodeForInvocations(node, m, id));
|
|
823
|
+
}
|
|
824
|
+
catch (error) {
|
|
825
|
+
analyze_1.logger.error(`> WARNING: got exception ${error}. Continuing...`);
|
|
826
|
+
}
|
|
705
827
|
}
|
|
706
828
|
});
|
|
707
829
|
}
|
|
708
|
-
exports.processInvocations = processInvocations;
|
|
709
830
|
/**
|
|
710
831
|
* Builds a Famix model for an invocation of a method or a function
|
|
711
832
|
* @param n A node
|
|
@@ -721,3 +842,30 @@ function processNodeForInvocations(n, m, id) {
|
|
|
721
842
|
analyze_1.logger.error(`> WARNING: got exception ${error}. ScopeDeclaration invalid for ${n.getSymbol().getFullyQualifiedName()}. Continuing...`);
|
|
722
843
|
}
|
|
723
844
|
}
|
|
845
|
+
/**
|
|
846
|
+
* Builds a Famix model for the inheritances of the classes and interfaces of the source files
|
|
847
|
+
* @param classes An array of classes
|
|
848
|
+
* @param interfaces An array of interfaces
|
|
849
|
+
*/
|
|
850
|
+
function processConcretisations(classes, interfaces, functions) {
|
|
851
|
+
analyze_1.logger.info(`processConcretisations: Creating concretisations:`);
|
|
852
|
+
classes.forEach(cls => {
|
|
853
|
+
analyze_1.logger.debug(`processConcretisations: Checking class concretisation for ${cls.getName()}`);
|
|
854
|
+
analyze_1.entityDictionary.createFamixConcretisationClassOrInterfaceSpecialisation(cls);
|
|
855
|
+
analyze_1.entityDictionary.createFamixConcretisationGenericInstantiation(cls);
|
|
856
|
+
analyze_1.entityDictionary.createFamixConcretisationInterfaceClass(cls);
|
|
857
|
+
analyze_1.entityDictionary.createFamixConcretisationTypeInstanciation(cls);
|
|
858
|
+
});
|
|
859
|
+
interfaces.forEach(inter => {
|
|
860
|
+
analyze_1.logger.debug(`processConcretisations: Checking interface concretisation for ${inter.getName()}`);
|
|
861
|
+
analyze_1.entityDictionary.createFamixConcretisationTypeInstanciation(inter);
|
|
862
|
+
analyze_1.entityDictionary.createFamixConcretisationClassOrInterfaceSpecialisation(inter);
|
|
863
|
+
});
|
|
864
|
+
functions.forEach(func => {
|
|
865
|
+
if (func instanceof ts_morph_1.FunctionDeclaration || func instanceof ts_morph_1.MethodDeclaration) {
|
|
866
|
+
analyze_1.logger.debug(`processConcretisations: Checking Method concretisation`);
|
|
867
|
+
analyze_1.entityDictionary.createFamixConcretisationFunctionInstantiation(func);
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvY2Vzc19mdW5jdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYW5hbHl6ZV9mdW5jdGlvbnMvcHJvY2Vzc19mdW5jdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFpQ0Esc0NBY0M7QUFRRCxnRkFzQkM7QUFNRCxvQ0FZQztBQXFDRCw4QkFHQztBQUVELGtDQUlDO0FBeW9CRCwwQ0FXQztBQTRCRCwwR0F1QkM7QUFPRCx3RUE2Q0M7QUFpQkQsa0RBNkJDO0FBTUQsZ0RBYUM7QUF1QkQsd0RBcUJDO0FBci9CRCx1Q0FBb2xCO0FBQ3BsQixvRUFBc0Q7QUFDdEQsNkVBQWlFO0FBQ2pFLHVDQUF5QjtBQUN6Qix3Q0FBdUQ7QUFDdkQsZ0NBQWdDO0FBS25CLFFBQUEseUJBQXlCLEdBQUcsSUFBSSxHQUFHLEVBQW1LLENBQUMsQ0FBQywrSUFBK0k7QUFFdlYsUUFBQSxTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQXFDLENBQUMsQ0FBQyx3SUFBd0k7QUFDbE0sUUFBQSxPQUFPLEdBQUcsSUFBSSxLQUFLLEVBQW9CLENBQUMsQ0FBQywrQ0FBK0M7QUFDeEYsUUFBQSxVQUFVLEdBQUcsSUFBSSxLQUFLLEVBQXdCLENBQUMsQ0FBQyxrREFBa0Q7QUFDbEcsUUFBQSxPQUFPLEdBQUcsSUFBSSxLQUFLLEVBQWMsQ0FBQyxDQUFDLGtEQUFrRDtBQUNyRixRQUFBLGdCQUFnQixHQUFHLElBQUksS0FBSyxFQUErQyxDQUFDLENBQUMsK0JBQStCO0FBR3pIOzs7O0dBSUc7QUFDSCxTQUFTLG1CQUFtQixDQUFDLFVBQXNCO0lBQy9DLE9BQU8sVUFBVSxDQUFDLHFCQUFxQixFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxVQUFVLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0FBQzFHLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsYUFBYSxD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QyxDQUFDO1FBQzlELDBCQUFnQixDQUFDLDBDQUEwQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRXJFLENBQUMsQ0FBQyxDQUFDO0lBQ0gsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUN2QixnQkFBTSxDQUFDLEtBQUssQ0FBQyxpRUFBaUUsS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNqRywwQkFBZ0IsQ0FBQywwQ0FBMEMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuRSwwQkFBZ0IsQ0FBQyx1REFBdUQsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNuRixDQUFDLENBQUMsQ0FBQztJQUNILFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDckIsSUFBRyxJQUFJLFlBQVksOEJBQW1CLElBQUksSUFBSSxZQUFZLDRCQUFpQixFQUFFLENBQUM7WUFDMUUsZ0JBQU0sQ0FBQyxLQUFLLENBQUMsd0RBQXdELENBQUMsQ0FBQztZQUN2RSwwQkFBZ0IsQ0FBQyw4Q0FBOEMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMxRSxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2xhc3NEZWNsYXJhdGlvbiwgTWV0aG9kRGVjbGFyYXRpb24sIFZhcmlhYmxlU3RhdGVtZW50LCBGdW5jdGlvbkRlY2xhcmF0aW9uLCBWYXJpYWJsZURlY2xhcmF0aW9uLCBJbnRlcmZhY2VEZWNsYXJhdGlvbiwgUGFyYW1ldGVyRGVjbGFyYXRpb24sIENvbnN0cnVjdG9yRGVjbGFyYXRpb24sIE1ldGhvZFNpZ25hdHVyZSwgU291cmNlRmlsZSwgTW9kdWxlRGVjbGFyYXRpb24sIFByb3BlcnR5RGVjbGFyYXRpb24sIFByb3BlcnR5U2lnbmF0dXJlLCBEZWNvcmF0b3IsIEdldEFjY2Vzc29yRGVjbGFyYXRpb24sIFNldEFjY2Vzc29yRGVjbGFyYXRpb24sIEV4cG9ydGVkRGVjbGFyYXRpb25zLCBDb21tZW50UmFuZ2UsIEVudW1EZWNsYXJhdGlvbiwgRW51bU1lbWJlciwgVHlwZVBhcmFtZXRlckRlY2xhcmF0aW9uLCBUeXBlQWxpYXNEZWNsYXJhdGlvbiwgU3ludGF4S2luZCwgRnVuY3Rpb25FeHByZXNzaW9uLCBCbG9jaywgSWRlbnRpZmllciwgRXhwcmVzc2lvbldpdGhUeXBlQXJndW1lbnRzLCBJbXBvcnREZWNsYXJhdGlvbiwgTm9kZSwgQXJyb3dGdW5jdGlvbiwgU2NvcGUsIENsYXNzRXhwcmVzc2lvbiB9IGZyb20gXCJ0cy1tb3JwaFwiO1xuaW1wb3J0ICogYXMgRmFtaXggZnJvbSBcIi4uL2xpYi9mYW1peC9zcmMvbW9kZWwvZmFtaXhcIjtcbmltcG9ydCB7IGNhbGN1bGF0ZSB9IGZyb20gXCIuLi9saWIvdHMtY29tcGxleC9jeWNsb21hdGljLXNlcnZpY2VcIjtcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCB7IGxvZ2dlciAsIGVudGl0eURpY3Rpb25hcnkgfSBmcm9tIFwiLi4vYW5hbHl6ZVwiO1xuaW1wb3J0IHsgZ2V0RlFOIH0gZnJvbSBcIi4uL2ZxblwiO1xuXG5leHBvcnQgdHlwZSBBY2Nlc3NpYmxlVFNNb3JwaEVsZW1lbnQgPSBQYXJhbWV0ZXJEZWNsYXJhdGlvbiB8IFZhcmlhYmxlRGVjbGFyYXRpb24gfCBQcm9wZXJ0eURlY2xhcmF0aW9uIHwgRW51bU1lbWJlcjtcbmV4cG9ydCB0eXBlIEZhbWl4SUQgPSBudW1iZXI7XG5cbmV4cG9ydCBjb25zdCBtZXRob2RzQW5kRnVuY3Rpb25zV2l0aElkID0gbmV3IE1hcDxudW1iZXIsIE1ldGhvZERlY2xhcmF0aW9uIHwgQ29uc3RydWN0b3JEZWNsYXJhdGlvbiB8IEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBTZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgRnVuY3Rpb25EZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRXhwcmVzc2lvbiB8IEFycm93RnVuY3Rpb24+KCk7IC8vIE1hcHMgdGhlIEZhbWl4IG1ldGhvZCwgY29uc3RydWN0b3IsIGdldHRlciwgc2V0dGVyIGFuZCBmdW5jdGlvbiBpZHMgdG8gdGhlaXIgdHMtbW9ycGggbWV0aG9kLCBjb25zdHJ1Y3RvciwgZ2V0dGVyLCBzZXR0ZXIgb3IgZnVuY3Rpb24gb2JqZWN0XG5cbmV4cG9ydCBjb25zdCBhY2Nlc3NNYXAgPSBuZXcgTWFwPEZhbWl4SUQsIEFjY2Vzc2libGVUU01vcnBoRWxlbWVudD4oKTsgLy8gTWFwcyB0aGUgRmFtaXggcGFyYW1ldGVyLCB2YXJpYWJsZSwgcHJvcGVydHkgYW5kIGVudW0gdmFsdWUgaWRzIHRvIHRoZWlyIHRzLW1vcnBoIHBhcmFtZXRlciwgdmFyaWFibGUsIHByb3BlcnR5IG9yIGVudW0gbWVtYmVyIG9iamVjdFxuZXhwb3J0IGNvbnN0IGNsYXNzZXMgPSBuZXcgQXJyYXk8Q2xhc3NEZWNsYXJhdGlvbj4oKTsgLy8gQXJyYXkgb2YgYWxsIHRoZSBjbGFzc2VzIG9mIHRoZSBzb3VyY2UgZmlsZXNcbmV4cG9ydCBjb25zdCBpbnRlcmZhY2VzID0gbmV3IEFycmF5PEludGVyZmFjZURlY2xhcmF0aW9uPigpOyAvLyBBcnJheSBvZiBhbGwgdGhlIGludGVyZmFjZXMgb2YgdGhlIHNvdXJjZSBmaWxlc1xuZXhwb3J0IGNvbnN0IG1vZHVsZXMgPSBuZXcgQXJyYXk8U291cmNlRmlsZT4oKTsgLy8gQXJyYXkgb2YgYWxsIHRoZSBzb3VyY2UgZmlsZXMgd2hpY2ggYXJlIG1vZHVsZXNcbmV4cG9ydCBjb25zdCBsaXN0T2ZFeHBvcnRNYXBzID0gbmV3IEFycmF5PFJlYWRvbmx5TWFwPHN0cmluZywgRXhwb3J0ZWREZWNsYXJhdGlvbnNbXT4+KCk7IC8vIEFycmF5IG9mIGFsbCB0aGUgZXhwb3J0IG1hcHNcbmV4cG9ydCBsZXQgY3VycmVudENDOiB1bmtub3duOyAvLyBTdG9yZXMgdGhlIGN5Y2xvbWF0aWMgY29tcGxleGl0eSBtZXRyaWNzIGZvciB0aGUgY3VycmVudCBzb3VyY2UgZmlsZVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgZmlsZSBoYXMgYW55IGltcG9ydHMgb3IgZXhwb3J0cyB0byBiZSBjb25zaWRlcmVkIGEgbW9kdWxlXG4gKiBAcGFyYW0gc291cmNlRmlsZSBBIHNvdXJjZSBmaWxlXG4gKiBAcmV0dXJucyBBIGJvb2xlYW4gaW5kaWNhdGluZyBpZiB0aGUgZmlsZSBpcyBhIG1vZHVsZVxuICovXG5mdW5jdGlvbiBpc1NvdXJjZUZpbGVBTW9kdWxlKHNvdXJjZUZpbGU6IFNvdXJjZUZpbGUpOiBib29sZWFuIHtcbiAgICByZXR1cm4gc291cmNlRmlsZS5nZXRJbXBvcnREZWNsYXJhdGlvbnMoKS5sZW5ndGggPiAwIHx8IHNvdXJjZUZpbGUuZ2V0RXhwb3J0ZWREZWNsYXJhdGlvbnMoKS5zaXplID4gMDtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBwYXRoIG9mIGEgbW9kdWxlIHRvIGJlIGltcG9ydGVkXG4gKiBAcGFyYW0gaSBBbiBpbXBvcnQgZGVjbGFyYXRpb25cbiAqIEByZXR1cm5zIFRoZSBwYXRoIG9mIHRoZSBtb2R1bGUgdG8gYmUgaW1wb3J0ZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1vZHVsZVBhdGgoaTogSW1wb3J0RGVjbGFyYXRpb24pOiBzdHJpbmcge1xuICAgIGxldCBwYXRoOiBzdHJpbmc7XG4gICAgaWYgKGkuZ2V0TW9kdWxlU3BlY2lmaWVyU291cmNlRmlsZSgpID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGkuZ2V0TW9kdWxlU3BlY2lmaWVyVmFsdWUoKS5zdWJzdHJpbmcoaS5nZXRNb2R1bGVTcGVjaWZpZXJWYWx1ZSgpLmxlbmd0aCAtIDMpID09PSBcIi50c1wiKSB7XG4gICAgICAgICAgICBwYXRoID0gaS5nZXRNb2R1bGVTcGVjaWZpZXJWYWx1ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcGF0aCA9IGkuZ2V0TW9kdWxlU3BlY2lmaWVyVmFsdWUoKSArIFwiLnRzXCI7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHBhdGggPSBpLmdldE1vZHVsZVNwZWNpZmllclNvdXJjZUZpbGUoKS5nZXRGaWxlUGF0aCgpO1xuICAgIH1cbiAgICByZXR1cm4gcGF0aDtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBpbnRlcmZhY2VzIGltcGxlbWVudGVkIG9yIGV4dGVuZGVkIGJ5IGEgY2xhc3Mgb3IgYW4gaW50ZXJmYWNlXG4gKiBAcGFyYW0gaW50ZXJmYWNlcyBBbiBhcnJheSBvZiBpbnRlcmZhY2VzXG4gKiBAcGFyYW0gc3ViQ2xhc3MgQSBjbGFzcyBvciBhbiBpbnRlcmZhY2VcbiAqIEByZXR1cm5zIEFuIGFycmF5IG9mIEludGVyZmFjZURlY2xhcmF0aW9uIGFuZCBFeHByZXNzaW9uV2l0aFR5cGVBcmd1bWVudHMgY29udGFpbmluZyB0aGUgaW50ZXJmYWNlcyBpbXBsZW1lbnRlZCBvciBleHRlbmRlZCBieSB0aGUgc3ViQ2xhc3NcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEltcGxlbWVudGVkT3JFeHRlbmRlZEludGVyZmFjZXMoaW50ZXJmYWNlczogQXJyYXk8SW50ZXJmYWNlRGVjbGFyYXRpb24+LCBzdWJDbGFzczogQ2xhc3NEZWNsYXJhdGlvbiB8IEludGVyZmFjZURlY2xhcmF0aW9uKTogQXJyYXk8SW50ZXJmYWNlRGVjbGFyYXRpb24gfCBFeHByZXNzaW9uV2l0aFR5cGVBcmd1bWVudHM+IHtcbiAgICBsZXQgaW1wT3JFeHRJbnRlcmZhY2VzOiBBcnJheTxFeHByZXNzaW9uV2l0aFR5cGVBcmd1bWVudHM+O1xuICAgIGlmIChzdWJDbGFzcyBpbnN0YW5jZW9mIENsYXNzRGVjbGFyYXRpb24pIHtcbiAgICAgICAgaW1wT3JFeHRJbnRlcmZhY2VzID0gc3ViQ2xhc3MuZ2V0SW1wbGVtZW50cygpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaW1wT3JFeHRJbnRlcmZhY2VzID0gc3ViQ2xhc3MuZ2V0RXh0ZW5kcygpO1xuICAgIH1cblxuICAgIGNvbnN0IGludGVyZmFjZXNOYW1lcyA9IGludGVyZmFjZXMubWFwKGkgPT4gaS5nZXROYW1lKCkpO1xuICAgIGNvbnN0IGltcGxlbWVudGVkT3JFeHRlbmRlZEludGVyZmFjZXMgPSBuZXcgQXJyYXk8SW50ZXJmYWNlRGVjbGFyYXRpb24gfCBFeHByZXNzaW9uV2l0aFR5cGVBcmd1bWVudHM+KCk7XG5cbiAgICBpbXBPckV4dEludGVyZmFjZXMuZm9yRWFjaChpID0+IHtcbiAgICAgICAgaWYgKGludGVyZmFjZXNOYW1lcy5pbmNsdWRlcyhpLmdldEV4cHJlc3Npb24oKS5nZXRUZXh0KCkpKSB7XG4gICAgICAgICAgICBpbXBsZW1lbnRlZE9yRXh0ZW5kZWRJbnRlcmZhY2VzLnB1c2goaW50ZXJmYWNlc1tpbnRlcmZhY2VzTmFtZXMuaW5kZXhPZihpLmdldEV4cHJlc3Npb24oKS5nZXRUZXh0KCkpXSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpbXBsZW1lbnRlZE9yRXh0ZW5kZWRJbnRlcmZhY2VzLnB1c2goaSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBpbXBsZW1lbnRlZE9yRXh0ZW5kZWRJbnRlcmZhY2VzO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciBhbiBhcnJheSBvZiBzb3VyY2UgZmlsZXNcbiAqIEBwYXJhbSBzb3VyY2VGaWxlcyBBbiBhcnJheSBvZiBzb3VyY2UgZmlsZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NGaWxlcyhzb3VyY2VGaWxlczogQXJyYXk8U291cmNlRmlsZT4pOiB2b2lkIHtcbiAgICBzb3VyY2VGaWxlcy5mb3JFYWNoKGZpbGUgPT4ge1xuICAgICAgICBsb2dnZXIuaW5mbyhgRmlsZTogPj4+Pj4+Pj4+PiAke2ZpbGUuZ2V0RmlsZVBhdGgoKX1gKTtcblxuICAgICAgICAvLyBDb21wdXRlcyB0aGUgY3ljbG9tYXRpYyBjb21wbGV4aXR5IG1ldHJpY3MgZm9yIHRoZSBjdXJyZW50IHNvdXJjZSBmaWxlIGlmIGl0IGV4aXN0cyAoaS5lLiBpZiBpdCBpcyBub3QgZnJvbSBhIGplc3QgdGVzdClcbiAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoZmlsZS5nZXRGaWxlUGF0aCgpKSlcbiAgICAgICAgICAgIGN1cnJlbnRDQyA9IGNhbGN1bGF0ZShmaWxlLmdldEZpbGVQYXRoKCkpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBjdXJyZW50Q0MgPSAwO1xuXG4gICAgICAgIHByb2Nlc3NGaWxlKGZpbGUpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciBhIHNvdXJjZSBmaWxlXG4gKiBAcGFyYW0gZiBBIHNvdXJjZSBmaWxlXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NGaWxlKGY6IFNvdXJjZUZpbGUpOiB2b2lkIHtcbiAgICBjb25zdCBpc01vZHVsZSA9IGlzU291cmNlRmlsZUFNb2R1bGUoZik7XG5cbiAgICBpZiAoaXNNb2R1bGUpIHtcbiAgICAgICAgbW9kdWxlcy5wdXNoKGYpO1xuICAgIH1cblxuICAgIGNvbnN0IGV4cG9ydE1hcCA9IGYuZ2V0RXhwb3J0ZWREZWNsYXJhdGlvbnMoKTtcbiAgICBpZiAoZXhwb3J0TWFwKSBsaXN0T2ZFeHBvcnRNYXBzLnB1c2goZXhwb3J0TWFwKTtcblxuICAgIGNvbnN0IGZteEZpbGUgPSBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZU9yR2V0RmFtaXhGaWxlKGYsIGlzTW9kdWxlKTtcblxuICAgIGxvZ2dlci5kZWJ1ZyhgcHJvY2Vzc0ZpbGU6IGZpbGU6ICR7Zi5nZXRCYXNlTmFtZSgpfSwgZnFuID0gJHtmbXhGaWxlLmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpfWApO1xuXG4gICAgcHJvY2Vzc0NvbW1lbnRzKGYsIGZteEZpbGUpO1xuXG4gICAgcHJvY2Vzc0FsaWFzZXMoZiwgZm14RmlsZSk7XG5cbiAgICBwcm9jZXNzQ2xhc3NlcyhmLCBmbXhGaWxlKTtcblxuICAgIHByb2Nlc3NJbnRlcmZhY2VzKGYsIGZteEZpbGUpO1xuXG4gICAgcHJvY2Vzc1ZhcmlhYmxlcyhmLCBmbXhGaWxlKTtcblxuICAgIHByb2Nlc3NFbnVtcyhmLCBmbXhGaWxlKTtcblxuICAgIHByb2Nlc3NGdW5jdGlvbnMoZiwgZm14RmlsZSk7XG5cbiAgICBwcm9jZXNzTW9kdWxlcyhmLCBmbXhGaWxlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQW1iaWVudChub2RlOiBNb2R1bGVEZWNsYXJhdGlvbik6IGJvb2xlYW4ge1xuICAgIC8vIEFuIGFtYmllbnQgbW9kdWxlIGhhcyB0aGUgRGVjbGFyZUtleXdvcmQgbW9kaWZpZXIuXG4gICAgcmV0dXJuIChub2RlLmdldE1vZGlmaWVycygpPy5zb21lKG1vZGlmaWVyID0+IG1vZGlmaWVyLmdldEtpbmQoKSA9PT0gU3ludGF4S2luZC5EZWNsYXJlS2V5d29yZCkpID8/IGZhbHNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNOYW1lc3BhY2Uobm9kZTogTW9kdWxlRGVjbGFyYXRpb24pOiBib29sZWFuIHtcbiAgICAvLyBDaGVjayBpZiB0aGUgbW9kdWxlIGRlY2xhcmF0aW9uIGhhcyBhIG5hbWVzcGFjZSBrZXl3b3JkLlxuICAgIC8vIFRoaXMgYXBwcm9hY2ggdXNlcyB0aGUgZ2V0Q2hpbGRyZW4oKSBtZXRob2QgdG8gaW5zcGVjdCB0aGUgc3ludGF4IGRpcmVjdGx5LlxuICAgIHJldHVybiBub2RlLmdldENoaWxkcmVuT2ZLaW5kKFN5bnRheEtpbmQuTmFtZXNwYWNlS2V5d29yZCkubGVuZ3RoID4gMDtcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgYSBtb2R1bGUgKGFsc28gbmFtZXNwYWNlKVxuICogQHBhcmFtIG0gQSBuYW1lc3BhY2VcbiAqIEByZXR1cm5zIEEgRmFtaXguTW9kdWxlIHJlcHJlc2VudGluZyB0aGUgbW9kdWxlXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NNb2R1bGUobTogTW9kdWxlRGVjbGFyYXRpb24pOiBGYW1peC5Nb2R1bGUge1xuICAgIGNvbnN0IGZteE1vZHVsZSA9IGVudGl0eURpY3Rpb25hcnkuY3JlYXRlT3JHZXRGYW1peE1vZHVsZShtKTtcblxuICAgIGxvZ2dlci5kZWJ1ZyhgbW9kdWxlOiAke20uZ2V0TmFtZSgpfSwgKCR7bS5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksICR7Zm14TW9kdWxlLmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpfWApO1xuXG4gICAgcHJvY2Vzc0NvbW1lbnRzKG0sIGZteE1vZHVsZSk7XG5cbiAgICBwcm9jZXNzQWxpYXNlcyhtLCBmbXhNb2R1bGUpO1xuXG4gICAgcHJvY2Vzc0NsYXNzZXMobSwgZm14TW9kdWxlKTtcblxuICAgIHByb2Nlc3NJbnRlcmZhY2VzKG0sIGZteE1vZHVsZSk7XG5cbiAgICBwcm9jZXNzVmFyaWFibGVzKG0sIGZteE1vZHVsZSk7XG5cbiAgICBwcm9jZXNzRW51bXMobSwgZm14TW9kdWxlKTtcbiAgICBcbiAgICBwcm9jZXNzRnVuY3Rpb25zKG0sIGZteE1vZHVsZSk7XG5cbiAgICBwcm9jZXNzTW9kdWxlcyhtLCBmbXhNb2R1bGUpO1xuXG4gICAgcmV0dXJuIGZteE1vZHVsZTtcbn1cblxudHlwZSBDb250YWluZXJUeXBlcyA9IFNvdXJjZUZpbGUgfCBNb2R1bGVEZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRGVjbGFyYXRpb24gfCBGdW5jdGlvbkV4cHJlc3Npb24gfCBNZXRob2REZWNsYXJhdGlvbiB8IENvbnN0cnVjdG9yRGVjbGFyYXRpb24gfCBHZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IEFycm93RnVuY3Rpb247XG5cbnR5cGUgU2NvcGVkVHlwZXMgPSBGYW1peC5TY3JpcHRFbnRpdHkgfCBGYW1peC5Nb2R1bGUgfCBGYW1peC5GdW5jdGlvbiB8IEZhbWl4Lk1ldGhvZCB8IEZhbWl4LkFjY2Vzc29yO1xuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciB0aGUgYWxpYXNlcyBvZiBhIGNvbnRhaW5lclxuICogQHBhcmFtIG0gQSBjb250YWluZXIgKGEgc291cmNlIGZpbGUsIGEgbmFtZXNwYWNlLCBhIGZ1bmN0aW9uIG9yIGEgbWV0aG9kKVxuICogQHBhcmFtIGZteFNjb3BlIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgY29udGFpbmVyXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NBbGlhc2VzKG06IENvbnRhaW5lclR5cGVzLCBmbXhTY29wZTogU2NvcGVkVHlwZXMpOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NBbGlhc2VzOiAtLS0tLS0tLS0tIEZpbmRpbmcgQWxpYXNlczpgKTtcbiAgICBtLmdldFR5cGVBbGlhc2VzKCkuZm9yRWFjaChhID0+IHtcbiAgICAgICAgY29uc3QgZm14QWxpYXMgPSBwcm9jZXNzQWxpYXMoYSk7XG4gICAgICAgIGZteFNjb3BlLmFkZEFsaWFzKGZteEFsaWFzKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgdGhlIGNsYXNzZXMgb2YgYSBjb250YWluZXJcbiAqIEBwYXJhbSBtIEEgY29udGFpbmVyIChhIHNvdXJjZSBmaWxlIG9yIGEgbmFtZXNwYWNlKVxuICogQHBhcmFtIGZteFNjb3BlIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgY29udGFpbmVyXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NDbGFzc2VzKG06IFNvdXJjZUZpbGUgfCBNb2R1bGVEZWNsYXJhdGlvbiwgZm14U2NvcGU6IEZhbWl4LlNjcmlwdEVudGl0eSB8IEZhbWl4Lk1vZHVsZSApOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NDbGFzc2VzOiAtLS0tLS0tLS0tIEZpbmRpbmcgQ2xhc3NlczpgKTtcbiAgICBjb25zdCBjbGFzc2VzSW5BcnJvd0Z1bmN0aW9ucyA9IGdldENsYXNzZXNEZWNsYXJlZEluQXJyb3dGdW5jdGlvbnMobSk7XG4gICAgY29uc3QgY2xhc3NlcyA9IG0uZ2V0Q2xhc3NlcygpLmNvbmNhdChjbGFzc2VzSW5BcnJvd0Z1bmN0aW9ucyk7XG4gICAgY2xhc3Nlcy5mb3JFYWNoKGMgPT4ge1xuICAgICAgICBjb25zdCBmbXhDbGFzcyA9IHByb2Nlc3NDbGFzcyhjKTtcbiAgICAgICAgZm14U2NvcGUuYWRkVHlwZShmbXhDbGFzcyk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEFycm93RnVuY3Rpb25DbGFzc2VzKGY6IEFycm93RnVuY3Rpb24pOiBDbGFzc0RlY2xhcmF0aW9uW10ge1xuICAgIGNvbnN0IGNsYXNzZXM6IENsYXNzRGVjbGFyYXRpb25bXSA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZmluZENsYXNzZXMobm9kZTogYW55KSB7XG4gICAgICAgIGlmIChub2RlLmdldEtpbmQoKSA9PT0gU3ludGF4S2luZC5DbGFzc0RlY2xhcmF0aW9uKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2gobm9kZSBhcyBDbGFzc0RlY2xhcmF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBub2RlLmdldENoaWxkcmVuKCkuZm9yRWFjaChmaW5kQ2xhc3Nlcyk7XG4gICAgfVxuXG4gICAgZmluZENsYXNzZXMoZik7XG4gICAgcmV0dXJuIGNsYXNzZXM7XG59XG5cbi8qKlxuICogdHMtbW9ycGggZG9lc24ndCBmaW5kIGNsYXNzZXMgaW4gYXJyb3cgZnVuY3Rpb25zLCBzbyB3ZSBuZWVkIHRvIGZpbmQgdGhlbSBtYW51YWxseVxuICogQHBhcmFtIHMgQSBzb3VyY2UgZmlsZSBcbiAqIEByZXR1cm5zIHRoZSBDbGFzc0RlY2xhcmF0aW9uIG9iamVjdHMgZm91bmQgaW4gYXJyb3cgZnVuY3Rpb25zIG9mIHRoZSBzb3VyY2UgZmlsZVxuICovXG5mdW5jdGlvbiBnZXRDbGFzc2VzRGVjbGFyZWRJbkFycm93RnVuY3Rpb25zKHM6IFNvdXJjZUZpbGUgfCBNb2R1bGVEZWNsYXJhdGlvbik6IENsYXNzRGVjbGFyYXRpb25bXSB7XG4gICAgY29uc3QgYXJyb3dGdW5jdGlvbnMgPSBzLmdldERlc2NlbmRhbnRzT2ZLaW5kKFN5bnRheEtpbmQuQXJyb3dGdW5jdGlvbik7XG4gICAgY29uc3QgY2xhc3Nlc0luQXJyb3dGdW5jdGlvbnMgPSBhcnJvd0Z1bmN0aW9ucy5tYXAoZiA9PiBnZXRBcnJvd0Z1bmN0aW9uQ2xhc3NlcyhmKSkuZmxhdCgpO1xuICAgIHJldHVybiBjbGFzc2VzSW5BcnJvd0Z1bmN0aW9ucztcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgdGhlIGludGVyZmFjZXMgb2YgYSBjb250YWluZXJcbiAqIEBwYXJhbSBtIEEgY29udGFpbmVyIChhIHNvdXJjZSBmaWxlIG9yIGEgbmFtZXNwYWNlKVxuICogQHBhcmFtIGZteFNjb3BlIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgY29udGFpbmVyXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NJbnRlcmZhY2VzKG06IFNvdXJjZUZpbGUgfCBNb2R1bGVEZWNsYXJhdGlvbiwgZm14U2NvcGU6IEZhbWl4LlNjcmlwdEVudGl0eSB8IEZhbWl4Lk1vZHVsZSApOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NJbnRlcmZhY2VzOiAtLS0tLS0tLS0tIEZpbmRpbmcgSW50ZXJmYWNlczpgKTtcbiAgICBtLmdldEludGVyZmFjZXMoKS5mb3JFYWNoKGkgPT4ge1xuICAgICAgICBjb25zdCBmbXhJbnRlcmZhY2UgPSBwcm9jZXNzSW50ZXJmYWNlKGkpO1xuICAgICAgICBmbXhTY29wZS5hZGRUeXBlKGZteEludGVyZmFjZSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIHRoZSB2YXJpYWJsZXMgb2YgYSBjb250YWluZXJcbiAqIEBwYXJhbSBtIEEgY29udGFpbmVyIChhIHNvdXJjZSBmaWxlLCBhIG5hbWVzcGFjZSwgYSBmdW5jdGlvbiBvciBhIG1ldGhvZClcbiAqIEBwYXJhbSBmbXhTY29wZSBUaGUgRmFtaXggbW9kZWwgb2YgdGhlIGNvbnRhaW5lclxuICovXG5mdW5jdGlvbiBwcm9jZXNzVmFyaWFibGVzKG06IENvbnRhaW5lclR5cGVzLCBmbXhTY29wZTogRmFtaXguU2NyaXB0RW50aXR5IHwgRmFtaXguTW9kdWxlIHwgRmFtaXguRnVuY3Rpb24gfCBGYW1peC5NZXRob2QgfCBGYW1peC5BY2Nlc3Nvcik6IHZvaWQge1xuICAgIGxvZ2dlci5kZWJ1ZyhgcHJvY2Vzc1ZhcmlhYmxlczogLS0tLS0tLS0tLSBGaW5kaW5nIFZhcmlhYmxlczpgKTtcbiAgICBtLmdldFZhcmlhYmxlU3RhdGVtZW50cygpLmZvckVhY2godiA9PiB7XG4gICAgICAgIGNvbnN0IGZteFZhcmlhYmxlcyA9IHByb2Nlc3NWYXJpYWJsZVN0YXRlbWVudCh2KTtcbiAgICAgICAgZm14VmFyaWFibGVzLmZvckVhY2goZm14VmFyaWFibGUgPT4ge1xuICAgICAgICAgICAgZm14U2NvcGUuYWRkVmFyaWFibGUoZm14VmFyaWFibGUpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgdGhlIGVudW1zIG9mIGEgY29udGFpbmVyXG4gKiBAcGFyYW0gbSBBIGNvbnRhaW5lciAoYSBzb3VyY2UgZmlsZSwgYSBuYW1lc3BhY2UsIGEgZnVuY3Rpb24gb3IgYSBtZXRob2QpXG4gKiBAcGFyYW0gZm14U2NvcGUgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBjb250YWluZXJcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0VudW1zKG06IENvbnRhaW5lclR5cGVzLCBmbXhTY29wZTogU2NvcGVkVHlwZXMpOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NFbnVtczogLS0tLS0tLS0tLSBGaW5kaW5nIEVudW1zOmApO1xuICAgIG0uZ2V0RW51bXMoKS5mb3JFYWNoKGUgPT4ge1xuICAgICAgICBjb25zdCBmbXhFbnVtID0gcHJvY2Vzc0VudW0oZSk7XG4gICAgICAgIGZteFNjb3BlLmFkZFR5cGUoZm14RW51bSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIHRoZSBmdW5jdGlvbnMgb2YgYSBjb250YWluZXJcbiAqIEBwYXJhbSBtIEEgY29udGFpbmVyIChhIHNvdXJjZSBmaWxlLCBhIG5hbWVzcGFjZSwgYSBmdW5jdGlvbiBvciBhIG1ldGhvZClcbiAqIEBwYXJhbSBmbXhTY29wZSBUaGUgRmFtaXggbW9kZWwgb2YgdGhlIGNvbnRhaW5lclxuICovXG5mdW5jdGlvbiBwcm9jZXNzRnVuY3Rpb25zKG06IENvbnRhaW5lclR5cGVzLCBmbXhTY29wZTogU2NvcGVkVHlwZXMpOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYEZpbmRpbmcgRnVuY3Rpb25zOmApO1xuICAgIG0uZ2V0RnVuY3Rpb25zKCkuZm9yRWFjaChmID0+IHtcbiAgICAgICAgY29uc3QgZm14RnVuY3Rpb24gPSBwcm9jZXNzRnVuY3Rpb24oZik7XG4gICAgICAgIGZteFNjb3BlLmFkZEZ1bmN0aW9uKGZteEZ1bmN0aW9uKTtcbiAgICB9KTtcblxuICAgIC8vZmluZCBhcnJvdyBmdW5jdGlvbnNcbiAgICBsb2dnZXIuZGVidWcoYEZpbmRpbmcgRnVuY3Rpb25zOmApO1xuICAgIGNvbnN0IGFycm93RnVuY3Rpb25zID0gbS5nZXREZXNjZW5kYW50c09mS2luZChTeW50YXhLaW5kLkFycm93RnVuY3Rpb24pO1xuICAgIGFycm93RnVuY3Rpb25zLmZvckVhY2goYWYgPT4ge1xuICAgICAgICBjb25zdCBmbXhGdW5jdGlvbiA9IHByb2Nlc3NGdW5jdGlvbihhZik7XG4gICAgICAgIGZteFNjb3BlLmFkZEZ1bmN0aW9uKGZteEZ1bmN0aW9uKTtcbiAgICB9KVxufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciB0aGUgbW9kdWxlcyBvZiBhIGNvbnRhaW5lci5cbiAqIEBwYXJhbSBtIEEgY29udGFpbmVyIChhIHNvdXJjZSBmaWxlIG9yIGEgbmFtZXNwYWNlKVxuICogQHBhcmFtIGZteFNjb3BlIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgY29udGFpbmVyXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NNb2R1bGVzKG06IFNvdXJjZUZpbGUgfCBNb2R1bGVEZWNsYXJhdGlvbiwgZm14U2NvcGU6IEZhbWl4LlNjcmlwdEVudGl0eSB8IEZhbWl4Lk1vZHVsZSApOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYEZpbmRpbmcgTW9kdWxlczpgKTtcbiAgICBtLmdldE1vZHVsZXMoKS5mb3JFYWNoKG1kID0+IHtcbiAgICAgICAgY29uc3QgZm14TW9kdWxlID0gcHJvY2Vzc01vZHVsZShtZCk7XG4gICAgICAgIGZteFNjb3BlLmFkZE1vZHVsZShmbXhNb2R1bGUpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciBhbiBhbGlhc1xuICogQHBhcmFtIGEgQW4gYWxpYXNcbiAqIEByZXR1cm5zIEEgRmFtaXguQWxpYXMgcmVwcmVzZW50aW5nIHRoZSBhbGlhc1xuICovXG5mdW5jdGlvbiBwcm9jZXNzQWxpYXMoYTogVHlwZUFsaWFzRGVjbGFyYXRpb24pOiBGYW1peC5BbGlhcyB7XG4gICAgY29uc3QgZm14QWxpYXMgPSBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZUZhbWl4QWxpYXMoYSk7XG5cbiAgICBsb2dnZXIuZGVidWcoYEFsaWFzOiAke2EuZ2V0TmFtZSgpfSwgKCR7YS5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksIGZxbiA9ICR7Zm14QWxpYXMuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCl9YCk7XG5cbiAgICBwcm9jZXNzQ29tbWVudHMoYSwgZm14QWxpYXMpO1xuXG4gICAgcmV0dXJuIGZteEFsaWFzO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciBhIGNsYXNzXG4gKiBAcGFyYW0gYyBBIGNsYXNzXG4gKiBAcmV0dXJucyBBIEZhbWl4LkNsYXNzIG9yIGEgRmFtaXguUGFyYW1ldHJpY0NsYXNzIHJlcHJlc2VudGluZyB0aGUgY2xhc3NcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0NsYXNzKGM6IENsYXNzRGVjbGFyYXRpb24pOiBGYW1peC5DbGFzcyB8IEZhbWl4LlBhcmFtZXRyaWNDbGFzcyB7XG4gICAgY2xhc3Nlcy5wdXNoKGMpO1xuXG4gICAgY29uc3QgZm14Q2xhc3MgPSBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZU9yR2V0RmFtaXhDbGFzcyhjKTtcblxuICAgIGxvZ2dlci5kZWJ1ZyhgQ2xhc3M6ICR7Yy5nZXROYW1lKCl9LCAoJHtjLmdldFR5cGUoKS5nZXRUZXh0KCl9KSwgZnFuID0gJHtmbXhDbGFzcy5nZXRGdWxseVF1YWxpZmllZE5hbWUoKX1gKTtcblxuICAgIHByb2Nlc3NDb21tZW50cyhjLCBmbXhDbGFzcyk7XG5cbiAgICBwcm9jZXNzRGVjb3JhdG9ycyhjLCBmbXhDbGFzcyk7XG5cbiAgICBwcm9jZXNzU3RydWN0dXJlZFR5cGUoYywgZm14Q2xhc3MpO1xuXG4gICAgYy5nZXRDb25zdHJ1Y3RvcnMoKS5mb3JFYWNoKGNvbiA9PiB7XG4gICAgICAgIGNvbnN0IGZteENvbiA9IHByb2Nlc3NNZXRob2QoY29uKTtcbiAgICAgICAgZm14Q2xhc3MuYWRkTWV0aG9kKGZteENvbik7XG4gICAgfSk7XG5cbiAgICBjLmdldEdldEFjY2Vzc29ycygpLmZvckVhY2goYWNjID0+IHtcbiAgICAgICAgY29uc3QgZm14QWNjID0gcHJvY2Vzc01ldGhvZChhY2MpO1xuICAgICAgICBmbXhDbGFzcy5hZGRNZXRob2QoZm14QWNjKTtcbiAgICB9KTtcbiAgICBcbiAgICBjLmdldFNldEFjY2Vzc29ycygpLmZvckVhY2goYWNjID0+IHtcbiAgICAgICAgY29uc3QgZm14QWNjID0gcHJvY2Vzc01ldGhvZChhY2MpO1xuICAgICAgICBmbXhDbGFzcy5hZGRNZXRob2QoZm14QWNjKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBmbXhDbGFzcztcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgYW4gaW50ZXJmYWNlXG4gKiBAcGFyYW0gaSBBbiBpbnRlcmZhY2VcbiAqIEByZXR1cm5zIEEgRmFtaXguSW50ZXJmYWNlIG9yIGEgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZSByZXByZXNlbnRpbmcgdGhlIGludGVyZmFjZVxuICovXG5mdW5jdGlvbiBwcm9jZXNzSW50ZXJmYWNlKGk6IEludGVyZmFjZURlY2xhcmF0aW9uKTogRmFtaXguSW50ZXJmYWNlIHwgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZSB7XG4gICAgaW50ZXJmYWNlcy5wdXNoKGkpO1xuXG4gICAgY29uc3QgZm14SW50ZXJmYWNlID0gZW50aXR5RGljdGlvbmFyeS5jcmVhdGVPckdldEZhbWl4SW50ZXJmYWNlKGkpO1xuXG4gICAgbG9nZ2VyLmRlYnVnKGBJbnRlcmZhY2U6ICR7aS5nZXROYW1lKCl9LCAoJHtpLmdldFR5cGUoKS5nZXRUZXh0KCl9KSwgZnFuID0gJHtmbXhJbnRlcmZhY2UuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCl9YCk7XG5cbiAgICBwcm9jZXNzQ29tbWVudHMoaSwgZm14SW50ZXJmYWNlKTtcblxuICAgIHByb2Nlc3NTdHJ1Y3R1cmVkVHlwZShpLCBmbXhJbnRlcmZhY2UpO1xuXG4gICAgcmV0dXJuIGZteEludGVyZmFjZTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgdGhlIHR5cGUgcGFyYW1ldGVycywgcHJvcGVydGllcyBhbmQgbWV0aG9kcyBvZiBhIHN0cnVjdHVyZWQgdHlwZVxuICogQHBhcmFtIGMgQSBzdHJ1Y3R1cmVkIHR5cGUgKGEgY2xhc3Mgb3IgYW4gaW50ZXJmYWNlKVxuICogQHBhcmFtIGZteFNjb3BlIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgc3RydWN0dXJlZCB0eXBlXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NTdHJ1Y3R1cmVkVHlwZShjOiBDbGFzc0RlY2xhcmF0aW9uIHwgSW50ZXJmYWNlRGVjbGFyYXRpb24sIGZteFNjb3BlOiBGYW1peC5DbGFzcyB8IEZhbWl4LlBhcmFtZXRyaWNDbGFzcyB8IEZhbWl4LkludGVyZmFjZSB8IEZhbWl4LlBhcmFtZXRyaWNJbnRlcmZhY2UpOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYEZpbmRpbmcgUHJvcGVydGllcyBhbmQgTWV0aG9kczpgKTtcbiAgICBpZiAoZm14U2NvcGUgaW5zdGFuY2VvZiBGYW1peC5QYXJhbWV0cmljQ2xhc3MgfHwgZm14U2NvcGUgaW5zdGFuY2VvZiBGYW1peC5QYXJhbWV0cmljSW50ZXJmYWNlKSB7XG4gICAgICAgIHByb2Nlc3NUeXBlUGFyYW1ldGVycyhjLCBmbXhTY29wZSk7XG4gICAgfVxuXG4gICAgYy5nZXRQcm9wZXJ0aWVzKCkuZm9yRWFjaChwcm9wID0+IHtcbiAgICAgICAgY29uc3QgZm14UHJvcGVydHkgPSBwcm9jZXNzUHJvcGVydHkocHJvcCk7XG4gICAgICAgIGZteFNjb3BlLmFkZFByb3BlcnR5KGZteFByb3BlcnR5KTtcbiAgICB9KTtcblxuICAgIGMuZ2V0TWV0aG9kcygpLmZvckVhY2gobSA9PiB7XG4gICAgICAgIGNvbnN0IGZteE1ldGhvZCA9IHByb2Nlc3NNZXRob2QobSk7XG4gICAgICAgIGZteFNjb3BlLmFkZE1ldGhvZChmbXhNZXRob2QpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciBhIHByb3BlcnR5XG4gKiBAcGFyYW0gcCBBIHByb3BlcnR5XG4gKiBAcmV0dXJucyBBIEZhbWl4LlByb3BlcnR5IHJlcHJlc2VudGluZyB0aGUgcHJvcGVydHlcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc1Byb3BlcnR5KHA6IFByb3BlcnR5RGVjbGFyYXRpb24gfCBQcm9wZXJ0eVNpZ25hdHVyZSk6IEZhbWl4LlByb3BlcnR5IHtcbiAgICBjb25zdCBmbXhQcm9wZXJ0eSA9IGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhQcm9wZXJ0eShwKTtcblxuICAgIGxvZ2dlci5kZWJ1ZyhgcHJvcGVydHk6ICR7cC5nZXROYW1lKCl9LCAoJHtwLmdldFR5cGUoKS5nZXRUZXh0KCl9KSwgZnFuID0gJHtmbXhQcm9wZXJ0eS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKX1gKTtcbiAgICBsb2dnZXIuZGVidWcoYCAtLS0+IEl0J3MgYSBQcm9wZXJ0eSR7KHAgaW5zdGFuY2VvZiBQcm9wZXJ0eVNpZ25hdHVyZSkgPyBcIlNpZ25hdHVyZVwiIDogXCJEZWNsYXJhdGlvblwifSFgKTtcbiAgICBjb25zdCBhbmNlc3RvciA9IHAuZ2V0Rmlyc3RBbmNlc3Rvck9yVGhyb3coKTtcbiAgICBsb2dnZXIuZGVidWcoYCAtLS0+IEl0cyBmaXJzdCBhbmNlc3RvciBpcyBhICR7YW5jZXN0b3IuZ2V0S2luZE5hbWUoKX1gKTtcblxuICAgIC8vIGRlY29yYXRvcnNcbiAgICBpZiAoIShwIGluc3RhbmNlb2YgUHJvcGVydHlTaWduYXR1cmUpKSB7XG4gICAgICAgIHByb2Nlc3NEZWNvcmF0b3JzKHAsIGZteFByb3BlcnR5KTtcbiAgICAgICAgLy8gb25seSBhZGQgYWNjZXNzIGlmIHRoZSBwJ3MgZmlyc3QgYW5jZXN0b3IgaXMgbm90IGEgUHJvcGVydHlEZWNsYXJhdGlvblxuICAgICAgICBpZiAoYW5jZXN0b3IuZ2V0S2luZE5hbWUoKSAhPT0gXCJQcm9wZXJ0eURlY2xhcmF0aW9uXCIpIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgYWRkaW5nIGFjY2VzcyB0byBtYXA6ICR7cC5nZXROYW1lKCl9LCAoJHtwLmdldFR5cGUoKS5nZXRUZXh0KCl9KSBGYW1peCAke2ZteFByb3BlcnR5LmdldE5hbWUoKX0gaWQ6ICR7Zm14UHJvcGVydHkuaWR9YCk7XG4gICAgICAgICAgICBhY2Nlc3NNYXAuc2V0KGZteFByb3BlcnR5LmlkLCBwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb2Nlc3NDb21tZW50cyhwLCBmbXhQcm9wZXJ0eSk7XG5cbiAgICByZXR1cm4gZm14UHJvcGVydHk7XG59XG5cbi8qKlxuICAgICAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciBhIG1ldGhvZCBvciBhbiBhY2Nlc3NvclxuICAgICAqIEBwYXJhbSBtIEEgbWV0aG9kIG9yIGFuIGFjY2Vzc29yXG4gICAgICogQHJldHVybnMgQSBGYW1peC5NZXRob2Qgb3IgYSBGYW1peC5BY2Nlc3NvciByZXByZXNlbnRpbmcgdGhlIG1ldGhvZCBvciB0aGUgYWNjZXNzb3JcbiAgICAgKi9cbmZ1bmN0aW9uIHByb2Nlc3NNZXRob2QobTogTWV0aG9kRGVjbGFyYXRpb24gfCBDb25zdHJ1Y3RvckRlY2xhcmF0aW9uIHwgTWV0aG9kU2lnbmF0dXJlIHwgR2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IFNldEFjY2Vzc29yRGVjbGFyYXRpb24pOiBGYW1peC5NZXRob2QgfCBGYW1peC5BY2Nlc3NvciB7XG4gICAgY29uc3QgZm14TWV0aG9kID0gZW50aXR5RGljdGlvbmFyeS5jcmVhdGVPckdldEZhbWl4TWV0aG9kKG0sIGN1cnJlbnRDQyk7XG5cbiAgICBsb2dnZXIuZGVidWcoYE1ldGhvZDogJHshKG0gaW5zdGFuY2VvZiBDb25zdHJ1Y3RvckRlY2xhcmF0aW9uKSA/IG0uZ2V0TmFtZSgpIDogXCJjb25zdHJ1Y3RvclwifSwgKCR7bS5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksIHBhcmVudDogJHsobS5nZXRQYXJlbnQoKSBhcyBDbGFzc0RlY2xhcmF0aW9uIHwgSW50ZXJmYWNlRGVjbGFyYXRpb24pLmdldE5hbWUoKX0sIGZxbiA9ICR7Zm14TWV0aG9kLmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpfWApO1xuXG4gICAgcHJvY2Vzc0NvbW1lbnRzKG0sIGZteE1ldGhvZCk7XG5cbiAgICBwcm9jZXNzVHlwZVBhcmFtZXRlcnMobSwgZm14TWV0aG9kKTtcblxuICAgIHByb2Nlc3NQYXJhbWV0ZXJzKG0sIGZteE1ldGhvZCk7XG5cbiAgICBpZiAoIShtIGluc3RhbmNlb2YgTWV0aG9kU2lnbmF0dXJlKSkge1xuICAgICAgICBwcm9jZXNzQWxpYXNlcyhtLCBmbXhNZXRob2QpO1xuXG4gICAgICAgIHByb2Nlc3NWYXJpYWJsZXMobSwgZm14TWV0aG9kKTtcblxuICAgICAgICBwcm9jZXNzRW51bXMobSwgZm14TWV0aG9kKTtcblxuICAgICAgICBwcm9jZXNzRnVuY3Rpb25zKG0sIGZteE1ldGhvZCk7XG5cbiAgICAgICAgcHJvY2Vzc0Z1bmN0aW9uRXhwcmVzc2lvbnMobSwgZm14TWV0aG9kKTtcblxuICAgICAgICBtZXRob2RzQW5kRnVuY3Rpb25zV2l0aElkLnNldChmbXhNZXRob2QuaWQsIG0pO1xuICAgIH1cblxuICAgIGlmIChtIGluc3RhbmNlb2YgTWV0aG9kRGVjbGFyYXRpb24gfHwgbSBpbnN0YW5jZW9mIEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfHwgbSBpbnN0YW5jZW9mIFNldEFjY2Vzc29yRGVjbGFyYXRpb24pIHtcbiAgICAgICAgcHJvY2Vzc0RlY29yYXRvcnMobSwgZm14TWV0aG9kKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZm14TWV0aG9kO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciBhIGZ1bmN0aW9uXG4gKiBAcGFyYW0gZiBBIGZ1bmN0aW9uXG4gKiBAcmV0dXJucyBBIEZhbWl4LkZ1bmN0aW9uIHJlcHJlc2VudGluZyB0aGUgZnVuY3Rpb25cbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0Z1bmN0aW9uKGY6IEZ1bmN0aW9uRGVjbGFyYXRpb24gfCBGdW5jdGlvbkV4cHJlc3Npb24gfCBBcnJvd0Z1bmN0aW9uKTogRmFtaXguRnVuY3Rpb24ge1xuXG4gICAgbG9nZ2VyLmRlYnVnKGBGdW5jdGlvbjogJHsoZiBpbnN0YW5jZW9mIEFycm93RnVuY3Rpb24gPyBcImFub255bW91c1wiIDogZi5nZXROYW1lKCkgPyBmLmdldE5hbWUoKSA6IFwiYW5vbnltb3VzXCIpfSwgKCR7Zi5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksIGZxbiA9ICR7Z2V0RlFOKGYpfWApO1xuXG4gICAgbGV0IGZteEZ1bmN0aW9uO1xuICAgIGlmKCBmIGluc3RhbmNlb2YgQXJyb3dGdW5jdGlvbikge1xuICAgICAgICBmbXhGdW5jdGlvbiA9IGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhBcnJvd0Z1bmN0aW9uKGYsIGN1cnJlbnRDQyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm14RnVuY3Rpb24gPSBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZU9yR2V0RmFtaXhGdW5jdGlvbihmLCBjdXJyZW50Q0MpO1xuICAgIH1cblxuICAgIHByb2Nlc3NDb21tZW50cyhmLCBmbXhGdW5jdGlvbik7XG5cbiAgICBwcm9jZXNzQWxpYXNlcyhmLCBmbXhGdW5jdGlvbik7XG5cbiAgICBwcm9jZXNzVHlwZVBhcmFtZXRlcnMoZiwgZm14RnVuY3Rpb24pO1xuXG4gICAgcHJvY2Vzc1BhcmFtZXRlcnMoZiwgZm14RnVuY3Rpb24pO1xuXG4gICAgcHJvY2Vzc1ZhcmlhYmxlcyhmLCBmbXhGdW5jdGlvbik7XG5cbiAgICBwcm9jZXNzRW51bXMoZiwgZm14RnVuY3Rpb24pO1xuXG4gICAgcHJvY2Vzc0Z1bmN0aW9ucyhmLCBmbXhGdW5jdGlvbik7XG5cbiAgICBpZiAoZiBpbnN0YW5jZW9mIEZ1bmN0aW9uRGVjbGFyYXRpb24gJiYgIShmLmdldFBhcmVudCgpIGluc3RhbmNlb2YgQmxvY2spKSB7XG4gICAgICAgIHByb2Nlc3NGdW5jdGlvbkV4cHJlc3Npb25zKGYsIGZteEZ1bmN0aW9uKTtcbiAgICB9XG5cbiAgICBtZXRob2RzQW5kRnVuY3Rpb25zV2l0aElkLnNldChmbXhGdW5jdGlvbi5pZCwgZik7XG5cbiAgICByZXR1cm4gZm14RnVuY3Rpb247XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIHRoZSBmdW5jdGlvbiBleHByZXNzaW9ucyBvZiBhIGZ1bmN0aW9uIG9yIGEgbWV0aG9kXG4gKiBAcGFyYW0gZiBBIGZ1bmN0aW9uIG9yIGEgbWV0aG9kXG4gKiBAcGFyYW0gZm14U2NvcGUgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBmdW5jdGlvbiBvciB0aGUgbWV0aG9kXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NGdW5jdGlvbkV4cHJlc3Npb25zKGY6IEZ1bmN0aW9uRGVjbGFyYXRpb24gfCBNZXRob2REZWNsYXJhdGlvbiB8IENvbnN0cnVjdG9yRGVjbGFyYXRpb24gfCBHZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiwgZm14U2NvcGU6IEZhbWl4LkZ1bmN0aW9uIHwgRmFtaXguTWV0aG9kIHwgRmFtaXguQWNjZXNzb3IpOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYEZpbmRpbmcgRnVuY3Rpb24gRXhwcmVzc2lvbnM6YCk7XG4gICAgY29uc3QgZnVuY3Rpb25FeHByZXNzaW9ucyA9IGYuZ2V0RGVzY2VuZGFudHNPZktpbmQoU3ludGF4S2luZC5GdW5jdGlvbkV4cHJlc3Npb24pO1xuICAgIGZ1bmN0aW9uRXhwcmVzc2lvbnMuZm9yRWFjaCgoZnVuYykgPT4ge1xuICAgICAgICBjb25zdCBmbXhGdW5jID0gcHJvY2Vzc0Z1bmN0aW9uKGZ1bmMpO1xuICAgICAgICBmbXhTY29wZS5hZGRGdW5jdGlvbihmbXhGdW5jKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgdGhlIHBhcmFtZXRlcnMgb2YgYSBtZXRob2Qgb3IgYSBmdW5jdGlvblxuICogQHBhcmFtIG0gQSBtZXRob2Qgb3IgYSBmdW5jdGlvblxuICogQHBhcmFtIGZteFNjb3BlIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgbWV0aG9kIG9yIHRoZSBmdW5jdGlvblxuICovXG5mdW5jdGlvbiBwcm9jZXNzUGFyYW1ldGVycyhtOiBNZXRob2REZWNsYXJhdGlvbiB8IENvbnN0cnVjdG9yRGVjbGFyYXRpb24gfCBNZXRob2RTaWduYXR1cmUgfCBHZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRGVjbGFyYXRpb24gfCBGdW5jdGlvbkV4cHJlc3Npb24gfCBBcnJvd0Z1bmN0aW9uLCBmbXhTY29wZTogRmFtaXguTWV0aG9kIHwgRmFtaXguQWNjZXNzb3IgfCBGYW1peC5GdW5jdGlvbik6IHZvaWQge1xuICAgIGxvZ2dlci5kZWJ1ZyhgRmluZGluZyBQYXJhbWV0ZXJzOmApO1xuICAgIG0uZ2V0UGFyYW1ldGVycygpLmZvckVhY2gocGFyYW0gPT4ge1xuICAgICAgICBjb25zdCBmbXhQYXJhbSA9IHByb2Nlc3NQYXJhbWV0ZXIocGFyYW0pO1xuICAgICAgICBmbXhTY29wZS5hZGRQYXJhbWV0ZXIoZm14UGFyYW0pO1xuICAgICAgICAvLyBBZGRpdGlvbmFsIGhhbmRsaW5nIGZvciBQYXJhbWV0ZXIgUHJvcGVydGllcyBpbiBjb25zdHJ1Y3RvcnNcbiAgICAgICAgaWYgKG0gaW5zdGFuY2VvZiBDb25zdHJ1Y3RvckRlY2xhcmF0aW9uKSB7XG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgcGFyYW1ldGVyIGhhcyBhbnkgdmlzaWJpbGl0eSBtb2RpZmllclxuICAgICAgICAgICAgaWYgKHBhcmFtLmhhc01vZGlmaWVyKFN5bnRheEtpbmQuUHJpdmF0ZUtleXdvcmQpIHx8IHBhcmFtLmhhc01vZGlmaWVyKFN5bnRheEtpbmQuUHVibGljS2V5d29yZCkgfHwgcGFyYW0uaGFzTW9kaWZpZXIoU3ludGF4S2luZC5Qcm90ZWN0ZWRLZXl3b3JkKSB8fCBwYXJhbS5oYXNNb2RpZmllcihTeW50YXhLaW5kLlJlYWRvbmx5S2V5d29yZCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjbGFzc09mQ29uc3RydWN0b3IgPSBtLmdldFBhcmVudCgpO1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBQYXJhbWV0ZXIgUHJvcGVydHkgJHtwYXJhbS5nZXROYW1lKCl9IGluIGNvbnN0cnVjdG9yIG9mICR7Y2xhc3NPZkNvbnN0cnVjdG9yLmdldE5hbWUoKX0uYCk7XG4gICAgICAgICAgICAgICAgLy8gVHJlYXQgdGhlIHBhcmFtZXRlciBhcyBhIHByb3BlcnR5IGFuZCBhZGQgaXQgdG8gdGhlIGNsYXNzXG4gICAgICAgICAgICAgICAgY29uc3QgZm14UHJvcGVydHkgPSBwcm9jZXNzUGFyYW1ldGVyQXNQcm9wZXJ0eShwYXJhbSwgY2xhc3NPZkNvbnN0cnVjdG9yKTtcbiAgICAgICAgICAgICAgICBmbXhQcm9wZXJ0eS5yZWFkT25seSA9IHBhcmFtLmhhc01vZGlmaWVyKFN5bnRheEtpbmQuUmVhZG9ubHlLZXl3b3JkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfSk7XG59XG5cbi8vIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGNyZWF0ZSBhIEZhbWl4LlByb3BlcnR5IG1vZGVsIGZyb20gYSBQYXJhbWV0ZXJEZWNsYXJhdGlvblxuLy8gWW91J2xsIG5lZWQgdG8gaW1wbGVtZW50IGl0IGFjY29yZGluZyB0byB5b3VyIEZhbWl4IG1vZGVsIHN0cnVjdHVyZVxuZnVuY3Rpb24gcHJvY2Vzc1BhcmFtZXRlckFzUHJvcGVydHkocGFyYW06IFBhcmFtZXRlckRlY2xhcmF0aW9uLCBjOiBDbGFzc0RlY2xhcmF0aW9uIHwgQ2xhc3NFeHByZXNzaW9uKTogRmFtaXguUHJvcGVydHkge1xuICAgIC8vIENvbnZlcnQgdGhlIHBhcmFtZXRlciBpbnRvIGEgUHJvcGVydHlcbiAgICBjb25zdCBwcm9wZXJ0eVJlcHJlc2VudGF0aW9uID0gY29udmVydFBhcmFtZXRlclRvUHJvcGVydHlSZXByZXNlbnRhdGlvbihwYXJhbSk7XG5cbiAgICAvLyBBZGQgdGhlIHByb3BlcnR5IHRvIHRoZSBjbGFzcyBzbyB3ZSBjYW4gaGF2ZSBhIFByb3BlcnR5RGVjbGFyYXRpb24gb2JqZWN0XG4gICAgYy5hZGRQcm9wZXJ0eShwcm9wZXJ0eVJlcHJlc2VudGF0aW9uKTtcblxuICAgIGNvbnN0IHAgPSBjLmdldFByb3BlcnR5KHByb3BlcnR5UmVwcmVzZW50YXRpb24ubmFtZSk7XG4gICAgY29uc3QgZm14UHJvcGVydHkgPSBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZUZhbWl4UHJvcGVydHkocCk7XG4gICAgaWYgKGMgaW5zdGFuY2VvZiBDbGFzc0RlY2xhcmF0aW9uKSB7XG4gICAgICAgIGNvbnN0IGZteENsYXNzID0gZW50aXR5RGljdGlvbmFyeS5jcmVhdGVPckdldEZhbWl4Q2xhc3MoYyk7XG4gICAgICAgIGZteENsYXNzLmFkZFByb3BlcnR5KGZteFByb3BlcnR5KTtcbiAgICB9IGVsc2UgeyBcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5leHBlY3RlZCB0eXBlIENsYXNzRXhwcmVzc2lvbi5cIik7XG4gICAgfVxuXG4gICAgcHJvY2Vzc0NvbW1lbnRzKHAsIGZteFByb3BlcnR5KTtcblxuICAgIC8vIHJlbW92ZSB0aGUgcHJvcGVydHkgZnJvbSB0aGUgY2xhc3NcbiAgICBwLnJlbW92ZSgpO1xuXG4gICAgcmV0dXJuIGZteFByb3BlcnR5O1xuXG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRQYXJhbWV0ZXJUb1Byb3BlcnR5UmVwcmVzZW50YXRpb24ocGFyYW06IFBhcmFtZXRlckRlY2xhcmF0aW9uKSB7XG4gICAgLy8gRXh0cmFjdCBuYW1lXG4gICAgY29uc3QgcGFyYW1OYW1lID0gcGFyYW0uZ2V0TmFtZSgpO1xuXG4gICAgLy8gRXh0cmFjdCB0eXBlXG4gICAgY29uc3QgcGFyYW1UeXBlID0gcGFyYW0uZ2V0VHlwZSgpLmdldFRleHQocGFyYW0pO1xuXG4gICAgLy8gRGV0ZXJtaW5lIHZpc2liaWxpdHlcbiAgICBsZXQgc2NvcGU6IFNjb3BlO1xuICAgIGlmIChwYXJhbS5oYXNNb2RpZmllcihTeW50YXhLaW5kLlByaXZhdGVLZXl3b3JkKSkge1xuICAgICAgICBzY29wZSA9IFNjb3BlLlByaXZhdGU7XG4gICAgfSBlbHNlIGlmIChwYXJhbS5oYXNNb2RpZmllcihTeW50YXhLaW5kLlByb3RlY3RlZEtleXdvcmQpKSB7XG4gICAgICAgIHNjb3BlID0gU2NvcGUuUHJvdGVjdGVkO1xuICAgIH0gZWxzZSBpZiAocGFyYW0uaGFzTW9kaWZpZXIoU3ludGF4S2luZC5QdWJsaWNLZXl3b3JkKSkge1xuICAgICAgICBzY29wZSA9IFNjb3BlLlB1YmxpYztcbiAgICB9XG5cbiAgICAvLyBEZXRlcm1pbmUgaWYgcmVhZG9ubHlcbiAgICBjb25zdCBpc1JlYWRvbmx5ID0gcGFyYW0uaGFzTW9kaWZpZXIoU3ludGF4S2luZC5SZWFkb25seUtleXdvcmQpO1xuXG4gICAgLy8gQ3JlYXRlIGEgcmVwcmVzZW50YXRpb24gb2YgdGhlIHByb3BlcnR5XG4gICAgY29uc3QgcHJvcGVydHlSZXByZXNlbnRhdGlvbiA9IHtcbiAgICAgICAgbmFtZTogcGFyYW1OYW1lLFxuICAgICAgICB0eXBlOiBwYXJhbVR5cGUsXG4gICAgICAgIHNjb3BlOiBzY29wZSxcbiAgICAgICAgaXNSZWFkb25seTogaXNSZWFkb25seSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHByb3BlcnR5UmVwcmVzZW50YXRpb247XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIGEgcGFyYW1ldGVyXG4gKiBAcGFyYW0gcCBBIHBhcmFtZXRlclxuICogQHJldHVybnMgQSBGYW1peC5QYXJhbWV0ZXIgcmVwcmVzZW50aW5nIHRoZSBwYXJhbWV0ZXJcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc1BhcmFtZXRlcihwOiBQYXJhbWV0ZXJEZWNsYXJhdGlvbik6IEZhbWl4LlBhcmFtZXRlciB7XG4gICAgY29uc3QgZm14UGFyYW0gPSBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZUZhbWl4UGFyYW1ldGVyKHApO1xuXG4gICAgbG9nZ2VyLmRlYnVnKGBwYXJhbWV0ZXI6ICR7cC5nZXROYW1lKCl9LCAoJHtwLmdldFR5cGUoKS5nZXRUZXh0KCl9KSwgZnFuID0gJHtmbXhQYXJhbS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKX1gKTtcblxuICAgIHByb2Nlc3NDb21tZW50cyhwLCBmbXhQYXJhbSk7XG5cbiAgICBwcm9jZXNzRGVjb3JhdG9ycyhwLCBmbXhQYXJhbSk7XG5cbiAgICBjb25zdCBwYXJlbnQgPSBwLmdldFBhcmVudCgpO1xuXG4gICAgaWYgKCEocGFyZW50IGluc3RhbmNlb2YgTWV0aG9kU2lnbmF0dXJlKSkge1xuICAgICAgICBsb2dnZXIuZGVidWcoYGFkZGluZyBhY2Nlc3M6ICR7cC5nZXROYW1lKCl9LCAoJHtwLmdldFR5cGUoKS5nZXRUZXh0KCl9KSBGYW1peCAke2ZteFBhcmFtLmdldE5hbWUoKX1gKTtcbiAgICAgICAgYWNjZXNzTWFwLnNldChmbXhQYXJhbS5pZCwgcCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZteFBhcmFtO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciB0aGUgdHlwZSBwYXJhbWV0ZXJzIG9mIGEgY2xhc3MsIGFuIGludGVyZmFjZSwgYSBtZXRob2Qgb3IgYSBmdW5jdGlvblxuICogQHBhcmFtIGUgQSBjbGFzcywgYW4gaW50ZXJmYWNlLCBhIG1ldGhvZCBvciBhIGZ1bmN0aW9uXG4gKiBAcGFyYW0gZm14U2NvcGUgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBjbGFzcywgdGhlIGludGVyZmFjZSwgdGhlIG1ldGhvZCBvciB0aGUgZnVuY3Rpb25cbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc1R5cGVQYXJhbWV0ZXJzKGU6IENsYXNzRGVjbGFyYXRpb24gfCBJbnRlcmZhY2VEZWNsYXJhdGlvbiB8IE1ldGhvZERlY2xhcmF0aW9uIHwgQ29uc3RydWN0b3JEZWNsYXJhdGlvbiB8IE1ldGhvZFNpZ25hdHVyZSB8IEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBTZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgRnVuY3Rpb25EZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRXhwcmVzc2lvbiB8QXJyb3dGdW5jdGlvbiwgZm14U2NvcGU6IEZhbWl4LlBhcmFtZXRyaWNDbGFzcyB8IEZhbWl4LlBhcmFtZXRyaWNJbnRlcmZhY2UgfCBGYW1peC5NZXRob2QgfCBGYW1peC5BY2Nlc3NvciB8IEZhbWl4LkZ1bmN0aW9uIHwgRmFtaXguQXJyb3dGdW5jdGlvbik6IHZvaWQge1xuICAgIGxvZ2dlci5kZWJ1ZyhgRmluZGluZyBUeXBlIFBhcmFtZXRlcnM6YCk7XG4gICAgZS5nZXRUeXBlUGFyYW1ldGVycygpLmZvckVhY2godHAgPT4ge1xuICAgICAgICBjb25zdCBmbXhQYXJhbSA9IHByb2Nlc3NUeXBlUGFyYW1ldGVyKHRwKTtcbiAgICAgICAgZm14U2NvcGUuYWRkR2VuZXJpY1BhcmFtZXRlcihmbXhQYXJhbSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIGEgdHlwZSBwYXJhbWV0ZXJcbiAqIEBwYXJhbSB0cCBBIHR5cGUgcGFyYW1ldGVyXG4gKiBAcmV0dXJucyBBIEZhbWl4LlR5cGVQYXJhbWV0ZXIgcmVwcmVzZW50aW5nIHRoZSB0eXBlIHBhcmFtZXRlclxuICovXG5mdW5jdGlvbiBwcm9jZXNzVHlwZVBhcmFtZXRlcih0cDogVHlwZVBhcmFtZXRlckRlY2xhcmF0aW9uKTogRmFtaXguUGFyYW1ldGVyVHlwZSB7XG4gICAgY29uc3QgZm14VHlwZVBhcmFtZXRlciA9IGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhQYXJhbWV0ZXJUeXBlKHRwKTtcblxuICAgIGxvZ2dlci5kZWJ1ZyhgdHlwZSBwYXJhbWV0ZXI6ICR7dHAuZ2V0TmFtZSgpfSwgKCR7dHAuZ2V0VHlwZSgpLmdldFRleHQoKX0pLCBmcW4gPSAke2ZteFR5cGVQYXJhbWV0ZXIuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCl9YCk7XG5cbiAgICBwcm9jZXNzQ29tbWVudHModHAsIGZteFR5cGVQYXJhbWV0ZXIpO1xuXG4gICAgcmV0dXJuIGZteFR5cGVQYXJhbWV0ZXI7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIHRoZSB2YXJpYWJsZXMgb2YgYSB2YXJpYWJsZSBzdGF0ZW1lbnRcbiAqIEBwYXJhbSB2IEEgdmFyaWFibGUgc3RhdGVtZW50XG4gKiBAcmV0dXJucyBBbiBhcnJheSBvZiBGYW1peC5WYXJpYWJsZSByZXByZXNlbnRpbmcgdGhlIHZhcmlhYmxlc1xuICovXG5mdW5jdGlvbiBwcm9jZXNzVmFyaWFibGVTdGF0ZW1lbnQodjogVmFyaWFibGVTdGF0ZW1lbnQpOiBBcnJheTxGYW1peC5WYXJpYWJsZT4ge1xuICAgIGNvbnN0IGZteFZhcmlhYmxlcyA9IG5ldyBBcnJheTxGYW1peC5WYXJpYWJsZT4oKTtcblxuICAgIGxvZ2dlci5kZWJ1ZyhgVmFyaWFibGUgc3RhdGVtZW50OiAke3YuZ2V0VGV4dCgpfSwgKCR7di5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksICR7di5nZXREZWNsYXJhdGlvbktpbmRLZXl3b3JkcygpWzBdfSwgZnFuID0gJHt2LmdldERlY2xhcmF0aW9ucygpWzBdLmdldE5hbWUoKX1gKTtcblxuICAgIHYuZ2V0RGVjbGFyYXRpb25zKCkuZm9yRWFjaCh2YXJpYWJsZSA9PiB7XG4gICAgICAgIGNvbnN0IGZteFZhciA9IHByb2Nlc3NWYXJpYWJsZSh2YXJpYWJsZSk7XG4gICAgICAgIHByb2Nlc3NDb21tZW50cyh2LCBmbXhWYXIpO1xuICAgICAgICBmbXhWYXJpYWJsZXMucHVzaChmbXhWYXIpO1xuICAgIH0pOyBcblxuICAgIHJldHVybiBmbXhWYXJpYWJsZXM7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIGEgdmFyaWFibGVcbiAqIEBwYXJhbSB2IEEgdmFyaWFibGVcbiAqIEByZXR1cm5zIEEgRmFtaXguVmFyaWFibGUgcmVwcmVzZW50aW5nIHRoZSB2YXJpYWJsZVxuICovXG5mdW5jdGlvbiBwcm9jZXNzVmFyaWFibGUodjogVmFyaWFibGVEZWNsYXJhdGlvbik6IEZhbWl4LlZhcmlhYmxlIHtcbiAgICBjb25zdCBmbXhWYXIgPSBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZUZhbWl4VmFyaWFibGUodik7XG5cbiAgICBsb2dnZXIuZGVidWcoYHZhcmlhYmxlOiAke3YuZ2V0TmFtZSgpfSwgKCR7di5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksICR7di5nZXRJbml0aWFsaXplcigpID8gXCJpbml0aWFsaXplcjogXCIgKyB2LmdldEluaXRpYWxpemVyKCkuZ2V0VGV4dCgpIDogXCJpbml0aWFsaXplcjogXCJ9LCBmcW4gPSAke2ZteFZhci5nZXRGdWxseVF1YWxpZmllZE5hbWUoKX1gKTtcblxuICAgIHByb2Nlc3NDb21tZW50cyh2LCBmbXhWYXIpO1xuXG4gICAgbG9nZ2VyLmRlYnVnKGBhZGRpbmcgYWNjZXNzOiAke3YuZ2V0TmFtZSgpfSwgKCR7di5nZXRUeXBlKCkuZ2V0VGV4dCgpfSkgRmFtaXggJHtmbXhWYXIuZ2V0TmFtZSgpfWApO1xuICAgIGFjY2Vzc01hcC5zZXQoZm14VmFyLmlkLCB2KTtcblxuICAgIHJldHVybiBmbXhWYXI7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIGFuIGVudW1cbiAqIEBwYXJhbSBlIEFuIGVudW1cbiAqIEByZXR1cm5zIEEgRmFtaXguRW51bSByZXByZXNlbnRpbmcgdGhlIGVudW1cbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0VudW0oZTogRW51bURlY2xhcmF0aW9uKTogRmFtaXguRW51bSB7XG4gICAgY29uc3QgZm14RW51bSA9IGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhFbnVtKGUpO1xuXG4gICAgbG9nZ2VyLmRlYnVnKGBlbnVtOiAke2UuZ2V0TmFtZSgpfSwgKCR7ZS5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksIGZxbiA9ICR7Zm14RW51bS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKX1gKTtcblxuICAgIHByb2Nlc3NDb21tZW50cyhlLCBmbXhFbnVtKTtcblxuICAgIGUuZ2V0TWVtYmVycygpLmZvckVhY2gobSA9PiB7XG4gICAgICAgIGNvbnN0IGZteEVudW1WYWx1ZSA9IHByb2Nlc3NFbnVtVmFsdWUobSk7XG4gICAgICAgIGZteEVudW0uYWRkVmFsdWUoZm14RW51bVZhbHVlKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBmbXhFbnVtO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciBhbiBlbnVtIG1lbWJlclxuICogQHBhcmFtIHYgQW4gZW51bSBtZW1iZXJcbiAqIEByZXR1cm5zIEEgRmFtaXguRW51bVZhbHVlIHJlcHJlc2VudGluZyB0aGUgZW51bSBtZW1iZXJcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0VudW1WYWx1ZSh2OiBFbnVtTWVtYmVyKTogRmFtaXguRW51bVZhbHVlIHtcbiAgICBjb25zdCBmbXhFbnVtVmFsdWUgPSBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZUZhbWl4RW51bVZhbHVlKHYpO1xuXG4gICAgbG9nZ2VyLmRlYnVnKGBlbnVtIHZhbHVlOiAke3YuZ2V0TmFtZSgpfSwgKCR7di5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksIGZxbiA9ICR7Zm14RW51bVZhbHVlLmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpfWApO1xuXG4gICAgcHJvY2Vzc0NvbW1lbnRzKHYsIGZteEVudW1WYWx1ZSk7XG5cbiAgICBsb2dnZXIuZGVidWcoYGFkZGluZyBhY2Nlc3M6ICR7di5nZXROYW1lKCl9LCAoJHt2LmdldFR5cGUoKS5nZXRUZXh0KCl9KSBGYW1peCAke2ZteEVudW1WYWx1ZS5nZXROYW1lKCl9YCk7XG4gICAgYWNjZXNzTWFwLnNldChmbXhFbnVtVmFsdWUuaWQsIHYpO1xuXG4gICAgcmV0dXJuIGZteEVudW1WYWx1ZTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgdGhlIGRlY29yYXRvcnMgb2YgYSBjbGFzcywgYSBtZXRob2QsIGEgcGFyYW1ldGVyIG9yIGEgcHJvcGVydHlcbiAqIEBwYXJhbSBlIEEgY2xhc3MsIGEgbWV0aG9kLCBhIHBhcmFtZXRlciBvciBhIHByb3BlcnR5XG4gKiBAcGFyYW0gZm14U2NvcGUgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBjbGFzcywgdGhlIG1ldGhvZCwgdGhlIHBhcmFtZXRlciBvciB0aGUgcHJvcGVydHlcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0RlY29yYXRvcnMoZTogQ2xhc3NEZWNsYXJhdGlvbiB8IE1ldGhvZERlY2xhcmF0aW9uIHwgR2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IFNldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBQYXJhbWV0ZXJEZWNsYXJhdGlvbiB8IFByb3BlcnR5RGVjbGFyYXRpb24sIGZteFNjb3BlOiBGYW1peC5DbGFzcyB8IEZhbWl4LlBhcmFtZXRyaWNDbGFzcyB8IEZhbWl4Lk1ldGhvZCB8IEZhbWl4LkFjY2Vzc29yIHwgRmFtaXguUGFyYW1ldGVyIHwgRmFtaXguUHJvcGVydHkpOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYEZpbmRpbmcgRGVjb3JhdG9yczpgKTtcbiAgICBlLmdldERlY29yYXRvcnMoKS5mb3JFYWNoKGRlYyA9PiB7XG4gICAgICAgIGNvbnN0IGZteERlYyA9IHByb2Nlc3NEZWNvcmF0b3IoZGVjLCBlKTtcbiAgICAgICAgZm14U2NvcGUuYWRkRGVjb3JhdG9yKGZteERlYyk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIGEgZGVjb3JhdG9yXG4gKiBAcGFyYW0gZCBBIGRlY29yYXRvclxuICogQHBhcmFtIGUgQSBjbGFzcywgYSBtZXRob2QsIGEgcGFyYW1ldGVyIG9yIGEgcHJvcGVydHlcbiAqIEByZXR1cm5zIEEgRmFtaXguRGVjb3JhdG9yIHJlcHJlc2VudGluZyB0aGUgZGVjb3JhdG9yXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NEZWNvcmF0b3IoZDogRGVjb3JhdG9yLCBlOiBDbGFzc0RlY2xhcmF0aW9uIHwgTWV0aG9kRGVjbGFyYXRpb24gfCBHZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IFBhcmFtZXRlckRlY2xhcmF0aW9uIHwgUHJvcGVydHlEZWNsYXJhdGlvbik6IEZhbWl4LkRlY29yYXRvciB7XG4gICAgY29uc3QgZm14RGVjID0gZW50aXR5RGljdGlvbmFyeS5jcmVhdGVPckdldEZhbWl4RGVjb3JhdG9yKGQsIGUpO1xuXG4gICAgbG9nZ2VyLmRlYnVnKGBkZWNvcmF0b3I6ICR7ZC5nZXROYW1lKCl9LCAoJHtkLmdldFR5cGUoKS5nZXRUZXh0KCl9KSwgZnFuID0gJHtmbXhEZWMuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCl9YCk7XG5cbiAgICBwcm9jZXNzQ29tbWVudHMoZCwgZm14RGVjKTtcblxuICAgIHJldHVybiBmbXhEZWM7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIHRoZSBjb21tZW50c1xuICogQHBhcmFtIGUgQSB0cy1tb3JwaCBlbGVtZW50XG4gKiBAcGFyYW0gZm14U2NvcGUgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBuYW1lZCBlbnRpdHlcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0NvbW1lbnRzKGU6IFNvdXJjZUZpbGUgfCBNb2R1bGVEZWNsYXJhdGlvbiB8IENsYXNzRGVjbGFyYXRpb24gfCBJbnRlcmZhY2VEZWNsYXJhdGlvbiB8IE1ldGhvZERlY2xhcmF0aW9uIHwgQ29uc3RydWN0b3JEZWNsYXJhdGlvbiB8IE1ldGhvZFNpZ25hdHVyZSB8IEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBTZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgRnVuY3Rpb25EZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRXhwcmVzc2lvbiB8IFBhcmFtZXRlckRlY2xhcmF0aW9uIHwgVmFyaWFibGVEZWNsYXJhdGlvbiB8IFByb3BlcnR5RGVjbGFyYXRpb24gfCBQcm9wZXJ0eVNpZ25hdHVyZSB8IERlY29yYXRvciB8IEVudW1EZWNsYXJhdGlvbiB8IEVudW1NZW1iZXIgfCBUeXBlUGFyYW1ldGVyRGVjbGFyYXRpb24gfCBWYXJpYWJsZVN0YXRlbWVudCB8IFR5cGVBbGlhc0RlY2xhcmF0aW9uIHwgQXJyb3dGdW5jdGlvbiwgZm14U2NvcGU6IEZhbWl4Lk5hbWVkRW50aXR5KTogdm9pZCB7XG4gICAgbG9nZ2VyLmRlYnVnKGBQcm9jZXNzIGNvbW1lbnRzOmApO1xuICAgIGUuZ2V0TGVhZGluZ0NvbW1lbnRSYW5nZXMoKS5mb3JFYWNoKGMgPT4ge1xuICAgICAgICBjb25zdCBmbXhDb21tZW50ID0gcHJvY2Vzc0NvbW1lbnQoYywgZm14U2NvcGUpO1xuICAgICAgICBsb2dnZXIuZGVidWcoYGxlYWRpbmcgY29tbWVudHMsIGFkZENvbW1lbnQ6ICcke2MuZ2V0VGV4dCgpfSdgKTtcbiAgICAgICAgZm14U2NvcGUuYWRkQ29tbWVudChmbXhDb21tZW50KTsgLy8gcmVkdW5kYW50LCBidXQganVzdCBpbiBjYXNlXG4gICAgfSk7XG4gICAgZS5nZXRUcmFpbGluZ0NvbW1lbnRSYW5nZXMoKS5mb3JFYWNoKGMgPT4ge1xuICAgICAgICBjb25zdCBmbXhDb21tZW50ID0gcHJvY2Vzc0NvbW1lbnQoYywgZm14U2NvcGUpO1xuICAgICAgICBsb2dnZXIuZGVidWcoYHRyYWlsaW5nIGNvbW1lbnRzLCBhZGRDb21tZW50OiAnJHtjLmdldFRleHQoKX0nYCk7XG4gICAgICAgIGZteFNjb3BlLmFkZENvbW1lbnQoZm14Q29tbWVudCk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIGEgY29tbWVudFxuICogQHBhcmFtIGMgQSBjb21tZW50XG4gKiBAcGFyYW0gZm14U2NvcGUgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBjb21tZW50J3MgY29udGFpbmVyXG4gKiBAcmV0dXJucyBBIEZhbWl4LkNvbW1lbnQgcmVwcmVzZW50aW5nIHRoZSBjb21tZW50XG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NDb21tZW50KGM6IENvbW1lbnRSYW5nZSwgZm14U2NvcGU6IEZhbWl4Lk5hbWVkRW50aXR5KTogRmFtaXguQ29tbWVudCB7XG4gICAgY29uc3QgaXNKU0RvYyA9IGMuZ2V0VGV4dCgpLnN0YXJ0c1dpdGgoXCIvKipcIik7XG4gICAgbG9nZ2VyLmRlYnVnKGBwcm9jZXNzQ29tbWVudDogY29tbWVudDogJHtjLmdldFRleHQoKX0sIGlzSlNEb2MgPSAke2lzSlNEb2N9YCk7XG4gICAgY29uc3QgZm14Q29tbWVudCA9IGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhDb21tZW50KGMsIGZteFNjb3BlLCBpc0pTRG9jKTtcblxuICAgIHJldHVybiBmbXhDb21tZW50O1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciB0aGUgYWNjZXNzZXMgb24gdGhlIHBhcmFtZXRlcnMsIHZhcmlhYmxlcywgcHJvcGVydGllcyBhbmQgZW51bSBtZW1iZXJzIG9mIHRoZSBzb3VyY2UgZmlsZXNcbiAqIEBwYXJhbSBhY2Nlc3NNYXAgQSBtYXAgb2YgcGFyYW1ldGVycywgdmFyaWFibGVzLCBwcm9wZXJ0aWVzIGFuZCBlbnVtIG1lbWJlcnMgd2l0aCB0aGVpciBpZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0FjY2Vzc2VzKGFjY2Vzc01hcDogTWFwPEZhbWl4SUQsIEFjY2Vzc2libGVUU01vcnBoRWxlbWVudD4pOiB2b2lkIHtcbiAgICBsb2dnZXIuZGVidWcoYENyZWF0aW5nIGFjY2Vzc2VzOmApO1xuICAgIGFjY2Vzc01hcC5mb3JFYWNoKCh2LCBpZCkgPT4ge1xuICAgICAgICBsb2dnZXIuZGVidWcoYEFjY2Vzc2VzIHRvICR7di5nZXROYW1lKCl9YCk7XG4gICAgICAgIC8vIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB0ZW1wX25vZGVzID0gdi5maW5kUmVmZXJlbmNlc0FzTm9kZXMoKSBhcyBBcnJheTxJZGVudGlmaWVyPjtcbiAgICAgICAgICAgIHRlbXBfbm9kZXMuZm9yRWFjaChub2RlID0+IHByb2Nlc3NOb2RlRm9yQWNjZXNzZXMobm9kZSwgaWQpKTtcbiAgICAgICAgLy8gfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gICAgIGxvZ2dlci5lcnJvcihgPiBXQVJOSU5HOiBnb3QgZXhjZXB0aW9uIFwiJHtlcnJvcn1cIi5cXG5Db250aW51aW5nLi4uYCk7XG4gICAgICAgIC8vIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBGYW1peCBtb2RlbCBmb3IgYW4gYWNjZXNzIG9uIGEgcGFyYW1ldGVyLCB2YXJpYWJsZSwgcHJvcGVydHkgb3IgZW51bSBtZW1iZXJcbiAqIEBwYXJhbSBuIEEgbm9kZVxuICogQHBhcmFtIGlkIEFuIGlkIG9mIGEgcGFyYW1ldGVyLCBhIHZhcmlhYmxlLCBhIHByb3BlcnR5IG9yIGFuIGVudW0gbWVtYmVyXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NOb2RlRm9yQWNjZXNzZXMobjogSWRlbnRpZmllciwgaWQ6IG51bWJlcik6IHZvaWQge1xuICAgIC8vIHRyeSB7XG4gICAgICAgIC8vIHNvbWV0aW1lcyBub2RlJ3MgZmlyc3QgYW5jZXN0b3IgaXMgYSBQcm9wZXJ0eURlY2xhcmF0aW9uLCB3aGljaCBpcyBub3QgYW4gYWNjZXNzXG4gICAgICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZnVocm1hbmF0b3IvRmFtaXhUeXBlU2NyaXB0SW1wb3J0ZXIvaXNzdWVzLzlcbiAgICAgICAgLy8gY2hlY2sgZm9yIGEgbm9kZSB3aG9zZSBmaXJzdCBhbmNlc3RvciBpcyBhIHByb3BlcnR5IGRlY2xhcmF0aW9uIGFuZCBiYWlsP1xuICAgICAgICAvLyBUaGlzIG1heSBiZSBhIGJ1ZyBpbiB0cy1tb3JwaD9cbiAgICAgICAgaWYgKG4uZ2V0Rmlyc3RBbmNlc3Rvck9yVGhyb3coKS5nZXRLaW5kTmFtZSgpID09PSBcIlByb3BlcnR5RGVjbGFyYXRpb25cIikge1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBwcm9jZXNzTm9kZUZvckFjY2Vzc2VzOiBub2RlIGtpbmQ6ICR7bi5nZXRLaW5kTmFtZSgpfSwgJHtuLmdldFRleHQoKX0sICgke24uZ2V0VHlwZSgpLmdldFRleHQoKX0pJ3MgZmlyc3QgYW5jZXN0b3IgaXMgYSBQcm9wZXJ0eURlY2xhcmF0aW9uLiBTa2lwcGluZy4uLmApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhBY2Nlc3MobiwgaWQpO1xuICAgICAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NOb2RlRm9yQWNjZXNzZXM6IG5vZGUga2luZDogJHtuLmdldEtpbmROYW1lKCl9LCAke24uZ2V0VGV4dCgpfSwgKCR7bi5nZXRUeXBlKCkuZ2V0VGV4dCgpfSlgKTtcbiAgICAvLyB9IGNhdGNoIChlcnJvcikge1xuICAgIC8vICAgICBsb2dnZXIuZXJyb3IoYD4gR290IGV4Y2VwdGlvbiBcIiR7ZXJyb3J9XCIuXFxuU2NvcGVEZWNsYXJhdGlvbiBpbnZhbGlkIGZvciBcIiR7bi5nZXRTeW1ib2woKS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKX1cIi5cXG5Db250aW51aW5nLi4uYCk7XG4gICAgLy8gfVxufVxuXG5cbi8vIGV4cG9ydHMgaGFzIG5hbWUgLT4gRGVjbGFyYXRpb24gLS0gdGhlIGRlY2xhcmF0aW9uIGNhbiBiZSB1c2VkIHRvIGZpbmQgdGhlIEZhbWl4RWxlbWVudFxuXG4vLyBoYW5kbGUgYGltcG9ydCBwYXRoID0gcmVxdWlyZShcInBhdGhcIilgIGZvciBleGFtcGxlXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0ltcG9ydENsYXVzZXNGb3JJbXBvcnRFcXVhbHNEZWNsYXJhdGlvbnMoc291cmNlRmlsZXM6IEFycmF5PFNvdXJjZUZpbGU+LCBleHBvcnRzOiBBcnJheTxSZWFkb25seU1hcDxzdHJpbmcsIEV4cG9ydGVkRGVjbGFyYXRpb25zW10+Pik6IHZvaWQge1xuICAgIGxvZ2dlci5pbmZvKGBDcmVhdGluZyBpbXBvcnQgY2xhdXNlcyBmcm9tIEltcG9ydEVxdWFsc0RlY2xhcmF0aW9ucyBpbiBzb3VyY2UgZmlsZXM6YCk7XG4gICAgc291cmNlRmlsZXMuZm9yRWFjaChzb3VyY2VGaWxlID0+IHtcbiAgICAgICAgc291cmNlRmlsZS5mb3JFYWNoRGVzY2VuZGFudChub2RlID0+IHtcbiAgICAgICAgICAgIGlmIChOb2RlLmlzSW1wb3J0RXF1YWxzRGVjbGFyYXRpb24obm9kZSkpIHtcbiAgICAgICAgICAgICAgICAvLyBZb3UndmUgZm91bmQgYW4gSW1wb3J0RXF1YWxzRGVjbGFyYXRpb25cbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIkRlY2xhcmF0aW9uIE5hbWU6XCIsIG5vZGUuZ2V0TmFtZSgpKTtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIk1vZHVsZSBSZWZlcmVuY2UgVGV4dDpcIiwgbm9kZS5nZXRNb2R1bGVSZWZlcmVuY2UoKS5nZXRUZXh0KCkpO1xuICAgICAgICAgICAgICAgIC8vIHdoYXQncyB0aGUgbmFtZSBvZiB0aGUgaW1wb3J0ZWQgZW50aXR5P1xuICAgICAgICAgICAgICAgIC8vIGNvbnN0IGltcG9ydGVkRW50aXR5ID0gbm9kZS5nZXROYW1lKCk7XG4gICAgICAgICAgICAgICAgLy8gY3JlYXRlIGEgZmFtaXggaW1wb3J0IGNsYXVzZVxuICAgICAgICAgICAgICAgIGNvbnN0IG5hbWVkSW1wb3J0ID0gbm9kZS5nZXROYW1lTm9kZSgpO1xuICAgICAgICAgICAgICAgIGVudGl0eURpY3Rpb25hcnkub2xkQ3JlYXRlRmFtaXhJbXBvcnRDbGF1c2Uoe2ltcG9ydERlY2xhcmF0aW9uOiBub2RlLFxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRlclNvdXJjZUZpbGU6IHNvdXJjZUZpbGUsIFxuICAgICAgICAgICAgICAgICAgICBtb2R1bGVTcGVjaWZpZXJGaWxlUGF0aDogbm9kZS5nZXRNb2R1bGVSZWZlcmVuY2UoKS5nZXRUZXh0KCksIFxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRFbGVtZW50OiBuYW1lZEltcG9ydCwgXG4gICAgICAgICAgICAgICAgICAgIGlzSW5FeHBvcnRzOiBleHBvcnRzLmZpbmQoZSA9PiBlLmhhcyhuYW1lZEltcG9ydC5nZXRUZXh0KCkpKSAhPT0gdW5kZWZpbmVkLCBcbiAgICAgICAgICAgICAgICAgICAgaXNEZWZhdWx0RXhwb3J0OiBmYWxzZX0pO1xuICAgICAgICAgICAgICAgIC8vIGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhJbXBvcnRDbGF1c2UoaW1wb3J0ZWRFbnRpdHksIGltcG9ydGluZ0VudGl0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICApO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciB0aGUgaW1wb3J0IGNsYXVzZXMgb2YgdGhlIHNvdXJjZSBmaWxlcyB3aGljaCBhcmUgbW9kdWxlc1xuICogQHBhcmFtIG1vZHVsZXMgQW4gYXJyYXkgb2YgbW9kdWxlc1xuICogQHBhcmFtIGV4cG9ydHMgQW4gYXJyYXkgb2YgbWFwcyBvZiBleHBvcnRlZCBkZWNsYXJhdGlvbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NJbXBvcnRDbGF1c2VzRm9yTW9kdWxlcyhtb2R1bGVzOiBBcnJheTxTb3VyY2VGaWxlPiwgZXhwb3J0czogQXJyYXk8UmVhZG9ubHlNYXA8c3RyaW5nLCBFeHBvcnRlZERlY2xhcmF0aW9uc1tdPj4pOiB2b2lkIHtcbiAgICBsb2dnZXIuaW5mbyhgQ3JlYXRpbmcgaW1wb3J0IGNsYXVzZXMgZnJvbSAke21vZHVsZXMubGVuZ3RofSBtb2R1bGVzOmApO1xuICAgIG1vZHVsZXMuZm9yRWFjaChtb2R1bGUgPT4ge1xuICAgICAgICBjb25zdCBtb2R1bGVQYXRoID0gbW9kdWxlLmdldEZpbGVQYXRoKCkgKyBtb2R1bGUuZ2V0QmFzZU5hbWUoKTtcbiAgICAgICAgbW9kdWxlLmdldEltcG9ydERlY2xhcmF0aW9ucygpLmZvckVhY2goaW1wRGVjbCA9PiB7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhgSW1wb3J0aW5nICR7aW1wRGVjbC5nZXRNb2R1bGVTcGVjaWZpZXJWYWx1ZSgpfSBpbiAke21vZHVsZVBhdGh9YCk7XG4gICAgICAgICAgICBjb25zdCBwYXRoID0gZ2V0TW9kdWxlUGF0aChpbXBEZWNsKTtcblxuICAgICAgICAgICAgaW1wRGVjbC5nZXROYW1lZEltcG9ydHMoKS5mb3JFYWNoKG5hbWVkSW1wb3J0ID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgSW1wb3J0aW5nIChuYW1lZCkgJHtuYW1lZEltcG9ydC5nZXROYW1lKCl9IGZyb20gJHtpbXBEZWNsLmdldE1vZHVsZVNwZWNpZmllclZhbHVlKCl9IGluICR7bW9kdWxlUGF0aH1gKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpbXBvcnRlZEVudGl0eU5hbWUgPSBuYW1lZEltcG9ydC5nZXROYW1lKCk7XG4gICAgICAgICAgICAgICAgbGV0IGltcG9ydEZvdW5kSW5FeHBvcnRzID0gaXNJbkV4cG9ydHMoZXhwb3J0cywgaW1wb3J0ZWRFbnRpdHlOYW1lKTtcbiAgICAgICAgICAgICAgICBlbnRpdHlEaWN0aW9uYXJ5Lm9sZENyZWF0ZUZhbWl4SW1wb3J0Q2xhdXNlKHtpbXBvcnREZWNsYXJhdGlvbjogaW1wRGVjbCxcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0ZXJTb3VyY2VGaWxlOiBtb2R1bGUsIFxuICAgICAgICAgICAgICAgICAgICBtb2R1bGVTcGVjaWZpZXJGaWxlUGF0aDogcGF0aCwgXG4gICAgICAgICAgICAgICAgICAgIGltcG9ydEVsZW1lbnQ6IG5hbWVkSW1wb3J0LCBcbiAgICAgICAgICAgICAgICAgICAgaXNJbkV4cG9ydHM6IGltcG9ydEZvdW5kSW5FeHBvcnRzLCBcbiAgICAgICAgICAgICAgICAgICAgaXNEZWZhdWx0RXhwb3J0OiBmYWxzZX0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRJbXBvcnQgPSBpbXBEZWNsLmdldERlZmF1bHRJbXBvcnQoKTtcbiAgICAgICAgICAgIGlmIChkZWZhdWx0SW1wb3J0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgSW1wb3J0aW5nIChkZWZhdWx0KSAke2RlZmF1bHRJbXBvcnQuZ2V0VGV4dCgpfSBmcm9tICR7aW1wRGVjbC5nZXRNb2R1bGVTcGVjaWZpZXJWYWx1ZSgpfSBpbiAke21vZHVsZVBhdGh9YCk7XG4gICAgICAgICAgICAgICAgLy8gY2FsbCB3aXRoIG1vZHVsZSwgaW1wRGVjbC5nZXRNb2R1bGVTcGVjaWZpZXJWYWx1ZSgpLCBwYXRoLCBkZWZhdWx0SW1wb3J0LCBmYWxzZSwgdHJ1ZVxuICAgICAgICAgICAgICAgIGVudGl0eURpY3Rpb25hcnkub2xkQ3JlYXRlRmFtaXhJbXBvcnRDbGF1c2Uoe2ltcG9ydERlY2xhcmF0aW9uOiBpbXBEZWNsLFxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRlclNvdXJjZUZpbGU6IG1vZHVsZSxcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlU3BlY2lmaWVyRmlsZVBhdGg6IHBhdGgsXG4gICAgICAgICAgICAgICAgICAgIGltcG9ydEVsZW1lbnQ6IGRlZmF1bHRJbXBvcnQsXG4gICAgICAgICAgICAgICAgICAgIGlzSW5FeHBvcnRzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgaXNEZWZhdWx0RXhwb3J0OiB0cnVlfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IG5hbWVzcGFjZUltcG9ydCA9IGltcERlY2wuZ2V0TmFtZXNwYWNlSW1wb3J0KCk7XG4gICAgICAgICAgICBpZiAobmFtZXNwYWNlSW1wb3J0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgSW1wb3J0aW5nIChuYW1lc3BhY2UpICR7bmFtZXNwYWNlSW1wb3J0LmdldFRleHQoKX0gZnJvbSAke2ltcERlY2wuZ2V0TW9kdWxlU3BlY2lmaWVyVmFsdWUoKX0gaW4gJHttb2R1bGVQYXRofWApO1xuICAgICAgICAgICAgICAgIGVudGl0eURpY3Rpb25hcnkub2xkQ3JlYXRlRmFtaXhJbXBvcnRDbGF1c2Uoe2ltcG9ydERlY2xhcmF0aW9uOiBpbXBEZWNsLFxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRlclNvdXJjZUZpbGU6IG1vZHVsZSwgXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZVNwZWNpZmllckZpbGVQYXRoOiBwYXRoLCBcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RWxlbWVudDogbmFtZXNwYWNlSW1wb3J0LCBcbiAgICAgICAgICAgICAgICAgICAgaXNJbkV4cG9ydHM6IGZhbHNlLCBcbiAgICAgICAgICAgICAgICAgICAgaXNEZWZhdWx0RXhwb3J0OiBmYWxzZX0pO1xuICAgICAgICAgICAgICAgIC8vIGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhJbXBvcnRDbGF1c2UobW9kdWxlLCBpbXBEZWNsLmdldE1vZHVsZVNwZWNpZmllclZhbHVlKCksIHBhdGgsIG5hbWVzcGFjZUltcG9ydCwgZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7IFxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBpc0luRXhwb3J0cyhleHBvcnRzOiBSZWFkb25seU1hcDxzdHJpbmcsIEV4cG9ydGVkRGVjbGFyYXRpb25zW10+W10sIGltcG9ydGVkRW50aXR5TmFtZTogc3RyaW5nKSB7XG4gICAgbGV0IGltcG9ydEZvdW5kSW5FeHBvcnRzID0gZmFsc2U7XG4gICAgZXhwb3J0cy5mb3JFYWNoKGUgPT4ge1xuICAgICAgICBpZiAoZS5oYXMoaW1wb3J0ZWRFbnRpdHlOYW1lKSkge1xuICAgICAgICAgICAgaW1wb3J0Rm91bmRJbkV4cG9ydHMgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGltcG9ydEZvdW5kSW5FeHBvcnRzO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciB0aGUgaW5oZXJpdGFuY2VzIG9mIHRoZSBjbGFzc2VzIGFuZCBpbnRlcmZhY2VzIG9mIHRoZSBzb3VyY2UgZmlsZXNcbiAqIEBwYXJhbSBjbGFzc2VzIEFuIGFycmF5IG9mIGNsYXNzZXNcbiAqIEBwYXJhbSBpbnRlcmZhY2VzIEFuIGFycmF5IG9mIGludGVyZmFjZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NJbmhlcml0YW5jZXMoY2xhc3NlczogQ2xhc3NEZWNsYXJhdGlvbltdLCBpbnRlcmZhY2VzOiBJbnRlcmZhY2VEZWNsYXJhdGlvbltdKTogdm9pZCB7XG4gICAgbG9nZ2VyLmluZm8oYHByb2Nlc3NJbmhlcml0YW5jZXM6IENyZWF0aW5nIGluaGVyaXRhbmNlczpgKTtcbiAgICBjbGFzc2VzLmZvckVhY2goY2xzID0+IHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBwcm9jZXNzSW5oZXJpdGFuY2VzOiBDaGVja2luZyBjbGFzcyBpbmhlcml0YW5jZSBmb3IgJHtjbHMuZ2V0TmFtZSgpfWApO1xuICAgICAgICBjb25zdCBleHRDbGFzcyA9IGNscy5nZXRCYXNlQ2xhc3MoKTtcbiAgICAgICAgaWYgKGV4dENsYXNzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhJbmhlcml0YW5jZShjbHMsIGV4dENsYXNzKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBwcm9jZXNzSW5oZXJpdGFuY2VzOiBjbGFzczogJHtjbHMuZ2V0TmFtZSgpfSwgKCR7Y2xzLmdldFR5cGUoKS5nZXRUZXh0KCl9KSwgZXh0Q2xhc3M6ICR7ZXh0Q2xhc3MuZ2V0TmFtZSgpfSwgKCR7ZXh0Q2xhc3MuZ2V0VHlwZSgpLmdldFRleHQoKX0pYCk7XG4gICAgICAgIH1cblxuICAgICAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NJbmhlcml0YW5jZXM6IENoZWNraW5nIGludGVyZmFjZSBpbmhlcml0YW5jZSBmb3IgJHtjbHMuZ2V0TmFtZSgpfWApO1xuICAgICAgICBjb25zdCBpbXBsZW1lbnRlZEludGVyZmFjZXMgPSBnZXRJbXBsZW1lbnRlZE9yRXh0ZW5kZWRJbnRlcmZhY2VzKGludGVyZmFjZXMsIGNscyk7XG4gICAgICAgIGltcGxlbWVudGVkSW50ZXJmYWNlcy5mb3JFYWNoKGltcEludGVyID0+IHtcbiAgICAgICAgICAgIGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhJbmhlcml0YW5jZShjbHMsIGltcEludGVyKTtcblxuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBwcm9jZXNzSW5oZXJpdGFuY2VzOiBjbGFzczogJHtjbHMuZ2V0TmFtZSgpfSwgKCR7Y2xzLmdldFR5cGUoKS5nZXRUZXh0KCl9KSwgaW1wSW50ZXI6ICR7KGltcEludGVyIGluc3RhbmNlb2YgSW50ZXJmYWNlRGVjbGFyYXRpb24pID8gaW1wSW50ZXIuZ2V0TmFtZSgpIDogaW1wSW50ZXIuZ2V0RXhwcmVzc2lvbigpLmdldFRleHQoKX0sICgkeyhpbXBJbnRlciBpbnN0YW5jZW9mIEludGVyZmFjZURlY2xhcmF0aW9uKSA/IGltcEludGVyLmdldFR5cGUoKS5nZXRUZXh0KCkgOiBpbXBJbnRlci5nZXRFeHByZXNzaW9uKCkuZ2V0VGV4dCgpfSlgKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpbnRlcmZhY2VzLmZvckVhY2goaW50ZXIgPT4ge1xuICAgICAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NJbmhlcml0YW5jZXM6IENoZWNraW5nIGludGVyZmFjZSBpbmhlcml0YW5jZSBmb3IgJHtpbnRlci5nZXROYW1lKCl9YCk7XG4gICAgICAgIGNvbnN0IGV4dGVuZGVkSW50ZXJmYWNlcyA9IGdldEltcGxlbWVudGVkT3JFeHRlbmRlZEludGVyZmFjZXMoaW50ZXJmYWNlcywgaW50ZXIpO1xuICAgICAgICBleHRlbmRlZEludGVyZmFjZXMuZm9yRWFjaChleHRJbnRlciA9PiB7XG4gICAgICAgICAgICBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZUZhbWl4SW5oZXJpdGFuY2UoaW50ZXIsIGV4dEludGVyKTtcblxuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBwcm9jZXNzSW5oZXJpdGFuY2VzOiBpbnRlcjogJHtpbnRlci5nZXROYW1lKCl9LCAoJHtpbnRlci5nZXRUeXBlKCkuZ2V0VGV4dCgpfSksIGV4dEludGVyOiAkeyhleHRJbnRlciBpbnN0YW5jZW9mIEludGVyZmFjZURlY2xhcmF0aW9uKSA/IGV4dEludGVyLmdldE5hbWUoKSA6IGV4dEludGVyLmdldEV4cHJlc3Npb24oKS5nZXRUZXh0KCl9LCAoJHsoZXh0SW50ZXIgaW5zdGFuY2VvZiBJbnRlcmZhY2VEZWNsYXJhdGlvbikgPyBleHRJbnRlci5nZXRUeXBlKCkuZ2V0VGV4dCgpIDogZXh0SW50ZXIuZ2V0RXhwcmVzc2lvbigpLmdldFRleHQoKX0pYCk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciB0aGUgaW52b2NhdGlvbnMgb2YgdGhlIG1ldGhvZHMgYW5kIGZ1bmN0aW9ucyBvZiB0aGUgc291cmNlIGZpbGVzXG4gKiBAcGFyYW0gbWV0aG9kc0FuZEZ1bmN0aW9uc1dpdGhJZCBBIG1hcCBvZiBtZXRob2RzIGFuZCBmdW5jdGlvbnMgd2l0aCB0aGVpciBpZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0ludm9jYXRpb25zKG1ldGhvZHNBbmRGdW5jdGlvbnNXaXRoSWQ6IE1hcDxudW1iZXIsIE1ldGhvZERlY2xhcmF0aW9uIHwgQ29uc3RydWN0b3JEZWNsYXJhdGlvbiB8IEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBTZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgRnVuY3Rpb25EZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRXhwcmVzc2lvbiB8IEFycm93RnVuY3Rpb24+KTogdm9pZCB7XG4gICAgbG9nZ2VyLmluZm8oYENyZWF0aW5nIGludm9jYXRpb25zOmApO1xuICAgIG1ldGhvZHNBbmRGdW5jdGlvbnNXaXRoSWQuZm9yRWFjaCgobSwgaWQpID0+IHtcbiAgICAgICAgaWYgKCEobSBpbnN0YW5jZW9mIEFycm93RnVuY3Rpb24pKSB7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoYEludm9jYXRpb25zIHRvICR7KG0gaW5zdGFuY2VvZiBNZXRob2REZWNsYXJhdGlvbiB8fCBtIGluc3RhbmNlb2YgR2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8fCBtIGluc3RhbmNlb2YgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8fCBtIGluc3RhbmNlb2YgRnVuY3Rpb25EZWNsYXJhdGlvbikgPyBtLmdldE5hbWUoKSA6ICgobSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yRGVjbGFyYXRpb24pID8gJ2NvbnN0cnVjdG9yJyA6IChtLmdldE5hbWUoKSA/IG0uZ2V0TmFtZSgpIDogJ2Fub255bW91cycpKX1gKTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGVtcF9ub2RlcyA9IG0uZmluZFJlZmVyZW5jZXNBc05vZGVzKCkgYXMgQXJyYXk8SWRlbnRpZmllcj47XG4gICAgICAgICAgICAgICAgdGVtcF9ub2Rlcy5mb3JFYWNoKG5vZGUgPT4gcHJvY2Vzc05vZGVGb3JJbnZvY2F0aW9ucyhub2RlLCBtLCBpZCkpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYD4gV0FSTklORzogZ290IGV4Y2VwdGlvbiAke2Vycm9yfS4gQ29udGludWluZy4uLmApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgRmFtaXggbW9kZWwgZm9yIGFuIGludm9jYXRpb24gb2YgYSBtZXRob2Qgb3IgYSBmdW5jdGlvblxuICogQHBhcmFtIG4gQSBub2RlXG4gKiBAcGFyYW0gbSBBIG1ldGhvZCBvciBhIGZ1bmN0aW9uXG4gKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBtZXRob2Qgb3IgdGhlIGZ1bmN0aW9uXG4gKi9cbmZ1bmN0aW9uIHByb2Nlc3NOb2RlRm9ySW52b2NhdGlvbnMobjogSWRlbnRpZmllciwgbTogTWV0aG9kRGVjbGFyYXRpb24gfCBDb25zdHJ1Y3RvckRlY2xhcmF0aW9uIHwgR2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IFNldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBGdW5jdGlvbkRlY2xhcmF0aW9uIHwgRnVuY3Rpb25FeHByZXNzaW9uLCBpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgICAgZW50aXR5RGljdGlvbmFyeS5jcmVhdGVGYW1peEludm9jYXRpb24obiwgbSwgaWQpO1xuXG4gICAgICAgIGxvZ2dlci5kZWJ1Zyhgbm9kZTogbm9kZSwgKCR7bi5nZXRUeXBlKCkuZ2V0VGV4dCgpfSlgKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsb2dnZXIuZXJyb3IoYD4gV0FSTklORzogZ290IGV4Y2VwdGlvbiAke2Vycm9yfS4gU2NvcGVEZWNsYXJhdGlvbiBpbnZhbGlkIGZvciAke24uZ2V0U3ltYm9sKCkuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCl9LiBDb250aW51aW5nLi4uYCk7XG4gICAgfVxufVxuXG4vKipcbiAqIEJ1aWxkcyBhIEZhbWl4IG1vZGVsIGZvciB0aGUgaW5oZXJpdGFuY2VzIG9mIHRoZSBjbGFzc2VzIGFuZCBpbnRlcmZhY2VzIG9mIHRoZSBzb3VyY2UgZmlsZXNcbiAqIEBwYXJhbSBjbGFzc2VzIEFuIGFycmF5IG9mIGNsYXNzZXNcbiAqIEBwYXJhbSBpbnRlcmZhY2VzIEFuIGFycmF5IG9mIGludGVyZmFjZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NDb25jcmV0aXNhdGlvbnMoY2xhc3NlczogQ2xhc3NEZWNsYXJhdGlvbltdLCBpbnRlcmZhY2VzOiBJbnRlcmZhY2VEZWNsYXJhdGlvbltdLCBmdW5jdGlvbnM6IE1hcDxudW1iZXIsIE1ldGhvZERlY2xhcmF0aW9uIHwgQ29uc3RydWN0b3JEZWNsYXJhdGlvbiB8IEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBTZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgRnVuY3Rpb25EZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRXhwcmVzc2lvbiB8IEFycm93RnVuY3Rpb24+KTogdm9pZCB7XG4gICAgbG9nZ2VyLmluZm8oYHByb2Nlc3NDb25jcmV0aXNhdGlvbnM6IENyZWF0aW5nIGNvbmNyZXRpc2F0aW9uczpgKTtcbiAgICBjbGFzc2VzLmZvckVhY2goY2xzID0+IHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBwcm9jZXNzQ29uY3JldGlzYXRpb25zOiBDaGVja2luZyBjbGFzcyBjb25jcmV0aXNhdGlvbiBmb3IgJHtjbHMuZ2V0TmFtZSgpfWApO1xuICAgICAgICBlbnRpdHlEaWN0aW9uYXJ5LmNyZWF0ZUZhbWl4Q29uY3JldGlzYXRpb25DbGFzc09ySW50ZXJmYWNlU3BlY2lhbGlzYXRpb24oY2xzKTtcbiAgICAgICAgZW50aXR5RGljdGlvbmFyeS5jcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uR2VuZXJpY0luc3RhbnRpYXRpb24oY2xzKTtcbiAgICAgICAgZW50aXR5RGljdGlvbmFyeS5jcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uSW50ZXJmYWNlQ2xhc3MoY2xzKTtcbiAgICAgICAgZW50aXR5RGljdGlvbmFyeS5jcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uVHlwZUluc3RhbmNpYXRpb24oY2xzKTsgXG5cbiAgICB9KTtcbiAgICBpbnRlcmZhY2VzLmZvckVhY2goaW50ZXIgPT4ge1xuICAgICAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NDb25jcmV0aXNhdGlvbnM6IENoZWNraW5nIGludGVyZmFjZSBjb25jcmV0aXNhdGlvbiBmb3IgJHtpbnRlci5nZXROYW1lKCl9YCk7XG4gICAgICAgIGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhDb25jcmV0aXNhdGlvblR5cGVJbnN0YW5jaWF0aW9uKGludGVyKTsgXG4gICAgICAgIGVudGl0eURpY3Rpb25hcnkuY3JlYXRlRmFtaXhDb25jcmV0aXNhdGlvbkNsYXNzT3JJbnRlcmZhY2VTcGVjaWFsaXNhdGlvbihpbnRlcilcbiAgICB9KTtcbiAgICBmdW5jdGlvbnMuZm9yRWFjaChmdW5jID0+IHtcbiAgICAgICAgaWYoZnVuYyBpbnN0YW5jZW9mIEZ1bmN0aW9uRGVjbGFyYXRpb24gfHwgZnVuYyBpbnN0YW5jZW9mIE1ldGhvZERlY2xhcmF0aW9uICl7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoYHByb2Nlc3NDb25jcmV0aXNhdGlvbnM6IENoZWNraW5nIE1ldGhvZCBjb25jcmV0aXNhdGlvbmApO1xuICAgICAgICAgICAgZW50aXR5RGljdGlvbmFyeS5jcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uRnVuY3Rpb25JbnN0YW50aWF0aW9uKGZ1bmMpO1xuICAgICAgICB9XG4gICAgfSlcbn1cbiJdfQ==
|