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.
Files changed (119) hide show
  1. package/README.md +1 -1
  2. package/dist/analyze.js +4 -2
  3. package/dist/analyze_functions/process_functions.js +248 -100
  4. package/dist/famix2puml.js +1 -0
  5. package/dist/famix_functions/EntityDictionary.js +661 -155
  6. package/dist/famix_functions/helpers_creation.js +26 -6
  7. package/dist/fqn.js +156 -69
  8. package/dist/lib/famix/src/famix_JSON_exporter.js +1 -0
  9. package/dist/lib/famix/src/famix_base_element.js +1 -0
  10. package/dist/lib/famix/src/famix_repository.js +9 -8
  11. package/dist/lib/famix/src/index.js +1 -0
  12. package/dist/lib/famix/src/model/famix/access.js +3 -2
  13. package/dist/lib/famix/src/model/famix/accessor.js +1 -0
  14. package/dist/lib/famix/src/model/famix/alias.js +2 -1
  15. package/dist/lib/famix/src/model/famix/arrowFunction.js +17 -0
  16. package/dist/lib/famix/src/model/famix/behavioral_entity.js +13 -15
  17. package/dist/lib/famix/src/model/famix/class.js +1 -0
  18. package/dist/lib/famix/src/model/famix/comment.js +2 -1
  19. package/dist/lib/famix/src/model/famix/concretisation.js +31 -0
  20. package/dist/lib/famix/src/model/famix/container_entity.js +7 -6
  21. package/dist/lib/famix/src/model/famix/decorator.js +2 -1
  22. package/dist/lib/famix/src/model/famix/entity.js +1 -0
  23. package/dist/lib/famix/src/model/famix/enum.js +2 -1
  24. package/dist/lib/famix/src/model/famix/enum_value.js +2 -1
  25. package/dist/lib/famix/src/model/famix/function.js +1 -0
  26. package/dist/lib/famix/src/model/famix/implicit_variable.js +1 -0
  27. package/dist/lib/famix/src/model/famix/import_clause.js +5 -3
  28. package/dist/lib/famix/src/model/famix/index.js +18 -11
  29. package/dist/lib/famix/src/model/famix/indexed_file_anchor.js +3 -2
  30. package/dist/lib/famix/src/model/famix/inheritance.js +3 -2
  31. package/dist/lib/famix/src/model/famix/interface.js +2 -1
  32. package/dist/lib/famix/src/model/famix/invocation.js +3 -2
  33. package/dist/lib/famix/src/model/famix/method.js +2 -1
  34. package/dist/lib/famix/src/model/famix/module.js +53 -0
  35. package/dist/lib/famix/src/model/famix/named_entity.js +4 -3
  36. package/dist/lib/famix/src/model/famix/parameter.js +2 -1
  37. package/dist/lib/famix/src/model/famix/parameterConcretisation.js +44 -0
  38. package/dist/lib/famix/src/model/famix/parameter_type.js +22 -1
  39. package/dist/lib/famix/src/model/famix/parametric_arrow_function.js +31 -0
  40. package/dist/lib/famix/src/model/famix/parametric_class.js +44 -0
  41. package/dist/lib/famix/src/model/famix/parametric_function.js +31 -0
  42. package/dist/lib/famix/src/model/famix/parametric_interface.js +44 -0
  43. package/dist/lib/famix/src/model/famix/parametric_method.js +31 -0
  44. package/dist/lib/famix/src/model/famix/primitive_type.js +1 -0
  45. package/dist/lib/famix/src/model/famix/property.js +91 -9
  46. package/dist/lib/famix/src/model/famix/reference.js +3 -2
  47. package/dist/lib/famix/src/model/famix/scoping_entity.js +12 -10
  48. package/dist/lib/famix/src/model/famix/script_entity.js +1 -2
  49. package/dist/lib/famix/src/model/famix/source_anchor.js +1 -0
  50. package/dist/lib/famix/src/model/famix/source_language.js +1 -1
  51. package/dist/lib/famix/src/model/famix/sourced_entity.js +2 -1
  52. package/dist/lib/famix/src/model/famix/structural_entity.js +1 -0
  53. package/dist/lib/famix/src/model/famix/text_anchor.js +1 -0
  54. package/dist/lib/famix/src/model/famix/type.js +6 -4
  55. package/dist/lib/famix/src/model/famix/variable.js +1 -0
  56. package/dist/lib/ts-complex/cyclomatic-service.js +2 -2
  57. package/dist/ts2famix-cli-wrapper.js +16 -0
  58. package/dist/ts2famix-cli.js +8 -1
  59. package/dist/ts2famix-tsconfig.js +1 -0
  60. package/doc-uml/famix-typescript-model.puml +559 -0
  61. package/doc-uml/famix-typescript-model.svg +1 -0
  62. package/jest.config.json +2 -1
  63. package/package.json +10 -10
  64. package/src/analyze.ts +22 -21
  65. package/src/analyze_functions/process_functions.ts +272 -96
  66. package/src/famix_functions/EntityDictionary.ts +731 -182
  67. package/src/famix_functions/helpers_creation.ts +28 -2
  68. package/src/fqn.ts +132 -10
  69. package/src/lib/famix/src/famix_repository.ts +9 -9
  70. package/src/lib/famix/src/model/famix/access.ts +2 -2
  71. package/src/lib/famix/src/model/famix/alias.ts +1 -1
  72. package/src/lib/famix/src/model/famix/arrowFunction.ts +15 -0
  73. package/src/lib/famix/src/model/famix/behavioral_entity.ts +12 -19
  74. package/src/lib/famix/src/model/famix/comment.ts +1 -1
  75. package/src/lib/famix/src/model/famix/concretisation.ts +42 -0
  76. package/src/lib/famix/src/model/famix/container_entity.ts +6 -6
  77. package/src/lib/famix/src/model/famix/decorator.ts +1 -1
  78. package/src/lib/famix/src/model/famix/enum.ts +1 -1
  79. package/src/lib/famix/src/model/famix/enum_value.ts +1 -1
  80. package/src/lib/famix/src/model/famix/import_clause.ts +4 -3
  81. package/src/lib/famix/src/model/famix/index.ts +8 -5
  82. package/src/lib/famix/src/model/famix/indexed_file_anchor.ts +2 -2
  83. package/src/lib/famix/src/model/famix/inheritance.ts +3 -4
  84. package/src/lib/famix/src/model/famix/interface.ts +1 -1
  85. package/src/lib/famix/src/model/famix/invocation.ts +2 -2
  86. package/src/lib/famix/src/model/famix/method.ts +1 -1
  87. package/src/lib/famix/src/model/famix/module.ts +67 -1
  88. package/src/lib/famix/src/model/famix/named_entity.ts +3 -3
  89. package/src/lib/famix/src/model/famix/parameter.ts +1 -1
  90. package/src/lib/famix/src/model/famix/parameterConcretisation.ts +54 -0
  91. package/src/lib/famix/src/model/famix/parameter_type.ts +33 -6
  92. package/src/lib/famix/src/model/famix/parametric_arrow_function.ts +32 -0
  93. package/src/lib/famix/src/model/famix/parametric_class.ts +49 -0
  94. package/src/lib/famix/src/model/famix/parametric_function.ts +32 -0
  95. package/src/lib/famix/src/model/famix/parametric_interface.ts +49 -0
  96. package/src/lib/famix/src/model/famix/parametric_method.ts +32 -0
  97. package/src/lib/famix/src/model/famix/property.ts +109 -11
  98. package/src/lib/famix/src/model/famix/reference.ts +2 -2
  99. package/src/lib/famix/src/model/famix/scoping_entity.ts +12 -11
  100. package/src/lib/famix/src/model/famix/script_entity.ts +0 -2
  101. package/src/lib/famix/src/model/famix/source_language.ts +0 -1
  102. package/src/lib/famix/src/model/famix/sourced_entity.ts +1 -1
  103. package/src/lib/famix/src/model/famix/type.ts +5 -4
  104. package/src/ts2famix-cli-wrapper.ts +17 -0
  105. package/src/ts2famix-cli.ts +7 -1
  106. package/tsconfig.json +5 -5
  107. package/dist/lib/famix/src/model/famix/association.js +0 -36
  108. package/dist/lib/famix/src/model/famix/namespace.js +0 -24
  109. package/dist/lib/famix/src/model/famix/parameterizable_class.js +0 -30
  110. package/dist/lib/famix/src/model/famix/parameterizable_interface.js +0 -30
  111. package/dist/lib/famix/src/model/famix/parameterized_type.js +0 -36
  112. package/doc-uml/metamodel-full.svg +0 -1
  113. package/doc-uml/metamodel.svg +0 -1
  114. package/plantuml.jar +0 -0
  115. package/src/lib/famix/src/model/famix/association.ts +0 -44
  116. package/src/lib/famix/src/model/famix/namespace.ts +0 -28
  117. package/src/lib/famix/src/model/famix/parameterizable_class.ts +0 -31
  118. package/src/lib/famix/src/model/famix/parameterizable_interface.ts +0 -31
  119. package/src/lib/famix/src/model/famix/parameterized_type.ts +0 -40
@@ -28,6 +28,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.EntityDictionary = void 0;
30
30
  const ts_morph_1 = require("ts-morph");
31
+ const process_functions_1 = require("../analyze_functions/process_functions");
31
32
  const Famix = __importStar(require("../lib/famix/src/model/famix"));
32
33
  const analyze_1 = require("../analyze");
33
34
  const grapheme_splitter_1 = __importDefault(require("grapheme-splitter"));
@@ -35,15 +36,17 @@ const Helpers = __importStar(require("./helpers_creation"));
35
36
  const FQNFunctions = __importStar(require("../fqn"));
36
37
  const famix_repository_1 = require("../lib/famix/src/famix_repository");
37
38
  const path_1 = __importDefault(require("path"));
39
+ const lodash_1 = __importDefault(require("lodash"));
38
40
  class EntityDictionary {
39
41
  constructor() {
40
42
  this.famixRep = new famix_repository_1.FamixRepository();
41
43
  this.fmxAliasMap = new Map(); // Maps the alias names to their Famix model
42
44
  this.fmxClassMap = new Map(); // Maps the fully qualified class names to their Famix model
43
45
  this.fmxInterfaceMap = new Map(); // Maps the interface names to their Famix model
44
- this.fmxNamespaceMap = new Map(); // Maps the namespace names to their Famix model
46
+ this.fmxModuleMap = new Map(); // Maps the namespace names to their Famix model
45
47
  this.fmxFileMap = new Map(); // Maps the source file names to their Famix model
46
48
  this.fmxTypeMap = new Map(); // Maps the type names to their Famix model
49
+ this.fmxFunctionAndMethodMap = new Map; // Maps the function names to their Famix model
47
50
  this.UNKNOWN_VALUE = '(unknown due to parsing error)'; // The value to use when a name is not usable
48
51
  this.fmxElementObjectMap = new Map();
49
52
  this.famixRep.setFmxElementObjectMap(this.fmxElementObjectMap);
@@ -54,7 +57,7 @@ class EntityDictionary {
54
57
  * @param famixElement The Famix model of the source element
55
58
  */
56
59
  makeFamixIndexFileAnchor(sourceElement, famixElement) {
57
- analyze_1.logger.debug("making index file anchor for '" + (sourceElement === null || sourceElement === void 0 ? void 0 : sourceElement.getText()) + "' with famixElement " + famixElement.getJSON());
60
+ analyze_1.logger.debug("making index file anchor for '" + sourceElement?.getText() + "' with famixElement " + famixElement.getJSON());
58
61
  const fmxIndexFileAnchor = new Famix.IndexedFileAnchor();
59
62
  fmxIndexFileAnchor.setElement(famixElement);
60
63
  this.fmxElementObjectMap.set(famixElement, sourceElement);
@@ -117,8 +120,10 @@ class EntityDictionary {
117
120
  fmxIndexFileAnchor.setStartLine(sourceLineStart);
118
121
  fmxIndexFileAnchor.setEndLine(sourceLineEnd);
119
122
  }
120
- if (!(famixElement instanceof Famix.Association) && !(famixElement instanceof Famix.Comment) && !(sourceElement instanceof ts_morph_1.CommentRange) && !(sourceElement instanceof ts_morph_1.Identifier) && !(sourceElement instanceof ts_morph_1.ImportSpecifier) && !(sourceElement instanceof ts_morph_1.ExpressionWithTypeArguments)) {
121
- famixElement.setFullyQualifiedName(FQNFunctions.getFQN(sourceElement));
123
+ if (!(famixElement instanceof Famix.ImportClause || famixElement instanceof Famix.Access || famixElement instanceof Famix.Reference || famixElement instanceof Famix.Invocation || famixElement instanceof Famix.Inheritance) && !(famixElement instanceof Famix.Comment) && !(sourceElement instanceof ts_morph_1.CommentRange) && !(sourceElement instanceof ts_morph_1.Identifier) && !(sourceElement instanceof ts_morph_1.ImportSpecifier) && !(sourceElement instanceof ts_morph_1.ExpressionWithTypeArguments)) {
124
+ const fqn = FQNFunctions.getFQN(sourceElement);
125
+ analyze_1.logger.debug("Setting fully qualified name for " + famixElement.getJSON() + " to " + fqn);
126
+ famixElement.setFullyQualifiedName(fqn);
122
127
  }
123
128
  }
124
129
  else {
@@ -137,7 +142,7 @@ class EntityDictionary {
137
142
  * @returns The Famix model of the source file
138
143
  */
139
144
  createOrGetFamixFile(f, isModule) {
140
- let fmxFile;
145
+ let fmxFile; // | Famix.Module;
141
146
  const fileName = f.getBaseName();
142
147
  const fullyQualifiedFilename = f.getFilePath();
143
148
  if (!this.fmxFileMap.has(fullyQualifiedFilename)) {
@@ -161,25 +166,28 @@ class EntityDictionary {
161
166
  return fmxFile;
162
167
  }
163
168
  /**
164
- * Creates or gets a Famix namespace
165
- * @param m A namespace
166
- * @returns The Famix model of the namespace
169
+ * Creates or gets a Famix Module
170
+ * @param m A module
171
+ * @returns The Famix model of the module
167
172
  */
168
- createOrGetFamixNamespace(m) {
169
- let fmxNamespace;
170
- const namespaceName = m.getName();
171
- if (!this.fmxNamespaceMap.has(namespaceName)) {
172
- fmxNamespace = new Famix.Namespace();
173
- fmxNamespace.setName(namespaceName);
174
- this.makeFamixIndexFileAnchor(m, fmxNamespace);
175
- this.fmxNamespaceMap.set(namespaceName, fmxNamespace);
176
- this.famixRep.addElement(fmxNamespace);
173
+ createOrGetFamixModule(m) {
174
+ let fmxModule;
175
+ const moduleName = m.getName();
176
+ if (!this.fmxModuleMap.has(moduleName)) {
177
+ fmxModule = new Famix.Module();
178
+ fmxModule.setName(moduleName);
179
+ fmxModule.$isAmbient = (0, process_functions_1.isAmbient)(m);
180
+ fmxModule.$isNamespace = (0, process_functions_1.isNamespace)(m);
181
+ fmxModule.$isModule = !fmxModule.$isNamespace && !fmxModule.$isAmbient;
182
+ this.makeFamixIndexFileAnchor(m, fmxModule);
183
+ this.fmxModuleMap.set(moduleName, fmxModule);
184
+ this.famixRep.addElement(fmxModule);
177
185
  }
178
186
  else {
179
- fmxNamespace = this.fmxNamespaceMap.get(namespaceName);
187
+ fmxModule = this.fmxModuleMap.get(moduleName);
180
188
  }
181
- this.fmxElementObjectMap.set(fmxNamespace, m);
182
- return fmxNamespace;
189
+ this.fmxElementObjectMap.set(fmxModule, m);
190
+ return fmxModule;
183
191
  }
184
192
  /**
185
193
  * Creates a Famix alias
@@ -217,10 +225,10 @@ class EntityDictionary {
217
225
  const isAbstract = cls.isAbstract();
218
226
  const classFullyQualifiedName = FQNFunctions.getFQN(cls);
219
227
  const clsName = cls.getName();
228
+ const isGeneric = cls.getTypeParameters().length;
220
229
  if (!this.fmxClassMap.has(classFullyQualifiedName)) {
221
- const isGeneric = cls.getTypeParameters().length;
222
230
  if (isGeneric) {
223
- fmxClass = new Famix.ParameterizableClass();
231
+ fmxClass = new Famix.ParametricClass();
224
232
  }
225
233
  else {
226
234
  fmxClass = new Famix.Class();
@@ -231,11 +239,11 @@ class EntityDictionary {
231
239
  this.makeFamixIndexFileAnchor(cls, fmxClass);
232
240
  this.fmxClassMap.set(classFullyQualifiedName, fmxClass);
233
241
  this.famixRep.addElement(fmxClass);
242
+ this.fmxElementObjectMap.set(fmxClass, cls);
234
243
  }
235
244
  else {
236
245
  fmxClass = this.fmxClassMap.get(classFullyQualifiedName);
237
246
  }
238
- this.fmxElementObjectMap.set(fmxClass, cls);
239
247
  return fmxClass;
240
248
  }
241
249
  /**
@@ -247,10 +255,10 @@ class EntityDictionary {
247
255
  let fmxInterface;
248
256
  const interName = inter.getName();
249
257
  const interFullyQualifiedName = FQNFunctions.getFQN(inter);
250
- if (!this.fmxInterfaceMap.has(interName)) {
258
+ if (!this.fmxInterfaceMap.has(interFullyQualifiedName)) {
251
259
  const isGeneric = inter.getTypeParameters().length;
252
260
  if (isGeneric) {
253
- fmxInterface = new Famix.ParameterizableInterface();
261
+ fmxInterface = new Famix.ParametricInterface();
254
262
  }
255
263
  else {
256
264
  fmxInterface = new Famix.Interface();
@@ -259,13 +267,68 @@ class EntityDictionary {
259
267
  this.makeFamixIndexFileAnchor(inter, fmxInterface);
260
268
  this.fmxInterfaceMap.set(interFullyQualifiedName, fmxInterface);
261
269
  this.famixRep.addElement(fmxInterface);
270
+ this.fmxElementObjectMap.set(fmxInterface, inter);
262
271
  }
263
272
  else {
264
- fmxInterface = this.fmxInterfaceMap.get(interName);
273
+ fmxInterface = this.fmxInterfaceMap.get(interFullyQualifiedName);
265
274
  }
266
- this.fmxElementObjectMap.set(fmxInterface, inter);
267
275
  return fmxInterface;
268
276
  }
277
+ /**
278
+ * Creates or gets a Famix concrete element
279
+ * @param el A parametric Element
280
+ * @param elDeclaration the element declaration
281
+ * @param concreteArguments concrete arguments
282
+ * @returns A parametric Element
283
+ */
284
+ createOrGetFamixConcreteElement(el, elDeclaration, concreteArguments) {
285
+ let fullyQualifiedFilename = el.getFullyQualifiedName();
286
+ let params = "";
287
+ concreteArguments.map((param) => {
288
+ params = params + param.getText() + ',';
289
+ });
290
+ params = params.substring(0, params.length - 1);
291
+ fullyQualifiedFilename = Helpers.replaceLastBetweenTags(fullyQualifiedFilename, params);
292
+ let concElement;
293
+ if (!this.fmxInterfaceMap.has(fullyQualifiedFilename) && !this.fmxClassMap.has(fullyQualifiedFilename) && !this.fmxFunctionAndMethodMap.has(fullyQualifiedFilename)) {
294
+ concElement = lodash_1.default.cloneDeep(el);
295
+ concElement.setFullyQualifiedName(fullyQualifiedFilename);
296
+ concElement.clearGenericParameters();
297
+ concreteArguments.map((param) => {
298
+ const parameter = this.createOrGetFamixConcreteType(param);
299
+ concElement.addConcreteParameter(parameter);
300
+ });
301
+ if (el instanceof Famix.ParametricClass) {
302
+ this.fmxClassMap.set(fullyQualifiedFilename, concElement);
303
+ }
304
+ else if (el instanceof Famix.ParametricInterface) {
305
+ this.fmxInterfaceMap.set(fullyQualifiedFilename, concElement);
306
+ }
307
+ else if (el instanceof Famix.ParametricFunction) {
308
+ this.fmxFunctionAndMethodMap.set(fullyQualifiedFilename, concElement);
309
+ }
310
+ else if (el instanceof Famix.ParametricMethod) {
311
+ this.fmxFunctionAndMethodMap.set(fullyQualifiedFilename, concElement);
312
+ }
313
+ this.famixRep.addElement(concElement);
314
+ this.fmxElementObjectMap.set(concElement, elDeclaration);
315
+ }
316
+ else {
317
+ if (el instanceof Famix.ParametricClass) {
318
+ concElement = this.fmxClassMap.get(fullyQualifiedFilename);
319
+ }
320
+ else if (el instanceof Famix.ParametricInterface) {
321
+ concElement = this.fmxInterfaceMap.get(fullyQualifiedFilename);
322
+ }
323
+ else if (el instanceof Famix.ParametricFunction) {
324
+ concElement = this.fmxFunctionAndMethodMap.get(fullyQualifiedFilename);
325
+ }
326
+ else if (el instanceof Famix.ParametricMethod) {
327
+ concElement = this.fmxFunctionAndMethodMap.get(fullyQualifiedFilename);
328
+ }
329
+ }
330
+ return concElement;
331
+ }
269
332
  /**
270
333
  * Creates a Famix property
271
334
  * @param property A property
@@ -284,21 +347,37 @@ class EntityDictionary {
284
347
  }
285
348
  const fmxType = this.createOrGetFamixType(propTypeName, property);
286
349
  fmxProperty.setDeclaredType(fmxType);
287
- property.getModifiers().forEach(m => fmxProperty.addModifier(m.getText()));
350
+ // add the visibility (public, private, etc.) to the fmxProperty
351
+ fmxProperty.visibility = "";
352
+ property.getModifiers().forEach(m => {
353
+ switch (m.getText()) {
354
+ case ts_morph_1.Scope.Public:
355
+ fmxProperty.visibility = "public";
356
+ break;
357
+ case ts_morph_1.Scope.Protected:
358
+ fmxProperty.visibility = "protected";
359
+ break;
360
+ case ts_morph_1.Scope.Private:
361
+ fmxProperty.visibility = "private";
362
+ break;
363
+ case "static":
364
+ fmxProperty.setIsClassSide(true);
365
+ break;
366
+ case "readonly":
367
+ fmxProperty.readOnly = true;
368
+ break;
369
+ default:
370
+ break;
371
+ }
372
+ });
288
373
  if (!isSignature && property.getExclamationTokenNode()) {
289
- fmxProperty.addModifier("!");
374
+ fmxProperty.isDefinitelyAssigned = true;
290
375
  }
291
376
  if (property.getQuestionTokenNode()) {
292
- fmxProperty.addModifier("?");
377
+ fmxProperty.isOptional = true;
293
378
  }
294
379
  if (property.getName().substring(0, 1) === "#") {
295
- fmxProperty.addModifier("#");
296
- }
297
- if (fmxProperty.getModifiers().has("static")) {
298
- fmxProperty.setIsClassSide(true);
299
- }
300
- else {
301
- fmxProperty.setIsClassSide(false);
380
+ fmxProperty.isJavaScriptPrivate = true;
302
381
  }
303
382
  this.makeFamixIndexFileAnchor(property, fmxProperty);
304
383
  this.famixRep.addElement(fmxProperty);
@@ -311,86 +390,97 @@ class EntityDictionary {
311
390
  * @param currentCC The cyclomatic complexity metrics of the current source file
312
391
  * @returns The Famix model of the method or the accessor
313
392
  */
314
- createFamixMethod(method, currentCC) {
393
+ createOrGetFamixMethod(method, currentCC) {
315
394
  let fmxMethod;
316
- if (method instanceof ts_morph_1.GetAccessorDeclaration || method instanceof ts_morph_1.SetAccessorDeclaration) {
317
- fmxMethod = new Famix.Accessor();
318
- const isGetter = method instanceof ts_morph_1.GetAccessorDeclaration;
319
- const isSetter = method instanceof ts_morph_1.SetAccessorDeclaration;
320
- if (isGetter) {
321
- fmxMethod.setKind("getter");
395
+ const isGeneric = method.getTypeParameters().length > 0;
396
+ const functionFullyQualifiedName = FQNFunctions.getFQN(method);
397
+ if (!this.fmxFunctionAndMethodMap.has(functionFullyQualifiedName)) {
398
+ if (method instanceof ts_morph_1.GetAccessorDeclaration || method instanceof ts_morph_1.SetAccessorDeclaration) {
399
+ fmxMethod = new Famix.Accessor();
400
+ const isGetter = method instanceof ts_morph_1.GetAccessorDeclaration;
401
+ const isSetter = method instanceof ts_morph_1.SetAccessorDeclaration;
402
+ if (isGetter) {
403
+ fmxMethod.setKind("getter");
404
+ }
405
+ if (isSetter) {
406
+ fmxMethod.setKind("setter");
407
+ }
408
+ this.famixRep.addElement(fmxMethod);
322
409
  }
323
- if (isSetter) {
324
- fmxMethod.setKind("setter");
410
+ else {
411
+ if (isGeneric) {
412
+ fmxMethod = new Famix.ParametricMethod();
413
+ }
414
+ else {
415
+ fmxMethod = new Famix.Method();
416
+ }
417
+ this.famixRep.addElement(fmxMethod);
325
418
  }
326
- this.famixRep.addElement(fmxMethod);
327
- }
328
- else {
329
- fmxMethod = new Famix.Method();
330
- this.famixRep.addElement(fmxMethod);
331
- }
332
- const isConstructor = method instanceof ts_morph_1.ConstructorDeclaration;
333
- const isSignature = method instanceof ts_morph_1.MethodSignature;
334
- const isGeneric = method.getTypeParameters().length > 0;
335
- fmxMethod.setIsGeneric(isGeneric);
336
- let isAbstract = false;
337
- let isStatic = false;
338
- if (method instanceof ts_morph_1.MethodDeclaration || method instanceof ts_morph_1.GetAccessorDeclaration || method instanceof ts_morph_1.SetAccessorDeclaration) {
339
- isAbstract = method.isAbstract();
340
- isStatic = method.isStatic();
341
- }
342
- if (isConstructor) {
343
- fmxMethod.setKind("constructor");
344
- }
345
- fmxMethod.setIsAbstract(isAbstract);
346
- fmxMethod.setIsClassSide(isStatic);
347
- fmxMethod.setIsPrivate((method instanceof ts_morph_1.MethodDeclaration || method instanceof ts_morph_1.GetAccessorDeclaration || method instanceof ts_morph_1.SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'private')) !== undefined : false);
348
- fmxMethod.setIsProtected((method instanceof ts_morph_1.MethodDeclaration || method instanceof ts_morph_1.GetAccessorDeclaration || method instanceof ts_morph_1.SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'protected')) !== undefined : false);
349
- fmxMethod.setSignature(Helpers.computeSignature(method.getText()));
350
- let methodName;
351
- if (isConstructor) {
352
- methodName = "constructor";
353
- }
354
- else {
355
- methodName = method.getName();
356
- }
357
- fmxMethod.setName(methodName);
358
- if (!isConstructor) {
359
- if (method.getName().substring(0, 1) === "#") {
360
- fmxMethod.setIsPrivate(true);
419
+ const isConstructor = method instanceof ts_morph_1.ConstructorDeclaration;
420
+ const isSignature = method instanceof ts_morph_1.MethodSignature;
421
+ let isAbstract = false;
422
+ let isStatic = false;
423
+ if (method instanceof ts_morph_1.MethodDeclaration || method instanceof ts_morph_1.GetAccessorDeclaration || method instanceof ts_morph_1.SetAccessorDeclaration) {
424
+ isAbstract = method.isAbstract();
425
+ isStatic = method.isStatic();
361
426
  }
362
- }
363
- if (!fmxMethod.getIsPrivate() && !fmxMethod.getIsProtected()) {
364
- fmxMethod.setIsPublic(true);
365
- }
366
- else {
367
- fmxMethod.setIsPublic(false);
368
- }
369
- if (!isSignature) {
370
- fmxMethod.setCyclomaticComplexity(currentCC[fmxMethod.getName()]);
371
- }
372
- else {
373
- fmxMethod.setCyclomaticComplexity(0);
374
- }
375
- let methodTypeName = this.UNKNOWN_VALUE;
376
- try {
377
- methodTypeName = method.getReturnType().getText().trim();
378
- }
379
- catch (error) {
380
- analyze_1.logger.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of method: ${fmxMethod.getName()}. Continuing...`);
381
- }
382
- const fmxType = this.createOrGetFamixType(methodTypeName, method);
383
- fmxMethod.setDeclaredType(fmxType);
384
- fmxMethod.setNumberOfLinesOfCode(method.getEndLineNumber() - method.getStartLineNumber());
385
- const parameters = method.getParameters();
386
- fmxMethod.setNumberOfParameters(parameters.length);
387
- if (!isSignature) {
388
- fmxMethod.setNumberOfStatements(method.getStatements().length);
427
+ if (isConstructor) {
428
+ fmxMethod.setKind("constructor");
429
+ }
430
+ fmxMethod.setIsAbstract(isAbstract);
431
+ fmxMethod.setIsClassSide(isStatic);
432
+ fmxMethod.setIsPrivate((method instanceof ts_morph_1.MethodDeclaration || method instanceof ts_morph_1.GetAccessorDeclaration || method instanceof ts_morph_1.SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'private')) !== undefined : false);
433
+ fmxMethod.setIsProtected((method instanceof ts_morph_1.MethodDeclaration || method instanceof ts_morph_1.GetAccessorDeclaration || method instanceof ts_morph_1.SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'protected')) !== undefined : false);
434
+ fmxMethod.setSignature(Helpers.computeSignature(method.getText()));
435
+ let methodName;
436
+ if (isConstructor) {
437
+ methodName = "constructor";
438
+ }
439
+ else {
440
+ methodName = method.getName();
441
+ }
442
+ fmxMethod.setName(methodName);
443
+ if (!isConstructor) {
444
+ if (method.getName().substring(0, 1) === "#") {
445
+ fmxMethod.setIsPrivate(true);
446
+ }
447
+ }
448
+ if (!fmxMethod.getIsPrivate() && !fmxMethod.getIsProtected()) {
449
+ fmxMethod.setIsPublic(true);
450
+ }
451
+ else {
452
+ fmxMethod.setIsPublic(false);
453
+ }
454
+ if (!isSignature) {
455
+ fmxMethod.setCyclomaticComplexity(currentCC[fmxMethod.getName()]);
456
+ }
457
+ else {
458
+ fmxMethod.setCyclomaticComplexity(0);
459
+ }
460
+ let methodTypeName = this.UNKNOWN_VALUE;
461
+ try {
462
+ methodTypeName = method.getReturnType().getText().trim();
463
+ }
464
+ catch (error) {
465
+ analyze_1.logger.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of method: ${fmxMethod.getName()}. Continuing...`);
466
+ }
467
+ const fmxType = this.createOrGetFamixType(methodTypeName, method);
468
+ fmxMethod.setDeclaredType(fmxType);
469
+ fmxMethod.setNumberOfLinesOfCode(method.getEndLineNumber() - method.getStartLineNumber());
470
+ const parameters = method.getParameters();
471
+ fmxMethod.setNumberOfParameters(parameters.length);
472
+ if (!isSignature) {
473
+ fmxMethod.setNumberOfStatements(method.getStatements().length);
474
+ }
475
+ else {
476
+ fmxMethod.setNumberOfStatements(0);
477
+ }
478
+ this.makeFamixIndexFileAnchor(method, fmxMethod);
479
+ this.fmxFunctionAndMethodMap.set(functionFullyQualifiedName, fmxMethod);
389
480
  }
390
481
  else {
391
- fmxMethod.setNumberOfStatements(0);
482
+ fmxMethod = this.fmxFunctionAndMethodMap.get(functionFullyQualifiedName);
392
483
  }
393
- this.makeFamixIndexFileAnchor(method, fmxMethod);
394
484
  this.fmxElementObjectMap.set(fmxMethod, method);
395
485
  return fmxMethod;
396
486
  }
@@ -400,34 +490,47 @@ class EntityDictionary {
400
490
  * @param currentCC The cyclomatic complexity metrics of the current source file
401
491
  * @returns The Famix model of the function
402
492
  */
403
- createFamixFunction(func, currentCC) {
404
- const fmxFunction = new Famix.Function();
405
- if (func.getName()) {
406
- fmxFunction.setName(func.getName());
493
+ createOrGetFamixFunction(func, currentCC) {
494
+ let fmxFunction;
495
+ const isGeneric = func.getTypeParameters().length > 0;
496
+ const functionFullyQualifiedName = FQNFunctions.getFQN(func);
497
+ if (!this.fmxFunctionAndMethodMap.has(functionFullyQualifiedName)) {
498
+ if (isGeneric) {
499
+ fmxFunction = new Famix.ParametricFunction();
500
+ }
501
+ else {
502
+ fmxFunction = new Famix.Function();
503
+ }
504
+ if (func.getName()) {
505
+ fmxFunction.setName(func.getName());
506
+ }
507
+ else {
508
+ fmxFunction.setName("anonymous");
509
+ }
510
+ fmxFunction.setSignature(Helpers.computeSignature(func.getText()));
511
+ fmxFunction.setCyclomaticComplexity(currentCC[fmxFunction.getName()]);
512
+ fmxFunction.setFullyQualifiedName(functionFullyQualifiedName);
513
+ let functionTypeName = this.UNKNOWN_VALUE;
514
+ try {
515
+ functionTypeName = func.getReturnType().getText().trim();
516
+ }
517
+ catch (error) {
518
+ analyze_1.logger.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of function: ${func.getName()}. Continuing...`);
519
+ }
520
+ const fmxType = this.createOrGetFamixType(functionTypeName, func);
521
+ fmxFunction.setDeclaredType(fmxType);
522
+ fmxFunction.setNumberOfLinesOfCode(func.getEndLineNumber() - func.getStartLineNumber());
523
+ const parameters = func.getParameters();
524
+ fmxFunction.setNumberOfParameters(parameters.length);
525
+ fmxFunction.setNumberOfStatements(func.getStatements().length);
526
+ this.makeFamixIndexFileAnchor(func, fmxFunction);
527
+ this.famixRep.addElement(fmxFunction);
528
+ this.fmxElementObjectMap.set(fmxFunction, func);
529
+ this.fmxFunctionAndMethodMap.set(functionFullyQualifiedName, fmxFunction);
407
530
  }
408
531
  else {
409
- fmxFunction.setName("anonymous");
410
- }
411
- fmxFunction.setSignature(Helpers.computeSignature(func.getText()));
412
- fmxFunction.setCyclomaticComplexity(currentCC[fmxFunction.getName()]);
413
- const isGeneric = func.getTypeParameters().length > 0;
414
- fmxFunction.setIsGeneric(isGeneric);
415
- let functionTypeName = this.UNKNOWN_VALUE;
416
- try {
417
- functionTypeName = func.getReturnType().getText().trim();
532
+ fmxFunction = this.fmxFunctionAndMethodMap.get(functionFullyQualifiedName);
418
533
  }
419
- catch (error) {
420
- analyze_1.logger.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of function: ${func.getName()}. Continuing...`);
421
- }
422
- const fmxType = this.createOrGetFamixType(functionTypeName, func);
423
- fmxFunction.setDeclaredType(fmxType);
424
- fmxFunction.setNumberOfLinesOfCode(func.getEndLineNumber() - func.getStartLineNumber());
425
- const parameters = func.getParameters();
426
- fmxFunction.setNumberOfParameters(parameters.length);
427
- fmxFunction.setNumberOfStatements(func.getStatements().length);
428
- this.makeFamixIndexFileAnchor(func, fmxFunction);
429
- this.famixRep.addElement(fmxFunction);
430
- this.fmxElementObjectMap.set(fmxFunction, func);
431
534
  return fmxFunction;
432
535
  }
433
536
  /**
@@ -465,6 +568,68 @@ class EntityDictionary {
465
568
  this.fmxElementObjectMap.set(fmxParameterType, tp);
466
569
  return fmxParameterType;
467
570
  }
571
+ /**
572
+ * Creates a Famix type parameter
573
+ * @param tp A type parameter
574
+ * @returns The Famix model of the type parameter
575
+ */
576
+ createOrGetFamixConcreteType(param) {
577
+ const typeParameterDeclaration = param.getSymbol()?.getDeclarations()[0];
578
+ const parameterTypeName = param.getText();
579
+ let fmxParameterType;
580
+ let isClassOrInterface = false;
581
+ if (this.fmxClassMap.has(parameterTypeName)) {
582
+ this.fmxClassMap.forEach((obj, name) => {
583
+ if (obj instanceof Famix.ParametricClass) {
584
+ if (name === param.getText() && obj.getGenericParameters().size > 0) {
585
+ fmxParameterType = obj;
586
+ isClassOrInterface = true;
587
+ }
588
+ }
589
+ else {
590
+ if (name === param.getText()) {
591
+ fmxParameterType = obj;
592
+ isClassOrInterface = true;
593
+ }
594
+ }
595
+ });
596
+ }
597
+ if (this.fmxInterfaceMap.has(parameterTypeName)) {
598
+ this.fmxInterfaceMap.forEach((obj, name) => {
599
+ if (obj instanceof Famix.ParametricInterface) {
600
+ if (name === param.getText() && obj.getGenericParameters().size > 0) {
601
+ fmxParameterType = obj;
602
+ isClassOrInterface = true;
603
+ }
604
+ }
605
+ else {
606
+ if (name === param.getText()) {
607
+ fmxParameterType = obj;
608
+ isClassOrInterface = true;
609
+ }
610
+ }
611
+ });
612
+ }
613
+ if (!isClassOrInterface) {
614
+ if (!this.fmxTypeMap.has(parameterTypeName)) {
615
+ if (parameterTypeName === "number" || parameterTypeName === "string" || parameterTypeName === "boolean" || parameterTypeName === "bigint" || parameterTypeName === "symbol" || parameterTypeName === "undefined" || parameterTypeName === "null" || parameterTypeName === "any" || parameterTypeName === "unknown" || parameterTypeName === "never" || parameterTypeName === "void") {
616
+ fmxParameterType = new Famix.PrimitiveType();
617
+ fmxParameterType.setIsStub(true);
618
+ }
619
+ else {
620
+ fmxParameterType = new Famix.ParameterType();
621
+ }
622
+ fmxParameterType.setName(parameterTypeName);
623
+ this.famixRep.addElement(fmxParameterType);
624
+ this.fmxTypeMap.set(parameterTypeName, fmxParameterType);
625
+ this.fmxElementObjectMap.set(fmxParameterType, typeParameterDeclaration);
626
+ }
627
+ else {
628
+ fmxParameterType = this.fmxTypeMap.get(parameterTypeName);
629
+ }
630
+ }
631
+ return fmxParameterType;
632
+ }
468
633
  /**
469
634
  * Creates a Famix variable
470
635
  * @param variable A variable
@@ -568,30 +733,34 @@ class EntityDictionary {
568
733
  createOrGetFamixType(typeName, element) {
569
734
  let fmxType;
570
735
  let isPrimitiveType = false;
571
- let isParameterizedType = false;
572
- analyze_1.logger.debug("Creating (or getting) type: '" + typeName + "' of element: " + (element === null || element === void 0 ? void 0 : element.getText()) + " of kind: " + (element === null || element === void 0 ? void 0 : element.getKindName()));
736
+ let isParameterType = false;
737
+ analyze_1.logger.debug("Creating (or getting) type: '" + typeName + "' of element: " + element?.getText() + " of kind: " + element?.getKindName());
573
738
  let ancestor;
574
739
  if (element !== undefined) {
575
740
  const typeAncestor = Helpers.findTypeAncestor(element);
741
+ if (!typeAncestor) {
742
+ throw new Error(`Ancestor not found for element ${element.getText()}.`);
743
+ }
576
744
  const ancestorFullyQualifiedName = FQNFunctions.getFQN(typeAncestor);
577
745
  ancestor = this.famixRep.getFamixEntityByFullyQualifiedName(ancestorFullyQualifiedName);
578
746
  if (!ancestor) {
579
- throw new Error(`Ancestor ${ancestorFullyQualifiedName} not found.`);
747
+ analyze_1.logger.debug(`Ancestor ${FQNFunctions.getFQN(typeAncestor)} not found. Adding the new type.`);
748
+ ancestor = this.createOrGetFamixType(typeAncestor.getText(), typeAncestor);
580
749
  }
581
750
  }
582
751
  if (typeName === "number" || typeName === "string" || typeName === "boolean" || typeName === "bigint" || typeName === "symbol" || typeName === "undefined" || typeName === "null" || typeName === "any" || typeName === "unknown" || typeName === "never" || typeName === "void") {
583
752
  isPrimitiveType = true;
584
753
  }
585
754
  if (!isPrimitiveType && typeName.includes("<") && typeName.includes(">") && !(typeName.includes("=>"))) {
586
- isParameterizedType = true;
755
+ isParameterType = true;
587
756
  }
588
757
  if (!this.fmxTypeMap.has(typeName)) {
589
758
  if (isPrimitiveType) {
590
759
  fmxType = new Famix.PrimitiveType();
591
760
  fmxType.setIsStub(true);
592
761
  }
593
- else if (isParameterizedType) {
594
- fmxType = new Famix.ParameterizedType();
762
+ else if (isParameterType) {
763
+ fmxType = new Famix.ParameterType();
595
764
  const parameterTypeNames = typeName.substring(typeName.indexOf("<") + 1, typeName.indexOf(">")).split(",").map(s => s.trim());
596
765
  const baseTypeName = typeName.substring(0, typeName.indexOf("<")).trim();
597
766
  parameterTypeNames.forEach(parameterTypeName => {
@@ -623,13 +792,20 @@ class EntityDictionary {
623
792
  */
624
793
  createFamixAccess(node, id) {
625
794
  const fmxVar = this.famixRep.getFamixEntityById(id);
795
+ if (!fmxVar) {
796
+ throw new Error(`Famix entity with id ${id} not found, for node ${node.getText()} in ${node.getSourceFile().getBaseName()} at line ${node.getStartLineNumber()}.`);
797
+ }
798
+ analyze_1.logger.debug(`Creating FamixAccess. Node: [${node.getKindName()}] '${node.getText()}' at line ${node.getStartLineNumber()} in ${node.getSourceFile().getBaseName()}, id: ${id} refers to fmxVar '${fmxVar.getFullyQualifiedName()}'.`);
626
799
  const nodeReferenceAncestor = Helpers.findAncestor(node);
627
800
  const ancestorFullyQualifiedName = FQNFunctions.getFQN(nodeReferenceAncestor);
628
- const accessor = this.famixRep.getFamixEntityByFullyQualifiedName(ancestorFullyQualifiedName);
801
+ let accessor = this.famixRep.getFamixEntityByFullyQualifiedName(ancestorFullyQualifiedName);
802
+ if (!accessor) {
803
+ analyze_1.logger.error(`Ancestor ${ancestorFullyQualifiedName} of kind ${nodeReferenceAncestor.getKindName()} not found.`);
804
+ // accessor = this.createOrGetFamixType(ancestorFullyQualifiedName, nodeReferenceAncestor as TypeDeclaration);
805
+ }
629
806
  const fmxAccess = new Famix.Access();
630
807
  fmxAccess.setAccessor(accessor);
631
808
  fmxAccess.setVariable(fmxVar);
632
- this.makeFamixIndexFileAnchor(node, fmxAccess);
633
809
  this.famixRep.addElement(fmxAccess);
634
810
  this.fmxElementObjectMap.set(fmxAccess, node);
635
811
  }
@@ -651,7 +827,6 @@ class EntityDictionary {
651
827
  fmxInvocation.setReceiver(receiver);
652
828
  fmxInvocation.addCandidate(fmxMethodOrFunction);
653
829
  fmxInvocation.setSignature(fmxMethodOrFunction.getSignature());
654
- this.makeFamixIndexFileAnchor(node, fmxInvocation);
655
830
  this.famixRep.addElement(fmxInvocation);
656
831
  this.fmxElementObjectMap.set(fmxInvocation, node);
657
832
  }
@@ -709,10 +884,16 @@ class EntityDictionary {
709
884
  }
710
885
  fmxInheritance.setSubclass(subClass);
711
886
  fmxInheritance.setSuperclass(superClass);
712
- this.makeFamixIndexFileAnchor(null, fmxInheritance);
713
887
  this.famixRep.addElement(fmxInheritance);
714
888
  this.fmxElementObjectMap.set(fmxInheritance, null);
715
889
  }
890
+ createFamixImportClause(importedEntity, importingEntity) {
891
+ const fmxImportClause = new Famix.ImportClause();
892
+ fmxImportClause.setImportedEntity(importedEntity);
893
+ fmxImportClause.setImportingEntity(importingEntity);
894
+ importingEntity.addOutgoingImport(fmxImportClause);
895
+ this.famixRep.addElement(fmxImportClause);
896
+ }
716
897
  /**
717
898
  * Creates a Famix import clause
718
899
  * @param importClauseInfo The information needed to create a Famix import clause
@@ -723,9 +904,8 @@ class EntityDictionary {
723
904
  * @param isInExports A boolean indicating if the imported entity is in the exports
724
905
  * @param isDefaultExport A boolean indicating if the imported entity is a default export
725
906
  */
726
- createFamixImportClause(importClauseInfo) {
727
- var _a, _b;
728
- const { importDeclaration, importer, moduleSpecifierFilePath, importElement, isInExports, isDefaultExport } = importClauseInfo;
907
+ oldCreateFamixImportClause(importClauseInfo) {
908
+ const { importDeclaration, importerSourceFile: importer, moduleSpecifierFilePath, importElement, isInExports, isDefaultExport } = importClauseInfo;
729
909
  analyze_1.logger.debug(`createFamixImportClause: Creating import clause:`);
730
910
  const fmxImportClause = new Famix.ImportClause();
731
911
  let importedEntity;
@@ -736,6 +916,7 @@ class EntityDictionary {
736
916
  const pathInProject = this.convertToRelativePath(absolutePath, absolutePathProject).replace(/\\/g, "/");
737
917
  let pathName = "{" + pathInProject + "}.";
738
918
  // Named imports, e.g. import { ClassW } from "./complexExportModule";
919
+ // Start with simple import clause (without referring to the actual variable)
739
920
  if (importDeclaration instanceof ts_morph_1.ImportDeclaration
740
921
  && importElement instanceof ts_morph_1.ImportSpecifier) {
741
922
  importedEntityName = importElement.getName();
@@ -751,12 +932,14 @@ class EntityDictionary {
751
932
  }
752
933
  this.makeFamixIndexFileAnchor(importElement, importedEntity);
753
934
  importedEntity.setFullyQualifiedName(pathName);
935
+ // must add entity to repository
936
+ this.famixRep.addElement(importedEntity);
754
937
  }
755
938
  }
756
939
  // handle import equals declarations, e.g. import myModule = require("./complexExportModule");
757
940
  // TypeScript can't determine the type of the imported module, so we create a Module entity
758
941
  else if (importDeclaration instanceof ts_morph_1.ImportEqualsDeclaration) {
759
- importedEntityName = importDeclaration === null || importDeclaration === void 0 ? void 0 : importDeclaration.getName();
942
+ importedEntityName = importDeclaration?.getName();
760
943
  pathName = pathName + importedEntityName;
761
944
  importedEntity = new Famix.StructuralEntity();
762
945
  importedEntity.setName(importedEntityName);
@@ -773,26 +956,349 @@ class EntityDictionary {
773
956
  this.makeFamixIndexFileAnchor(importElement, importedEntity);
774
957
  importedEntity.setFullyQualifiedName(pathName);
775
958
  }
776
- this.famixRep.addElement(importedEntity);
959
+ // I don't think it should be added to the repository if it exists already
960
+ if (!isInExports)
961
+ this.famixRep.addElement(importedEntity);
777
962
  const importerFullyQualifiedName = FQNFunctions.getFQN(importer);
778
963
  const fmxImporter = this.famixRep.getFamixEntityByFullyQualifiedName(importerFullyQualifiedName);
779
964
  fmxImportClause.setImportingEntity(fmxImporter);
780
965
  fmxImportClause.setImportedEntity(importedEntity);
781
966
  if (importDeclaration instanceof ts_morph_1.ImportEqualsDeclaration) {
782
- fmxImportClause.setModuleSpecifier(importDeclaration === null || importDeclaration === void 0 ? void 0 : importDeclaration.getModuleReference().getText());
967
+ fmxImportClause.setModuleSpecifier(importDeclaration?.getModuleReference().getText());
783
968
  }
784
969
  else {
785
- fmxImportClause.setModuleSpecifier(importDeclaration === null || importDeclaration === void 0 ? void 0 : importDeclaration.getModuleSpecifierValue());
970
+ fmxImportClause.setModuleSpecifier(importDeclaration?.getModuleSpecifierValue());
786
971
  }
787
- analyze_1.logger.debug(`createFamixImportClause: ${(_a = fmxImportClause.getImportedEntity()) === null || _a === void 0 ? void 0 : _a.getName()} (of type ${Helpers.getSubTypeName(fmxImportClause.getImportedEntity())}) is imported by ${(_b = fmxImportClause.getImportingEntity()) === null || _b === void 0 ? void 0 : _b.getName()}`);
788
- // make an index file anchor for the import clause
789
- this.makeFamixIndexFileAnchor(importDeclaration, fmxImportClause);
972
+ analyze_1.logger.debug(`createFamixImportClause: ${fmxImportClause.getImportedEntity()?.getName()} (of type ${Helpers.getSubTypeName(fmxImportClause.getImportedEntity())}) is imported by ${fmxImportClause.getImportingEntity()?.getName()}`);
790
973
  fmxImporter.addOutgoingImport(fmxImportClause);
791
974
  this.famixRep.addElement(fmxImportClause);
792
975
  this.fmxElementObjectMap.set(fmxImportClause, importDeclaration);
793
976
  }
977
+ /**
978
+ * Creates a Famix Arrow Function
979
+ * @param arrowExpression An Expression
980
+ * @returns The Famix model of the variable
981
+ */
982
+ createFamixArrowFunction(arrowExpression, currentCC) {
983
+ let fmxArrowFunction;
984
+ const arrowFunction = arrowExpression.asKindOrThrow(ts_morph_1.SyntaxKind.ArrowFunction);
985
+ const isGeneric = arrowFunction.getTypeParameters().length > 0;
986
+ if (isGeneric) {
987
+ fmxArrowFunction = new Famix.ParametricArrowFunction();
988
+ }
989
+ else {
990
+ fmxArrowFunction = new Famix.ArrowFunction();
991
+ }
992
+ // Get the parent of the arrow function (the variable declaration)
993
+ const parent = arrowFunction.getParentIfKind(ts_morph_1.SyntaxKind.VariableDeclaration);
994
+ let functionName = '(NO_NAME)';
995
+ if (parent && parent instanceof ts_morph_1.VariableDeclaration) {
996
+ // Get the name of the variable
997
+ functionName = parent.getName();
998
+ }
999
+ if (functionName) {
1000
+ fmxArrowFunction.setName(functionName);
1001
+ }
1002
+ else {
1003
+ fmxArrowFunction.setName("anonymous");
1004
+ }
1005
+ // Signature of an arrow function is (parameters) => return_type
1006
+ const parametersSignature = arrowFunction.getParameters().map(p => p.getText()).join(", ");
1007
+ const returnTypeSignature = arrowFunction.getReturnType().getText();
1008
+ fmxArrowFunction.setSignature(`(${parametersSignature}) => ${returnTypeSignature}`);
1009
+ fmxArrowFunction.setCyclomaticComplexity(currentCC[fmxArrowFunction.getName()]);
1010
+ let functionTypeName = this.UNKNOWN_VALUE;
1011
+ try {
1012
+ functionTypeName = arrowFunction.getReturnType().getText().trim();
1013
+ }
1014
+ catch (error) {
1015
+ analyze_1.logger.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of function: ${functionName}. Continuing...`);
1016
+ }
1017
+ const fmxType = this.createOrGetFamixType(functionTypeName, arrowFunction);
1018
+ fmxArrowFunction.setDeclaredType(fmxType);
1019
+ fmxArrowFunction.setNumberOfLinesOfCode(arrowFunction.getEndLineNumber() - arrowFunction.getStartLineNumber());
1020
+ const parameters = arrowFunction.getParameters();
1021
+ fmxArrowFunction.setNumberOfParameters(parameters.length);
1022
+ fmxArrowFunction.setNumberOfStatements(arrowFunction.getStatements().length);
1023
+ this.makeFamixIndexFileAnchor(arrowExpression, fmxArrowFunction);
1024
+ this.famixRep.addElement(fmxArrowFunction);
1025
+ this.fmxElementObjectMap.set(fmxArrowFunction, arrowFunction);
1026
+ return fmxArrowFunction;
1027
+ }
1028
+ /**
1029
+ * Creates a Famix concretisation
1030
+ * @param cls A class
1031
+ * @returns The Famix model of the concretisation
1032
+ */
1033
+ createFamixConcretisation(conEntity, genEntity) {
1034
+ const fmxConcretisation = new Famix.Concretisation();
1035
+ fmxConcretisation.setConcreteEntity(conEntity);
1036
+ fmxConcretisation.setGenericEntity(genEntity);
1037
+ this.fmxElementObjectMap.set(fmxConcretisation, null);
1038
+ this.famixRep.addElement(fmxConcretisation);
1039
+ const parameterConcretisation = this.createFamixParameterConcrestisation(fmxConcretisation);
1040
+ return fmxConcretisation;
1041
+ }
1042
+ /**
1043
+ * Creates a Famix concretisation
1044
+ * @param concretisation A FamixConcretisation
1045
+ * @returns The Famix model of the ParameterConcrestisation
1046
+ */
1047
+ createFamixParameterConcrestisation(concretisation) {
1048
+ const conClass = concretisation.getConcreteEntity();
1049
+ const genClass = concretisation.getGenericEntity();
1050
+ const parameterConcretisations = this.famixRep._getAllEntitiesWithType("ParameterConcretisation");
1051
+ const concreteParameters = conClass.getConcreteParameters();
1052
+ const genericParameters = genClass.getGenericParameters();
1053
+ let conClassTypeParametersIterator = concreteParameters.values();
1054
+ let genClassTypeParametersIterator = genericParameters.values();
1055
+ let fmxParameterConcretisation;
1056
+ for (let i = 0; i < genericParameters.size; i++) {
1057
+ const conClassTypeParameter = conClassTypeParametersIterator.next().value;
1058
+ const genClassTypeParameter = genClassTypeParametersIterator.next().value;
1059
+ let createParameterConcretisation = true;
1060
+ if (conClassTypeParameter && genClassTypeParameter && conClassTypeParameter.getName() != genClassTypeParameter.getName()) {
1061
+ parameterConcretisations.forEach((param) => {
1062
+ if (conClassTypeParameter.getName() == param.getConcreteParameter().getName() && genClassTypeParameter.getName() == param.getGenericParameter().getName()) {
1063
+ createParameterConcretisation = false;
1064
+ fmxParameterConcretisation = param;
1065
+ }
1066
+ });
1067
+ if (createParameterConcretisation) {
1068
+ fmxParameterConcretisation = new Famix.ParameterConcretisation();
1069
+ fmxParameterConcretisation.setGenericParameter(genClassTypeParameter);
1070
+ fmxParameterConcretisation.setConcreteParameter(conClassTypeParameter);
1071
+ fmxParameterConcretisation.addConcretisation(concretisation);
1072
+ this.fmxElementObjectMap.set(fmxParameterConcretisation, null);
1073
+ }
1074
+ else {
1075
+ fmxParameterConcretisation.addConcretisation(concretisation);
1076
+ }
1077
+ this.famixRep.addElement(fmxParameterConcretisation);
1078
+ }
1079
+ }
1080
+ return fmxParameterConcretisation;
1081
+ }
1082
+ /**
1083
+ * Creates a Famix concretisation between two classes or two interfaces
1084
+ * @param element A class or an Interface
1085
+ */
1086
+ createFamixConcretisationClassOrInterfaceSpecialisation(element) {
1087
+ const superEntity = element.getExtends();
1088
+ let superEntityArray;
1089
+ if (superEntity) {
1090
+ superEntityArray = Array.isArray(superEntity) ? superEntity : [superEntity];
1091
+ }
1092
+ if (superEntityArray && superEntityArray.length > 0) {
1093
+ superEntityArray.forEach(entity => {
1094
+ let entityIsGeneric;
1095
+ const superEntitySymbol = entity.getExpression().getSymbolOrThrow();
1096
+ let superEntityDeclaration;
1097
+ if (superEntity instanceof ts_morph_1.ExpressionWithTypeArguments) {
1098
+ superEntityDeclaration = superEntitySymbol.getDeclarations()[0].asKind(ts_morph_1.ts.SyntaxKind.ClassDeclaration);
1099
+ }
1100
+ else {
1101
+ superEntityDeclaration = superEntitySymbol.getDeclarations()[0].asKind(ts_morph_1.ts.SyntaxKind.InterfaceDeclaration);
1102
+ }
1103
+ if (superEntityDeclaration) {
1104
+ entityIsGeneric = superEntityDeclaration.getTypeParameters().length > 0;
1105
+ }
1106
+ if (entityIsGeneric) {
1107
+ let EntityDeclaration;
1108
+ let genEntity;
1109
+ if (superEntity instanceof ts_morph_1.ExpressionWithTypeArguments) {
1110
+ EntityDeclaration = entity.getExpression().getSymbol().getDeclarations()[0];
1111
+ genEntity = this.createOrGetFamixClass(EntityDeclaration);
1112
+ }
1113
+ else {
1114
+ EntityDeclaration = entity.getExpression().getSymbol().getDeclarations()[0];
1115
+ genEntity = this.createOrGetFamixInterface(EntityDeclaration);
1116
+ }
1117
+ const genParams = EntityDeclaration.getTypeParameters().map((param) => param.getText());
1118
+ const args = element.getHeritageClauses()[0].getTypeNodes()[0].getTypeArguments();
1119
+ const conParams = element.getHeritageClauses()[0].getTypeNodes()[0].getTypeArguments().map((param) => param.getText());
1120
+ if (!Helpers.arraysAreEqual(conParams, genParams)) {
1121
+ let conEntity;
1122
+ conEntity = this.createOrGetFamixConcreteElement(genEntity, EntityDeclaration, args);
1123
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1124
+ let createConcretisation = true;
1125
+ concretisations.forEach((conc) => {
1126
+ if (genEntity.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == conEntity.getFullyQualifiedName()) {
1127
+ createConcretisation = false;
1128
+ }
1129
+ });
1130
+ if (createConcretisation) {
1131
+ const fmxConcretisation = this.createFamixConcretisation(conEntity, genEntity);
1132
+ }
1133
+ }
1134
+ }
1135
+ });
1136
+ }
1137
+ }
1138
+ /**
1139
+ * Creates a Famix concretisation between a class and its instanciations
1140
+ * @param cls A class
1141
+ */
1142
+ createFamixConcretisationGenericInstantiation(cls) {
1143
+ const isGeneric = cls.getTypeParameters().length > 0;
1144
+ if (isGeneric) {
1145
+ const instances = cls.getSourceFile().getDescendantsOfKind(ts_morph_1.ts.SyntaxKind.NewExpression)
1146
+ .filter(newExpr => {
1147
+ const expression = newExpr.getExpression();
1148
+ return expression.getText() === cls.getName();
1149
+ });
1150
+ instances.forEach(instance => {
1151
+ const instanceIsGeneric = instance.getTypeArguments().length > 0;
1152
+ if (instanceIsGeneric) {
1153
+ const conParams = instance.getTypeArguments().map((param) => param.getText());
1154
+ const genEntity = this.createOrGetFamixClass(cls);
1155
+ const genParams = cls.getTypeParameters().map((param) => param.getText());
1156
+ if (!Helpers.arraysAreEqual(conParams, genParams)) {
1157
+ let conEntity;
1158
+ conEntity = this.createOrGetFamixConcreteElement(genEntity, cls, instance.getTypeArguments());
1159
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1160
+ let createConcretisation = true;
1161
+ concretisations.forEach((conc) => {
1162
+ if (genEntity.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == conEntity.getFullyQualifiedName()) {
1163
+ createConcretisation = false;
1164
+ }
1165
+ });
1166
+ if (createConcretisation) {
1167
+ const fmxConcretisation = this.createFamixConcretisation(conEntity, genEntity);
1168
+ }
1169
+ }
1170
+ }
1171
+ });
1172
+ }
1173
+ }
1174
+ /**
1175
+ * Creates a Famix concretisation between a class and its instanciations
1176
+ * @param func A function
1177
+ */
1178
+ createFamixConcretisationFunctionInstantiation(element) {
1179
+ const isGeneric = element.getTypeParameters().length > 0;
1180
+ if (isGeneric) {
1181
+ const genParams = element.getTypeParameters().map(param => param.getText());
1182
+ const uses = element.findReferencesAsNodes();
1183
+ uses.forEach(usage => {
1184
+ let currentNode = usage;
1185
+ while (currentNode) {
1186
+ if (currentNode.getKind() === ts_morph_1.SyntaxKind.CallExpression) {
1187
+ const callExpression = currentNode.asKind(ts_morph_1.SyntaxKind.CallExpression);
1188
+ const instanceIsGeneric = callExpression.getTypeArguments().length > 0;
1189
+ if (instanceIsGeneric) {
1190
+ const args = callExpression.getTypeArguments();
1191
+ const conParams = callExpression.getTypeArguments().map(param => param.getText());
1192
+ if (!Helpers.arraysAreEqual(conParams, genParams)) {
1193
+ let genElement;
1194
+ if (element instanceof ts_morph_1.FunctionDeclaration) {
1195
+ genElement = this.createOrGetFamixFunction(element, 0);
1196
+ }
1197
+ else {
1198
+ genElement = this.createOrGetFamixMethod(element, 0);
1199
+ }
1200
+ let concElement;
1201
+ concElement = this.createOrGetFamixConcreteElement(genElement, element, args);
1202
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1203
+ let createConcretisation = true;
1204
+ concretisations.forEach((conc) => {
1205
+ if (genElement.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == concElement.getFullyQualifiedName()) {
1206
+ createConcretisation = false;
1207
+ }
1208
+ });
1209
+ if (createConcretisation) {
1210
+ const fmxConcretisation = this.createFamixConcretisation(concElement, genElement);
1211
+ }
1212
+ }
1213
+ }
1214
+ break;
1215
+ }
1216
+ // Remonter à l'élément parent (utile si le nœud de référence est un enfant)
1217
+ currentNode = currentNode.getParent();
1218
+ }
1219
+ });
1220
+ }
1221
+ }
1222
+ /**
1223
+ * Creates a Famix concretisation between a class and an interface
1224
+ * @param cls A class
1225
+ */
1226
+ createFamixConcretisationInterfaceClass(cls) {
1227
+ const superInterfaces = cls.getImplements();
1228
+ superInterfaces.forEach(interfaceType => {
1229
+ const interfaceIsGeneric = interfaceType.getTypeArguments().length > 0;
1230
+ if (interfaceIsGeneric) {
1231
+ const interfaceDeclaration = interfaceType.getExpression().getSymbol().getDeclarations()[0];
1232
+ const genParams = interfaceDeclaration.getTypeParameters().map((param) => param.getText());
1233
+ const conParams = cls.getHeritageClauses()[0].getTypeNodes()[0].getTypeArguments().map((param) => param.getText());
1234
+ const args = cls.getHeritageClauses()[0].getTypeNodes()[0].getTypeArguments();
1235
+ if (!Helpers.arraysAreEqual(conParams, genParams)) {
1236
+ const genInterface = this.createOrGetFamixInterface(interfaceDeclaration);
1237
+ const conInterface = this.createOrGetFamixConcreteElement(genInterface, interfaceDeclaration, args);
1238
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1239
+ let createConcretisation = true;
1240
+ concretisations.forEach((conc) => {
1241
+ if (genInterface.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == conInterface.getFullyQualifiedName()) {
1242
+ createConcretisation = false;
1243
+ }
1244
+ });
1245
+ if (createConcretisation) {
1246
+ const fmxConcretisation = this.createFamixConcretisation(conInterface, genInterface);
1247
+ }
1248
+ }
1249
+ }
1250
+ });
1251
+ }
1252
+ /**
1253
+ * Creates a Famix concretisation between an interface and a Type
1254
+ * @param element A variable or a function
1255
+ * @param inter An interface
1256
+ */
1257
+ createFamixConcretisationTypeInstanciation(element) {
1258
+ const isGeneric = element.getTypeParameters().length > 0;
1259
+ if (isGeneric) {
1260
+ const genParams = element.getTypeParameters().map(param => param.getText());
1261
+ const uses = element.findReferencesAsNodes();
1262
+ uses.forEach(use => {
1263
+ let parentNode = use.getParent();
1264
+ while (parentNode) {
1265
+ if (parentNode.getKind() === ts_morph_1.SyntaxKind.TypeReference) {
1266
+ const typeReferenceNode = parentNode.asKind(ts_morph_1.SyntaxKind.TypeReference);
1267
+ const typeReferenceNodeIsGeneric = typeReferenceNode.getTypeArguments().length > 0;
1268
+ if (typeReferenceNodeIsGeneric) { }
1269
+ const args = typeReferenceNode.getTypeArguments();
1270
+ const conParams = typeReferenceNode.getTypeArguments().map(param => param.getText());
1271
+ if (!Helpers.arraysAreEqual(conParams, genParams)) {
1272
+ let genElement;
1273
+ if (element instanceof ts_morph_1.ClassDeclaration) {
1274
+ genElement = this.createOrGetFamixClass(element);
1275
+ }
1276
+ else {
1277
+ genElement = this.createOrGetFamixInterface(element);
1278
+ }
1279
+ let concElement;
1280
+ concElement = this.createOrGetFamixConcreteElement(genElement, element, args);
1281
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1282
+ let createConcretisation = true;
1283
+ concretisations.forEach((conc) => {
1284
+ if (genElement.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == concElement.getFullyQualifiedName()) {
1285
+ createConcretisation = false;
1286
+ }
1287
+ });
1288
+ if (createConcretisation) {
1289
+ const fmxConcretisation = this.createFamixConcretisation(concElement, genElement);
1290
+ }
1291
+ }
1292
+ break;
1293
+ }
1294
+ parentNode = parentNode.getParent();
1295
+ }
1296
+ });
1297
+ }
1298
+ }
794
1299
  convertToRelativePath(absolutePath, absolutePathProject) {
795
1300
  return absolutePath.replace(absolutePathProject, "").slice(1);
796
1301
  }
797
1302
  }
798
1303
  exports.EntityDictionary = EntityDictionary;
1304
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRW50aXR5RGljdGlvbmFyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9mYW1peF9mdW5jdGlvbnMvRW50aXR5RGljdGlvbmFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHVDQUE2bEI7QUFDN2xCLDhFQUFnRjtBQUNoRixvRUFBc0Q7QUFDdEQsd0NBQTRDO0FBQzVDLDBFQUFpRDtBQUNqRCw0REFBOEM7QUFDOUMscURBQXVDO0FBQ3ZDLHdFQUFvRTtBQUNwRSxnREFBd0I7QUFDeEIsb0RBQXVCO0FBTXZCLE1BQWEsZ0JBQWdCO0lBYXpCO1FBWE8sYUFBUSxHQUFHLElBQUksa0NBQWUsRUFBRSxDQUFDO1FBQ2hDLGdCQUFXLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUMsQ0FBQyw0Q0FBNEM7UUFDMUYsZ0JBQVcsR0FBRyxJQUFJLEdBQUcsRUFBK0MsQ0FBQyxDQUFDLDREQUE0RDtRQUNsSSxvQkFBZSxHQUFHLElBQUksR0FBRyxFQUF1RCxDQUFDLENBQUMsZ0RBQWdEO1FBQ2xJLGlCQUFZLEdBQUcsSUFBSSxHQUFHLEVBQXdCLENBQUMsQ0FBQyxnREFBZ0Q7UUFDaEcsZUFBVSxHQUFHLElBQUksR0FBRyxFQUE2QyxDQUFDLENBQUMsa0RBQWtEO1FBQ3JILGVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBa0UsQ0FBQyxDQUFDLDJDQUEyQztRQUNuSSw0QkFBdUIsR0FBRyxJQUFJLEdBQThGLENBQUEsQ0FBQywrQ0FBK0M7UUFDNUssa0JBQWEsR0FBRyxnQ0FBZ0MsQ0FBQyxDQUFDLDZDQUE2QztRQUNoRyx3QkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBa0MsQ0FBQztRQUduRSxJQUFJLENBQUMsUUFBUSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksd0JBQXdCLENBQUMsYUFBZ0MsRUFB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QXc2Q0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDbGFzc0RlY2xhcmF0aW9uLCBDb25zdHJ1Y3RvckRlY2xhcmF0aW9uLCBGdW5jdGlvbkRlY2xhcmF0aW9uLCBJZGVudGlmaWVyLCBJbnRlcmZhY2VEZWNsYXJhdGlvbiwgTWV0aG9kRGVjbGFyYXRpb24sIE1ldGhvZFNpZ25hdHVyZSwgTW9kdWxlRGVjbGFyYXRpb24sIFByb3BlcnR5RGVjbGFyYXRpb24sIFByb3BlcnR5U2lnbmF0dXJlLCBTb3VyY2VGaWxlLCBUeXBlUGFyYW1ldGVyRGVjbGFyYXRpb24sIFZhcmlhYmxlRGVjbGFyYXRpb24sIFBhcmFtZXRlckRlY2xhcmF0aW9uLCBEZWNvcmF0b3IsIEdldEFjY2Vzc29yRGVjbGFyYXRpb24sIFNldEFjY2Vzc29yRGVjbGFyYXRpb24sIEltcG9ydFNwZWNpZmllciwgQ29tbWVudFJhbmdlLCBFbnVtRGVjbGFyYXRpb24sIEVudW1NZW1iZXIsIFR5cGVBbGlhc0RlY2xhcmF0aW9uLCBGdW5jdGlvbkV4cHJlc3Npb24sIEV4cHJlc3Npb25XaXRoVHlwZUFyZ3VtZW50cywgSW1wb3J0RGVjbGFyYXRpb24sIEltcG9ydEVxdWFsc0RlY2xhcmF0aW9uLCBTeW50YXhLaW5kLCBFeHByZXNzaW9uLCBUeXBlTm9kZSwgTm9kZSwgdHMsIFNjb3BlLCBUeXBlLCBBcnJvd0Z1bmN0aW9uIH0gZnJvbSBcInRzLW1vcnBoXCI7XG5pbXBvcnQgeyBpc0FtYmllbnQsIGlzTmFtZXNwYWNlIH0gZnJvbSBcIi4uL2FuYWx5emVfZnVuY3Rpb25zL3Byb2Nlc3NfZnVuY3Rpb25zXCI7XG5pbXBvcnQgKiBhcyBGYW1peCBmcm9tIFwiLi4vbGliL2ZhbWl4L3NyYy9tb2RlbC9mYW1peFwiO1xuaW1wb3J0IHsgbG9nZ2VyLCBjb25maWcgfSBmcm9tIFwiLi4vYW5hbHl6ZVwiO1xuaW1wb3J0IEdyYXBoZW1lU3BsaXR0ZXIgZnJvbSBcImdyYXBoZW1lLXNwbGl0dGVyXCI7XG5pbXBvcnQgKiBhcyBIZWxwZXJzIGZyb20gXCIuL2hlbHBlcnNfY3JlYXRpb25cIjtcbmltcG9ydCAqIGFzIEZRTkZ1bmN0aW9ucyBmcm9tIFwiLi4vZnFuXCI7XG5pbXBvcnQgeyBGYW1peFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vbGliL2ZhbWl4L3NyYy9mYW1peF9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcblxuZXhwb3J0IHR5cGUgVFNNb3JwaE9iamVjdFR5cGUgPSBJbXBvcnREZWNsYXJhdGlvbiB8IEltcG9ydEVxdWFsc0RlY2xhcmF0aW9uIHwgU291cmNlRmlsZSB8IE1vZHVsZURlY2xhcmF0aW9uIHwgQ2xhc3NEZWNsYXJhdGlvbiB8IEludGVyZmFjZURlY2xhcmF0aW9uIHwgTWV0aG9kRGVjbGFyYXRpb24gfCBDb25zdHJ1Y3RvckRlY2xhcmF0aW9uIHwgTWV0aG9kU2lnbmF0dXJlIHwgRnVuY3Rpb25EZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRXhwcmVzc2lvbiB8IFBhcmFtZXRlckRlY2xhcmF0aW9uIHwgVmFyaWFibGVEZWNsYXJhdGlvbiB8IFByb3BlcnR5RGVjbGFyYXRpb24gfCBQcm9wZXJ0eVNpZ25hdHVyZSB8IFR5cGVQYXJhbWV0ZXJEZWNsYXJhdGlvbiB8IElkZW50aWZpZXIgfCBEZWNvcmF0b3IgfCBHZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IEltcG9ydFNwZWNpZmllciB8IENvbW1lbnRSYW5nZSB8IEVudW1EZWNsYXJhdGlvbiB8IEVudW1NZW1iZXIgfCBUeXBlQWxpYXNEZWNsYXJhdGlvbiB8IEV4cHJlc3Npb25XaXRoVHlwZUFyZ3VtZW50cztcblxuZXhwb3J0IHR5cGUgVHlwZURlY2xhcmF0aW9uID0gVHlwZUFsaWFzRGVjbGFyYXRpb24gfCBQcm9wZXJ0eURlY2xhcmF0aW9uIHwgUHJvcGVydHlTaWduYXR1cmUgfCBNZXRob2REZWNsYXJhdGlvbiB8IENvbnN0cnVjdG9yRGVjbGFyYXRpb24gfCBNZXRob2RTaWduYXR1cmUgfCBHZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRGVjbGFyYXRpb24gfCBGdW5jdGlvbkV4cHJlc3Npb24gfCBQYXJhbWV0ZXJEZWNsYXJhdGlvbiB8IFZhcmlhYmxlRGVjbGFyYXRpb24gfCBFbnVtTWVtYmVyO1xuXG5leHBvcnQgY2xhc3MgRW50aXR5RGljdGlvbmFyeSB7XG4gICAgXG4gICAgcHVibGljIGZhbWl4UmVwID0gbmV3IEZhbWl4UmVwb3NpdG9yeSgpO1xuICAgIHByaXZhdGUgZm14QWxpYXNNYXAgPSBuZXcgTWFwPHN0cmluZywgRmFtaXguQWxpYXM+KCk7IC8vIE1hcHMgdGhlIGFsaWFzIG5hbWVzIHRvIHRoZWlyIEZhbWl4IG1vZGVsXG4gICAgcHJpdmF0ZSBmbXhDbGFzc01hcCA9IG5ldyBNYXA8c3RyaW5nLCBGYW1peC5DbGFzcyB8IEZhbWl4LlBhcmFtZXRyaWNDbGFzcz4oKTsgLy8gTWFwcyB0aGUgZnVsbHkgcXVhbGlmaWVkIGNsYXNzIG5hbWVzIHRvIHRoZWlyIEZhbWl4IG1vZGVsXG4gICAgcHJpdmF0ZSBmbXhJbnRlcmZhY2VNYXAgPSBuZXcgTWFwPHN0cmluZywgRmFtaXguSW50ZXJmYWNlIHwgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZT4oKTsgLy8gTWFwcyB0aGUgaW50ZXJmYWNlIG5hbWVzIHRvIHRoZWlyIEZhbWl4IG1vZGVsXG4gICAgcHJpdmF0ZSBmbXhNb2R1bGVNYXAgPSBuZXcgTWFwPHN0cmluZywgRmFtaXguTW9kdWxlPigpOyAvLyBNYXBzIHRoZSBuYW1lc3BhY2UgbmFtZXMgdG8gdGhlaXIgRmFtaXggbW9kZWxcbiAgICBwcml2YXRlIGZteEZpbGVNYXAgPSBuZXcgTWFwPHN0cmluZywgRmFtaXguU2NyaXB0RW50aXR5IHwgRmFtaXguTW9kdWxlPigpOyAvLyBNYXBzIHRoZSBzb3VyY2UgZmlsZSBuYW1lcyB0byB0aGVpciBGYW1peCBtb2RlbFxuICAgIHByaXZhdGUgZm14VHlwZU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBGYW1peC5UeXBlIHwgRmFtaXguUHJpbWl0aXZlVHlwZSB8IEZhbWl4LlBhcmFtZXRlclR5cGU+KCk7IC8vIE1hcHMgdGhlIHR5cGUgbmFtZXMgdG8gdGhlaXIgRmFtaXggbW9kZWxcbiAgICBwcml2YXRlIGZteEZ1bmN0aW9uQW5kTWV0aG9kTWFwID0gbmV3IE1hcDxzdHJpbmcsIEZhbWl4LkZ1bmN0aW9uIHwgRmFtaXguUGFyYW1ldHJpY0Z1bmN0aW9uIHwgRmFtaXguTWV0aG9kIHwgRmFtaXguUGFyYW1ldHJpY01ldGhvZD4gLy8gTWFwcyB0aGUgZnVuY3Rpb24gbmFtZXMgdG8gdGhlaXIgRmFtaXggbW9kZWxcbiAgICBwcml2YXRlIFVOS05PV05fVkFMVUUgPSAnKHVua25vd24gZHVlIHRvIHBhcnNpbmcgZXJyb3IpJzsgLy8gVGhlIHZhbHVlIHRvIHVzZSB3aGVuIGEgbmFtZSBpcyBub3QgdXNhYmxlXG4gICAgcHVibGljIGZteEVsZW1lbnRPYmplY3RNYXAgPSBuZXcgTWFwPEZhbWl4LkVudGl0eSxUU01vcnBoT2JqZWN0VHlwZT4oKTtcbiAgICAgICAgICAgIFxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmZhbWl4UmVwLnNldEZteEVsZW1lbnRPYmplY3RNYXAodGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwKTsgICAgICBcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlcyBhIEZhbWl4IGluZGV4IGZpbGUgYW5jaG9yXG4gICAgICogQHBhcmFtIHNvdXJjZUVsZW1lbnQgQSBzb3VyY2UgZWxlbWVudFxuICAgICAqIEBwYXJhbSBmYW1peEVsZW1lbnQgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBzb3VyY2UgZWxlbWVudFxuICAgICAqL1xuICAgIHB1YmxpYyBtYWtlRmFtaXhJbmRleEZpbGVBbmNob3Ioc291cmNlRWxlbWVudDogVFNNb3JwaE9iamVjdFR5cGUsIGZhbWl4RWxlbWVudDogRmFtaXguU291cmNlZEVudGl0eSk6IHZvaWQge1xuICAgICAgICBsb2dnZXIuZGVidWcoXCJtYWtpbmcgaW5kZXggZmlsZSBhbmNob3IgZm9yICdcIiArIHNvdXJjZUVsZW1lbnQ/LmdldFRleHQoKSArIFwiJyB3aXRoIGZhbWl4RWxlbWVudCBcIiArIGZhbWl4RWxlbWVudC5nZXRKU09OKCkpO1xuICAgICAgICBjb25zdCBmbXhJbmRleEZpbGVBbmNob3IgPSBuZXcgRmFtaXguSW5kZXhlZEZpbGVBbmNob3IoKTtcbiAgICAgICAgZm14SW5kZXhGaWxlQW5jaG9yLnNldEVsZW1lbnQoZmFtaXhFbGVtZW50KTtcbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmYW1peEVsZW1lbnQsIHNvdXJjZUVsZW1lbnQpO1xuXG4gICAgICAgIGlmIChzb3VyY2VFbGVtZW50ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBjb25zdCBhYnNvbHV0ZVBhdGhQcm9qZWN0ID0gdGhpcy5mYW1peFJlcC5nZXRBYnNvbHV0ZVBhdGgoKTtcbiAgICAgICAgXG4gICAgICAgICAgICBjb25zdCBhYnNvbHV0ZVBhdGggPSBwYXRoLm5vcm1hbGl6ZShzb3VyY2VFbGVtZW50LmdldFNvdXJjZUZpbGUoKS5nZXRGaWxlUGF0aCgpKTtcblxuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25Ob2RlTW9kdWxlcyA9IGFic29sdXRlUGF0aC5pbmRleE9mKCdub2RlX21vZHVsZXMnKTtcblxuICAgICAgICAgICAgbGV0IHBhdGhJblByb2plY3Q6IHN0cmluZyA9IFwiXCI7XG5cbiAgICAgICAgICAgIGlmIChwb3NpdGlvbk5vZGVNb2R1bGVzICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhdGhGcm9tTm9kZU1vZHVsZXMgPSBhYnNvbHV0ZVBhdGguc3Vic3RyaW5nKHBvc2l0aW9uTm9kZU1vZHVsZXMpO1xuICAgICAgICAgICAgICAgIHBhdGhJblByb2plY3QgPSBwYXRoRnJvbU5vZGVNb2R1bGVzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwYXRoSW5Qcm9qZWN0ID0gdGhpcy5jb252ZXJ0VG9SZWxhdGl2ZVBhdGgoYWJzb2x1dGVQYXRoLCBhYnNvbHV0ZVBhdGhQcm9qZWN0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gcmV2ZXJ0IGFueSBiYWNrc2xhc2hlcyB0byBmb3J3YXJkIHNsYXNoZXMgKHBhdGgubm9ybWFsaXplIG9uIHdpbmRvd3MgaW50cm9kdWNlcyB0aGVtKVxuICAgICAgICAgICAgcGF0aEluUHJvamVjdCA9IHBhdGhJblByb2plY3QucmVwbGFjZSgvXFxcXC9nLCBcIi9cIik7XG5cbiAgICAgICAgICAgIGZteEluZGV4RmlsZUFuY2hvci5zZXRGaWxlTmFtZShwYXRoSW5Qcm9qZWN0KTtcbiAgICAgICAgICAgIGxldCBzb3VyY2VTdGFydCwgc291cmNlRW5kLCBzb3VyY2VMaW5lU3RhcnQsIHNvdXJjZUxpbmVFbmQ6IG51bWJlcjtcbiAgICAgICAgICAgIGlmICghKHNvdXJjZUVsZW1lbnQgaW5zdGFuY2VvZiBDb21tZW50UmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgc291cmNlU3RhcnQgPSBzb3VyY2VFbGVtZW50LmdldFN0YXJ0KCk7XG4gICAgICAgICAgICAgICAgc291cmNlRW5kID0gc291cmNlRWxlbWVudC5nZXRFbmQoKTtcbiAgICAgICAgICAgICAgICBzb3VyY2VMaW5lU3RhcnQgPSBzb3VyY2VFbGVtZW50LmdldFN0YXJ0TGluZU51bWJlcigpO1xuICAgICAgICAgICAgICAgIHNvdXJjZUxpbmVFbmQgPSBzb3VyY2VFbGVtZW50LmdldEVuZExpbmVOdW1iZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc291cmNlU3RhcnQgPSBzb3VyY2VFbGVtZW50LmdldFBvcygpO1xuICAgICAgICAgICAgICAgIHNvdXJjZUVuZCA9IHNvdXJjZUVsZW1lbnQuZ2V0RW5kKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29uZmlnLmV4cGVjdEdyYXBoZW1lcykge1xuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAqIFRoZSBmb2xsb3dpbmcgbG9naWMgaGFuZGxlcyB0aGUgY2FzZSBvZiBtdWx0aS1jb2RlIHBvaW50IGNoYXJhY3RlcnMgKGUuZy4gZW1vamkpIGluIHRoZSBzb3VyY2UgdGV4dC5cbiAgICAgICAgICAgICAgICAgKiBUaGlzIGlzIG5lZWRlZCBiZWNhdXNlIFBoYXJvL1NtYWxsdGFsayB0cmVhdHMgbXVsdGktY29kZSBwb2ludCBjaGFyYWN0ZXJzIGFzIGEgc2luZ2xlIGNoYXJhY3RlciwgXG4gICAgICAgICAgICAgICAgICogYnV0IEphdmFTY3JpcHQgdHJlYXRzIHRoZW0gYXMgbXVsdGlwbGUgY2hhcmFjdGVycy4gVGhpcyBtZWFucyB0aGF0IHRoZSBzdGFydCBhbmQgZW5kIHBvc2l0aW9uc1xuICAgICAgICAgICAgICAgICAqIG9mIGEgc291cmNlIGVsZW1lbnQgaW4gUGhhcm8vU21hbGx0YWxrIHdpbGwgYmUgZGlmZmVyZW50IHRoYW4gdGhlIHN0YXJ0IGFuZCBlbmQgcG9zaXRpb25zIG9mIHRoZVxuICAgICAgICAgICAgICAgICAqIHNhbWUgc291cmNlIGVsZW1lbnQgaW4gSmF2YVNjcmlwdC4gVGhpcyBsb2dpYyBmaW5kcyB0aGUgc3RhcnQgYW5kIGVuZCBwb3NpdGlvbnMgb2YgdGhlIHNvdXJjZVxuICAgICAgICAgICAgICAgICAqIGVsZW1lbnQgaW4gSmF2YVNjcmlwdCBhbmQgdGhlbiB1c2VzIHRob3NlIHBvc2l0aW9ucyB0byBzZXQgdGhlIHN0YXJ0IGFuZCBlbmQgcG9zaXRpb25zIG9mIHRoZVxuICAgICAgICAgICAgICAgICAqIEZhbWl4IGluZGV4IGZpbGUgYW5jaG9yLlxuICAgICAgICAgICAgICAgICAqIEl0IGRlcGVuZHMgb24gY29kZSBpbiB0aGUgJ2dyYXBoZW1lLXNwbGl0dGVyJyBwYWNrYWdlIGluIG5wbS5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBjb25zdCBzcGxpdHRlciA9IG5ldyBHcmFwaGVtZVNwbGl0dGVyKCk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc291cmNlRmlsZVRleHQgPSBzb3VyY2VFbGVtZW50LmdldFNvdXJjZUZpbGUoKS5nZXRGdWxsVGV4dCgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGhhc0dyYXBoZW1lQ2x1c3RlcnMgPSBzcGxpdHRlci5jb3VudEdyYXBoZW1lcyhzb3VyY2VGaWxlVGV4dCkgPiAxO1xuICAgICAgICAgICAgICAgIGlmIChoYXNHcmFwaGVtZUNsdXN0ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZUVsZW1lbnRUZXh0ID0gc291cmNlRmlsZVRleHQuc3Vic3RyaW5nKHNvdXJjZVN0YXJ0LCBzb3VyY2VFbmQpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VFbGVtZW50VGV4dEdyYXBoZW1lcyA9IHNwbGl0dGVyLnNwbGl0R3JhcGhlbWVzKHNvdXJjZUVsZW1lbnRUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc291cmNlRmlsZVRleHRHcmFwaGVtZXMgPSBzcGxpdHRlci5zcGxpdEdyYXBoZW1lcyhzb3VyY2VGaWxlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG51bWJlck9mR3JhcGhlbWVDbHVzdGVyc0JlZm9yZVN0YXJ0ID0gc3BsaXR0ZXIuY291bnRHcmFwaGVtZXMoc291cmNlRmlsZVRleHQuc3Vic3RyaW5nKDAsIHNvdXJjZVN0YXJ0KSk7XG4gICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAvLyBmaW5kIHRoZSBzdGFydCBvZiB0aGUgc291cmNlRWxlbWVudFRleHRHcmFwaGVtZXMgYXJyYXkgaW4gdGhlIHNvdXJjZUZpbGVUZXh0R3JhcGhlbWVzIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZVN0YXJ0ID0gSGVscGVycy5pbmRleE9mU3BsaXRBcnJheSh7c2VhcmNoQXJyYXk6IHNvdXJjZUZpbGVUZXh0R3JhcGhlbWVzLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0QXJyYXk6IHNvdXJjZUVsZW1lbnRUZXh0R3JhcGhlbWVzLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHNvdXJjZVN0YXJ0IC0gbnVtYmVyT2ZHcmFwaGVtZUNsdXN0ZXJzQmVmb3JlU3RhcnR9KTtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlRW5kID0gc291cmNlU3RhcnQgKyBzb3VyY2VFbGVtZW50VGV4dEdyYXBoZW1lcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfSBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG5vdGU6IHRoZSArMSBpcyBiZWNhdXNlIHRoZSBzb3VyY2UgYW5jaG9yIGlzIDEtYmFzZWQsIGJ1dCB0cy1tb3JwaCBpcyAwLWJhc2VkXG4gICAgICAgICAgICBmbXhJbmRleEZpbGVBbmNob3Iuc2V0U3RhcnRQb3Moc291cmNlU3RhcnQgKyAxKTtcbiAgICAgICAgICAgIGZteEluZGV4RmlsZUFuY2hvci5zZXRFbmRQb3Moc291cmNlRW5kICsgMSk7XG4gICAgICAgICAgICBpZiAoIShzb3VyY2VFbGVtZW50IGluc3RhbmNlb2YgQ29tbWVudFJhbmdlKSkge1xuICAgICAgICAgICAgICAgIGZteEluZGV4RmlsZUFuY2hvci5zZXRTdGFydExpbmUoc291cmNlTGluZVN0YXJ0KTtcbiAgICAgICAgICAgICAgICBmbXhJbmRleEZpbGVBbmNob3Iuc2V0RW5kTGluZShzb3VyY2VMaW5lRW5kKTsgICAgXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKGZhbWl4RWxlbWVudCBpbnN0YW5jZW9mIEZhbWl4LkltcG9ydENsYXVzZSB8fCBmYW1peEVsZW1lbnQgaW5zdGFuY2VvZiBGYW1peC5BY2Nlc3MgfHwgZmFtaXhFbGVtZW50IGluc3RhbmNlb2YgRmFtaXguUmVmZXJlbmNlIHx8IGZhbWl4RWxlbWVudCBpbnN0YW5jZW9mIEZhbWl4Lkludm9jYXRpb24gfHwgZmFtaXhFbGVtZW50IGluc3RhbmNlb2YgRmFtaXguSW5oZXJpdGFuY2UpICYmICEoZmFtaXhFbGVtZW50IGluc3RhbmNlb2YgRmFtaXguQ29tbWVudCkgJiYgIShzb3VyY2VFbGVtZW50IGluc3RhbmNlb2YgQ29tbWVudFJhbmdlKSAmJiAhKHNvdXJjZUVsZW1lbnQgaW5zdGFuY2VvZiBJZGVudGlmaWVyKSAmJiAhKHNvdXJjZUVsZW1lbnQgaW5zdGFuY2VvZiBJbXBvcnRTcGVjaWZpZXIpICYmICEoc291cmNlRWxlbWVudCBpbnN0YW5jZW9mIEV4cHJlc3Npb25XaXRoVHlwZUFyZ3VtZW50cykpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmcW4gPSBGUU5GdW5jdGlvbnMuZ2V0RlFOKHNvdXJjZUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhcIlNldHRpbmcgZnVsbHkgcXVhbGlmaWVkIG5hbWUgZm9yIFwiICsgZmFtaXhFbGVtZW50LmdldEpTT04oKSArIFwiIHRvIFwiICsgZnFuKTtcbiAgICAgICAgICAgICAgICAoZmFtaXhFbGVtZW50IGFzIEZhbWl4Lk5hbWVkRW50aXR5KS5zZXRGdWxseVF1YWxpZmllZE5hbWUoZnFuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHNvdXJjZUVsZW1lbnQgaXMgbnVsbFxuICAgICAgICAgICAgbG9nZ2VyLndhcm4oXCJzb3VyY2VFbGVtZW50IGlzIG51bGwgZm9yIGZhbWl4RWxlbWVudCBcIiArIGZhbWl4RWxlbWVudC5nZXRKU09OKCkpO1xuICAgICAgICAgICAgZm14SW5kZXhGaWxlQW5jaG9yLnNldEZpbGVOYW1lKFwidW5rbm93blwiKTtcbiAgICAgICAgICAgIGZteEluZGV4RmlsZUFuY2hvci5zZXRTdGFydFBvcygwKTtcbiAgICAgICAgICAgIGZteEluZGV4RmlsZUFuY2hvci5zZXRFbmRQb3MoMCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14SW5kZXhGaWxlQW5jaG9yKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIG9yIGdldHMgYSBGYW1peCBzY3JpcHQgZW50aXR5IG9yIG1vZHVsZVxuICAgICAqIEBwYXJhbSBmIEEgc291cmNlIGZpbGVcbiAgICAgKiBAcGFyYW0gaXNNb2R1bGUgQSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhlIHNvdXJjZSBmaWxlIGlzIGEgbW9kdWxlXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBzb3VyY2UgZmlsZVxuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVPckdldEZhbWl4RmlsZShmOiBTb3VyY2VGaWxlLCBpc01vZHVsZTogYm9vbGVhbik6IEZhbWl4LlNjcmlwdEVudGl0eSB8IEZhbWl4Lk1vZHVsZSB7XG4gICAgICAgIGxldCBmbXhGaWxlOiBGYW1peC5TY3JpcHRFbnRpdHk7IC8vIHwgRmFtaXguTW9kdWxlO1xuXG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gZi5nZXRCYXNlTmFtZSgpO1xuICAgICAgICBjb25zdCBmdWxseVF1YWxpZmllZEZpbGVuYW1lID0gZi5nZXRGaWxlUGF0aCgpO1xuICAgICAgICBpZiAoIXRoaXMuZm14RmlsZU1hcC5oYXMoZnVsbHlRdWFsaWZpZWRGaWxlbmFtZSkpIHtcbiAgICAgICAgICAgIGlmIChpc01vZHVsZSkge1xuICAgICAgICAgICAgICAgIGZteEZpbGUgPSBuZXcgRmFtaXguTW9kdWxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmbXhGaWxlID0gbmV3IEZhbWl4LlNjcmlwdEVudGl0eSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm14RmlsZS5zZXROYW1lKGZpbGVOYW1lKTtcbiAgICAgICAgICAgIGZteEZpbGUuc2V0TnVtYmVyT2ZMaW5lc09mVGV4dChmLmdldEVuZExpbmVOdW1iZXIoKSAtIGYuZ2V0U3RhcnRMaW5lTnVtYmVyKCkpO1xuICAgICAgICAgICAgZm14RmlsZS5zZXROdW1iZXJPZkNoYXJhY3RlcnMoZi5nZXRGdWxsVGV4dCgpLmxlbmd0aCk7XG5cbiAgICAgICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKGYsIGZteEZpbGUpO1xuXG4gICAgICAgICAgICB0aGlzLmZteEZpbGVNYXAuc2V0KGZ1bGx5UXVhbGlmaWVkRmlsZW5hbWUsIGZteEZpbGUpO1xuICAgICAgICAgICAgdGhpcy5mYW1peFJlcC5hZGRFbGVtZW50KGZteEZpbGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm14RmlsZSA9IHRoaXMuZm14RmlsZU1hcC5nZXQoZnVsbHlRdWFsaWZpZWRGaWxlbmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGZteEZpbGUsZik7XG4gICAgICAgIHJldHVybiBmbXhGaWxlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgb3IgZ2V0cyBhIEZhbWl4IE1vZHVsZVxuICAgICAqIEBwYXJhbSBtIEEgbW9kdWxlXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBtb2R1bGVcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlT3JHZXRGYW1peE1vZHVsZShtOiBNb2R1bGVEZWNsYXJhdGlvbik6IEZhbWl4Lk1vZHVsZSB7XG4gICAgICAgIGxldCBmbXhNb2R1bGU6IEZhbWl4Lk1vZHVsZTtcbiAgICAgICAgY29uc3QgbW9kdWxlTmFtZSA9IG0uZ2V0TmFtZSgpO1xuICAgICAgICBpZiAoIXRoaXMuZm14TW9kdWxlTWFwLmhhcyhtb2R1bGVOYW1lKSkge1xuICAgICAgICAgICAgZm14TW9kdWxlID0gbmV3IEZhbWl4Lk1vZHVsZSgpO1xuICAgICAgICAgICAgZm14TW9kdWxlLnNldE5hbWUobW9kdWxlTmFtZSk7XG4gICAgICAgICAgICBmbXhNb2R1bGUuJGlzQW1iaWVudCA9IGlzQW1iaWVudChtKTtcbiAgICAgICAgICAgIGZteE1vZHVsZS4kaXNOYW1lc3BhY2UgPSBpc05hbWVzcGFjZShtKTtcbiAgICAgICAgICAgIGZteE1vZHVsZS4kaXNNb2R1bGUgPSAhZm14TW9kdWxlLiRpc05hbWVzcGFjZSAmJiAhZm14TW9kdWxlLiRpc0FtYmllbnQ7XG5cbiAgICAgICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKG0sIGZteE1vZHVsZSk7XG5cbiAgICAgICAgICAgIHRoaXMuZm14TW9kdWxlTWFwLnNldChtb2R1bGVOYW1lLCBmbXhNb2R1bGUpO1xuXG4gICAgICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14TW9kdWxlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZteE1vZHVsZSA9IHRoaXMuZm14TW9kdWxlTWFwLmdldChtb2R1bGVOYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZm14RWxlbWVudE9iamVjdE1hcC5zZXQoZm14TW9kdWxlLG0pO1xuICAgICAgICByZXR1cm4gZm14TW9kdWxlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBGYW1peCBhbGlhc1xuICAgICAqIEBwYXJhbSBhIEFuIGFsaWFzXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBhbGlhc1xuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVGYW1peEFsaWFzKGE6IFR5cGVBbGlhc0RlY2xhcmF0aW9uKTogRmFtaXguQWxpYXMge1xuICAgICAgICBsZXQgZm14QWxpYXM6IEZhbWl4LkFsaWFzO1xuICAgICAgICBjb25zdCBhbGlhc05hbWUgPSBhLmdldE5hbWUoKTtcbiAgICAgICAgY29uc3QgYWxpYXNGdWxseVF1YWxpZmllZE5hbWUgPSBhLmdldFR5cGUoKS5nZXRUZXh0KCk7IC8vIEZRTkZ1bmN0aW9ucy5nZXRGUU4oYSk7XG4gICAgICAgIGlmICghdGhpcy5mbXhBbGlhc01hcC5oYXMoYWxpYXNGdWxseVF1YWxpZmllZE5hbWUpKSB7XG4gICAgICAgICAgICBmbXhBbGlhcyA9IG5ldyBGYW1peC5BbGlhcygpO1xuICAgICAgICAgICAgZm14QWxpYXMuc2V0TmFtZShhLmdldE5hbWUoKSk7XG4gICAgICAgICAgICBjb25zdCBhbGlhc05hbWVXaXRoR2VuZXJpY3MgPSBhbGlhc05hbWUgKyAoYS5nZXRUeXBlUGFyYW1ldGVycygpLmxlbmd0aCA/IChcIjxcIiArIGEuZ2V0VHlwZVBhcmFtZXRlcnMoKS5tYXAodHAgPT4gdHAuZ2V0TmFtZSgpKS5qb2luKFwiLCBcIikgKyBcIj5cIikgOiBcIlwiKTtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgPiBOT1RFOiBhbGlhcyAke2FsaWFzTmFtZX0gaGFzIGZ1bGx5IHF1YWxpZmllZCBuYW1lICR7YWxpYXNGdWxseVF1YWxpZmllZE5hbWV9IGFuZCBuYW1lIHdpdGggZ2VuZXJpY3MgJHthbGlhc05hbWVXaXRoR2VuZXJpY3N9LmApO1xuXG4gICAgICAgICAgICBjb25zdCBmbXhUeXBlID0gdGhpcy5jcmVhdGVPckdldEZhbWl4VHlwZShhbGlhc05hbWVXaXRoR2VuZXJpY3MsIGEpO1xuICAgICAgICAgICAgZm14QWxpYXMuc2V0QWxpYXNlZEVudGl0eShmbXhUeXBlKTtcblxuICAgICAgICAgICAgdGhpcy5tYWtlRmFtaXhJbmRleEZpbGVBbmNob3IoYSwgZm14QWxpYXMpO1xuXG4gICAgICAgICAgICB0aGlzLmZteEFsaWFzTWFwLnNldChhbGlhc0Z1bGx5UXVhbGlmaWVkTmFtZSwgZm14QWxpYXMpO1xuXG4gICAgICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14QWxpYXMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm14QWxpYXMgPSB0aGlzLmZteEFsaWFzTWFwLmdldChhbGlhc0Z1bGx5UXVhbGlmaWVkTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhBbGlhcyxhKTtcblxuICAgICAgICByZXR1cm4gZm14QWxpYXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBvciBnZXRzIGEgRmFtaXggY2xhc3Mgb3IgcGFyYW1ldGVyaXphYmxlIGNsYXNzXG4gICAgICogQHBhcmFtIGNscyBBIGNsYXNzXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBjbGFzc1xuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVPckdldEZhbWl4Q2xhc3MoY2xzOiBDbGFzc0RlY2xhcmF0aW9uKTogRmFtaXguQ2xhc3MgfCBGYW1peC5QYXJhbWV0cmljQ2xhc3Mge1xuICAgICAgICBsZXQgZm14Q2xhc3M6IEZhbWl4LkNsYXNzIHwgRmFtaXguUGFyYW1ldHJpY0NsYXNzO1xuICAgICAgICBjb25zdCBpc0Fic3RyYWN0ID0gY2xzLmlzQWJzdHJhY3QoKTtcbiAgICAgICAgY29uc3QgY2xhc3NGdWxseVF1YWxpZmllZE5hbWUgPSBGUU5GdW5jdGlvbnMuZ2V0RlFOKGNscyk7XG4gICAgICAgIGNvbnN0IGNsc05hbWUgPSBjbHMuZ2V0TmFtZSgpO1xuICAgICAgICBjb25zdCBpc0dlbmVyaWMgPSBjbHMuZ2V0VHlwZVBhcmFtZXRlcnMoKS5sZW5ndGg7XG4gICAgICAgIGlmICghdGhpcy5mbXhDbGFzc01hcC5oYXMoY2xhc3NGdWxseVF1YWxpZmllZE5hbWUpKSB7XG4gICAgICAgICAgICBpZiAoaXNHZW5lcmljKSB7XG4gICAgICAgICAgICAgICAgZm14Q2xhc3MgPSBuZXcgRmFtaXguUGFyYW1ldHJpY0NsYXNzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmbXhDbGFzcyA9IG5ldyBGYW1peC5DbGFzcygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmbXhDbGFzcy5zZXROYW1lKGNsc05hbWUpO1xuICAgICAgICAgICAgZm14Q2xhc3Muc2V0RnVsbHlRdWFsaWZpZWROYW1lKGNsYXNzRnVsbHlRdWFsaWZpZWROYW1lKTtcbiAgICAgICAgICAgIGZteENsYXNzLnNldElzQWJzdHJhY3QoaXNBYnN0cmFjdCk7XG5cbiAgICAgICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKGNscywgZm14Q2xhc3MpO1xuXG4gICAgICAgICAgICB0aGlzLmZteENsYXNzTWFwLnNldChjbGFzc0Z1bGx5UXVhbGlmaWVkTmFtZSwgZm14Q2xhc3MpO1xuXG4gICAgICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14Q2xhc3MpO1xuXG4gICAgICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGZteENsYXNzLGNscyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmbXhDbGFzcyA9IHRoaXMuZm14Q2xhc3NNYXAuZ2V0KGNsYXNzRnVsbHlRdWFsaWZpZWROYW1lKSBhcyAoRmFtaXguQ2xhc3MgfCBGYW1peC5QYXJhbWV0cmljQ2xhc3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZteENsYXNzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgb3IgZ2V0cyBhIEZhbWl4IGludGVyZmFjZSBvciBwYXJhbWV0ZXJpemFibGUgaW50ZXJmYWNlXG4gICAgICogQHBhcmFtIGludGVyIEFuIGludGVyZmFjZVxuICAgICAqIEByZXR1cm5zIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgaW50ZXJmYWNlXG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZU9yR2V0RmFtaXhJbnRlcmZhY2UoaW50ZXI6IEludGVyZmFjZURlY2xhcmF0aW9uKTogRmFtaXguSW50ZXJmYWNlIHwgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZSB7XG4gICAgICAgIGxldCBmbXhJbnRlcmZhY2U6IEZhbWl4LkludGVyZmFjZSB8IEZhbWl4LlBhcmFtZXRyaWNJbnRlcmZhY2U7XG4gICAgICAgIGNvbnN0IGludGVyTmFtZSA9IGludGVyLmdldE5hbWUoKTtcbiAgICAgICAgY29uc3QgaW50ZXJGdWxseVF1YWxpZmllZE5hbWUgPSBGUU5GdW5jdGlvbnMuZ2V0RlFOKGludGVyKTtcbiAgICAgICAgaWYgKCF0aGlzLmZteEludGVyZmFjZU1hcC5oYXMoaW50ZXJGdWxseVF1YWxpZmllZE5hbWUpKSB7XG4gICAgICAgICAgICBjb25zdCBpc0dlbmVyaWMgPSBpbnRlci5nZXRUeXBlUGFyYW1ldGVycygpLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChpc0dlbmVyaWMpIHtcbiAgICAgICAgICAgICAgICBmbXhJbnRlcmZhY2UgPSBuZXcgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm14SW50ZXJmYWNlID0gbmV3IEZhbWl4LkludGVyZmFjZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmbXhJbnRlcmZhY2Uuc2V0TmFtZShpbnRlck5hbWUpO1xuXG4gICAgICAgICAgICB0aGlzLm1ha2VGYW1peEluZGV4RmlsZUFuY2hvcihpbnRlciwgZm14SW50ZXJmYWNlKTtcblxuICAgICAgICAgICAgdGhpcy5mbXhJbnRlcmZhY2VNYXAuc2V0KGludGVyRnVsbHlRdWFsaWZpZWROYW1lLCBmbXhJbnRlcmZhY2UpO1xuXG4gICAgICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14SW50ZXJmYWNlKTtcblxuICAgICAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhJbnRlcmZhY2UsaW50ZXIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm14SW50ZXJmYWNlID0gdGhpcy5mbXhJbnRlcmZhY2VNYXAuZ2V0KGludGVyRnVsbHlRdWFsaWZpZWROYW1lKSBhcyAoRmFtaXguSW50ZXJmYWNlIHwgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZteEludGVyZmFjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIG9yIGdldHMgYSBGYW1peCBjb25jcmV0ZSBlbGVtZW50XG4gICAgICogQHBhcmFtIGVsIEEgcGFyYW1ldHJpYyBFbGVtZW50ICAgXG4gICAgICogQHBhcmFtIGVsRGVjbGFyYXRpb24gdGhlIGVsZW1lbnQgZGVjbGFyYXRpb25cbiAgICAgKiBAcGFyYW0gY29uY3JldGVBcmd1bWVudHMgY29uY3JldGUgYXJndW1lbnRzXG4gICAgICogQHJldHVybnMgQSBwYXJhbWV0cmljIEVsZW1lbnQgIFxuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVPckdldEZhbWl4Q29uY3JldGVFbGVtZW50KGVsIDogRmFtaXguUGFyYW1ldHJpY0NsYXNzIHwgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZSB8IEZhbWl4LlBhcmFtZXRyaWNGdW5jdGlvbiB8IEZhbWl4LlBhcmFtZXRyaWNNZXRob2QsIGVsRGVjbGFyYXRpb24gOiBDbGFzc0RlY2xhcmF0aW9uIHwgSW50ZXJmYWNlRGVjbGFyYXRpb24gfCBGdW5jdGlvbkRlY2xhcmF0aW9uIHwgTWV0aG9kRGVjbGFyYXRpb24sIGNvbmNyZXRlQXJndW1lbnRzIDogYW55KTogRmFtaXguUGFyYW1ldHJpY0NsYXNzIHwgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZSB8IEZhbWl4LlBhcmFtZXRyaWNGdW5jdGlvbiB8IEZhbWl4LlBhcmFtZXRyaWNNZXRob2Qge1xuICAgICAgICBcbiAgICAgICAgbGV0IGZ1bGx5UXVhbGlmaWVkRmlsZW5hbWUgPSBlbC5nZXRGdWxseVF1YWxpZmllZE5hbWUoKTtcbiAgICAgICAgbGV0IHBhcmFtcyA9IFwiXCI7XG4gICAgICAgIFxuICAgICAgICBjb25jcmV0ZUFyZ3VtZW50cy5tYXAoKHBhcmFtKSA9PiB7XG4gICAgICAgICAgICBwYXJhbXMgPSBwYXJhbXMrcGFyYW0uZ2V0VGV4dCgpKycsJ1xuICAgICAgICB9KVxuICAgICAgICBcbiAgICAgICAgcGFyYW1zID0gcGFyYW1zLnN1YnN0cmluZygwLCBwYXJhbXMubGVuZ3RoIC0gMSlcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgZnVsbHlRdWFsaWZpZWRGaWxlbmFtZSA9IEhlbHBlcnMucmVwbGFjZUxhc3RCZXR3ZWVuVGFncyhmdWxseVF1YWxpZmllZEZpbGVuYW1lLHBhcmFtcyk7XG5cbiAgICAgICAgbGV0IGNvbmNFbGVtZW50O1xuXG4gICAgICAgIGlmICghdGhpcy5mbXhJbnRlcmZhY2VNYXAuaGFzKGZ1bGx5UXVhbGlmaWVkRmlsZW5hbWUpICYmICF0aGlzLmZteENsYXNzTWFwLmhhcyhmdWxseVF1YWxpZmllZEZpbGVuYW1lKSAmJiAhdGhpcy5mbXhGdW5jdGlvbkFuZE1ldGhvZE1hcC5oYXMoZnVsbHlRdWFsaWZpZWRGaWxlbmFtZSkpe1xuICAgICAgICAgICAgY29uY0VsZW1lbnQgPSBfLmNsb25lRGVlcChlbCk7IFxuICAgICAgICAgICAgY29uY0VsZW1lbnQuc2V0RnVsbHlRdWFsaWZpZWROYW1lKGZ1bGx5UXVhbGlmaWVkRmlsZW5hbWUpO1xuICAgICAgICAgICAgY29uY0VsZW1lbnQuY2xlYXJHZW5lcmljUGFyYW1ldGVycygpO1xuICAgICAgICAgICAgY29uY3JldGVBcmd1bWVudHMubWFwKChwYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcmFtZXRlciA9IHRoaXMuY3JlYXRlT3JHZXRGYW1peENvbmNyZXRlVHlwZShwYXJhbSk7XG4gICAgICAgICAgICAgICAgY29uY0VsZW1lbnQuYWRkQ29uY3JldGVQYXJhbWV0ZXIocGFyYW1ldGVyKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIChlbCBpbnN0YW5jZW9mIEZhbWl4LlBhcmFtZXRyaWNDbGFzcykge1xuICAgICAgICAgICAgICAgIHRoaXMuZm14Q2xhc3NNYXAuc2V0KGZ1bGx5UXVhbGlmaWVkRmlsZW5hbWUsIGNvbmNFbGVtZW50IGFzIEZhbWl4LlBhcmFtZXRyaWNDbGFzcyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGVsIGluc3RhbmNlb2YgRmFtaXguUGFyYW1ldHJpY0ludGVyZmFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZm14SW50ZXJmYWNlTWFwLnNldChmdWxseVF1YWxpZmllZEZpbGVuYW1lLCBjb25jRWxlbWVudCBhcyBGYW1peC5QYXJhbWV0cmljSW50ZXJmYWNlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZWwgaW5zdGFuY2VvZiBGYW1peC5QYXJhbWV0cmljRnVuY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZteEZ1bmN0aW9uQW5kTWV0aG9kTWFwLnNldChmdWxseVF1YWxpZmllZEZpbGVuYW1lLCBjb25jRWxlbWVudCBhcyBGYW1peC5QYXJhbWV0cmljRnVuY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChlbCBpbnN0YW5jZW9mIEZhbWl4LlBhcmFtZXRyaWNNZXRob2QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZteEZ1bmN0aW9uQW5kTWV0aG9kTWFwLnNldChmdWxseVF1YWxpZmllZEZpbGVuYW1lLCBjb25jRWxlbWVudCBhcyBGYW1peC5QYXJhbWV0cmljTWV0aG9kKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChjb25jRWxlbWVudCk7XG4gICAgICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGNvbmNFbGVtZW50LGVsRGVjbGFyYXRpb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGVsIGluc3RhbmNlb2YgRmFtaXguUGFyYW1ldHJpY0NsYXNzKSB7XG4gICAgICAgICAgICAgICAgY29uY0VsZW1lbnQgPSB0aGlzLmZteENsYXNzTWFwLmdldChmdWxseVF1YWxpZmllZEZpbGVuYW1lKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZWwgaW5zdGFuY2VvZiBGYW1peC5QYXJhbWV0cmljSW50ZXJmYWNlKSB7XG4gICAgICAgICAgICAgICAgY29uY0VsZW1lbnQgPSB0aGlzLmZteEludGVyZmFjZU1hcC5nZXQoZnVsbHlRdWFsaWZpZWRGaWxlbmFtZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGVsIGluc3RhbmNlb2YgRmFtaXguUGFyYW1ldHJpY0Z1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgY29uY0VsZW1lbnQgPSB0aGlzLmZteEZ1bmN0aW9uQW5kTWV0aG9kTWFwLmdldChmdWxseVF1YWxpZmllZEZpbGVuYW1lKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZWwgaW5zdGFuY2VvZiBGYW1peC5QYXJhbWV0cmljTWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgY29uY0VsZW1lbnQgPSB0aGlzLmZteEZ1bmN0aW9uQW5kTWV0aG9kTWFwLmdldChmdWxseVF1YWxpZmllZEZpbGVuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29uY0VsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIEZhbWl4IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHByb3BlcnR5IEEgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyBUaGUgRmFtaXggbW9kZWwgb2YgdGhlIHByb3BlcnR5XG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZUZhbWl4UHJvcGVydHkocHJvcGVydHk6IFByb3BlcnR5RGVjbGFyYXRpb24gfCBQcm9wZXJ0eVNpZ25hdHVyZSk6IEZhbWl4LlByb3BlcnR5IHtcbiAgICAgICAgY29uc3QgZm14UHJvcGVydHkgPSBuZXcgRmFtaXguUHJvcGVydHkoKTtcbiAgICAgICAgY29uc3QgaXNTaWduYXR1cmUgPSBwcm9wZXJ0eSBpbnN0YW5jZW9mIFByb3BlcnR5U2lnbmF0dXJlO1xuICAgICAgICBmbXhQcm9wZXJ0eS5zZXROYW1lKHByb3BlcnR5LmdldE5hbWUoKSk7XG5cbiAgICAgICAgbGV0IHByb3BUeXBlTmFtZSA9IHRoaXMuVU5LTk9XTl9WQUxVRTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHByb3BUeXBlTmFtZSA9IHByb3BlcnR5LmdldFR5cGUoKS5nZXRUZXh0KCkudHJpbSgpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGA+IFdBUk5JTkc6IGdvdCBleGNlcHRpb24gJHtlcnJvcn0uIEZhaWxlZCB0byBnZXQgdXNhYmxlIG5hbWUgZm9yIHByb3BlcnR5OiAke3Byb3BlcnR5LmdldE5hbWUoKX0uIENvbnRpbnVpbmcuLi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZteFR5cGUgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhUeXBlKHByb3BUeXBlTmFtZSwgcHJvcGVydHkpO1xuICAgICAgICBmbXhQcm9wZXJ0eS5zZXREZWNsYXJlZFR5cGUoZm14VHlwZSk7XG5cbiAgICAgICAgLy8gYWRkIHRoZSB2aXNpYmlsaXR5IChwdWJsaWMsIHByaXZhdGUsIGV0Yy4pIHRvIHRoZSBmbXhQcm9wZXJ0eVxuICAgICAgICBmbXhQcm9wZXJ0eS52aXNpYmlsaXR5ID0gXCJcIjtcblxuICAgICAgICBwcm9wZXJ0eS5nZXRNb2RpZmllcnMoKS5mb3JFYWNoKG0gPT4ge1xuICAgICAgICAgICAgc3dpdGNoIChtLmdldFRleHQoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgU2NvcGUuUHVibGljOlxuICAgICAgICAgICAgICAgICAgICBmbXhQcm9wZXJ0eS52aXNpYmlsaXR5ID0gXCJwdWJsaWNcIjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBTY29wZS5Qcm90ZWN0ZWQ6XG4gICAgICAgICAgICAgICAgICAgIGZteFByb3BlcnR5LnZpc2liaWxpdHkgPSBcInByb3RlY3RlZFwiO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFNjb3BlLlByaXZhdGU6XG4gICAgICAgICAgICAgICAgICAgIGZteFByb3BlcnR5LnZpc2liaWxpdHkgPSBcInByaXZhdGVcIjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcInN0YXRpY1wiOlxuICAgICAgICAgICAgICAgICAgICBmbXhQcm9wZXJ0eS5zZXRJc0NsYXNzU2lkZSh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcInJlYWRvbmx5XCI6XG4gICAgICAgICAgICAgICAgICAgIGZteFByb3BlcnR5LnJlYWRPbmx5ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghaXNTaWduYXR1cmUgJiYgcHJvcGVydHkuZ2V0RXhjbGFtYXRpb25Ub2tlbk5vZGUoKSkge1xuICAgICAgICAgICAgZm14UHJvcGVydHkuaXNEZWZpbml0ZWx5QXNzaWduZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwcm9wZXJ0eS5nZXRRdWVzdGlvblRva2VuTm9kZSgpKSB7XG4gICAgICAgICAgICBmbXhQcm9wZXJ0eS5pc09wdGlvbmFsID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocHJvcGVydHkuZ2V0TmFtZSgpLnN1YnN0cmluZygwLCAxKSA9PT0gXCIjXCIpIHtcbiAgICAgICAgICAgIGZteFByb3BlcnR5LmlzSmF2YVNjcmlwdFByaXZhdGUgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tYWtlRmFtaXhJbmRleEZpbGVBbmNob3IocHJvcGVydHksIGZteFByb3BlcnR5KTtcblxuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14UHJvcGVydHkpO1xuXG4gICAgICAgIHRoaXMuZm14RWxlbWVudE9iamVjdE1hcC5zZXQoZm14UHJvcGVydHkscHJvcGVydHkpO1xuXG4gICAgICAgIHJldHVybiBmbXhQcm9wZXJ0eTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgRmFtaXggbWV0aG9kIG9yIGFjY2Vzc29yXG4gICAgICogQHBhcmFtIG1ldGhvZCBBIG1ldGhvZCBvciBhbiBhY2Nlc3NvclxuICAgICAqIEBwYXJhbSBjdXJyZW50Q0MgVGhlIGN5Y2xvbWF0aWMgY29tcGxleGl0eSBtZXRyaWNzIG9mIHRoZSBjdXJyZW50IHNvdXJjZSBmaWxlXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBtZXRob2Qgb3IgdGhlIGFjY2Vzc29yXG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZU9yR2V0RmFtaXhNZXRob2QobWV0aG9kOiBNZXRob2REZWNsYXJhdGlvbiB8IENvbnN0cnVjdG9yRGVjbGFyYXRpb24gfCBNZXRob2RTaWduYXR1cmUgfCBHZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiwgY3VycmVudENDOiB1bmtub3duKTogRmFtaXguTWV0aG9kIHwgRmFtaXguQWNjZXNzb3IgfCBGYW1peC5QYXJhbWV0cmljTWV0aG9kIHtcbiAgICAgICAgbGV0IGZteE1ldGhvZDogRmFtaXguTWV0aG9kIHwgRmFtaXguQWNjZXNzb3IgfCBGYW1peC5QYXJhbWV0cmljTWV0aG9kO1xuICAgICAgICBjb25zdCBpc0dlbmVyaWMgPSBtZXRob2QuZ2V0VHlwZVBhcmFtZXRlcnMoKS5sZW5ndGggPiAwO1xuICAgICAgICBjb25zdCBmdW5jdGlvbkZ1bGx5UXVhbGlmaWVkTmFtZSA9IEZRTkZ1bmN0aW9ucy5nZXRGUU4obWV0aG9kKTtcbiAgICAgICAgaWYgKCF0aGlzLmZteEZ1bmN0aW9uQW5kTWV0aG9kTWFwLmhhcyhmdW5jdGlvbkZ1bGx5UXVhbGlmaWVkTmFtZSkpIHtcblxuICAgICAgICAgICAgaWYgKG1ldGhvZCBpbnN0YW5jZW9mIEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfHwgbWV0aG9kIGluc3RhbmNlb2YgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbikge1xuICAgICAgICAgICAgICAgIGZteE1ldGhvZCA9IG5ldyBGYW1peC5BY2Nlc3NvcigpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlzR2V0dGVyID0gbWV0aG9kIGluc3RhbmNlb2YgR2V0QWNjZXNzb3JEZWNsYXJhdGlvbjtcbiAgICAgICAgICAgICAgICBjb25zdCBpc1NldHRlciA9IG1ldGhvZCBpbnN0YW5jZW9mIFNldEFjY2Vzc29yRGVjbGFyYXRpb247XG4gICAgICAgICAgICAgICAgaWYgKGlzR2V0dGVyKSB7KGZteE1ldGhvZCBhcyBGYW1peC5BY2Nlc3Nvcikuc2V0S2luZChcImdldHRlclwiKTt9XG4gICAgICAgICAgICAgICAgaWYgKGlzU2V0dGVyKSB7KGZteE1ldGhvZCBhcyBGYW1peC5BY2Nlc3Nvcikuc2V0S2luZChcInNldHRlclwiKTt9XG4gICAgICAgICAgICAgICAgdGhpcy5mYW1peFJlcC5hZGRFbGVtZW50KGZteE1ldGhvZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNHZW5lcmljKSB7XG4gICAgICAgICAgICAgICAgICAgIGZteE1ldGhvZCA9IG5ldyBGYW1peC5QYXJhbWV0cmljTWV0aG9kKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmbXhNZXRob2QgPSBuZXcgRmFtaXguTWV0aG9kKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChmbXhNZXRob2QpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaXNDb25zdHJ1Y3RvciA9IG1ldGhvZCBpbnN0YW5jZW9mIENvbnN0cnVjdG9yRGVjbGFyYXRpb247XG4gICAgICAgICAgICBjb25zdCBpc1NpZ25hdHVyZSA9IG1ldGhvZCBpbnN0YW5jZW9mIE1ldGhvZFNpZ25hdHVyZTtcblxuICAgICAgICAgICAgbGV0IGlzQWJzdHJhY3QgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBpc1N0YXRpYyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKG1ldGhvZCBpbnN0YW5jZW9mIE1ldGhvZERlY2xhcmF0aW9uIHx8IG1ldGhvZCBpbnN0YW5jZW9mIEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfHwgbWV0aG9kIGluc3RhbmNlb2YgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbikge1xuICAgICAgICAgICAgICAgIGlzQWJzdHJhY3QgPSBtZXRob2QuaXNBYnN0cmFjdCgpO1xuICAgICAgICAgICAgICAgIGlzU3RhdGljID0gbWV0aG9kLmlzU3RhdGljKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc0NvbnN0cnVjdG9yKSB7KGZteE1ldGhvZCBhcyBGYW1peC5BY2Nlc3Nvcikuc2V0S2luZChcImNvbnN0cnVjdG9yXCIpO31cbiAgICAgICAgICAgIGZteE1ldGhvZC5zZXRJc0Fic3RyYWN0KGlzQWJzdHJhY3QpO1xuICAgICAgICAgICAgZm14TWV0aG9kLnNldElzQ2xhc3NTaWRlKGlzU3RhdGljKTtcbiAgICAgICAgICAgIGZteE1ldGhvZC5zZXRJc1ByaXZhdGUoKG1ldGhvZCBpbnN0YW5jZW9mIE1ldGhvZERlY2xhcmF0aW9uIHx8IG1ldGhvZCBpbnN0YW5jZW9mIEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfHwgbWV0aG9kIGluc3RhbmNlb2YgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbikgPyAobWV0aG9kLmdldE1vZGlmaWVycygpLmZpbmQoeCA9PiB4LmdldFRleHQoKSA9PT0gJ3ByaXZhdGUnKSkgIT09IHVuZGVmaW5lZCA6IGZhbHNlKTtcbiAgICAgICAgICAgIGZteE1ldGhvZC5zZXRJc1Byb3RlY3RlZCgobWV0aG9kIGluc3RhbmNlb2YgTWV0aG9kRGVjbGFyYXRpb24gfHwgbWV0aG9kIGluc3RhbmNlb2YgR2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8fCBtZXRob2QgaW5zdGFuY2VvZiBTZXRBY2Nlc3NvckRlY2xhcmF0aW9uKSA/IChtZXRob2QuZ2V0TW9kaWZpZXJzKCkuZmluZCh4ID0+IHguZ2V0VGV4dCgpID09PSAncHJvdGVjdGVkJykpICE9PSB1bmRlZmluZWQgOiBmYWxzZSk7XG4gICAgICAgICAgICBmbXhNZXRob2Quc2V0U2lnbmF0dXJlKEhlbHBlcnMuY29tcHV0ZVNpZ25hdHVyZShtZXRob2QuZ2V0VGV4dCgpKSk7XG5cbiAgICAgICAgICAgIGxldCBtZXRob2ROYW1lOiBzdHJpbmc7XG4gICAgICAgICAgICBpZiAoaXNDb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgIG1ldGhvZE5hbWUgPSBcImNvbnN0cnVjdG9yXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBtZXRob2ROYW1lID0gKG1ldGhvZCBhcyBNZXRob2REZWNsYXJhdGlvbiB8IE1ldGhvZFNpZ25hdHVyZSB8IEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBTZXRBY2Nlc3NvckRlY2xhcmF0aW9uKS5nZXROYW1lKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmbXhNZXRob2Quc2V0TmFtZShtZXRob2ROYW1lKTtcblxuICAgICAgICAgICAgaWYgKCFpc0NvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1ldGhvZC5nZXROYW1lKCkuc3Vic3RyaW5nKDAsIDEpID09PSBcIiNcIikge1xuICAgICAgICAgICAgICAgICAgICBmbXhNZXRob2Quc2V0SXNQcml2YXRlKHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFmbXhNZXRob2QuZ2V0SXNQcml2YXRlKCkgJiYgIWZteE1ldGhvZC5nZXRJc1Byb3RlY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgZm14TWV0aG9kLnNldElzUHVibGljKHRydWUpOyAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZteE1ldGhvZC5zZXRJc1B1YmxpYyhmYWxzZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaXNTaWduYXR1cmUpIHtcbiAgICAgICAgICAgICAgICBmbXhNZXRob2Quc2V0Q3ljbG9tYXRpY0NvbXBsZXhpdHkoY3VycmVudENDW2ZteE1ldGhvZC5nZXROYW1lKCldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZteE1ldGhvZC5zZXRDeWNsb21hdGljQ29tcGxleGl0eSgwKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IG1ldGhvZFR5cGVOYW1lID0gdGhpcy5VTktOT1dOX1ZBTFVFOyBcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbWV0aG9kVHlwZU5hbWUgPSBtZXRob2QuZ2V0UmV0dXJuVHlwZSgpLmdldFRleHQoKS50cmltKCk7ICAgICAgICAgICAgXG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgPiBXQVJOSU5HOiBnb3QgZXhjZXB0aW9uICR7ZXJyb3J9LiBGYWlsZWQgdG8gZ2V0IHVzYWJsZSBuYW1lIGZvciByZXR1cm4gdHlwZSBvZiBtZXRob2Q6ICR7Zm14TWV0aG9kLmdldE5hbWUoKX0uIENvbnRpbnVpbmcuLi5gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgZm14VHlwZSA9IHRoaXMuY3JlYXRlT3JHZXRGYW1peFR5cGUobWV0aG9kVHlwZU5hbWUsIG1ldGhvZCk7XG4gICAgICAgICAgICBmbXhNZXRob2Quc2V0RGVjbGFyZWRUeXBlKGZteFR5cGUpO1xuICAgICAgICAgICAgZm14TWV0aG9kLnNldE51bWJlck9mTGluZXNPZkNvZGUobWV0aG9kLmdldEVuZExpbmVOdW1iZXIoKSAtIG1ldGhvZC5nZXRTdGFydExpbmVOdW1iZXIoKSk7XG4gICAgICAgICAgICBjb25zdCBwYXJhbWV0ZXJzID0gbWV0aG9kLmdldFBhcmFtZXRlcnMoKTtcbiAgICAgICAgICAgIGZteE1ldGhvZC5zZXROdW1iZXJPZlBhcmFtZXRlcnMocGFyYW1ldGVycy5sZW5ndGgpO1xuXG4gICAgICAgICAgICBpZiAoIWlzU2lnbmF0dXJlKSB7XG4gICAgICAgICAgICAgICAgZm14TWV0aG9kLnNldE51bWJlck9mU3RhdGVtZW50cyhtZXRob2QuZ2V0U3RhdGVtZW50cygpLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmbXhNZXRob2Quc2V0TnVtYmVyT2ZTdGF0ZW1lbnRzKDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICB0aGlzLm1ha2VGYW1peEluZGV4RmlsZUFuY2hvcihtZXRob2QsIGZteE1ldGhvZCk7XG5cbiAgICAgICAgICAgIHRoaXMuZm14RnVuY3Rpb25BbmRNZXRob2RNYXAuc2V0KGZ1bmN0aW9uRnVsbHlRdWFsaWZpZWROYW1lLCBmbXhNZXRob2QpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm14TWV0aG9kID0gdGhpcy5mbXhGdW5jdGlvbkFuZE1ldGhvZE1hcC5nZXQoZnVuY3Rpb25GdWxseVF1YWxpZmllZE5hbWUpIGFzIChGYW1peC5NZXRob2QgfCBGYW1peC5BY2Nlc3NvciB8IEZhbWl4LlBhcmFtZXRyaWNNZXRob2QpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhNZXRob2QsbWV0aG9kKTtcbiAgICAgICAgXG4gICAgICAgIHJldHVybiBmbXhNZXRob2Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIEZhbWl4IGZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGZ1bmMgQSBmdW5jdGlvblxuICAgICAqIEBwYXJhbSBjdXJyZW50Q0MgVGhlIGN5Y2xvbWF0aWMgY29tcGxleGl0eSBtZXRyaWNzIG9mIHRoZSBjdXJyZW50IHNvdXJjZSBmaWxlXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVPckdldEZhbWl4RnVuY3Rpb24oZnVuYzogRnVuY3Rpb25EZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRXhwcmVzc2lvbiwgY3VycmVudENDOiB1bmtub3duKTogRmFtaXguRnVuY3Rpb24gfCBGYW1peC5QYXJhbWV0cmljRnVuY3Rpb24ge1xuICAgICAgICBsZXQgZm14RnVuY3Rpb246IEZhbWl4LkZ1bmN0aW9uIHwgRmFtaXguUGFyYW1ldHJpY0Z1bmN0aW9uO1xuICAgICAgICBjb25zdCBpc0dlbmVyaWMgPSBmdW5jLmdldFR5cGVQYXJhbWV0ZXJzKCkubGVuZ3RoID4gMDsgICAgICAgIFxuICAgICAgICBjb25zdCBmdW5jdGlvbkZ1bGx5UXVhbGlmaWVkTmFtZSA9IEZRTkZ1bmN0aW9ucy5nZXRGUU4oZnVuYyk7XG4gICAgICAgIGlmICghdGhpcy5mbXhGdW5jdGlvbkFuZE1ldGhvZE1hcC5oYXMoZnVuY3Rpb25GdWxseVF1YWxpZmllZE5hbWUpKSB7XG4gICAgICAgICAgICBpZiAoaXNHZW5lcmljKSB7XG4gICAgICAgICAgICAgICAgZm14RnVuY3Rpb24gPSBuZXcgRmFtaXguUGFyYW1ldHJpY0Z1bmN0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmbXhGdW5jdGlvbiA9IG5ldyBGYW1peC5GdW5jdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgaWYgKGZ1bmMuZ2V0TmFtZSgpKSB7XG4gICAgICAgICAgICAgICAgZm14RnVuY3Rpb24uc2V0TmFtZShmdW5jLmdldE5hbWUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmbXhGdW5jdGlvbi5zZXROYW1lKFwiYW5vbnltb3VzXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmbXhGdW5jdGlvbi5zZXRTaWduYXR1cmUoSGVscGVycy5jb21wdXRlU2lnbmF0dXJlKGZ1bmMuZ2V0VGV4dCgpKSk7XG4gICAgICAgICAgICBmbXhGdW5jdGlvbi5zZXRDeWNsb21hdGljQ29tcGxleGl0eShjdXJyZW50Q0NbZm14RnVuY3Rpb24uZ2V0TmFtZSgpXSk7XG4gICAgICAgICAgICBmbXhGdW5jdGlvbi5zZXRGdWxseVF1YWxpZmllZE5hbWUoZnVuY3Rpb25GdWxseVF1YWxpZmllZE5hbWUpO1xuICAgIFxuICAgICAgICAgICAgbGV0IGZ1bmN0aW9uVHlwZU5hbWUgPSB0aGlzLlVOS05PV05fVkFMVUU7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uVHlwZU5hbWUgPSBmdW5jLmdldFJldHVyblR5cGUoKS5nZXRUZXh0KCkudHJpbSgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYD4gV0FSTklORzogZ290IGV4Y2VwdGlvbiAke2Vycm9yfS4gRmFpbGVkIHRvIGdldCB1c2FibGUgbmFtZSBmb3IgcmV0dXJuIHR5cGUgb2YgZnVuY3Rpb246ICR7ZnVuYy5nZXROYW1lKCl9LiBDb250aW51aW5nLi4uYCk7XG4gICAgICAgICAgICB9XG4gICAgXG4gICAgICAgICAgICBjb25zdCBmbXhUeXBlID0gdGhpcy5jcmVhdGVPckdldEZhbWl4VHlwZShmdW5jdGlvblR5cGVOYW1lLCBmdW5jKTtcbiAgICAgICAgICAgIGZteEZ1bmN0aW9uLnNldERlY2xhcmVkVHlwZShmbXhUeXBlKTtcbiAgICAgICAgICAgIGZteEZ1bmN0aW9uLnNldE51bWJlck9mTGluZXNPZkNvZGUoZnVuYy5nZXRFbmRMaW5lTnVtYmVyKCkgLSBmdW5jLmdldFN0YXJ0TGluZU51bWJlcigpKTtcbiAgICAgICAgICAgIGNvbnN0IHBhcmFtZXRlcnMgPSBmdW5jLmdldFBhcmFtZXRlcnMoKTtcbiAgICAgICAgICAgIGZteEZ1bmN0aW9uLnNldE51bWJlck9mUGFyYW1ldGVycyhwYXJhbWV0ZXJzLmxlbmd0aCk7XG4gICAgICAgICAgICBmbXhGdW5jdGlvbi5zZXROdW1iZXJPZlN0YXRlbWVudHMoZnVuYy5nZXRTdGF0ZW1lbnRzKCkubGVuZ3RoKTtcbiAgICBcbiAgICAgICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKGZ1bmMsIGZteEZ1bmN0aW9uKTtcbiAgICBcbiAgICAgICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChmbXhGdW5jdGlvbik7XG4gICAgXG4gICAgICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGZteEZ1bmN0aW9uLGZ1bmMpO1xuXG4gICAgICAgICAgICB0aGlzLmZteEZ1bmN0aW9uQW5kTWV0aG9kTWFwLnNldChmdW5jdGlvbkZ1bGx5UXVhbGlmaWVkTmFtZSwgZm14RnVuY3Rpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm14RnVuY3Rpb24gPSB0aGlzLmZteEZ1bmN0aW9uQW5kTWV0aG9kTWFwLmdldChmdW5jdGlvbkZ1bGx5UXVhbGlmaWVkTmFtZSkgYXMgKEZhbWl4LkZ1bmN0aW9uIHwgRmFtaXguUGFyYW1ldHJpY0Z1bmN0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbXhGdW5jdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgRmFtaXggcGFyYW1ldGVyXG4gICAgICogQHBhcmFtIHBhcmFtIEEgcGFyYW1ldGVyXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRmFtaXhQYXJhbWV0ZXIocGFyYW06IFBhcmFtZXRlckRlY2xhcmF0aW9uKTogRmFtaXguUGFyYW1ldGVyIHtcbiAgICAgICAgY29uc3QgZm14UGFyYW0gPSBuZXcgRmFtaXguUGFyYW1ldGVyKCk7XG5cbiAgICAgICAgbGV0IHBhcmFtVHlwZU5hbWUgPSB0aGlzLlVOS05PV05fVkFMVUU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBwYXJhbVR5cGVOYW1lID0gcGFyYW0uZ2V0VHlwZSgpLmdldFRleHQoKS50cmltKCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoYD4gV0FSTklORzogZ290IGV4Y2VwdGlvbiAke2Vycm9yfS4gRmFpbGVkIHRvIGdldCB1c2FibGUgbmFtZSBmb3IgcGFyYW1ldGVyOiAke3BhcmFtLmdldE5hbWUoKX0uIENvbnRpbnVpbmcuLi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZteFR5cGUgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhUeXBlKHBhcmFtVHlwZU5hbWUsIHBhcmFtKTtcbiAgICAgICAgZm14UGFyYW0uc2V0RGVjbGFyZWRUeXBlKGZteFR5cGUpO1xuICAgICAgICBmbXhQYXJhbS5zZXROYW1lKHBhcmFtLmdldE5hbWUoKSk7XG5cbiAgICAgICAgdGhpcy5tYWtlRmFtaXhJbmRleEZpbGVBbmNob3IocGFyYW0sIGZteFBhcmFtKTtcblxuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14UGFyYW0pO1xuXG4gICAgICAgIHRoaXMuZm14RWxlbWVudE9iamVjdE1hcC5zZXQoZm14UGFyYW0scGFyYW0pO1xuXG4gICAgICAgIHJldHVybiBmbXhQYXJhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgRmFtaXggdHlwZSBwYXJhbWV0ZXJcbiAgICAgKiBAcGFyYW0gdHAgQSB0eXBlIHBhcmFtZXRlclxuICAgICAqIEByZXR1cm5zIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgdHlwZSBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRmFtaXhQYXJhbWV0ZXJUeXBlKHRwOiBUeXBlUGFyYW1ldGVyRGVjbGFyYXRpb24pOiBGYW1peC5QYXJhbWV0ZXJUeXBlIHtcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGZteFBhcmFtZXRlclR5cGUgPSBuZXcgRmFtaXguUGFyYW1ldGVyVHlwZSgpO1xuICAgXG4gICAgICAgIGZteFBhcmFtZXRlclR5cGUuc2V0TmFtZSh0cC5nZXROYW1lKCkpOyAgICAgIFxuXG4gICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKHRwLCBmbXhQYXJhbWV0ZXJUeXBlKTtcblxuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14UGFyYW1ldGVyVHlwZSk7XG5cbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhQYXJhbWV0ZXJUeXBlLHRwKTtcblxuICAgICAgICByZXR1cm4gZm14UGFyYW1ldGVyVHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgRmFtaXggdHlwZSBwYXJhbWV0ZXJcbiAgICAgKiBAcGFyYW0gdHAgQSB0eXBlIHBhcmFtZXRlclxuICAgICAqIEByZXR1cm5zIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgdHlwZSBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlT3JHZXRGYW1peENvbmNyZXRlVHlwZShwYXJhbTogVHlwZU5vZGUpOiBGYW1peC5QYXJhbWV0ZXJUeXBlIHwgRmFtaXguUHJpbWl0aXZlVHlwZSB8IEZhbWl4LkNsYXNzIHwgRmFtaXguSW50ZXJmYWNlIHtcbiAgICAgICAgY29uc3QgdHlwZVBhcmFtZXRlckRlY2xhcmF0aW9uID0gcGFyYW0uZ2V0U3ltYm9sKCk/LmdldERlY2xhcmF0aW9ucygpWzBdIGFzIFR5cGVQYXJhbWV0ZXJEZWNsYXJhdGlvbjtcbiAgICAgICAgY29uc3QgcGFyYW1ldGVyVHlwZU5hbWUgOiBzdHJpbmcgPSBwYXJhbS5nZXRUZXh0KCk7XG4gICAgICAgIGxldCBmbXhQYXJhbWV0ZXJUeXBlOiBGYW1peC5UeXBlIHwgRmFtaXguQ2xhc3MgfCBGYW1peC5JbnRlcmZhY2U7XG5cbiAgICAgICAgbGV0IGlzQ2xhc3NPckludGVyZmFjZSA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5mbXhDbGFzc01hcC5oYXMocGFyYW1ldGVyVHlwZU5hbWUpKXtcbiAgICAgICAgICAgIHRoaXMuZm14Q2xhc3NNYXAuZm9yRWFjaCgob2JqLCBuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYob2JqIGluc3RhbmNlb2YgRmFtaXguUGFyYW1ldHJpY0NsYXNzKXtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgPT09IHBhcmFtLmdldFRleHQoKSAmJiBvYmouZ2V0R2VuZXJpY1BhcmFtZXRlcnMoKS5zaXplPjApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZteFBhcmFtZXRlclR5cGUgPSBvYmo7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NsYXNzT3JJbnRlcmZhY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IFxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuYW1lID09PSBwYXJhbS5nZXRUZXh0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZteFBhcmFtZXRlclR5cGUgPSBvYmo7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NsYXNzT3JJbnRlcmZhY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IFxuICAgICAgICAgICAgICAgIH0gICBcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5mbXhJbnRlcmZhY2VNYXAuaGFzKHBhcmFtZXRlclR5cGVOYW1lKSl7XG4gICAgICAgICAgICB0aGlzLmZteEludGVyZmFjZU1hcC5mb3JFYWNoKChvYmosIG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICBpZihvYmogaW5zdGFuY2VvZiBGYW1peC5QYXJhbWV0cmljSW50ZXJmYWNlKXtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgPT09IHBhcmFtLmdldFRleHQoKSAmJiBvYmouZ2V0R2VuZXJpY1BhcmFtZXRlcnMoKS5zaXplPjApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZteFBhcmFtZXRlclR5cGUgPSBvYmo7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NsYXNzT3JJbnRlcmZhY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IFxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuYW1lID09PSBwYXJhbS5nZXRUZXh0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZteFBhcmFtZXRlclR5cGUgPSBvYmo7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NsYXNzT3JJbnRlcmZhY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IFxuICAgICAgICAgICAgICAgIH0gICBcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cblxuICAgICAgICBpZighaXNDbGFzc09ySW50ZXJmYWNlKXtcbiAgICAgICAgICAgIGlmICghdGhpcy5mbXhUeXBlTWFwLmhhcyhwYXJhbWV0ZXJUeXBlTmFtZSkpIHsgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGlmIChwYXJhbWV0ZXJUeXBlTmFtZSA9PT0gXCJudW1iZXJcIiB8fCBwYXJhbWV0ZXJUeXBlTmFtZSA9PT0gXCJzdHJpbmdcIiB8fCBwYXJhbWV0ZXJUeXBlTmFtZSA9PT0gXCJib29sZWFuXCIgfHwgcGFyYW1ldGVyVHlwZU5hbWUgPT09IFwiYmlnaW50XCIgfHwgcGFyYW1ldGVyVHlwZU5hbWUgPT09IFwic3ltYm9sXCIgfHwgcGFyYW1ldGVyVHlwZU5hbWUgPT09IFwidW5kZWZpbmVkXCIgfHwgcGFyYW1ldGVyVHlwZU5hbWUgPT09IFwibnVsbFwiIHx8IHBhcmFtZXRlclR5cGVOYW1lID09PSBcImFueVwiIHx8IHBhcmFtZXRlclR5cGVOYW1lID09PSBcInVua25vd25cIiB8fCBwYXJhbWV0ZXJUeXBlTmFtZSA9PT0gXCJuZXZlclwiIHx8IHBhcmFtZXRlclR5cGVOYW1lID09PSBcInZvaWRcIikge1xuICAgICAgICAgICAgICAgICAgICBmbXhQYXJhbWV0ZXJUeXBlID0gbmV3IEZhbWl4LlByaW1pdGl2ZVR5cGUoKTtcbiAgICAgICAgICAgICAgICAgICAgZm14UGFyYW1ldGVyVHlwZS5zZXRJc1N0dWIodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZm14UGFyYW1ldGVyVHlwZSA9IG5ldyBGYW1peC5QYXJhbWV0ZXJUeXBlKCk7XG4gICAgICAgICAgICAgICAgfSBcbiAgICBcbiAgICAgICAgICAgICAgICBmbXhQYXJhbWV0ZXJUeXBlLnNldE5hbWUocGFyYW1ldGVyVHlwZU5hbWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChmbXhQYXJhbWV0ZXJUeXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZteFR5cGVNYXAuc2V0KHBhcmFtZXRlclR5cGVOYW1lLCBmbXhQYXJhbWV0ZXJUeXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGZteFBhcmFtZXRlclR5cGUsdHlwZVBhcmFtZXRlckRlY2xhcmF0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZteFBhcmFtZXRlclR5cGUgPSB0aGlzLmZteFR5cGVNYXAuZ2V0KHBhcmFtZXRlclR5cGVOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbXhQYXJhbWV0ZXJUeXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBGYW1peCB2YXJpYWJsZVxuICAgICAqIEBwYXJhbSB2YXJpYWJsZSBBIHZhcmlhYmxlXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSB2YXJpYWJsZVxuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVGYW1peFZhcmlhYmxlKHZhcmlhYmxlOiBWYXJpYWJsZURlY2xhcmF0aW9uKTogRmFtaXguVmFyaWFibGUge1xuICAgICAgICBjb25zdCBmbXhWYXJpYWJsZSA9IG5ldyBGYW1peC5WYXJpYWJsZSgpO1xuICAgIFxuICAgICAgICBsZXQgdmFyaWFibGVUeXBlTmFtZSA9IHRoaXMuVU5LTk9XTl9WQUxVRTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhcmlhYmxlVHlwZU5hbWUgPSB2YXJpYWJsZS5nZXRUeXBlKCkuZ2V0VGV4dCgpLnRyaW0oKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgPiBXQVJOSU5HOiBnb3QgZXhjZXB0aW9uICR7ZXJyb3J9LiBGYWlsZWQgdG8gZ2V0IHVzYWJsZSBuYW1lIGZvciB2YXJpYWJsZTogJHt2YXJpYWJsZS5nZXROYW1lKCl9LiBDb250aW51aW5nLi4uYCk7XG4gICAgICAgIH1cbiAgICBcbiAgICAgICAgY29uc3QgZm14VHlwZSA9IHRoaXMuY3JlYXRlT3JHZXRGYW1peFR5cGUodmFyaWFibGVUeXBlTmFtZSwgdmFyaWFibGUpO1xuICAgICAgICBmbXhWYXJpYWJsZS5zZXREZWNsYXJlZFR5cGUoZm14VHlwZSk7XG4gICAgICAgIGZteFZhcmlhYmxlLnNldE5hbWUodmFyaWFibGUuZ2V0TmFtZSgpKTtcbiAgICBcbiAgICAgICAgdGhpcy5tYWtlRmFtaXhJbmRleEZpbGVBbmNob3IodmFyaWFibGUsIGZteFZhcmlhYmxlKTtcbiAgICBcbiAgICAgICAgdGhpcy5mYW1peFJlcC5hZGRFbGVtZW50KGZteFZhcmlhYmxlKTtcbiAgICBcbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhWYXJpYWJsZSx2YXJpYWJsZSk7XG4gICAgXG4gICAgICAgIHJldHVybiBmbXhWYXJpYWJsZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgRmFtaXggZW51bVxuICAgICAqIEBwYXJhbSBlbnVtRW50aXR5IEFuIGVudW1cbiAgICAgKiBAcmV0dXJucyBUaGUgRmFtaXggbW9kZWwgb2YgdGhlIGVudW1cbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRmFtaXhFbnVtKGVudW1FbnRpdHk6IEVudW1EZWNsYXJhdGlvbik6IEZhbWl4LkVudW0ge1xuICAgICAgICBjb25zdCBmbXhFbnVtID0gbmV3IEZhbWl4LkVudW0oKTtcbiAgICAgICAgZm14RW51bS5zZXROYW1lKGVudW1FbnRpdHkuZ2V0TmFtZSgpKTtcblxuICAgICAgICB0aGlzLm1ha2VGYW1peEluZGV4RmlsZUFuY2hvcihlbnVtRW50aXR5LCBmbXhFbnVtKTtcblxuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14RW51bSk7XG5cbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhFbnVtLGVudW1FbnRpdHkpO1xuXG4gICAgICAgIHJldHVybiBmbXhFbnVtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBGYW1peCBlbnVtIHZhbHVlXG4gICAgICogQHBhcmFtIGVudW1NZW1iZXIgQW4gZW51bSBtZW1iZXJcbiAgICAgKiBAcmV0dXJucyBUaGUgRmFtaXggbW9kZWwgb2YgdGhlIGVudW0gbWVtYmVyXG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZUZhbWl4RW51bVZhbHVlKGVudW1NZW1iZXI6IEVudW1NZW1iZXIpOiBGYW1peC5FbnVtVmFsdWUge1xuICAgICAgICBjb25zdCBmbXhFbnVtVmFsdWUgPSBuZXcgRmFtaXguRW51bVZhbHVlKCk7XG5cbiAgICAgICAgbGV0IGVudW1WYWx1ZVR5cGVOYW1lID0gdGhpcy5VTktOT1dOX1ZBTFVFO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZW51bVZhbHVlVHlwZU5hbWUgPSBlbnVtTWVtYmVyLmdldFR5cGUoKS5nZXRUZXh0KCkudHJpbSgpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGA+IFdBUk5JTkc6IGdvdCBleGNlcHRpb24gJHtlcnJvcn0uIEZhaWxlZCB0byBnZXQgdXNhYmxlIG5hbWUgZm9yIGVudW0gdmFsdWU6ICR7ZW51bU1lbWJlci5nZXROYW1lKCl9LiBDb250aW51aW5nLi4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmbXhUeXBlID0gdGhpcy5jcmVhdGVPckdldEZhbWl4VHlwZShlbnVtVmFsdWVUeXBlTmFtZSwgZW51bU1lbWJlcik7XG4gICAgICAgIGZteEVudW1WYWx1ZS5zZXREZWNsYXJlZFR5cGUoZm14VHlwZSk7XG4gICAgICAgIGZteEVudW1WYWx1ZS5zZXROYW1lKGVudW1NZW1iZXIuZ2V0TmFtZSgpKTtcblxuICAgICAgICB0aGlzLm1ha2VGYW1peEluZGV4RmlsZUFuY2hvcihlbnVtTWVtYmVyLCBmbXhFbnVtVmFsdWUpO1xuXG4gICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChmbXhFbnVtVmFsdWUpO1xuXG4gICAgICAgIHRoaXMuZm14RWxlbWVudE9iamVjdE1hcC5zZXQoZm14RW51bVZhbHVlLGVudW1NZW1iZXIpO1xuXG4gICAgICAgIHJldHVybiBmbXhFbnVtVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBvciBnZXRzIGEgRmFtaXggZGVjb3JhdG9yXG4gICAgICogQHBhcmFtIGRlY29yYXRvciBBIGRlY29yYXRvclxuICAgICAqIEBwYXJhbSBkZWNvcmF0ZWRFbnRpdHkgQSBjbGFzcywgYSBtZXRob2QsIGEgcGFyYW1ldGVyIG9yIGEgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyBUaGUgRmFtaXggbW9kZWwgb2YgdGhlIGRlY29yYXRvclxuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVPckdldEZhbWl4RGVjb3JhdG9yKGRlY29yYXRvcjogRGVjb3JhdG9yLCBkZWNvcmF0ZWRFbnRpdHk6IENsYXNzRGVjbGFyYXRpb24gfCBNZXRob2REZWNsYXJhdGlvbiB8IEdldEFjY2Vzc29yRGVjbGFyYXRpb24gfCBTZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgUGFyYW1ldGVyRGVjbGFyYXRpb24gfCBQcm9wZXJ0eURlY2xhcmF0aW9uKTogRmFtaXguRGVjb3JhdG9yIHtcbiAgICAgICAgY29uc3QgZm14RGVjb3JhdG9yID0gbmV3IEZhbWl4LkRlY29yYXRvcigpO1xuICAgICAgICBjb25zdCBkZWNvcmF0b3JOYW1lID0gXCJAXCIgKyBkZWNvcmF0b3IuZ2V0TmFtZSgpO1xuICAgICAgICBjb25zdCBkZWNvcmF0b3JFeHByZXNzaW9uID0gZGVjb3JhdG9yLmdldFRleHQoKS5zdWJzdHJpbmcoMSk7XG5cbiAgICAgICAgZm14RGVjb3JhdG9yLnNldE5hbWUoZGVjb3JhdG9yTmFtZSk7XG4gICAgICAgIGZteERlY29yYXRvci5zZXREZWNvcmF0b3JFeHByZXNzaW9uKGRlY29yYXRvckV4cHJlc3Npb24pO1xuICAgICAgICBjb25zdCBkZWNvcmF0ZWRFbnRpdHlGdWxseVF1YWxpZmllZE5hbWUgPSBGUU5GdW5jdGlvbnMuZ2V0RlFOKGRlY29yYXRlZEVudGl0eSk7XG4gICAgICAgIGNvbnN0IGZteERlY29yYXRlZEVudGl0eSA9IHRoaXMuZmFtaXhSZXAuZ2V0RmFtaXhFbnRpdHlCeUZ1bGx5UXVhbGlmaWVkTmFtZShkZWNvcmF0ZWRFbnRpdHlGdWxseVF1YWxpZmllZE5hbWUpIGFzIEZhbWl4Lk5hbWVkRW50aXR5O1xuICAgICAgICBmbXhEZWNvcmF0b3Iuc2V0RGVjb3JhdGVkRW50aXR5KGZteERlY29yYXRlZEVudGl0eSk7XG5cbiAgICAgICAgdGhpcy5tYWtlRmFtaXhJbmRleEZpbGVBbmNob3IoZGVjb3JhdG9yLCBmbXhEZWNvcmF0b3IpO1xuXG4gICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChmbXhEZWNvcmF0b3IpO1xuXG4gICAgICAgIHRoaXMuZm14RWxlbWVudE9iamVjdE1hcC5zZXQoZm14RGVjb3JhdG9yLGRlY29yYXRvcik7XG5cbiAgICAgICAgcmV0dXJuIGZteERlY29yYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgRmFtaXggY29tbWVudFxuICAgICAqIEBwYXJhbSBjb21tZW50IEEgY29tbWVudFxuICAgICAqIEBwYXJhbSBmbXhTY29wZSBUaGUgRmFtaXggbW9kZWwgb2YgdGhlIGNvbW1lbnQncyBjb250YWluZXJcbiAgICAgKiBAcGFyYW0gaXNKU0RvYyBBIGJvb2xlYW4gaW5kaWNhdGluZyBpZiB0aGUgY29tbWVudCBpcyBhIEpTRG9jXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBjb21tZW50XG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZUZhbWl4Q29tbWVudChjb21tZW50OiBDb21tZW50UmFuZ2UsIGZteFNjb3BlOiBGYW1peC5OYW1lZEVudGl0eSwgaXNKU0RvYzogYm9vbGVhbik6IEZhbWl4LkNvbW1lbnQge1xuICAgICAgICBsb2dnZXIuZGVidWcoYD4gTk9URTogY3JlYXRpbmcgY29tbWVudCAke2NvbW1lbnQuZ2V0VGV4dCgpfSBpbiBzY29wZSAke2ZteFNjb3BlLmdldE5hbWUoKX0uYCk7XG4gICAgICAgIGNvbnN0IGZteENvbW1lbnQgPSBuZXcgRmFtaXguQ29tbWVudCgpO1xuICAgICAgICBmbXhDb21tZW50LnNldENvbnRhaW5lcihmbXhTY29wZSk7ICAvLyBhZGRzIGNvbW1lbnQgdG8gdGhlIGNvbnRhaW5lcidzIGNvbW1lbnRzIGNvbGxlY3Rpb25cbiAgICAgICAgZm14Q29tbWVudC5zZXRJc0pTRG9jKGlzSlNEb2MpO1xuXG4gICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKGNvbW1lbnQsIGZteENvbW1lbnQpO1xuXG4gICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChmbXhDb21tZW50KTtcblxuICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGZteENvbW1lbnQsY29tbWVudCk7XG5cbiAgICAgICAgcmV0dXJuIGZteENvbW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBvciBnZXRzIGEgRmFtaXggdHlwZVxuICAgICAqIEBwYXJhbSB0eXBlTmFtZSBBIHR5cGUgbmFtZVxuICAgICAqIEBwYXJhbSBlbGVtZW50IEEgdHMtbW9ycGggZWxlbWVudFxuICAgICAqIEByZXR1cm5zIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgdHlwZVxuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVPckdldEZhbWl4VHlwZSh0eXBlTmFtZTogc3RyaW5nLCBlbGVtZW50OiBUeXBlRGVjbGFyYXRpb24pOiBGYW1peC5UeXBlIHwgRmFtaXguUHJpbWl0aXZlVHlwZSB8IEZhbWl4LlBhcmFtZXRlclR5cGUge1xuICAgICAgICBsZXQgZm14VHlwZTogRmFtaXguVHlwZSB8IEZhbWl4LlByaW1pdGl2ZVR5cGUgfCBGYW1peC5QYXJhbWV0ZXJUeXBlO1xuICAgICAgICBsZXQgaXNQcmltaXRpdmVUeXBlID0gZmFsc2U7XG4gICAgICAgIGxldCBpc1BhcmFtZXRlclR5cGUgPSBmYWxzZTtcblxuICAgICAgICBsb2dnZXIuZGVidWcoXCJDcmVhdGluZyAob3IgZ2V0dGluZykgdHlwZTogJ1wiICsgdHlwZU5hbWUgKyBcIicgb2YgZWxlbWVudDogXCIgKyBlbGVtZW50Py5nZXRUZXh0KCkgKyBcIiBvZiBraW5kOiBcIiArIGVsZW1lbnQ/LmdldEtpbmROYW1lKCkpO1xuICAgICAgICBsZXQgYW5jZXN0b3I6IEZhbWl4LkNvbnRhaW5lckVudGl0eTtcbiAgICAgICAgaWYgKGVsZW1lbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29uc3QgdHlwZUFuY2VzdG9yID0gSGVscGVycy5maW5kVHlwZUFuY2VzdG9yKGVsZW1lbnQpO1xuICAgICAgICAgICAgaWYgKCF0eXBlQW5jZXN0b3IpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFuY2VzdG9yIG5vdCBmb3VuZCBmb3IgZWxlbWVudCAke2VsZW1lbnQuZ2V0VGV4dCgpfS5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGFuY2VzdG9yRnVsbHlRdWFsaWZpZWROYW1lID0gRlFORnVuY3Rpb25zLmdldEZRTih0eXBlQW5jZXN0b3IpO1xuICAgICAgICAgICAgYW5jZXN0b3IgPSB0aGlzLmZhbWl4UmVwLmdldEZhbWl4RW50aXR5QnlGdWxseVF1YWxpZmllZE5hbWUoYW5jZXN0b3JGdWxseVF1YWxpZmllZE5hbWUpIGFzIEZhbWl4LkNvbnRhaW5lckVudGl0eTtcbiAgICAgICAgICAgIGlmICghYW5jZXN0b3IpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZGVidWcoYEFuY2VzdG9yICR7RlFORnVuY3Rpb25zLmdldEZRTih0eXBlQW5jZXN0b3IpfSBub3QgZm91bmQuIEFkZGluZyB0aGUgbmV3IHR5cGUuYCk7XG4gICAgICAgICAgICAgICAgYW5jZXN0b3IgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhUeXBlKHR5cGVBbmNlc3Rvci5nZXRUZXh0KCksIHR5cGVBbmNlc3RvciBhcyBUeXBlRGVjbGFyYXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVOYW1lID09PSBcIm51bWJlclwiIHx8IHR5cGVOYW1lID09PSBcInN0cmluZ1wiIHx8IHR5cGVOYW1lID09PSBcImJvb2xlYW5cIiB8fCB0eXBlTmFtZSA9PT0gXCJiaWdpbnRcIiB8fCB0eXBlTmFtZSA9PT0gXCJzeW1ib2xcIiB8fCB0eXBlTmFtZSA9PT0gXCJ1bmRlZmluZWRcIiB8fCB0eXBlTmFtZSA9PT0gXCJudWxsXCIgfHwgdHlwZU5hbWUgPT09IFwiYW55XCIgfHwgdHlwZU5hbWUgPT09IFwidW5rbm93blwiIHx8IHR5cGVOYW1lID09PSBcIm5ldmVyXCIgfHwgdHlwZU5hbWUgPT09IFwidm9pZFwiKSB7XG4gICAgICAgICAgICBpc1ByaW1pdGl2ZVR5cGUgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWlzUHJpbWl0aXZlVHlwZSAmJiB0eXBlTmFtZS5pbmNsdWRlcyhcIjxcIikgJiYgdHlwZU5hbWUuaW5jbHVkZXMoXCI+XCIpICYmICEodHlwZU5hbWUuaW5jbHVkZXMoXCI9PlwiKSkpIHtcbiAgICAgICAgICAgIGlzUGFyYW1ldGVyVHlwZSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuZm14VHlwZU1hcC5oYXModHlwZU5hbWUpKSB7XG4gICAgICAgICAgICBpZiAoaXNQcmltaXRpdmVUeXBlKSB7XG4gICAgICAgICAgICAgICAgZm14VHlwZSA9IG5ldyBGYW1peC5QcmltaXRpdmVUeXBlKCk7XG4gICAgICAgICAgICAgICAgZm14VHlwZS5zZXRJc1N0dWIodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpc1BhcmFtZXRlclR5cGUpIHtcbiAgICAgICAgICAgICAgICBmbXhUeXBlID0gbmV3IEZhbWl4LlBhcmFtZXRlclR5cGUoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJhbWV0ZXJUeXBlTmFtZXMgPSB0eXBlTmFtZS5zdWJzdHJpbmcodHlwZU5hbWUuaW5kZXhPZihcIjxcIikgKyAxLCB0eXBlTmFtZS5pbmRleE9mKFwiPlwiKSkuc3BsaXQoXCIsXCIpLm1hcChzID0+IHMudHJpbSgpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBiYXNlVHlwZU5hbWUgPSB0eXBlTmFtZS5zdWJzdHJpbmcoMCwgdHlwZU5hbWUuaW5kZXhPZihcIjxcIikpLnRyaW0oKTtcbiAgICAgICAgICAgICAgICBwYXJhbWV0ZXJUeXBlTmFtZXMuZm9yRWFjaChwYXJhbWV0ZXJUeXBlTmFtZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZteFBhcmFtZXRlclR5cGUgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhUeXBlKHBhcmFtZXRlclR5cGVOYW1lLCBlbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgKGZteFR5cGUgYXMgRmFtaXguUGFyYW1ldGVyVHlwZSkuYWRkQXJndW1lbnQoZm14UGFyYW1ldGVyVHlwZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZm14QmFzZVR5cGUgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhUeXBlKGJhc2VUeXBlTmFtZSwgZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgKGZteFR5cGUgYXMgRmFtaXguUGFyYW1ldGVyVHlwZSkuc2V0QmFzZVR5cGUoZm14QmFzZVR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm14VHlwZSA9IG5ldyBGYW1peC5UeXBlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZteFR5cGUuc2V0TmFtZSh0eXBlTmFtZSk7XG4gICAgICAgICAgICBmbXhUeXBlLnNldENvbnRhaW5lcihhbmNlc3Rvcik7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKGVsZW1lbnQsIGZteFR5cGUpO1xuXG4gICAgICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14VHlwZSk7XG5cbiAgICAgICAgICAgIHRoaXMuZm14VHlwZU1hcC5zZXQodHlwZU5hbWUsIGZteFR5cGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm14VHlwZSA9IHRoaXMuZm14VHlwZU1hcC5nZXQodHlwZU5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhUeXBlLGVsZW1lbnQpO1xuXG4gICAgICAgIHJldHVybiBmbXhUeXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBGYW1peCBhY2Nlc3NcbiAgICAgKiBAcGFyYW0gbm9kZSBBIG5vZGVcbiAgICAgKiBAcGFyYW0gaWQgQW4gaWQgb2YgYSBwYXJhbWV0ZXIsIGEgdmFyaWFibGUsIGEgcHJvcGVydHkgb3IgYW4gZW51bSBtZW1iZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRmFtaXhBY2Nlc3Mobm9kZTogSWRlbnRpZmllciwgaWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBmbXhWYXIgPSB0aGlzLmZhbWl4UmVwLmdldEZhbWl4RW50aXR5QnlJZChpZCkgYXMgRmFtaXguU3RydWN0dXJhbEVudGl0eTtcbiAgICAgICAgaWYgKCFmbXhWYXIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFtaXggZW50aXR5IHdpdGggaWQgJHtpZH0gbm90IGZvdW5kLCBmb3Igbm9kZSAke25vZGUuZ2V0VGV4dCgpfSBpbiAke25vZGUuZ2V0U291cmNlRmlsZSgpLmdldEJhc2VOYW1lKCl9IGF0IGxpbmUgJHtub2RlLmdldFN0YXJ0TGluZU51bWJlcigpfS5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgQ3JlYXRpbmcgRmFtaXhBY2Nlc3MuIE5vZGU6IFske25vZGUuZ2V0S2luZE5hbWUoKX1dICcke25vZGUuZ2V0VGV4dCgpfScgYXQgbGluZSAke25vZGUuZ2V0U3RhcnRMaW5lTnVtYmVyKCl9IGluICR7bm9kZS5nZXRTb3VyY2VGaWxlKCkuZ2V0QmFzZU5hbWUoKX0sIGlkOiAke2lkfSByZWZlcnMgdG8gZm14VmFyICcke2ZteFZhci5nZXRGdWxseVF1YWxpZmllZE5hbWUoKX0nLmApO1xuXG4gICAgICAgIGNvbnN0IG5vZGVSZWZlcmVuY2VBbmNlc3RvciA9IEhlbHBlcnMuZmluZEFuY2VzdG9yKG5vZGUpO1xuICAgICAgICBjb25zdCBhbmNlc3RvckZ1bGx5UXVhbGlmaWVkTmFtZSA9IEZRTkZ1bmN0aW9ucy5nZXRGUU4obm9kZVJlZmVyZW5jZUFuY2VzdG9yKTtcbiAgICAgICAgbGV0IGFjY2Vzc29yID0gdGhpcy5mYW1peFJlcC5nZXRGYW1peEVudGl0eUJ5RnVsbHlRdWFsaWZpZWROYW1lKGFuY2VzdG9yRnVsbHlRdWFsaWZpZWROYW1lKSBhcyBGYW1peC5Db250YWluZXJFbnRpdHk7XG4gICAgICAgIGlmICghYWNjZXNzb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgQW5jZXN0b3IgJHthbmNlc3RvckZ1bGx5UXVhbGlmaWVkTmFtZX0gb2Yga2luZCAke25vZGVSZWZlcmVuY2VBbmNlc3Rvci5nZXRLaW5kTmFtZSgpfSBub3QgZm91bmQuYCk7XG4gICAgICAgICAgICAvLyBhY2Nlc3NvciA9IHRoaXMuY3JlYXRlT3JHZXRGYW1peFR5cGUoYW5jZXN0b3JGdWxseVF1YWxpZmllZE5hbWUsIG5vZGVSZWZlcmVuY2VBbmNlc3RvciBhcyBUeXBlRGVjbGFyYXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZm14QWNjZXNzID0gbmV3IEZhbWl4LkFjY2VzcygpO1xuICAgICAgICBmbXhBY2Nlc3Muc2V0QWNjZXNzb3IoYWNjZXNzb3IpO1xuICAgICAgICBmbXhBY2Nlc3Muc2V0VmFyaWFibGUoZm14VmFyKTtcblxuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14QWNjZXNzKTtcblxuICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGZteEFjY2Vzcyxub2RlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgRmFtaXggaW52b2NhdGlvblxuICAgICAqIEBwYXJhbSBub2RlIEEgbm9kZVxuICAgICAqIEBwYXJhbSBtIEEgbWV0aG9kIG9yIGEgZnVuY3Rpb25cbiAgICAgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBtZXRob2Qgb3IgdGhlIGZ1bmN0aW9uXG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZUZhbWl4SW52b2NhdGlvbihub2RlOiBJZGVudGlmaWVyLCBtOiBNZXRob2REZWNsYXJhdGlvbiB8IENvbnN0cnVjdG9yRGVjbGFyYXRpb24gfCBHZXRBY2Nlc3NvckRlY2xhcmF0aW9uIHwgU2V0QWNjZXNzb3JEZWNsYXJhdGlvbiB8IEZ1bmN0aW9uRGVjbGFyYXRpb24gfCBGdW5jdGlvbkV4cHJlc3Npb24sIGlkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZm14TWV0aG9kT3JGdW5jdGlvbiA9IHRoaXMuZmFtaXhSZXAuZ2V0RmFtaXhFbnRpdHlCeUlkKGlkKSBhcyBGYW1peC5CZWhhdmlvcmFsRW50aXR5O1xuICAgICAgICBjb25zdCBub2RlUmVmZXJlbmNlQW5jZXN0b3IgPSBIZWxwZXJzLmZpbmRBbmNlc3Rvcihub2RlKTtcbiAgICAgICAgY29uc3QgYW5jZXN0b3JGdWxseVF1YWxpZmllZE5hbWUgPSBGUU5GdW5jdGlvbnMuZ2V0RlFOKG5vZGVSZWZlcmVuY2VBbmNlc3Rvcik7XG4gICAgICAgIGNvbnN0IHNlbmRlciA9IHRoaXMuZmFtaXhSZXAuZ2V0RmFtaXhFbnRpdHlCeUZ1bGx5UXVhbGlmaWVkTmFtZShhbmNlc3RvckZ1bGx5UXVhbGlmaWVkTmFtZSkgYXMgRmFtaXguQ29udGFpbmVyRW50aXR5O1xuICAgICAgICBjb25zdCByZWNlaXZlckZ1bGx5UXVhbGlmaWVkTmFtZSA9IEZRTkZ1bmN0aW9ucy5nZXRGUU4obS5nZXRQYXJlbnQoKSk7XG4gICAgICAgIGNvbnN0IHJlY2VpdmVyID0gdGhpcy5mYW1peFJlcC5nZXRGYW1peEVudGl0eUJ5RnVsbHlRdWFsaWZpZWROYW1lKHJlY2VpdmVyRnVsbHlRdWFsaWZpZWROYW1lKSBhcyBGYW1peC5OYW1lZEVudGl0eTtcblxuICAgICAgICBjb25zdCBmbXhJbnZvY2F0aW9uID0gbmV3IEZhbWl4Lkludm9jYXRpb24oKTtcbiAgICAgICAgZm14SW52b2NhdGlvbi5zZXRTZW5kZXIoc2VuZGVyKTtcbiAgICAgICAgZm14SW52b2NhdGlvbi5zZXRSZWNlaXZlcihyZWNlaXZlcik7XG4gICAgICAgIGZteEludm9jYXRpb24uYWRkQ2FuZGlkYXRlKGZteE1ldGhvZE9yRnVuY3Rpb24pO1xuICAgICAgICBmbXhJbnZvY2F0aW9uLnNldFNpZ25hdHVyZShmbXhNZXRob2RPckZ1bmN0aW9uLmdldFNpZ25hdHVyZSgpKTtcblxuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14SW52b2NhdGlvbik7XG5cbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhJbnZvY2F0aW9uLG5vZGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBGYW1peCBpbmhlcml0YW5jZVxuICAgICAqIEBwYXJhbSBjbHMgQSBjbGFzcyBvciBhbiBpbnRlcmZhY2UgKHN1YmNsYXNzKVxuICAgICAqIEBwYXJhbSBpbmhDbGFzcyBUaGUgaW5oZXJpdGVkIGNsYXNzIG9yIGludGVyZmFjZSAoc3VwZXJjbGFzcylcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRmFtaXhJbmhlcml0YW5jZShjbHM6IENsYXNzRGVjbGFyYXRpb24gfCBJbnRlcmZhY2VEZWNsYXJhdGlvbiwgaW5oQ2xhc3M6IENsYXNzRGVjbGFyYXRpb24gfCBJbnRlcmZhY2VEZWNsYXJhdGlvbiB8IEV4cHJlc3Npb25XaXRoVHlwZUFyZ3VtZW50cyk6IHZvaWQge1xuICAgICAgICBjb25zdCBmbXhJbmhlcml0YW5jZSA9IG5ldyBGYW1peC5Jbmhlcml0YW5jZSgpO1xuICAgICAgICAvLyBjb25zdCBjbHNOYW1lID0gY2xzLmdldE5hbWUoKTtcbiAgICAgICAgY29uc3QgY2xhc3NGdWxseVF1YWxpZmllZE5hbWUgPSBGUU5GdW5jdGlvbnMuZ2V0RlFOKGNscyk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgY3JlYXRlRmFtaXhJbmhlcml0YW5jZTogY2xhc3NGdWxseVF1YWxpZmllZE5hbWU6IGNsYXNzIGZxbiA9ICR7Y2xhc3NGdWxseVF1YWxpZmllZE5hbWV9YCk7XG4gICAgICAgIGxldCBzdWJDbGFzczogRmFtaXguQ2xhc3MgfCBGYW1peC5JbnRlcmZhY2U7XG4gICAgICAgIGlmIChjbHMgaW5zdGFuY2VvZiBDbGFzc0RlY2xhcmF0aW9uKSB7XG4gICAgICAgICAgICBzdWJDbGFzcyA9IHRoaXMuZm14Q2xhc3NNYXAuZ2V0KGNsYXNzRnVsbHlRdWFsaWZpZWROYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHN1YkNsYXNzID0gdGhpcy5mbXhJbnRlcmZhY2VNYXAuZ2V0KGNsYXNzRnVsbHlRdWFsaWZpZWROYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgbGV0IGluaENsYXNzTmFtZTogc3RyaW5nO1xuICAgICAgICBsZXQgaW5oQ2xhc3NGdWxseVF1YWxpZmllZE5hbWU6IHN0cmluZztcbiAgICAgICAgbGV0IHN1cGVyQ2xhc3M6IEZhbWl4LkNsYXNzIHwgRmFtaXguSW50ZXJmYWNlO1xuICAgICAgICBpZiAoaW5oQ2xhc3MgaW5zdGFuY2VvZiBDbGFzc0RlY2xhcmF0aW9uIHx8IGluaENsYXNzIGluc3RhbmNlb2YgSW50ZXJmYWNlRGVjbGFyYXRpb24pIHtcbiAgICAgICAgICAgIGluaENsYXNzTmFtZSA9IGluaENsYXNzLmdldE5hbWUoKTtcbiAgICAgICAgICAgIGluaENsYXNzRnVsbHlRdWFsaWZpZWROYW1lID0gRlFORnVuY3Rpb25zLmdldEZRTihpbmhDbGFzcyk7XG4gICAgICAgICAgICBpZiAoaW5oQ2xhc3MgaW5zdGFuY2VvZiBDbGFzc0RlY2xhcmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgc3VwZXJDbGFzcyA9IHRoaXMuZm14Q2xhc3NNYXAuZ2V0KGluaENsYXNzRnVsbHlRdWFsaWZpZWROYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1cGVyQ2xhc3MgPSB0aGlzLmZteEludGVyZmFjZU1hcC5nZXQoaW5oQ2xhc3NGdWxseVF1YWxpZmllZE5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gaW5oQ2xhc3MgaXMgYW4gRXhwcmVzc2lvbldpdGhUeXBlQXJndW1lbnRzXG4gICAgICAgICAgICBpbmhDbGFzc05hbWUgPSBpbmhDbGFzcy5nZXRFeHByZXNzaW9uKCkuZ2V0VGV4dCgpO1xuICAgICAgICAgICAgLy8gd2hhdCBpcyBpbmhDbGFzc0Z1bGx5UXVhbGlmaWVkTmFtZT8gVE9ET1xuICAgICAgICAgICAgaW5oQ2xhc3NGdWxseVF1YWxpZmllZE5hbWUgPSAnVW5kZWZpbmVkX1Njb3BlX2Zyb21faW1wb3J0ZXIuJyArIGluaENsYXNzTmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdXBlckNsYXNzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmIChpbmhDbGFzcyBpbnN0YW5jZW9mIENsYXNzRGVjbGFyYXRpb24pIHtcbiAgICAgICAgICAgICAgICBzdXBlckNsYXNzID0gbmV3IEZhbWl4LkNsYXNzKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5mbXhDbGFzc01hcC5zZXQoaW5oQ2xhc3NGdWxseVF1YWxpZmllZE5hbWUsIHN1cGVyQ2xhc3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc3VwZXJDbGFzcyA9IG5ldyBGYW1peC5JbnRlcmZhY2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZteEludGVyZmFjZU1hcC5zZXQoaW5oQ2xhc3NGdWxseVF1YWxpZmllZE5hbWUsIHN1cGVyQ2xhc3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KHN1cGVyQ2xhc3MsaW5oQ2xhc3MpO1xuXG4gICAgICAgICAgICBzdXBlckNsYXNzLnNldE5hbWUoaW5oQ2xhc3NOYW1lKTtcbiAgICAgICAgICAgIHN1cGVyQ2xhc3Muc2V0RnVsbHlRdWFsaWZpZWROYW1lKGluaENsYXNzRnVsbHlRdWFsaWZpZWROYW1lKTtcbiAgICAgICAgICAgIHN1cGVyQ2xhc3Muc2V0SXNTdHViKHRydWUpO1xuXG4gICAgICAgICAgICB0aGlzLm1ha2VGYW1peEluZGV4RmlsZUFuY2hvcihpbmhDbGFzcywgc3VwZXJDbGFzcyk7XG4gICAgICAgIFxuICAgICAgICAgICAgdGhpcy5mYW1peFJlcC5hZGRFbGVtZW50KHN1cGVyQ2xhc3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm14SW5oZXJpdGFuY2Uuc2V0U3ViY2xhc3Moc3ViQ2xhc3MpO1xuICAgICAgICBmbXhJbmhlcml0YW5jZS5zZXRTdXBlcmNsYXNzKHN1cGVyQ2xhc3MpO1xuXG4gICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChmbXhJbmhlcml0YW5jZSk7XG5cbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhJbmhlcml0YW5jZSxudWxsKTtcblxuICAgIH1cblxuICAgIHB1YmxpYyBjcmVhdGVGYW1peEltcG9ydENsYXVzZShpbXBvcnRlZEVudGl0eTogRmFtaXguTmFtZWRFbnRpdHksIGltcG9ydGluZ0VudGl0eTogRmFtaXguTW9kdWxlKSB7XG4gICAgICAgIGNvbnN0IGZteEltcG9ydENsYXVzZSA9IG5ldyBGYW1peC5JbXBvcnRDbGF1c2UoKTtcbiAgICAgICAgZm14SW1wb3J0Q2xhdXNlLnNldEltcG9ydGVkRW50aXR5KGltcG9ydGVkRW50aXR5KTtcbiAgICAgICAgZm14SW1wb3J0Q2xhdXNlLnNldEltcG9ydGluZ0VudGl0eShpbXBvcnRpbmdFbnRpdHkpO1xuICAgICAgICBpbXBvcnRpbmdFbnRpdHkuYWRkT3V0Z29pbmdJbXBvcnQoZm14SW1wb3J0Q2xhdXNlKTtcbiAgICAgICAgdGhpcy5mYW1peFJlcC5hZGRFbGVtZW50KGZteEltcG9ydENsYXVzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIEZhbWl4IGltcG9ydCBjbGF1c2VcbiAgICAgKiBAcGFyYW0gaW1wb3J0Q2xhdXNlSW5mbyBUaGUgaW5mb3JtYXRpb24gbmVlZGVkIHRvIGNyZWF0ZSBhIEZhbWl4IGltcG9ydCBjbGF1c2VcbiAgICAgKiBAcGFyYW0gaW1wb3J0RGVjbGFyYXRpb24gVGhlIGltcG9ydCBkZWNsYXJhdGlvblxuICAgICAqIEBwYXJhbSBpbXBvcnRlciBBIHNvdXJjZSBmaWxlIHdoaWNoIGlzIGEgbW9kdWxlXG4gICAgICogQHBhcmFtIG1vZHVsZVNwZWNpZmllckZpbGVQYXRoIFRoZSBwYXRoIG9mIHRoZSBtb2R1bGUgd2hlcmUgdGhlIGV4cG9ydCBkZWNsYXJhdGlvbiBpc1xuICAgICAqIEBwYXJhbSBpbXBvcnRFbGVtZW50IFRoZSBpbXBvcnRlZCBlbnRpdHlcbiAgICAgKiBAcGFyYW0gaXNJbkV4cG9ydHMgQSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhlIGltcG9ydGVkIGVudGl0eSBpcyBpbiB0aGUgZXhwb3J0c1xuICAgICAqIEBwYXJhbSBpc0RlZmF1bHRFeHBvcnQgQSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhlIGltcG9ydGVkIGVudGl0eSBpcyBhIGRlZmF1bHQgZXhwb3J0XG4gICAgICovXG4gICAgcHVibGljIG9sZENyZWF0ZUZhbWl4SW1wb3J0Q2xhdXNlKGltcG9ydENsYXVzZUluZm86IHtpbXBvcnREZWNsYXJhdGlvbj86IEltcG9ydERlY2xhcmF0aW9uIHwgSW1wb3J0RXF1YWxzRGVjbGFyYXRpb24sIGltcG9ydGVyU291cmNlRmlsZTogU291cmNlRmlsZSwgbW9kdWxlU3BlY2lmaWVyRmlsZVBhdGg6IHN0cmluZywgaW1wb3J0RWxlbWVudDogSW1wb3J0U3BlY2lmaWVyIHwgSWRlbnRpZmllciwgaXNJbkV4cG9ydHM6IGJvb2xlYW4sIGlzRGVmYXVsdEV4cG9ydDogYm9vbGVhbn0pOiB2b2lkIHtcbiAgICAgICAgY29uc3Qge2ltcG9ydERlY2xhcmF0aW9uLCBpbXBvcnRlclNvdXJjZUZpbGU6IGltcG9ydGVyLCBtb2R1bGVTcGVjaWZpZXJGaWxlUGF0aCwgaW1wb3J0RWxlbWVudCwgaXNJbkV4cG9ydHMsIGlzRGVmYXVsdEV4cG9ydH0gPSBpbXBvcnRDbGF1c2VJbmZvO1xuICAgICAgICBsb2dnZXIuZGVidWcoYGNyZWF0ZUZhbWl4SW1wb3J0Q2xhdXNlOiBDcmVhdGluZyBpbXBvcnQgY2xhdXNlOmApO1xuICAgICAgICBjb25zdCBmbXhJbXBvcnRDbGF1c2UgPSBuZXcgRmFtaXguSW1wb3J0Q2xhdXNlKCk7XG5cbiAgICAgICAgbGV0IGltcG9ydGVkRW50aXR5OiBGYW1peC5OYW1lZEVudGl0eSB8IEZhbWl4LlN0cnVjdHVyYWxFbnRpdHk7XG4gICAgICAgIGxldCBpbXBvcnRlZEVudGl0eU5hbWU6IHN0cmluZztcblxuICAgICAgICBjb25zdCBhYnNvbHV0ZVBhdGhQcm9qZWN0ID0gdGhpcy5mYW1peFJlcC5nZXRBYnNvbHV0ZVBhdGgoKTtcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHBhdGgubm9ybWFsaXplKG1vZHVsZVNwZWNpZmllckZpbGVQYXRoKTtcbiAgICAgICAgLy8gY29udmVydCB0aGUgcGF0aCBhbmQgcmVtb3ZlIGFueSB3aW5kb3dzIGJhY2tzbGFzaGVzIGludHJvZHVjZWQgYnkgcGF0aC5ub3JtYWxpemVcbiAgICAgICAgY29uc3QgcGF0aEluUHJvamVjdDogc3RyaW5nID0gdGhpcy5jb252ZXJ0VG9SZWxhdGl2ZVBhdGgoYWJzb2x1dGVQYXRoLCBhYnNvbHV0ZVBhdGhQcm9qZWN0KS5yZXBsYWNlKC9cXFxcL2csIFwiL1wiKTtcbiAgICAgICAgbGV0IHBhdGhOYW1lID0gXCJ7XCIgKyBwYXRoSW5Qcm9qZWN0ICsgXCJ9LlwiO1xuXG4gICAgICAgIC8vIE5hbWVkIGltcG9ydHMsIGUuZy4gaW1wb3J0IHsgQ2xhc3NXIH0gZnJvbSBcIi4vY29tcGxleEV4cG9ydE1vZHVsZVwiO1xuXG4gICAgICAgIC8vIFN0YXJ0IHdpdGggc2ltcGxlIGltcG9ydCBjbGF1c2UgKHdpdGhvdXQgcmVmZXJyaW5nIHRvIHRoZSBhY3R1YWwgdmFyaWFibGUpXG5cbiAgICAgICAgaWYgKGltcG9ydERlY2xhcmF0aW9uIGluc3RhbmNlb2YgSW1wb3J0RGVjbGFyYXRpb24gXG4gICAgICAgICAgICAmJiBpbXBvcnRFbGVtZW50IGluc3RhbmNlb2YgSW1wb3J0U3BlY2lmaWVyKSB7IFxuICAgICAgICAgICAgICAgIGltcG9ydGVkRW50aXR5TmFtZSA9IGltcG9ydEVsZW1lbnQuZ2V0TmFtZSgpO1xuICAgICAgICAgICAgcGF0aE5hbWUgPSBwYXRoTmFtZSArIGltcG9ydGVkRW50aXR5TmFtZTtcbiAgICAgICAgICAgIGlmIChpc0luRXhwb3J0cykge1xuICAgICAgICAgICAgICAgIGltcG9ydGVkRW50aXR5ID0gdGhpcy5mYW1peFJlcC5nZXRGYW1peEVudGl0eUJ5RnVsbHlRdWFsaWZpZWROYW1lKHBhdGhOYW1lKSBhcyBGYW1peC5OYW1lZEVudGl0eTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpbXBvcnRlZEVudGl0eSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgaW1wb3J0ZWRFbnRpdHkgPSBuZXcgRmFtaXguTmFtZWRFbnRpdHkoKTtcbiAgICAgICAgICAgICAgICBpbXBvcnRlZEVudGl0eS5zZXROYW1lKGltcG9ydGVkRW50aXR5TmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc0luRXhwb3J0cykge1xuICAgICAgICAgICAgICAgICAgICBpbXBvcnRlZEVudGl0eS5zZXRJc1N0dWIodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKGltcG9ydEVsZW1lbnQsIGltcG9ydGVkRW50aXR5KTtcbiAgICAgICAgICAgICAgICBpbXBvcnRlZEVudGl0eS5zZXRGdWxseVF1YWxpZmllZE5hbWUocGF0aE5hbWUpO1xuICAgICAgICAgICAgICAgIC8vIG11c3QgYWRkIGVudGl0eSB0byByZXBvc2l0b3J5XG4gICAgICAgICAgICAgICAgdGhpcy5mYW1peFJlcC5hZGRFbGVtZW50KGltcG9ydGVkRW50aXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBoYW5kbGUgaW1wb3J0IGVxdWFscyBkZWNsYXJhdGlvbnMsIGUuZy4gaW1wb3J0IG15TW9kdWxlID0gcmVxdWlyZShcIi4vY29tcGxleEV4cG9ydE1vZHVsZVwiKTtcbiAgICAgICAgLy8gVHlwZVNjcmlwdCBjYW4ndCBkZXRlcm1pbmUgdGhlIHR5cGUgb2YgdGhlIGltcG9ydGVkIG1vZHVsZSwgc28gd2UgY3JlYXRlIGEgTW9kdWxlIGVudGl0eVxuICAgICAgICBlbHNlIGlmIChpbXBvcnREZWNsYXJhdGlvbiBpbnN0YW5jZW9mIEltcG9ydEVxdWFsc0RlY2xhcmF0aW9uKSB7XG4gICAgICAgICAgICBpbXBvcnRlZEVudGl0eU5hbWUgPSBpbXBvcnREZWNsYXJhdGlvbj8uZ2V0TmFtZSgpO1xuICAgICAgICAgICAgcGF0aE5hbWUgPSBwYXRoTmFtZSArIGltcG9ydGVkRW50aXR5TmFtZTtcbiAgICAgICAgICAgIGltcG9ydGVkRW50aXR5ID0gbmV3IEZhbWl4LlN0cnVjdHVyYWxFbnRpdHkoKTtcbiAgICAgICAgICAgIGltcG9ydGVkRW50aXR5LnNldE5hbWUoaW1wb3J0ZWRFbnRpdHlOYW1lKTtcbiAgICAgICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKGltcG9ydEVsZW1lbnQsIGltcG9ydGVkRW50aXR5KTtcbiAgICAgICAgICAgIGltcG9ydGVkRW50aXR5LnNldEZ1bGx5UXVhbGlmaWVkTmFtZShwYXRoTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBhbnlUeXBlID0gdGhpcy5jcmVhdGVPckdldEZhbWl4VHlwZSgnYW55JywgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIChpbXBvcnRlZEVudGl0eSBhcyBGYW1peC5TdHJ1Y3R1cmFsRW50aXR5KS5zZXREZWNsYXJlZFR5cGUoYW55VHlwZSk7XG4gICAgICAgIH0gZWxzZSB7ICAvLyBkZWZhdWx0IGltcG9ydHMsIGUuZy4gaW1wb3J0IENsYXNzVyBmcm9tIFwiLi9jb21wbGV4RXhwb3J0TW9kdWxlXCI7ICBcbiAgICAgICAgICAgIGltcG9ydGVkRW50aXR5TmFtZSA9IGltcG9ydEVsZW1lbnQuZ2V0VGV4dCgpO1xuICAgICAgICAgICAgcGF0aE5hbWUgPSBwYXRoTmFtZSArIChpc0RlZmF1bHRFeHBvcnQgPyBcImRlZmF1bHRFeHBvcnRcIiA6IFwibmFtZXNwYWNlRXhwb3J0XCIpO1xuICAgICAgICAgICAgaW1wb3J0ZWRFbnRpdHkgPSBuZXcgRmFtaXguTmFtZWRFbnRpdHkoKTtcbiAgICAgICAgICAgIGltcG9ydGVkRW50aXR5LnNldE5hbWUoaW1wb3J0ZWRFbnRpdHlOYW1lKTtcbiAgICAgICAgICAgIHRoaXMubWFrZUZhbWl4SW5kZXhGaWxlQW5jaG9yKGltcG9ydEVsZW1lbnQsIGltcG9ydGVkRW50aXR5KTtcbiAgICAgICAgICAgIGltcG9ydGVkRW50aXR5LnNldEZ1bGx5UXVhbGlmaWVkTmFtZShwYXRoTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSSBkb24ndCB0aGluayBpdCBzaG91bGQgYmUgYWRkZWQgdG8gdGhlIHJlcG9zaXRvcnkgaWYgaXQgZXhpc3RzIGFscmVhZHlcbiAgICAgICAgaWYgKCFpc0luRXhwb3J0cykgdGhpcy5mYW1peFJlcC5hZGRFbGVtZW50KGltcG9ydGVkRW50aXR5KTtcbiAgICAgICAgY29uc3QgaW1wb3J0ZXJGdWxseVF1YWxpZmllZE5hbWUgPSBGUU5GdW5jdGlvbnMuZ2V0RlFOKGltcG9ydGVyKTtcbiAgICAgICAgY29uc3QgZm14SW1wb3J0ZXIgPSB0aGlzLmZhbWl4UmVwLmdldEZhbWl4RW50aXR5QnlGdWxseVF1YWxpZmllZE5hbWUoaW1wb3J0ZXJGdWxseVF1YWxpZmllZE5hbWUpIGFzIEZhbWl4Lk1vZHVsZTtcbiAgICAgICAgZm14SW1wb3J0Q2xhdXNlLnNldEltcG9ydGluZ0VudGl0eShmbXhJbXBvcnRlcik7XG4gICAgICAgIGZteEltcG9ydENsYXVzZS5zZXRJbXBvcnRlZEVudGl0eShpbXBvcnRlZEVudGl0eSk7XG4gICAgICAgIGlmIChpbXBvcnREZWNsYXJhdGlvbiBpbnN0YW5jZW9mIEltcG9ydEVxdWFsc0RlY2xhcmF0aW9uKSB7XG4gICAgICAgICAgICBmbXhJbXBvcnRDbGF1c2Uuc2V0TW9kdWxlU3BlY2lmaWVyKGltcG9ydERlY2xhcmF0aW9uPy5nZXRNb2R1bGVSZWZlcmVuY2UoKS5nZXRUZXh0KCkgYXMgc3RyaW5nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZteEltcG9ydENsYXVzZS5zZXRNb2R1bGVTcGVjaWZpZXIoaW1wb3J0RGVjbGFyYXRpb24/LmdldE1vZHVsZVNwZWNpZmllclZhbHVlKCkgYXMgc3RyaW5nKTtcbiAgICAgICAgfVxuICAgIFxuICAgICAgICBsb2dnZXIuZGVidWcoYGNyZWF0ZUZhbWl4SW1wb3J0Q2xhdXNlOiAke2ZteEltcG9ydENsYXVzZS5nZXRJbXBvcnRlZEVudGl0eSgpPy5nZXROYW1lKCl9IChvZiB0eXBlICR7XG4gICAgICAgICAgICBIZWxwZXJzLmdldFN1YlR5cGVOYW1lKGZteEltcG9ydENsYXVzZS5nZXRJbXBvcnRlZEVudGl0eSgpKX0pIGlzIGltcG9ydGVkIGJ5ICR7Zm14SW1wb3J0Q2xhdXNlLmdldEltcG9ydGluZ0VudGl0eSgpPy5nZXROYW1lKCl9YCk7XG5cbiAgICAgICAgZm14SW1wb3J0ZXIuYWRkT3V0Z29pbmdJbXBvcnQoZm14SW1wb3J0Q2xhdXNlKTtcblxuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14SW1wb3J0Q2xhdXNlKTtcblxuICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGZteEltcG9ydENsYXVzZSxpbXBvcnREZWNsYXJhdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIEZhbWl4IEFycm93IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGFycm93RXhwcmVzc2lvbiBBbiBFeHByZXNzaW9uXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSB2YXJpYWJsZVxuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVGYW1peEFycm93RnVuY3Rpb24oYXJyb3dFeHByZXNzaW9uOiBFeHByZXNzaW9uICxjdXJyZW50Q0M6IHVua25vd24pOiBGYW1peC5BcnJvd0Z1bmN0aW9uIHwgRmFtaXguUGFyYW1ldHJpY0Fycm93RnVuY3Rpb24ge1xuICAgICAgICBcbiAgICAgICAgbGV0IGZteEFycm93RnVuY3Rpb246IEZhbWl4LkFycm93RnVuY3Rpb24gfCBGYW1peC5QYXJhbWV0cmljQXJyb3dGdW5jdGlvbjtcblxuICAgICAgICBjb25zdCBhcnJvd0Z1bmN0aW9uID0gYXJyb3dFeHByZXNzaW9uLmFzS2luZE9yVGhyb3coU3ludGF4S2luZC5BcnJvd0Z1bmN0aW9uKTtcblxuICAgICAgICBjb25zdCBpc0dlbmVyaWMgPSBhcnJvd0Z1bmN0aW9uLmdldFR5cGVQYXJhbWV0ZXJzKCkubGVuZ3RoID4gMDtcblxuICAgICAgICBpZiAoaXNHZW5lcmljKSB7XG4gICAgICAgICAgICBmbXhBcnJvd0Z1bmN0aW9uID0gbmV3IEZhbWl4LlBhcmFtZXRyaWNBcnJvd0Z1bmN0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmbXhBcnJvd0Z1bmN0aW9uID0gbmV3IEZhbWl4LkFycm93RnVuY3Rpb24oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCB0aGUgcGFyZW50IG9mIHRoZSBhcnJvdyBmdW5jdGlvbiAodGhlIHZhcmlhYmxlIGRlY2xhcmF0aW9uKVxuICAgICAgICBjb25zdCBwYXJlbnQgPSBhcnJvd0Z1bmN0aW9uLmdldFBhcmVudElmS2luZChTeW50YXhLaW5kLlZhcmlhYmxlRGVjbGFyYXRpb24pO1xuICAgICAgICBsZXQgZnVuY3Rpb25OYW1lID0gJyhOT19OQU1FKSc7XG5cbiAgICAgICAgaWYgKHBhcmVudCAmJiBwYXJlbnQgaW5zdGFuY2VvZiBWYXJpYWJsZURlY2xhcmF0aW9uKSB7XG4gICAgICAgICAgICAvLyBHZXQgdGhlIG5hbWUgb2YgdGhlIHZhcmlhYmxlXG4gICAgICAgICAgICBmdW5jdGlvbk5hbWUgPSBwYXJlbnQuZ2V0TmFtZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1bmN0aW9uTmFtZSkge1xuICAgICAgICAgICAgZm14QXJyb3dGdW5jdGlvbi5zZXROYW1lKGZ1bmN0aW9uTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmbXhBcnJvd0Z1bmN0aW9uLnNldE5hbWUoXCJhbm9ueW1vdXNcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTaWduYXR1cmUgb2YgYW4gYXJyb3cgZnVuY3Rpb24gaXMgKHBhcmFtZXRlcnMpID0+IHJldHVybl90eXBlXG4gICAgICAgIGNvbnN0IHBhcmFtZXRlcnNTaWduYXR1cmUgPSBhcnJvd0Z1bmN0aW9uLmdldFBhcmFtZXRlcnMoKS5tYXAocCA9PiBwLmdldFRleHQoKSkuam9pbihcIiwgXCIpO1xuICAgICAgICBjb25zdCByZXR1cm5UeXBlU2lnbmF0dXJlID0gYXJyb3dGdW5jdGlvbi5nZXRSZXR1cm5UeXBlKCkuZ2V0VGV4dCgpO1xuICAgICAgICBmbXhBcnJvd0Z1bmN0aW9uLnNldFNpZ25hdHVyZShgKCR7cGFyYW1ldGVyc1NpZ25hdHVyZX0pID0+ICR7cmV0dXJuVHlwZVNpZ25hdHVyZX1gKTtcbiAgICAgICAgZm14QXJyb3dGdW5jdGlvbi5zZXRDeWNsb21hdGljQ29tcGxleGl0eShjdXJyZW50Q0NbZm14QXJyb3dGdW5jdGlvbi5nZXROYW1lKCldKTtcblxuICAgICAgICBsZXQgZnVuY3Rpb25UeXBlTmFtZSA9IHRoaXMuVU5LTk9XTl9WQUxVRTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZ1bmN0aW9uVHlwZU5hbWUgPSBhcnJvd0Z1bmN0aW9uLmdldFJldHVyblR5cGUoKS5nZXRUZXh0KCkudHJpbSgpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGA+IFdBUk5JTkc6IGdvdCBleGNlcHRpb24gJHtlcnJvcn0uIEZhaWxlZCB0byBnZXQgdXNhYmxlIG5hbWUgZm9yIHJldHVybiB0eXBlIG9mIGZ1bmN0aW9uOiAke2Z1bmN0aW9uTmFtZX0uIENvbnRpbnVpbmcuLi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZteFR5cGUgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhUeXBlKGZ1bmN0aW9uVHlwZU5hbWUsIGFycm93RnVuY3Rpb24gYXMgdW5rbm93biBhcyBGdW5jdGlvbkRlY2xhcmF0aW9uKTtcbiAgICAgICAgZm14QXJyb3dGdW5jdGlvbi5zZXREZWNsYXJlZFR5cGUoZm14VHlwZSk7XG4gICAgICAgIGZteEFycm93RnVuY3Rpb24uc2V0TnVtYmVyT2ZMaW5lc09mQ29kZShhcnJvd0Z1bmN0aW9uLmdldEVuZExpbmVOdW1iZXIoKSAtIGFycm93RnVuY3Rpb24uZ2V0U3RhcnRMaW5lTnVtYmVyKCkpO1xuICAgICAgICBjb25zdCBwYXJhbWV0ZXJzID0gYXJyb3dGdW5jdGlvbi5nZXRQYXJhbWV0ZXJzKCk7XG4gICAgICAgIGZteEFycm93RnVuY3Rpb24uc2V0TnVtYmVyT2ZQYXJhbWV0ZXJzKHBhcmFtZXRlcnMubGVuZ3RoKTtcbiAgICAgICAgZm14QXJyb3dGdW5jdGlvbi5zZXROdW1iZXJPZlN0YXRlbWVudHMoYXJyb3dGdW5jdGlvbi5nZXRTdGF0ZW1lbnRzKCkubGVuZ3RoKTtcblxuICAgICAgICB0aGlzLm1ha2VGYW1peEluZGV4RmlsZUFuY2hvcihhcnJvd0V4cHJlc3Npb24gYXMgdW5rbm93biBhcyBUU01vcnBoT2JqZWN0VHlwZSwgZm14QXJyb3dGdW5jdGlvbik7XG4gICAgICAgIHRoaXMuZmFtaXhSZXAuYWRkRWxlbWVudChmbXhBcnJvd0Z1bmN0aW9uKTtcbiAgICAgICAgdGhpcy5mbXhFbGVtZW50T2JqZWN0TWFwLnNldChmbXhBcnJvd0Z1bmN0aW9uLGFycm93RnVuY3Rpb24gYXMgdW5rbm93biBhcyBUU01vcnBoT2JqZWN0VHlwZSk7XG5cbiAgICAgICAgcmV0dXJuIGZteEFycm93RnVuY3Rpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIEZhbWl4IGNvbmNyZXRpc2F0aW9uXG4gICAgICogQHBhcmFtIGNscyBBIGNsYXNzXG4gICAgICogQHJldHVybnMgVGhlIEZhbWl4IG1vZGVsIG9mIHRoZSBjb25jcmV0aXNhdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBjcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uKGNvbkVudGl0eSA6IEZhbWl4LlBhcmFtZXRyaWNDbGFzcyB8IEZhbWl4LlBhcmFtZXRyaWNJbnRlcmZhY2UgfCBGYW1peC5QYXJhbWV0cmljRnVuY3Rpb24gfCBGYW1peC5QYXJhbWV0cmljTWV0aG9kICxnZW5FbnRpdHkgOiBGYW1peC5QYXJhbWV0cmljQ2xhc3MgfCBGYW1peC5QYXJhbWV0cmljSW50ZXJmYWNlIHwgRmFtaXguUGFyYW1ldHJpY0Z1bmN0aW9uIHwgRmFtaXguUGFyYW1ldHJpY01ldGhvZCk6IEZhbWl4LkNvbmNyZXRpc2F0aW9uIHtcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGZteENvbmNyZXRpc2F0aW9uIDogRmFtaXguQ29uY3JldGlzYXRpb24gPSBuZXcgRmFtaXguQ29uY3JldGlzYXRpb24oKTsgICAgICAgICAgICAgIFxuICAgICAgICBcbiAgICAgICAgZm14Q29uY3JldGlzYXRpb24uc2V0Q29uY3JldGVFbnRpdHkoY29uRW50aXR5KTtcbiAgICAgICAgZm14Q29uY3JldGlzYXRpb24uc2V0R2VuZXJpY0VudGl0eShnZW5FbnRpdHkpO1xuICAgICAgICB0aGlzLmZteEVsZW1lbnRPYmplY3RNYXAuc2V0KGZteENvbmNyZXRpc2F0aW9uLG51bGwpO1xuICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14Q29uY3JldGlzYXRpb24pOyAgICBcbiAgICAgICAgY29uc3QgcGFyYW1ldGVyQ29uY3JldGlzYXRpb24gPSB0aGlzLmNyZWF0ZUZhbWl4UGFyYW1ldGVyQ29uY3Jlc3Rpc2F0aW9uKGZteENvbmNyZXRpc2F0aW9uKTtcbiAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gZm14Q29uY3JldGlzYXRpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIEZhbWl4IGNvbmNyZXRpc2F0aW9uXG4gICAgICogQHBhcmFtIGNvbmNyZXRpc2F0aW9uIEEgRmFtaXhDb25jcmV0aXNhdGlvblxuICAgICAqIEByZXR1cm5zIFRoZSBGYW1peCBtb2RlbCBvZiB0aGUgUGFyYW1ldGVyQ29uY3Jlc3Rpc2F0aW9uXG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZUZhbWl4UGFyYW1ldGVyQ29uY3Jlc3Rpc2F0aW9uKGNvbmNyZXRpc2F0aW9uOiBGYW1peC5Db25jcmV0aXNhdGlvbik6IEZhbWl4LlBhcmFtZXRlckNvbmNyZXRpc2F0aW9uIHtcbiAgICAgICAgY29uc3QgY29uQ2xhc3MgPSBjb25jcmV0aXNhdGlvbi5nZXRDb25jcmV0ZUVudGl0eSgpO1xuICAgICAgICBjb25zdCBnZW5DbGFzcyA9IGNvbmNyZXRpc2F0aW9uLmdldEdlbmVyaWNFbnRpdHkoKTtcbiAgICAgICAgY29uc3QgcGFyYW1ldGVyQ29uY3JldGlzYXRpb25zID0gdGhpcy5mYW1peFJlcC5fZ2V0QWxsRW50aXRpZXNXaXRoVHlwZShcIlBhcmFtZXRlckNvbmNyZXRpc2F0aW9uXCIpO1xuICAgICAgICBjb25zdCBjb25jcmV0ZVBhcmFtZXRlcnMgPSBjb25DbGFzcy5nZXRDb25jcmV0ZVBhcmFtZXRlcnMoKTtcbiAgICAgICAgY29uc3QgZ2VuZXJpY1BhcmFtZXRlcnMgPSBnZW5DbGFzcy5nZXRHZW5lcmljUGFyYW1ldGVycygpO1xuICAgICAgICBcbiAgICAgICAgbGV0IGNvbkNsYXNzVHlwZVBhcmFtZXRlcnNJdGVyYXRvciA9IGNvbmNyZXRlUGFyYW1ldGVycy52YWx1ZXMoKTtcbiAgICAgICAgbGV0IGdlbkNsYXNzVHlwZVBhcmFtZXRlcnNJdGVyYXRvciA9IGdlbmVyaWNQYXJhbWV0ZXJzLnZhbHVlcygpO1xuICAgICAgICBsZXQgZm14UGFyYW1ldGVyQ29uY3JldGlzYXRpb24gOiBGYW1peC5QYXJhbWV0ZXJDb25jcmV0aXNhdGlvbjtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdlbmVyaWNQYXJhbWV0ZXJzLnNpemU7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgY29uQ2xhc3NUeXBlUGFyYW1ldGVyID0gY29uQ2xhc3NUeXBlUGFyYW1ldGVyc0l0ZXJhdG9yLm5leHQoKS52YWx1ZTtcbiAgICAgICAgICAgIGNvbnN0IGdlbkNsYXNzVHlwZVBhcmFtZXRlciA9IGdlbkNsYXNzVHlwZVBhcmFtZXRlcnNJdGVyYXRvci5uZXh0KCkudmFsdWU7XG4gICAgICAgICAgICBsZXQgY3JlYXRlUGFyYW1ldGVyQ29uY3JldGlzYXRpb24gOiBib29sZWFuID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmKGNvbkNsYXNzVHlwZVBhcmFtZXRlciAmJiBnZW5DbGFzc1R5cGVQYXJhbWV0ZXIgJiYgY29uQ2xhc3NUeXBlUGFyYW1ldGVyLmdldE5hbWUoKSAhPSBnZW5DbGFzc1R5cGVQYXJhbWV0ZXIuZ2V0TmFtZSgpKXtcbiAgICAgICAgICAgICAgICBwYXJhbWV0ZXJDb25jcmV0aXNhdGlvbnMuZm9yRWFjaCgocGFyYW0gOiBGYW1peC5QYXJhbWV0ZXJDb25jcmV0aXNhdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29uQ2xhc3NUeXBlUGFyYW1ldGVyLmdldE5hbWUoKSA9PSBwYXJhbS5nZXRDb25jcmV0ZVBhcmFtZXRlcigpLmdldE5hbWUoKSAmJiBnZW5DbGFzc1R5cGVQYXJhbWV0ZXIuZ2V0TmFtZSgpID09IHBhcmFtLmdldEdlbmVyaWNQYXJhbWV0ZXIoKS5nZXROYW1lKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZVBhcmFtZXRlckNvbmNyZXRpc2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBmbXhQYXJhbWV0ZXJDb25jcmV0aXNhdGlvbiA9IHBhcmFtO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICBpZiAoY3JlYXRlUGFyYW1ldGVyQ29uY3JldGlzYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgZm14UGFyYW1ldGVyQ29uY3JldGlzYXRpb24gPSBuZXcgRmFtaXguUGFyYW1ldGVyQ29uY3JldGlzYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgZm14UGFyYW1ldGVyQ29uY3JldGlzYXRpb24uc2V0R2VuZXJpY1BhcmFtZXRlcihnZW5DbGFzc1R5cGVQYXJhbWV0ZXIpO1xuICAgICAgICAgICAgICAgICAgICBmbXhQYXJhbWV0ZXJDb25jcmV0aXNhdGlvbi5zZXRDb25jcmV0ZVBhcmFtZXRlcihjb25DbGFzc1R5cGVQYXJhbWV0ZXIpO1xuICAgICAgICAgICAgICAgICAgICBmbXhQYXJhbWV0ZXJDb25jcmV0aXNhdGlvbi5hZGRDb25jcmV0aXNhdGlvbihjb25jcmV0aXNhdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZm14RWxlbWVudE9iamVjdE1hcC5zZXQoZm14UGFyYW1ldGVyQ29uY3JldGlzYXRpb24sbnVsbCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZm14UGFyYW1ldGVyQ29uY3JldGlzYXRpb24uYWRkQ29uY3JldGlzYXRpb24oY29uY3JldGlzYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmZhbWl4UmVwLmFkZEVsZW1lbnQoZm14UGFyYW1ldGVyQ29uY3JldGlzYXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgXG4gICAgICAgIHJldHVybiBmbXhQYXJhbWV0ZXJDb25jcmV0aXNhdGlvbjtcblxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBGYW1peCBjb25jcmV0aXNhdGlvbiBiZXR3ZWVuIHR3byBjbGFzc2VzIG9yIHR3byBpbnRlcmZhY2VzXG4gICAgICogQHBhcmFtIGVsZW1lbnQgQSBjbGFzcyBvciBhbiBJbnRlcmZhY2VcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRmFtaXhDb25jcmV0aXNhdGlvbkNsYXNzT3JJbnRlcmZhY2VTcGVjaWFsaXNhdGlvbihlbGVtZW50OiBDbGFzc0RlY2xhcmF0aW9uIHwgSW50ZXJmYWNlRGVjbGFyYXRpb24pe1xuICAgICAgICBcbiAgICAgICAgY29uc3Qgc3VwZXJFbnRpdHkgPSBlbGVtZW50LmdldEV4dGVuZHMoKTtcbiAgICAgICAgbGV0IHN1cGVyRW50aXR5QXJyYXk7XG4gICAgICAgIGlmIChzdXBlckVudGl0eSl7XG4gICAgICAgICAgICBzdXBlckVudGl0eUFycmF5ID0gQXJyYXkuaXNBcnJheShzdXBlckVudGl0eSkgPyBzdXBlckVudGl0eSA6IFtzdXBlckVudGl0eV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN1cGVyRW50aXR5QXJyYXkgJiYgc3VwZXJFbnRpdHlBcnJheS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzdXBlckVudGl0eUFycmF5LmZvckVhY2goZW50aXR5ID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgZW50aXR5SXNHZW5lcmljO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN1cGVyRW50aXR5U3ltYm9sID0gZW50aXR5LmdldEV4cHJlc3Npb24oKS5nZXRTeW1ib2xPclRocm93KCk7XG4gICAgICAgICAgICAgICAgbGV0IHN1cGVyRW50aXR5RGVjbGFyYXRpb247XG4gICAgICAgICAgICAgICAgaWYgKHN1cGVyRW50aXR5IGluc3RhbmNlb2YgRXhwcmVzc2lvbldpdGhUeXBlQXJndW1lbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1cGVyRW50aXR5RGVjbGFyYXRpb24gPSBzdXBlckVudGl0eVN5bWJvbC5nZXREZWNsYXJhdGlvbnMoKVswXS5hc0tpbmQodHMuU3ludGF4S2luZC5DbGFzc0RlY2xhcmF0aW9uKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzdXBlckVudGl0eURlY2xhcmF0aW9uID0gc3VwZXJFbnRpdHlTeW1ib2wuZ2V0RGVjbGFyYXRpb25zKClbMF0uYXNLaW5kKHRzLlN5bnRheEtpbmQuSW50ZXJmYWNlRGVjbGFyYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc3VwZXJFbnRpdHlEZWNsYXJhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBlbnRpdHlJc0dlbmVyaWMgPSBzdXBlckVudGl0eURlY2xhcmF0aW9uLmdldFR5cGVQYXJhbWV0ZXJzKCkubGVuZ3RoID4gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGVudGl0eUlzR2VuZXJpYykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgRW50aXR5RGVjbGFyYXRpb247XG4gICAgICAgICAgICAgICAgICAgIGxldCBnZW5FbnRpdHk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdXBlckVudGl0eSBpbnN0YW5jZW9mIEV4cHJlc3Npb25XaXRoVHlwZUFyZ3VtZW50cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgRW50aXR5RGVjbGFyYXRpb24gPSBlbnRpdHkuZ2V0RXhwcmVzc2lvbigpLmdldFN5bWJvbCgpLmdldERlY2xhcmF0aW9ucygpWzBdIGFzIENsYXNzRGVjbGFyYXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICBnZW5FbnRpdHkgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhDbGFzcyhFbnRpdHlEZWNsYXJhdGlvbikgYXMgRmFtaXguUGFyYW1ldHJpY0NsYXNzO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgRW50aXR5RGVjbGFyYXRpb24gPSBlbnRpdHkuZ2V0RXhwcmVzc2lvbigpLmdldFN5bWJvbCgpLmdldERlY2xhcmF0aW9ucygpWzBdIGFzIEludGVyZmFjZURlY2xhcmF0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2VuRW50aXR5ID0gdGhpcy5jcmVhdGVPckdldEZhbWl4SW50ZXJmYWNlKEVudGl0eURlY2xhcmF0aW9uKSBhcyBGYW1peC5QYXJhbWV0cmljSW50ZXJmYWNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGdlblBhcmFtcyA9IEVudGl0eURlY2xhcmF0aW9uLmdldFR5cGVQYXJhbWV0ZXJzKCkubWFwKChwYXJhbSkgPT4gcGFyYW0uZ2V0VGV4dCgpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJncyA9IGVsZW1lbnQuZ2V0SGVyaXRhZ2VDbGF1c2VzKClbMF0uZ2V0VHlwZU5vZGVzKClbMF0uZ2V0VHlwZUFyZ3VtZW50cygpXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvblBhcmFtcyA9IGVsZW1lbnQuZ2V0SGVyaXRhZ2VDbGF1c2VzKClbMF0uZ2V0VHlwZU5vZGVzKClbMF0uZ2V0VHlwZUFyZ3VtZW50cygpLm1hcCgocGFyYW0pID0+IHBhcmFtLmdldFRleHQoKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghSGVscGVycy5hcnJheXNBcmVFcXVhbChjb25QYXJhbXMsZ2VuUGFyYW1zKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbkVudGl0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbkVudGl0eSA9IHRoaXMuY3JlYXRlT3JHZXRGYW1peENvbmNyZXRlRWxlbWVudChnZW5FbnRpdHksRW50aXR5RGVjbGFyYXRpb24sYXJncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25jcmV0aXNhdGlvbnMgPSB0aGlzLmZhbWl4UmVwLl9nZXRBbGxFbnRpdGllc1dpdGhUeXBlKFwiQ29uY3JldGlzYXRpb25cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgY3JlYXRlQ29uY3JldGlzYXRpb24gOiBib29sZWFuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmNyZXRpc2F0aW9ucy5mb3JFYWNoKChjb25jIDogRmFtaXguQ29uY3JldGlzYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2VuRW50aXR5LmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpID09IGNvbmMuZ2V0R2VuZXJpY0VudGl0eSgpLmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpICYmIGNvbmMuZ2V0Q29uY3JldGVFbnRpdHkoKS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKSA9PSBjb25FbnRpdHkuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCkpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVDb25jcmV0aXNhdGlvbiA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlQ29uY3JldGlzYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmbXhDb25jcmV0aXNhdGlvbiA6IEZhbWl4LkNvbmNyZXRpc2F0aW9uID0gdGhpcy5jcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uKGNvbkVudGl0eSxnZW5FbnRpdHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gICAgICAgICAgIFxuICAgIH0gICAgXG4gICAgXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgRmFtaXggY29uY3JldGlzYXRpb24gYmV0d2VlbiBhIGNsYXNzIGFuZCBpdHMgaW5zdGFuY2lhdGlvbnNcbiAgICAgKiBAcGFyYW0gY2xzIEEgY2xhc3NcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRmFtaXhDb25jcmV0aXNhdGlvbkdlbmVyaWNJbnN0YW50aWF0aW9uKGNsczogQ2xhc3NEZWNsYXJhdGlvbil7XG4gICAgICAgXG4gICAgICAgIGNvbnN0IGlzR2VuZXJpYyA9IGNscy5nZXRUeXBlUGFyYW1ldGVycygpLmxlbmd0aCA+IDA7XG4gICAgICAgIGlmIChpc0dlbmVyaWMpIHtcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbmNlcyA9IGNscy5nZXRTb3VyY2VGaWxlKCkuZ2V0RGVzY2VuZGFudHNPZktpbmQodHMuU3ludGF4S2luZC5OZXdFeHByZXNzaW9uKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIobmV3RXhwciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cHJlc3Npb24gPSBuZXdFeHByLmdldEV4cHJlc3Npb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cHJlc3Npb24uZ2V0VGV4dCgpID09PSBjbHMuZ2V0TmFtZSgpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGluc3RhbmNlcy5mb3JFYWNoKGluc3RhbmNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbnN0YW5jZUlzR2VuZXJpYyA9IGluc3RhbmNlLmdldFR5cGVBcmd1bWVudHMoKS5sZW5ndGggPiAwO1xuICAgICAgICAgICAgICAgIGlmIChpbnN0YW5jZUlzR2VuZXJpYykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25QYXJhbXMgPSBpbnN0YW5jZS5nZXRUeXBlQXJndW1lbnRzKCkubWFwKChwYXJhbSkgPT4gcGFyYW0uZ2V0VGV4dCgpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZ2VuRW50aXR5ID0gdGhpcy5jcmVhdGVPckdldEZhbWl4Q2xhc3MoY2xzKSBhcyBGYW1peC5QYXJhbWV0cmljQ2xhc3M7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGdlblBhcmFtcyA9IGNscy5nZXRUeXBlUGFyYW1ldGVycygpLm1hcCgocGFyYW0pID0+IHBhcmFtLmdldFRleHQoKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghSGVscGVycy5hcnJheXNBcmVFcXVhbChjb25QYXJhbXMsZ2VuUGFyYW1zKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbkVudGl0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbkVudGl0eSA9IHRoaXMuY3JlYXRlT3JHZXRGYW1peENvbmNyZXRlRWxlbWVudChnZW5FbnRpdHksY2xzLGluc3RhbmNlLmdldFR5cGVBcmd1bWVudHMoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25jcmV0aXNhdGlvbnMgPSB0aGlzLmZhbWl4UmVwLl9nZXRBbGxFbnRpdGllc1dpdGhUeXBlKFwiQ29uY3JldGlzYXRpb25cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgY3JlYXRlQ29uY3JldGlzYXRpb24gOiBib29sZWFuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmNyZXRpc2F0aW9ucy5mb3JFYWNoKChjb25jIDogRmFtaXguQ29uY3JldGlzYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2VuRW50aXR5LmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpID09IGNvbmMuZ2V0R2VuZXJpY0VudGl0eSgpLmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpICYmIGNvbmMuZ2V0Q29uY3JldGVFbnRpdHkoKS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKSA9PSBjb25FbnRpdHkuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCkpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVDb25jcmV0aXNhdGlvbiA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlQ29uY3JldGlzYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmbXhDb25jcmV0aXNhdGlvbiA6IEZhbWl4LkNvbmNyZXRpc2F0aW9uID0gdGhpcy5jcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uKGNvbkVudGl0eSxnZW5FbnRpdHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBGYW1peCBjb25jcmV0aXNhdGlvbiBiZXR3ZWVuIGEgY2xhc3MgYW5kIGl0cyBpbnN0YW5jaWF0aW9uc1xuICAgICAqIEBwYXJhbSBmdW5jIEEgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRmFtaXhDb25jcmV0aXNhdGlvbkZ1bmN0aW9uSW5zdGFudGlhdGlvbihlbGVtZW50OiBGdW5jdGlvbkRlY2xhcmF0aW9uIHwgTWV0aG9kRGVjbGFyYXRpb24pe1xuICAgICAgICBjb25zdCBpc0dlbmVyaWMgPSBlbGVtZW50LmdldFR5cGVQYXJhbWV0ZXJzKCkubGVuZ3RoID4gMDtcbiAgICAgICAgaWYgKGlzR2VuZXJpYykge1xuICAgICAgICAgICAgY29uc3QgZ2VuUGFyYW1zID0gZWxlbWVudC5nZXRUeXBlUGFyYW1ldGVycygpLm1hcChwYXJhbSA9PiBwYXJhbS5nZXRUZXh0KCkpO1xuICAgICAgICAgICAgY29uc3QgdXNlcyA9IGVsZW1lbnQuZmluZFJlZmVyZW5jZXNBc05vZGVzKCk7ICAgIFxuICAgICAgICAgICAgdXNlcy5mb3JFYWNoKHVzYWdlID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudE5vZGUgPSB1c2FnZTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChjdXJyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudE5vZGUuZ2V0S2luZCgpID09PSBTeW50YXhLaW5kLkNhbGxFeHByZXNzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYWxsRXhwcmVzc2lvbiA9IGN1cnJlbnROb2RlLmFzS2luZChTeW50YXhLaW5kLkNhbGxFeHByZXNzaW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGluc3RhbmNlSXNHZW5lcmljID0gY2FsbEV4cHJlc3Npb24uZ2V0VHlwZUFyZ3VtZW50cygpLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5zdGFuY2VJc0dlbmVyaWMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhcmdzID0gY2FsbEV4cHJlc3Npb24uZ2V0VHlwZUFyZ3VtZW50cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvblBhcmFtcyA9IGNhbGxFeHByZXNzaW9uLmdldFR5cGVBcmd1bWVudHMoKS5tYXAocGFyYW0gPT4gcGFyYW0uZ2V0VGV4dCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUhlbHBlcnMuYXJyYXlzQXJlRXF1YWwoY29uUGFyYW1zLGdlblBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGdlbkVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGVsZW1lbnQgaW5zdGFuY2VvZiBGdW5jdGlvbkRlY2xhcmF0aW9uKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbkVsZW1lbnQgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhGdW5jdGlvbihlbGVtZW50LDApIGFzIEZhbWl4LlBhcmFtZXRyaWNGdW5jdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbkVsZW1lbnQgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhNZXRob2QoZWxlbWVudCwwKSBhcyBGYW1peC5QYXJhbWV0cmljTWV0aG9kO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb25jRWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uY0VsZW1lbnQgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhDb25jcmV0ZUVsZW1lbnQoZ2VuRWxlbWVudCxlbGVtZW50LGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25jcmV0aXNhdGlvbnMgPSB0aGlzLmZhbWl4UmVwLl9nZXRBbGxFbnRpdGllc1dpdGhUeXBlKFwiQ29uY3JldGlzYXRpb25cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjcmVhdGVDb25jcmV0aXNhdGlvbiA6IGJvb2xlYW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25jcmV0aXNhdGlvbnMuZm9yRWFjaCgoY29uYyA6IEZhbWl4LkNvbmNyZXRpc2F0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2VuRWxlbWVudC5nZXRGdWxseVF1YWxpZmllZE5hbWUoKSA9PSBjb25jLmdldEdlbmVyaWNFbnRpdHkoKS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKSAmJiBjb25jLmdldENvbmNyZXRlRW50aXR5KCkuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCkgPT0gY29uY0VsZW1lbnQuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCkpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZUNvbmNyZXRpc2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZUNvbmNyZXRpc2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmbXhDb25jcmV0aXNhdGlvbiA6IEZhbWl4LkNvbmNyZXRpc2F0aW9uID0gdGhpcy5jcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uKGNvbmNFbGVtZW50LGdlbkVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gUmVtb250ZXIgw6AgbCfDqWzDqW1lbnQgcGFyZW50ICh1dGlsZSBzaSBsZSBuxZN1ZCBkZSByw6lmw6lyZW5jZSBlc3QgdW4gZW5mYW50KVxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Tm9kZSA9IGN1cnJlbnROb2RlLmdldFBhcmVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIEZhbWl4IGNvbmNyZXRpc2F0aW9uIGJldHdlZW4gYSBjbGFzcyBhbmQgYW4gaW50ZXJmYWNlXG4gICAgICogQHBhcmFtIGNscyBBIGNsYXNzXG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZUZhbWl4Q29uY3JldGlzYXRpb25JbnRlcmZhY2VDbGFzcyhjbHM6IENsYXNzRGVjbGFyYXRpb24pe1xuICAgIFxuICAgICAgICBjb25zdCBzdXBlckludGVyZmFjZXMgPSBjbHMuZ2V0SW1wbGVtZW50cygpO1xuICAgICAgICBzdXBlckludGVyZmFjZXMuZm9yRWFjaChpbnRlcmZhY2VUeXBlID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGludGVyZmFjZUlzR2VuZXJpYyA9IGludGVyZmFjZVR5cGUuZ2V0VHlwZUFyZ3VtZW50cygpLmxlbmd0aD4wO1xuICAgICAgICAgICAgaWYgKGludGVyZmFjZUlzR2VuZXJpYykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGludGVyZmFjZURlY2xhcmF0aW9uID0gaW50ZXJmYWNlVHlwZS5nZXRFeHByZXNzaW9uKCkuZ2V0U3ltYm9sKCkuZ2V0RGVjbGFyYXRpb25zKClbMF0gYXMgSW50ZXJmYWNlRGVjbGFyYXRpb247XG4gICAgICAgICAgICAgICAgY29uc3QgZ2VuUGFyYW1zID0gaW50ZXJmYWNlRGVjbGFyYXRpb24uZ2V0VHlwZVBhcmFtZXRlcnMoKS5tYXAoKHBhcmFtKSA9PiBwYXJhbS5nZXRUZXh0KCkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvblBhcmFtcyA9IGNscy5nZXRIZXJpdGFnZUNsYXVzZXMoKVswXS5nZXRUeXBlTm9kZXMoKVswXS5nZXRUeXBlQXJndW1lbnRzKCkubWFwKChwYXJhbSkgPT4gcGFyYW0uZ2V0VGV4dCgpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBhcmdzID0gY2xzLmdldEhlcml0YWdlQ2xhdXNlcygpWzBdLmdldFR5cGVOb2RlcygpWzBdLmdldFR5cGVBcmd1bWVudHMoKTtcbiAgICAgICAgICAgICAgICBpZiAoIUhlbHBlcnMuYXJyYXlzQXJlRXF1YWwoY29uUGFyYW1zLGdlblBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZ2VuSW50ZXJmYWNlID0gdGhpcy5jcmVhdGVPckdldEZhbWl4SW50ZXJmYWNlKGludGVyZmFjZURlY2xhcmF0aW9uKSBhcyBGYW1peC5QYXJhbWV0cmljSW50ZXJmYWNlO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25JbnRlcmZhY2UgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhDb25jcmV0ZUVsZW1lbnQoZ2VuSW50ZXJmYWNlLGludGVyZmFjZURlY2xhcmF0aW9uLGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25jcmV0aXNhdGlvbnMgPSB0aGlzLmZhbWl4UmVwLl9nZXRBbGxFbnRpdGllc1dpdGhUeXBlKFwiQ29uY3JldGlzYXRpb25cIik7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjcmVhdGVDb25jcmV0aXNhdGlvbiA6IGJvb2xlYW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBjb25jcmV0aXNhdGlvbnMuZm9yRWFjaCgoY29uYyA6IEZhbWl4LkNvbmNyZXRpc2F0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2VuSW50ZXJmYWNlLmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpID09IGNvbmMuZ2V0R2VuZXJpY0VudGl0eSgpLmdldEZ1bGx5UXVhbGlmaWVkTmFtZSgpICYmIGNvbmMuZ2V0Q29uY3JldGVFbnRpdHkoKS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKSA9PSBjb25JbnRlcmZhY2UuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCkpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZUNvbmNyZXRpc2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVDb25jcmV0aXNhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm14Q29uY3JldGlzYXRpb24gOiBGYW1peC5Db25jcmV0aXNhdGlvbiA9IHRoaXMuY3JlYXRlRmFtaXhDb25jcmV0aXNhdGlvbihjb25JbnRlcmZhY2UsZ2VuSW50ZXJmYWNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIEZhbWl4IGNvbmNyZXRpc2F0aW9uIGJldHdlZW4gYW4gaW50ZXJmYWNlIGFuZCBhIFR5cGVcbiAgICAgKiBAcGFyYW0gZWxlbWVudCBBIHZhcmlhYmxlIG9yIGEgZnVuY3Rpb25cbiAgICAgKiBAcGFyYW0gaW50ZXIgQW4gaW50ZXJmYWNlXG4gICAgICovXG4gICAgcHVibGljIGNyZWF0ZUZhbWl4Q29uY3JldGlzYXRpb25UeXBlSW5zdGFuY2lhdGlvbihlbGVtZW50OiBJbnRlcmZhY2VEZWNsYXJhdGlvbiB8IENsYXNzRGVjbGFyYXRpb24pe1xuXG4gICAgICAgIGNvbnN0IGlzR2VuZXJpYyA9IGVsZW1lbnQuZ2V0VHlwZVBhcmFtZXRlcnMoKS5sZW5ndGggPiAwO1xuICAgICAgICBpZiAoaXNHZW5lcmljKSB7XG4gICAgICAgICAgICBjb25zdCBnZW5QYXJhbXMgPSBlbGVtZW50LmdldFR5cGVQYXJhbWV0ZXJzKCkubWFwKHBhcmFtID0+IHBhcmFtLmdldFRleHQoKSk7XG4gICAgICAgICAgICBjb25zdCB1c2VzID0gZWxlbWVudC5maW5kUmVmZXJlbmNlc0FzTm9kZXMoKTtcbiAgICAgICAgICAgIHVzZXMuZm9yRWFjaCh1c2UgPT4geyAgICAgICAgXG4gICAgICAgICAgICAgICAgbGV0IHBhcmVudE5vZGUgPSB1c2UuZ2V0UGFyZW50KCk7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUuZ2V0S2luZCgpID09PSBTeW50YXhLaW5kLlR5cGVSZWZlcmVuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHR5cGVSZWZlcmVuY2VOb2RlID0gcGFyZW50Tm9kZS5hc0tpbmQoU3ludGF4S2luZC5UeXBlUmVmZXJlbmNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHR5cGVSZWZlcmVuY2VOb2RlSXNHZW5lcmljID0gdHlwZVJlZmVyZW5jZU5vZGUuZ2V0VHlwZUFyZ3VtZW50cygpLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZVJlZmVyZW5jZU5vZGVJc0dlbmVyaWMpIHt9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJncyA9IHR5cGVSZWZlcmVuY2VOb2RlLmdldFR5cGVBcmd1bWVudHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25QYXJhbXMgPSB0eXBlUmVmZXJlbmNlTm9kZS5nZXRUeXBlQXJndW1lbnRzKCkubWFwKHBhcmFtID0+IHBhcmFtLmdldFRleHQoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFIZWxwZXJzLmFycmF5c0FyZUVxdWFsKGNvblBhcmFtcyxnZW5QYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBnZW5FbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihlbGVtZW50IGluc3RhbmNlb2YgQ2xhc3NEZWNsYXJhdGlvbil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5FbGVtZW50ID0gdGhpcy5jcmVhdGVPckdldEZhbWl4Q2xhc3MoZWxlbWVudCkgYXMgRmFtaXguUGFyYW1ldHJpY0NsYXNzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuRWxlbWVudCA9IHRoaXMuY3JlYXRlT3JHZXRGYW1peEludGVyZmFjZShlbGVtZW50KSBhcyBGYW1peC5QYXJhbWV0cmljSW50ZXJmYWNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb25jRWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uY0VsZW1lbnQgPSB0aGlzLmNyZWF0ZU9yR2V0RmFtaXhDb25jcmV0ZUVsZW1lbnQoZ2VuRWxlbWVudCxlbGVtZW50LGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25jcmV0aXNhdGlvbnMgPSB0aGlzLmZhbWl4UmVwLl9nZXRBbGxFbnRpdGllc1dpdGhUeXBlKFwiQ29uY3JldGlzYXRpb25cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjcmVhdGVDb25jcmV0aXNhdGlvbiA6IGJvb2xlYW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25jcmV0aXNhdGlvbnMuZm9yRWFjaCgoY29uYyA6IEZhbWl4LkNvbmNyZXRpc2F0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2VuRWxlbWVudC5nZXRGdWxseVF1YWxpZmllZE5hbWUoKSA9PSBjb25jLmdldEdlbmVyaWNFbnRpdHkoKS5nZXRGdWxseVF1YWxpZmllZE5hbWUoKSAmJiBjb25jLmdldENvbmNyZXRlRW50aXR5KCkuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCkgPT0gY29uY0VsZW1lbnQuZ2V0RnVsbHlRdWFsaWZpZWROYW1lKCkpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZUNvbmNyZXRpc2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZUNvbmNyZXRpc2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmbXhDb25jcmV0aXNhdGlvbiA6IEZhbWl4LkNvbmNyZXRpc2F0aW9uID0gdGhpcy5jcmVhdGVGYW1peENvbmNyZXRpc2F0aW9uKGNvbmNFbGVtZW50LGdlbkVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZSA9IHBhcmVudE5vZGUuZ2V0UGFyZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgY29udmVydFRvUmVsYXRpdmVQYXRoKGFic29sdXRlUGF0aDogc3RyaW5nLCBhYnNvbHV0ZVBhdGhQcm9qZWN0OiBzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIGFic29sdXRlUGF0aC5yZXBsYWNlKGFic29sdXRlUGF0aFByb2plY3QsIFwiXCIpLnNsaWNlKDEpO1xuICAgIH1cbn1cbiJdfQ==