semantifold 0.1.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 (111) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +71 -0
  3. package/build/index.d.ts +54 -0
  4. package/build/index.d.ts.map +1 -0
  5. package/build/index.js +45 -0
  6. package/build/src/backends/identifiers.d.ts +19 -0
  7. package/build/src/backends/identifiers.d.ts.map +1 -0
  8. package/build/src/backends/identifiers.js +93 -0
  9. package/build/src/backends/index.d.ts +35 -0
  10. package/build/src/backends/index.d.ts.map +1 -0
  11. package/build/src/backends/index.js +149 -0
  12. package/build/src/backends/java.d.ts +8 -0
  13. package/build/src/backends/java.d.ts.map +1 -0
  14. package/build/src/backends/java.js +172 -0
  15. package/build/src/backends/javascript.d.ts +8 -0
  16. package/build/src/backends/javascript.d.ts.map +1 -0
  17. package/build/src/backends/javascript.js +173 -0
  18. package/build/src/backends/php.d.ts +8 -0
  19. package/build/src/backends/php.d.ts.map +1 -0
  20. package/build/src/backends/php.js +175 -0
  21. package/build/src/backends/ruby.d.ts +8 -0
  22. package/build/src/backends/ruby.d.ts.map +1 -0
  23. package/build/src/backends/ruby.js +155 -0
  24. package/build/src/backends/scalars.d.ts +15 -0
  25. package/build/src/backends/scalars.d.ts.map +1 -0
  26. package/build/src/backends/scalars.js +138 -0
  27. package/build/src/backends/shared.d.ts +26 -0
  28. package/build/src/backends/shared.d.ts.map +1 -0
  29. package/build/src/backends/shared.js +424 -0
  30. package/build/src/backends/typescript.d.ts +8 -0
  31. package/build/src/backends/typescript.d.ts.map +1 -0
  32. package/build/src/backends/typescript.js +160 -0
  33. package/build/src/backends/writer.d.ts +87 -0
  34. package/build/src/backends/writer.d.ts.map +1 -0
  35. package/build/src/backends/writer.js +207 -0
  36. package/build/src/diagnostic.d.ts +67 -0
  37. package/build/src/diagnostic.d.ts.map +1 -0
  38. package/build/src/diagnostic.js +96 -0
  39. package/build/src/frontends/index.d.ts +14 -0
  40. package/build/src/frontends/index.d.ts.map +1 -0
  41. package/build/src/frontends/index.js +36 -0
  42. package/build/src/frontends/java.d.ts +12 -0
  43. package/build/src/frontends/java.d.ts.map +1 -0
  44. package/build/src/frontends/java.js +630 -0
  45. package/build/src/frontends/javascript-typescript.d.ts +19 -0
  46. package/build/src/frontends/javascript-typescript.d.ts.map +1 -0
  47. package/build/src/frontends/javascript-typescript.js +633 -0
  48. package/build/src/frontends/php.d.ts +12 -0
  49. package/build/src/frontends/php.d.ts.map +1 -0
  50. package/build/src/frontends/php.js +523 -0
  51. package/build/src/frontends/ruby.d.ts +12 -0
  52. package/build/src/frontends/ruby.d.ts.map +1 -0
  53. package/build/src/frontends/ruby.js +515 -0
  54. package/build/src/frontends/scalars.d.ts +19 -0
  55. package/build/src/frontends/scalars.d.ts.map +1 -0
  56. package/build/src/frontends/scalars.js +71 -0
  57. package/build/src/mapping.d.ts +160 -0
  58. package/build/src/mapping.d.ts.map +1 -0
  59. package/build/src/mapping.js +1120 -0
  60. package/build/src/semantic/location.d.ts +61 -0
  61. package/build/src/semantic/location.d.ts.map +1 -0
  62. package/build/src/semantic/location.js +142 -0
  63. package/build/src/semantic/operators.d.ts +16 -0
  64. package/build/src/semantic/operators.d.ts.map +1 -0
  65. package/build/src/semantic/operators.js +24 -0
  66. package/build/src/semantic/provenance.d.ts +74 -0
  67. package/build/src/semantic/provenance.d.ts.map +1 -0
  68. package/build/src/semantic/provenance.js +577 -0
  69. package/build/src/semantic/scalars.d.ts +19 -0
  70. package/build/src/semantic/scalars.d.ts.map +1 -0
  71. package/build/src/semantic/scalars.js +40 -0
  72. package/build/src/semantic/types.d.ts +1003 -0
  73. package/build/src/semantic/types.d.ts.map +1 -0
  74. package/build/src/semantic/types.js +279 -0
  75. package/build/src/semantic/validate.d.ts +60 -0
  76. package/build/src/semantic/validate.d.ts.map +1 -0
  77. package/build/src/semantic/validate.js +472 -0
  78. package/docs/architecture.md +39 -0
  79. package/docs/coding-standards.md +7 -0
  80. package/docs/goals.md +7 -0
  81. package/docs/language-support.md +69 -0
  82. package/docs/plans/2026-09-02-initial-toolchain.md +54 -0
  83. package/docs/source-maps.md +134 -0
  84. package/docs/testing.md +25 -0
  85. package/index.js +63 -0
  86. package/package.json +69 -0
  87. package/src/backends/identifiers.js +101 -0
  88. package/src/backends/index.js +159 -0
  89. package/src/backends/java.js +182 -0
  90. package/src/backends/javascript.js +184 -0
  91. package/src/backends/php.js +184 -0
  92. package/src/backends/ruby.js +163 -0
  93. package/src/backends/scalars.js +120 -0
  94. package/src/backends/shared.js +456 -0
  95. package/src/backends/typescript.js +168 -0
  96. package/src/backends/writer.js +224 -0
  97. package/src/diagnostic.js +103 -0
  98. package/src/frontends/index.js +36 -0
  99. package/src/frontends/java.js +735 -0
  100. package/src/frontends/javascript-typescript.js +718 -0
  101. package/src/frontends/php.js +593 -0
  102. package/src/frontends/ruby.js +622 -0
  103. package/src/frontends/scalars.js +77 -0
  104. package/src/mapping.js +1260 -0
  105. package/src/semantic/location.js +154 -0
  106. package/src/semantic/operators.js +28 -0
  107. package/src/semantic/provenance.js +629 -0
  108. package/src/semantic/scalars.js +44 -0
  109. package/src/semantic/types.js +319 -0
  110. package/src/semantic/validate.js +529 -0
  111. package/tsconfig.json +16 -0
@@ -0,0 +1,630 @@
1
+ // @ts-check
2
+ import { parser } from "@lezer/java";
3
+ import { SemantifoldDiagnostic, missingType, unsupportedSyntax } from "../diagnostic.js";
4
+ import { locationFromOffsets, moduleLocation } from "../semantic/location.js";
5
+ import { withAdaptedOperation } from "../semantic/operators.js";
6
+ import { withParserRanges } from "../semantic/provenance.js";
7
+ import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
8
+ import { sourceScalarType } from "./scalars.js";
9
+ /** @type {Readonly<Record<string, string>>} */
10
+ const simpleStringEscapes = Object.freeze({
11
+ "\"": "\"",
12
+ "'": "'",
13
+ "\\": "\\",
14
+ b: "\b",
15
+ f: "\f",
16
+ n: "\n",
17
+ r: "\r",
18
+ s: " ",
19
+ t: "\t"
20
+ });
21
+ const javaBinaryOperations = new Map([
22
+ ["+", "Add"],
23
+ ["-", "Subtract"],
24
+ ["*", "Multiply"],
25
+ ["&&", "And"],
26
+ ["||", "Or"],
27
+ ["==", "JavaEqual"],
28
+ ["!=", "JavaNotEqual"],
29
+ ["<", "LessThan"],
30
+ ["<=", "LessThanOrEqual"],
31
+ [">", "GreaterThan"],
32
+ [">=", "GreaterThanOrEqual"]
33
+ ]);
34
+ /**
35
+ * Returns all direct child syntax nodes.
36
+ * @param {import("@lezer/common").SyntaxNode} node - Parent syntax node.
37
+ * @returns {import("@lezer/common").SyntaxNode[]} Child syntax nodes.
38
+ */
39
+ function directChildren(node) {
40
+ const children = [];
41
+ for (let child = node.firstChild; child; child = child.nextSibling)
42
+ children.push(child);
43
+ return children;
44
+ }
45
+ /**
46
+ * Returns structural direct children, excluding known grammar delimiters.
47
+ * @param {import("@lezer/common").SyntaxNode} node - Parent syntax node.
48
+ * @returns {import("@lezer/common").SyntaxNode[]} Named children.
49
+ */
50
+ function structuralChildren(node) {
51
+ return directChildren(node).filter((child) => !["{", "}", "(", ")", ",", ";", "."].includes(child.name));
52
+ }
53
+ /**
54
+ * Finds all descendant syntax nodes with a given name.
55
+ * @param {import("@lezer/common").SyntaxNode} node - Root syntax node.
56
+ * @param {string} name - Node name.
57
+ * @returns {import("@lezer/common").SyntaxNode[]} Matching descendants.
58
+ */
59
+ function descendants(node, name) {
60
+ const matches = [];
61
+ for (const child of directChildren(node)) {
62
+ if (child.name == name)
63
+ matches.push(child);
64
+ matches.push(...descendants(child, name));
65
+ }
66
+ return matches;
67
+ }
68
+ /**
69
+ * Requires one direct child node.
70
+ * @param {import("@lezer/common").SyntaxNode} node - Parent node.
71
+ * @param {string} name - Child name.
72
+ * @param {string} filename - Source filename.
73
+ * @param {string} source - Complete source.
74
+ * @returns {import("@lezer/common").SyntaxNode} Child node.
75
+ */
76
+ function requiredChild(node, name, filename, source) {
77
+ const child = node.getChild(name);
78
+ if (!child)
79
+ return unsupportedSyntax("java", `${node.name} without ${name}`, nodeLocation(node, filename, source));
80
+ return child;
81
+ }
82
+ /**
83
+ * Returns a normalized Lezer node location.
84
+ * @param {import("@lezer/common").SyntaxNode} node - Lezer node.
85
+ * @param {string} filename - Source filename.
86
+ * @param {string} source - Complete source.
87
+ * @returns {import("../semantic/types.js").SourceLocation} Source location.
88
+ */
89
+ function nodeLocation(node, filename, source) {
90
+ return locationFromOffsets(filename, source, node.from, node.to);
91
+ }
92
+ /**
93
+ * Returns source text belonging to a syntax node.
94
+ * @param {import("@lezer/common").SyntaxNode} node - Lezer node.
95
+ * @param {string} source - Complete source.
96
+ * @returns {string} Node text.
97
+ */
98
+ function nodeText(node, source) {
99
+ return source.slice(node.from, node.to);
100
+ }
101
+ /**
102
+ * Converts a supported Java expression node.
103
+ * @param {import("@lezer/common").SyntaxNode} node - Lezer expression.
104
+ * @param {string} filename - Source filename.
105
+ * @param {string} source - Complete source.
106
+ * @returns {import("../semantic/types.js").Expression} Semantic expression.
107
+ */
108
+ function convertExpression(node, filename, source) {
109
+ const location = nodeLocation(node, filename, source);
110
+ if (node.name == "ParenthesizedExpression") {
111
+ const children = structuralChildren(node);
112
+ if (children.length != 1) {
113
+ return unsupportedSyntax("java", "unsupported parenthesized expression", location);
114
+ }
115
+ return convertExpression(children[0], filename, source);
116
+ }
117
+ if (node.name == "Identifier") {
118
+ return withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location, name: nodeText(node, source) }, { name: location });
119
+ }
120
+ if (node.name == "IntegerLiteral") {
121
+ const value = Number(nodeText(node, source));
122
+ if (!Number.isSafeInteger(value))
123
+ return unsupportedSyntax("java", "non-safe integer literal", location);
124
+ return withParserRanges({ kind: /** @type {const} */ ("IntegerLiteral"), location, value }, { literal: location });
125
+ }
126
+ if (node.name == "BooleanLiteral") {
127
+ return withParserRanges({ kind: /** @type {const} */ ("BooleanLiteral"), location, value: nodeText(node, source) == "true" }, { literal: location });
128
+ }
129
+ if (node.name == "StringLiteral") {
130
+ return withParserRanges({ kind: /** @type {const} */ ("StringLiteral"), location, value: decodeStringLiteral(node, filename, source) }, { literal: location });
131
+ }
132
+ if (node.name == "UnaryExpression") {
133
+ const children = structuralChildren(node);
134
+ const operatorNode = node.getChild("LogicOp") ?? node.getChild("ArithOp");
135
+ const operand = children.find((child) => child.name != "LogicOp" && child.name != "ArithOp");
136
+ const operator = operatorNode ? nodeText(operatorNode, source) : undefined;
137
+ if (!operatorNode || !operand || children.length != 2 || (operator != "!" && operator != "-")) {
138
+ return unsupportedSyntax("java", "unary expression", location);
139
+ }
140
+ if (operator == "!" && operand.name == "MethodInvocation" && isEqualsInvocation(operand, source)) {
141
+ return convertStringEquality(operand, true, location, nodeLocation(operatorNode, filename, source), filename, source);
142
+ }
143
+ const semantic = withAdaptedOperation(withParserRanges({
144
+ kind: "UnaryExpression",
145
+ location,
146
+ operand: convertExpression(operand, filename, source)
147
+ }, { operator: nodeLocation(operatorNode, filename, source) }), operator == "!" ? "Not" : "Negate");
148
+ return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
149
+ }
150
+ if (node.name == "BinaryExpression") {
151
+ const named = structuralChildren(node);
152
+ const operatorNode = node.getChild("CompareOp") ?? node.getChild("ArithOp") ?? node.getChild("LogicOp") ?? node.getChild("BitOp");
153
+ if (!operatorNode || named.length != 3)
154
+ return unsupportedSyntax("java", "binary expression", location);
155
+ const operands = [named[0], named[2]];
156
+ const unsupportedOperand = operands.find((operand) => !isSupportedExpressionNode(operand));
157
+ if (unsupportedOperand)
158
+ return unsupportedSyntax("java", unsupportedOperand.name, nodeLocation(unsupportedOperand, filename, source));
159
+ const operator = nodeText(operatorNode, source);
160
+ if (!javaBinaryOperations.has(operator))
161
+ return unsupportedSyntax("java", `binary ${operator}`, location);
162
+ const semantic = withAdaptedOperation(withParserRanges({
163
+ kind: "BinaryExpression",
164
+ left: convertExpression(operands[0], filename, source),
165
+ location,
166
+ right: convertExpression(operands[1], filename, source)
167
+ }, { operator: nodeLocation(operatorNode, filename, source) }), /** @type {import("../semantic/operators.js").AdaptedOperation} */ (javaBinaryOperations.get(operator)));
168
+ return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
169
+ }
170
+ if (node.name == "MethodInvocation") {
171
+ if (isEqualsInvocation(node, source)) {
172
+ const methodName = requiredChild(node, "MethodName", filename, source);
173
+ return convertStringEquality(node, false, location, nodeLocation(methodName, filename, source), filename, source);
174
+ }
175
+ const unsupportedReceiver = structuralChildren(node).find((child) => child.name != "MethodName" && child.name != "ArgumentList");
176
+ if (unsupportedReceiver)
177
+ return unsupportedSyntax("java", "method invocation receiver", nodeLocation(unsupportedReceiver, filename, source));
178
+ const methodName = requiredChild(node, "MethodName", filename, source);
179
+ const argumentList = requiredChild(node, "ArgumentList", filename, source);
180
+ const argumentNodes = structuralChildren(argumentList);
181
+ const unsupportedArgument = argumentNodes.find((child) => !isSupportedExpressionNode(child));
182
+ if (unsupportedArgument)
183
+ return unsupportedSyntax("java", `method argument ${unsupportedArgument.name}`, nodeLocation(unsupportedArgument, filename, source));
184
+ const arguments_ = argumentNodes.map((child) => convertExpression(child, filename, source));
185
+ return withParserRanges({ arguments: arguments_, callee: nodeText(methodName, source), kind: /** @type {const} */ ("CallExpression"), location }, {
186
+ callee: nodeLocation(methodName, filename, source)
187
+ });
188
+ }
189
+ return unsupportedSyntax("java", node.name, location);
190
+ }
191
+ /**
192
+ * Checks the one parser-native Java string equality invocation form.
193
+ * @param {import("@lezer/common").SyntaxNode} node - Method invocation node.
194
+ * @param {string} source - Complete source.
195
+ * @returns {boolean} Whether the invocation spells `.equals` with a receiver.
196
+ */
197
+ function isEqualsInvocation(node, source) {
198
+ const methodName = node.getChild("MethodName");
199
+ const receivers = structuralChildren(node).filter((child) => child.name != "MethodName" && child.name != "ArgumentList");
200
+ return methodName != null && nodeText(methodName, source) == "equals" && receivers.length == 1;
201
+ }
202
+ /**
203
+ * Converts Java `.equals` or its directly negated form without source-text inference.
204
+ * @param {import("@lezer/common").SyntaxNode} node - Parser method invocation.
205
+ * @param {boolean} negated - Whether a parser-owned unary not wraps the invocation.
206
+ * @param {import("../semantic/types.js").SourceLocation} location - Whole equality expression location.
207
+ * @param {import("../semantic/types.js").SourceLocation} operatorLocation - Parser-owned operator/method location.
208
+ * @param {string} filename - Source filename.
209
+ * @param {string} source - Complete source.
210
+ * @returns {import("../semantic/types.js").Expression} Adapted equality expression.
211
+ */
212
+ function convertStringEquality(node, negated, location, operatorLocation, filename, source) {
213
+ const argumentList = requiredChild(node, "ArgumentList", filename, source);
214
+ const arguments_ = structuralChildren(argumentList);
215
+ const receivers = structuralChildren(node).filter((child) => child.name != "MethodName" && child.name != "ArgumentList");
216
+ const unsupportedArgument = arguments_.find((child) => !isSupportedExpressionNode(child));
217
+ if (receivers.length != 1 || arguments_.length != 1 || unsupportedArgument) {
218
+ return unsupportedSyntax("java", "string equals invocation", nodeLocation(node, filename, source));
219
+ }
220
+ /** @type {Record<string, import("../semantic/types.js").SourceLocation>} */
221
+ const ranges = { operator: operatorLocation };
222
+ if (negated) {
223
+ ranges.equalityOperator = nodeLocation(requiredChild(node, "MethodName", filename, source), filename, source);
224
+ }
225
+ const semantic = withAdaptedOperation(withParserRanges({
226
+ kind: "BinaryExpression",
227
+ left: convertExpression(receivers[0], filename, source),
228
+ location,
229
+ right: convertExpression(arguments_[0], filename, source)
230
+ }, ranges), negated ? "StringNotEqual" : "StringEqual");
231
+ return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
232
+ }
233
+ /**
234
+ * Checks whether a Lezer node is in the expression subset.
235
+ * @param {import("@lezer/common").SyntaxNode} node - Java syntax node.
236
+ * @returns {boolean} Whether the node is supported.
237
+ */
238
+ function isSupportedExpressionNode(node) {
239
+ return [
240
+ "Identifier",
241
+ "IntegerLiteral",
242
+ "BooleanLiteral",
243
+ "StringLiteral",
244
+ "UnaryExpression",
245
+ "BinaryExpression",
246
+ "MethodInvocation",
247
+ "ParenthesizedExpression"
248
+ ].includes(node.name);
249
+ }
250
+ /**
251
+ * Applies Java Unicode translation before token-level string escape decoding.
252
+ * @param {string} literal - Parser-confirmed Java string literal.
253
+ * @param {import("../semantic/types.js").SourceLocation} location - Literal source location.
254
+ * @returns {string} Unicode-translated literal.
255
+ */
256
+ function translateUnicodeEscapes(literal, location) {
257
+ let translated = "";
258
+ let consecutiveBackslashes = 0;
259
+ let previousWasUnicodeEscape = false;
260
+ for (let index = 0; index < literal.length; index++) {
261
+ const character = literal[index];
262
+ const eligible = character == "\\" && (previousWasUnicodeEscape || consecutiveBackslashes % 2 == 0);
263
+ if (eligible && literal[index + 1] == "u") {
264
+ let digitsStart = index + 2;
265
+ while (literal[digitsStart] == "u")
266
+ digitsStart++;
267
+ const hexadecimal = literal.slice(digitsStart, digitsStart + 4);
268
+ const isHexadecimal = hexadecimal.length == 4 && [...hexadecimal].every((digit) => (digit >= "0" && digit <= "9") || (digit >= "A" && digit <= "F") || (digit >= "a" && digit <= "f"));
269
+ if (!isHexadecimal)
270
+ return unsupportedSyntax("java", "unsupported string escape", location);
271
+ const translatedCharacter = String.fromCharCode(Number.parseInt(hexadecimal, 16));
272
+ translated += translatedCharacter;
273
+ consecutiveBackslashes = translatedCharacter == "\\" ? consecutiveBackslashes + 1 : 0;
274
+ previousWasUnicodeEscape = true;
275
+ index = digitsStart + 3;
276
+ continue;
277
+ }
278
+ translated += character;
279
+ consecutiveBackslashes = character == "\\" ? consecutiveBackslashes + 1 : 0;
280
+ previousWasUnicodeEscape = false;
281
+ }
282
+ return translated;
283
+ }
284
+ /**
285
+ * Decodes the accepted escapes from one parser-confirmed Java string literal.
286
+ * @param {import("@lezer/common").SyntaxNode} node - Java StringLiteral node.
287
+ * @param {string} filename - Source filename.
288
+ * @param {string} source - Complete source.
289
+ * @returns {string} Decoded Unicode string.
290
+ */
291
+ function decodeStringLiteral(node, filename, source) {
292
+ const location = nodeLocation(node, filename, source);
293
+ const literal = translateUnicodeEscapes(nodeText(node, source), location);
294
+ let value = "";
295
+ for (let index = 1; index < literal.length - 1; index++) {
296
+ const character = literal[index];
297
+ if (character == "\"" || character == "\n" || character == "\r") {
298
+ return unsupportedSyntax("java", "invalid string literal", location);
299
+ }
300
+ if (character != "\\") {
301
+ value += character;
302
+ continue;
303
+ }
304
+ if (index + 1 >= literal.length - 1)
305
+ return unsupportedSyntax("java", "invalid string literal", location);
306
+ const escaped = literal[++index];
307
+ const simple = simpleStringEscapes[escaped];
308
+ if (simple !== undefined) {
309
+ value += simple;
310
+ continue;
311
+ }
312
+ if (escaped >= "0" && escaped <= "7") {
313
+ let octal = escaped;
314
+ const maximumLength = escaped <= "3" ? 3 : 2;
315
+ while (octal.length < maximumLength && literal[index + 1] >= "0" && literal[index + 1] <= "7") {
316
+ octal += literal[++index];
317
+ }
318
+ value += String.fromCharCode(Number.parseInt(octal, 8));
319
+ continue;
320
+ }
321
+ return unsupportedSyntax("java", "unsupported string escape", location);
322
+ }
323
+ if (!hasOnlyUnicodeScalars(value))
324
+ return unsupportedSyntax("java", "invalid Unicode string literal", location);
325
+ return value;
326
+ }
327
+ /**
328
+ * Converts one explicit Java return statement.
329
+ * @param {import("@lezer/common").SyntaxNode} statement - Java statement.
330
+ * @param {string} filename - Source filename.
331
+ * @param {string} source - Complete source.
332
+ * @returns {import("../semantic/types.js").ReturnStatement} Semantic return.
333
+ */
334
+ function convertReturn(statement, filename, source) {
335
+ const location = nodeLocation(statement, filename, source);
336
+ if (statement.name != "ReturnStatement")
337
+ return unsupportedSyntax("java", statement.name, location);
338
+ const expressionNodes = directChildren(statement).filter((child) => child.name != "return" && child.name != ";");
339
+ const expression = expressionNodes.length == 1 ? expressionNodes[0] : undefined;
340
+ if (!expression) {
341
+ const unsupported = expressionNodes[0];
342
+ return unsupportedSyntax("java", unsupported?.name ?? "empty return", unsupported ? nodeLocation(unsupported, filename, source) : location);
343
+ }
344
+ return { expression: convertExpression(expression, filename, source), kind: "ReturnStatement", location };
345
+ }
346
+ /**
347
+ * Converts one Java local declaration or assignment.
348
+ * @param {import("@lezer/common").SyntaxNode} statement - Java statement.
349
+ * @param {string} filename - Source filename.
350
+ * @param {string} source - Complete source.
351
+ * @returns {import("../semantic/types.js").LocalStatement} Semantic local statement.
352
+ */
353
+ function convertLocalStatement(statement, filename, source) {
354
+ const location = nodeLocation(statement, filename, source);
355
+ if (statement.name == "LocalVariableDeclaration") {
356
+ const declarators = statement.getChildren("VariableDeclarator");
357
+ const typeNode = declarationType(statement);
358
+ const varNode = statement.getChild("var");
359
+ const modifiers = statement.getChild("Modifiers");
360
+ const modifierChildren = modifiers ? structuralChildren(modifiers) : [];
361
+ if (varNode)
362
+ return unsupportedSyntax("java", "var local declaration", nodeLocation(varNode, filename, source));
363
+ if (declarators.length != 1)
364
+ return unsupportedSyntax("java", "multiple local declarators", location);
365
+ if (!typeNode || typeNode.name == "ArrayType")
366
+ return unsupportedSyntax("java", "unsupported local type", location);
367
+ if (modifierChildren.some((child) => child.name != "final") || modifierChildren.length > 1) {
368
+ return unsupportedSyntax("java", "unsupported local modifiers", modifiers ? nodeLocation(modifiers, filename, source) : location);
369
+ }
370
+ const declarator = declarators[0];
371
+ const definition = requiredChild(declarator, "Definition", filename, source);
372
+ const assignment = declarator.getChild("AssignOp");
373
+ const dimensions = declarator.getChildren("Dimension");
374
+ const initializerNodes = directChildren(declarator).filter((child) => child.name != "Definition" && child.name != "AssignOp");
375
+ if (dimensions.length > 0)
376
+ return unsupportedSyntax("java", "array local declaration", nodeLocation(declarator, filename, source));
377
+ if (!assignment || nodeText(assignment, source) != "=" || initializerNodes.length != 1) {
378
+ return unsupportedSyntax("java", "uninitialized local declaration", nodeLocation(declarator, filename, source));
379
+ }
380
+ const name = nodeText(definition, source);
381
+ return withParserRanges({
382
+ initializer: convertExpression(initializerNodes[0], filename, source),
383
+ kind: "LocalDeclaration",
384
+ location,
385
+ mutable: modifierChildren.length == 0,
386
+ name,
387
+ type: convertType(typeNode, `Local '${name}'`, location, filename, source)
388
+ }, { name: nodeLocation(definition, filename, source), operator: nodeLocation(assignment, filename, source) });
389
+ }
390
+ if (statement.name == "ExpressionStatement") {
391
+ const assignment = statement.getChild("AssignmentExpression");
392
+ if (!assignment)
393
+ return unsupportedSyntax("java", statement.name, location);
394
+ const children = structuralChildren(assignment);
395
+ const operator = assignment.getChild("AssignOp");
396
+ const target = children[0];
397
+ const expression = children.at(-1);
398
+ if (!operator || nodeText(operator, source) != "=")
399
+ return unsupportedSyntax("java", "compound assignment", nodeLocation(assignment, filename, source));
400
+ if (!target || target.name != "Identifier")
401
+ return unsupportedSyntax("java", target?.name ?? "assignment target", target ? nodeLocation(target, filename, source) : location);
402
+ if (!expression || expression == target || expression == operator)
403
+ return unsupportedSyntax("java", "assignment expression", nodeLocation(assignment, filename, source));
404
+ const targetExpression = withParserRanges({
405
+ kind: /** @type {const} */ ("IdentifierExpression"),
406
+ location: nodeLocation(target, filename, source),
407
+ name: nodeText(target, source)
408
+ }, { name: nodeLocation(target, filename, source) });
409
+ return withParserRanges({
410
+ expression: convertExpression(expression, filename, source),
411
+ kind: "AssignmentStatement",
412
+ location,
413
+ target: targetExpression
414
+ }, { operator: nodeLocation(operator, filename, source) });
415
+ }
416
+ return unsupportedSyntax("java", statement.name, location);
417
+ }
418
+ /**
419
+ * Converts one exhaustive direct Java block child.
420
+ * @param {import("@lezer/common").SyntaxNode} statement - Java statement.
421
+ * @param {string} filename - Source filename.
422
+ * @param {string} source - Complete source.
423
+ * @returns {import("../semantic/types.js").Statement} Semantic statement.
424
+ */
425
+ function convertStatement(statement, filename, source) {
426
+ if (statement.name == "ReturnStatement")
427
+ return convertReturn(statement, filename, source);
428
+ if (statement.name == "IfStatement")
429
+ return convertIf(statement, filename, source);
430
+ if (statement.name == "LocalVariableDeclaration")
431
+ return convertLocalStatement(statement, filename, source);
432
+ if (statement.name == "ExpressionStatement") {
433
+ if (statement.getChild("AssignmentExpression"))
434
+ return convertLocalStatement(statement, filename, source);
435
+ if (!statement.getChild("MethodInvocation")) {
436
+ return unsupportedSyntax("java", statement.name, nodeLocation(statement, filename, source));
437
+ }
438
+ return convertPrint(statement, filename, source);
439
+ }
440
+ return unsupportedSyntax("java", statement.name, nodeLocation(statement, filename, source));
441
+ }
442
+ /**
443
+ * Converts direct structural children of one Java block in source order.
444
+ * @param {import("@lezer/common").SyntaxNode} node - Java Block node.
445
+ * @param {string} filename - Source filename.
446
+ * @param {string} source - Complete source.
447
+ * @returns {import("../semantic/types.js").Block} Semantic block.
448
+ */
449
+ function convertBlock(node, filename, source) {
450
+ if (node.name != "Block")
451
+ return unsupportedSyntax("java", `expected block, received ${node.name}`, nodeLocation(node, filename, source));
452
+ return {
453
+ kind: "Block",
454
+ location: nodeLocation(node, filename, source),
455
+ statements: structuralChildren(node).map((statement) => convertStatement(statement, filename, source))
456
+ };
457
+ }
458
+ /**
459
+ * Requires an exact Java scalar type node.
460
+ * @param {import("@lezer/common").SyntaxNode | null} sourceType - Java type node.
461
+ * @param {string} subject - Typed subject.
462
+ * @param {import("../semantic/types.js").SourceLocation} location - Source location.
463
+ * @param {string} filename - Source filename.
464
+ * @param {string} source - Complete source.
465
+ * @returns {import("../semantic/types.js").TypeReference} Semantic type.
466
+ */
467
+ function convertType(sourceType, subject, location, filename, source) {
468
+ if (!sourceType)
469
+ return missingType("java", subject, location);
470
+ if (!["PrimitiveType", "TypeName", "ScopedTypeName"].includes(sourceType.name)) {
471
+ return unsupportedSyntax("java", "unsupported scalar type", location);
472
+ }
473
+ const type = sourceScalarType("java", nodeText(sourceType, source), nodeLocation(sourceType, filename, source));
474
+ if (!type)
475
+ return unsupportedSyntax("java", "unsupported scalar type", nodeLocation(sourceType, location.filename, source));
476
+ return type;
477
+ }
478
+ /**
479
+ * Returns the direct Java declaration type node supported by scalar conversion.
480
+ * @param {import("@lezer/common").SyntaxNode} node - Declaration node.
481
+ * @returns {import("@lezer/common").SyntaxNode | null} Type syntax node.
482
+ */
483
+ function declarationType(node) {
484
+ return node.getChild("PrimitiveType") ?? node.getChild("TypeName") ?? node.getChild("ScopedTypeName");
485
+ }
486
+ /**
487
+ * Converts the supported Java function method.
488
+ * @param {import("@lezer/common").SyntaxNode} node - Method declaration.
489
+ * @param {string} filename - Source filename.
490
+ * @param {string} source - Complete source.
491
+ * @returns {import("../semantic/types.js").FunctionDeclaration} Semantic function.
492
+ */
493
+ function convertFunction(node, filename, source) {
494
+ const location = nodeLocation(node, filename, source);
495
+ const definition = requiredChild(node, "Definition", filename, source);
496
+ const name = nodeText(definition, source);
497
+ const parametersNode = requiredChild(node, "FormalParameters", filename, source);
498
+ const parameters = parametersNode.getChildren("FormalParameter").map((parameter) => {
499
+ const parameterLocation = nodeLocation(parameter, filename, source);
500
+ const parameterNameNode = requiredChild(parameter, "Definition", filename, source);
501
+ const parameterName = nodeText(parameterNameNode, source);
502
+ const semanticParameter = {
503
+ kind: /** @type {const} */ ("Parameter"),
504
+ location: parameterLocation,
505
+ name: parameterName,
506
+ type: convertType(declarationType(parameter), `Parameter '${parameterName}'`, parameterLocation, filename, source)
507
+ };
508
+ return withParserRanges(semanticParameter, { name: nodeLocation(parameterNameNode, filename, source) });
509
+ });
510
+ const block = requiredChild(node, "Block", filename, source);
511
+ const body = convertBlock(block, filename, source);
512
+ return withParserRanges({
513
+ body,
514
+ kind: "FunctionDeclaration",
515
+ location,
516
+ name,
517
+ parameters,
518
+ returnType: convertType(declarationType(node), `Function '${name}' return`, location, filename, source)
519
+ }, { name: nodeLocation(definition, filename, source) });
520
+ }
521
+ /**
522
+ * Converts the existing exact Java if/else terminal with restricted branch prefixes.
523
+ * @param {import("@lezer/common").SyntaxNode} node - Java if statement.
524
+ * @param {string} filename - Source filename.
525
+ * @param {string} source - Complete source.
526
+ * @returns {import("../semantic/types.js").IfStatement} Semantic branch.
527
+ */
528
+ function convertIf(node, filename, source) {
529
+ const location = nodeLocation(node, filename, source);
530
+ const conditionContainer = requiredChild(node, "ParenthesizedExpression", filename, source);
531
+ const conditionNodes = structuralChildren(conditionContainer);
532
+ const condition = conditionNodes.length == 1 ? conditionNodes[0] : undefined;
533
+ const direct = directChildren(node);
534
+ const conditionIndex = direct.findIndex((child) => child.name == conditionContainer.name &&
535
+ child.from == conditionContainer.from && child.to == conditionContainer.to);
536
+ const consequentNode = direct[conditionIndex + 1];
537
+ const alternateNode = direct.at(-1) == consequentNode ? undefined : direct.at(-1);
538
+ if (!condition || !consequentNode || consequentNode.name != "Block") {
539
+ return unsupportedSyntax("java", "if without block consequent", location);
540
+ }
541
+ let alternate;
542
+ if (alternateNode?.name == "Block")
543
+ alternate = convertBlock(alternateNode, filename, source);
544
+ else if (alternateNode?.name == "IfStatement") {
545
+ alternate = {
546
+ kind: /** @type {const} */ ("Block"),
547
+ location: nodeLocation(alternateNode, filename, source),
548
+ statements: [convertIf(alternateNode, filename, source)]
549
+ };
550
+ }
551
+ else if (alternateNode && alternateNode.name != "else") {
552
+ return unsupportedSyntax("java", `if alternate ${alternateNode.name}`, nodeLocation(alternateNode, filename, source));
553
+ }
554
+ return {
555
+ ...(alternate ? { alternate } : {}),
556
+ condition: convertExpression(condition, filename, source),
557
+ consequent: convertBlock(consequentNode, filename, source),
558
+ kind: "IfStatement",
559
+ location
560
+ };
561
+ }
562
+ /**
563
+ * Converts Java's supported main method.
564
+ * @param {import("@lezer/common").SyntaxNode} node - Main method.
565
+ * @param {string} filename - Source filename.
566
+ * @param {string} source - Complete source.
567
+ * @returns {import("../semantic/types.js").EntryPoint} Semantic entry point.
568
+ */
569
+ function convertEntryPoint(node, filename, source) {
570
+ const location = nodeLocation(node, filename, source);
571
+ const block = requiredChild(node, "Block", filename, source);
572
+ const body = convertBlock(block, filename, source);
573
+ return { body, kind: "EntryPoint", location };
574
+ }
575
+ /**
576
+ * Converts one supported Java print statement.
577
+ * @param {import("@lezer/common").SyntaxNode} statement - Expression statement.
578
+ * @param {string} filename - Source filename.
579
+ * @param {string} source - Complete source.
580
+ * @returns {import("../semantic/types.js").PrintStatement} Semantic print.
581
+ */
582
+ function convertPrint(statement, filename, source) {
583
+ const location = nodeLocation(statement, filename, source);
584
+ const printInvocation = statement.getChild("MethodInvocation");
585
+ if (!printInvocation)
586
+ return unsupportedSyntax("java", "main without System.out.println", location);
587
+ const fieldAccess = printInvocation.getChild("FieldAccess");
588
+ const methodName = printInvocation.getChild("MethodName");
589
+ if (!fieldAccess || !methodName || nodeText(fieldAccess, source) != "System.out" || nodeText(methodName, source) != "println") {
590
+ return unsupportedSyntax("java", "main without System.out.println", nodeLocation(printInvocation, filename, source));
591
+ }
592
+ const argumentList = requiredChild(printInvocation, "ArgumentList", filename, source);
593
+ const arguments_ = structuralChildren(argumentList);
594
+ if (arguments_.length != 1) {
595
+ return unsupportedSyntax("java", "println without one supported argument", nodeLocation(argumentList, filename, source));
596
+ }
597
+ const printLocation = nodeLocation(printInvocation, filename, source);
598
+ return { expression: convertExpression(arguments_[0], filename, source), kind: "PrintStatement", location: printLocation };
599
+ }
600
+ /**
601
+ * Parses Java into the shared semantic module.
602
+ * @param {object} input - Parser input.
603
+ * @param {string} input.filename - Source filename.
604
+ * @param {string} input.source - Source text.
605
+ * @returns {import("../semantic/types.js").SemanticModule} Semantic module.
606
+ */
607
+ export function parseJava({ filename, source }) {
608
+ const tree = parser.parse(source);
609
+ const error = descendants(tree.topNode, "⚠")[0];
610
+ if (error) {
611
+ throw new SemantifoldDiagnostic({
612
+ code: "PARSE_ERROR",
613
+ language: "java",
614
+ location: nodeLocation(error, filename, source),
615
+ message: "Java parser reported invalid syntax."
616
+ });
617
+ }
618
+ const methods = descendants(tree.topNode, "MethodDeclaration");
619
+ const mainMethod = methods.find((method) => nodeText(requiredChild(method, "Definition", filename, source), source) == "main");
620
+ const functionMethods = methods.filter((method) => method != mainMethod);
621
+ const location = moduleLocation(filename, source);
622
+ if (functionMethods.length == 0)
623
+ return unsupportedSyntax("java", "class without a semantic function", location);
624
+ if (!mainMethod)
625
+ return unsupportedSyntax("java", "class without main", location);
626
+ const functions = functionMethods.map((method) => convertFunction(method, filename, source));
627
+ const entryPoint = convertEntryPoint(mainMethod, filename, source);
628
+ return { entryPoint, functions, kind: "Module", location };
629
+ }
630
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamF2YS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mcm9udGVuZHMvamF2YS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLGFBQWEsQ0FBQTtBQUNsQyxPQUFPLEVBQUMscUJBQXFCLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDdEYsT0FBTyxFQUFDLG1CQUFtQixFQUFFLGNBQWMsRUFBQyxNQUFNLHlCQUF5QixDQUFBO0FBQzNFLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLDBCQUEwQixDQUFBO0FBQzdELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLDJCQUEyQixDQUFBO0FBQzFELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHdCQUF3QixDQUFBO0FBQzVELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLGNBQWMsQ0FBQTtBQUU3QywrQ0FBK0M7QUFDL0MsTUFBTSxtQkFBbUIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ3hDLElBQUksRUFBRSxJQUFJO0lBQ1YsR0FBRyxFQUFFLEdBQUc7SUFDUixJQUFJLEVBQUUsSUFBSTtJQUNWLENBQUMsRUFBRSxJQUFJO0lBQ1AsQ0FBQyxFQUFFLElBQUk7SUFDUCxDQUFDLEVBQUUsSUFBSTtJQUNQLENBQUMsRUFBRSxJQUFJO0lBQ1AsQ0FBQyxFQUFFLEdBQUc7SUFDTixDQUFDLEVBQUUsSUFBSTtDQUNSLENBQUMsQ0FBQTtBQUNGLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDbkMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDO0lBQ1osQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDO0lBQ2pCLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQztJQUNqQixDQUFDLElBQUksRUFBRSxLQUFLLENBQUM7SUFDYixDQUFDLElBQUksRUFBRSxJQUFJ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LFNBQVMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxDQUFBO0FBQzFELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtwYXJzZXJ9IGZyb20gXCJAbGV6ZXIvamF2YVwiXG5pbXBvcnQge1NlbWFudGlmb2xkRGlhZ25vc3RpYywgbWlzc2luZ1R5cGUsIHVuc3VwcG9ydGVkU3ludGF4fSBmcm9tIFwiLi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge2xvY2F0aW9uRnJvbU9mZnNldHMsIG1vZHVsZUxvY2F0aW9ufSBmcm9tIFwiLi4vc2VtYW50aWMvbG9jYXRpb24uanNcIlxuaW1wb3J0IHt3aXRoQWRhcHRlZE9wZXJhdGlvbn0gZnJvbSBcIi4uL3NlbWFudGljL29wZXJhdG9ycy5qc1wiXG5pbXBvcnQge3dpdGhQYXJzZXJSYW5nZXN9IGZyb20gXCIuLi9zZW1hbnRpYy9wcm92ZW5hbmNlLmpzXCJcbmltcG9ydCB7aGFzT25seVVuaWNvZGVTY2FsYXJzfSBmcm9tIFwiLi4vc2VtYW50aWMvc2NhbGFycy5qc1wiXG5pbXBvcnQge3NvdXJjZVNjYWxhclR5cGV9IGZyb20gXCIuL3NjYWxhcnMuanNcIlxuXG4vKiogQHR5cGUge1JlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHN0cmluZz4+fSAqL1xuY29uc3Qgc2ltcGxlU3RyaW5nRXNjYXBlcyA9IE9iamVjdC5mcmVlemUoe1xuICBcIlxcXCJcIjogXCJcXFwiXCIsXG4gIFwiJ1wiOiBcIidcIixcbiAgXCJcXFxcXCI6IFwiXFxcXFwiLFxuICBiOiBcIlxcYlwiLFxuICBmOiBcIlxcZlwiLFxuICBuOiBcIlxcblwiLFxuICByOiBcIlxcclwiLFxuICBzOiBcIiBcIixcbiAgdDogXCJcXHRcIlxufSlcbmNvbnN0IGphdmFCaW5hcnlPcGVyYXRpb25zID0gbmV3IE1hcChbXG4gIFtcIitcIiwgXCJBZGRcIl0sXG4gIFtcIi1cIiwgXCJTdWJ0cmFjdFwiXSxcbiAgW1wiKlwiLCBcIk11bHRpcGx5XCJdLFxuICBbXCImJlwiLCBcIkFuZFwiXSxcbiAgW1wifHxcIiwgXCJPclwiXSxcbiAgW1wiPT1cIiwgXCJKYXZhRXF1YWxcIl0sXG4gIFtcIiE9XCIsIFwiSmF2YU5vdEVxdWFsXCJdLFxuICBbXCI8XCIsIFwiTGVzc1RoYW5cIl0sXG4gIFtcIjw9XCIsIFwiTGVzc1RoYW5PckVxdWFsXCJdLFxuICBbXCI+XCIsIFwiR3JlYXRlclRoYW5cIl0sXG4gIFtcIj49XCIsIFwiR3JlYXRlclRoYW5PckVxdWFsXCJdXG5dKVxuXG4vKipcbiAqIFJldHVybnMgYWxsIGRpcmVjdCBjaGlsZCBzeW50YXggbm9kZXMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIFBhcmVudCBzeW50YXggbm9kZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGVbXX0gQ2hpbGQgc3ludGF4IG5vZGVzLlxuICovXG5mdW5jdGlvbiBkaXJlY3RDaGlsZHJlbihub2RlKSB7XG4gIGNvbnN0IGNoaWxkcmVuID0gW11cblxuICBmb3IgKGxldCBjaGlsZCA9IG5vZGUuZmlyc3RDaGlsZDsgY2hpbGQ7IGNoaWxkID0gY2hpbGQubmV4dFNpYmxpbmcpIGNoaWxkcmVuLnB1c2goY2hpbGQpXG5cbiAgcmV0dXJuIGNoaWxkcmVuXG59XG5cbi8qKlxuICogUmV0dXJucyBzdHJ1Y3R1cmFsIGRpcmVjdCBjaGlsZHJlbiwgZXhjbHVkaW5nIGtub3duIGdyYW1tYXIgZGVsaW1pdGVycy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gUGFyZW50IHN5bnRheCBub2RlLlxuICogQHJldHVybnMge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZVtdfSBOYW1lZCBjaGlsZHJlbi5cbiAqL1xuZnVuY3Rpb24gc3RydWN0dXJhbENoaWxkcmVuKG5vZGUpIHtcbiAgcmV0dXJuIGRpcmVjdENoaWxkcmVuKG5vZGUpLmZpbHRlcigoY2hpbGQpID0+ICFbXCJ7XCIsIFwifVwiLCBcIihcIiwgXCIpXCIsIFwiLFwiLCBcIjtcIiwgXCIuXCJdLmluY2x1ZGVzKGNoaWxkLm5hbWUpKVxufVxuXG4vKipcbiAqIEZpbmRzIGFsbCBkZXNjZW5kYW50IHN5bnRheCBub2RlcyB3aXRoIGEgZ2l2ZW4gbmFtZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gUm9vdCBzeW50YXggbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gTm9kZSBuYW1lLlxuICogQHJldHVybnMge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZVtdfSBNYXRjaGluZyBkZXNjZW5kYW50cy5cbiAqL1xuZnVuY3Rpb24gZGVzY2VuZGFudHMobm9kZSwgbmFtZSkge1xuICBjb25zdCBtYXRjaGVzID0gW11cblxuICBmb3IgKGNvbnN0IGNoaWxkIG9mIGRpcmVjdENoaWxkcmVuKG5vZGUpKSB7XG4gICAgaWYgKGNoaWxkLm5hbWUgPT0gbmFtZSkgbWF0Y2hlcy5wdXNoKGNoaWxkKVxuICAgIG1hdGNoZXMucHVzaCguLi5kZXNjZW5kYW50cyhjaGlsZCwgbmFtZSkpXG4gIH1cblxuICByZXR1cm4gbWF0Y2hlc1xufVxuXG4vKipcbiAqIFJlcXVpcmVzIG9uZSBkaXJlY3QgY2hpbGQgbm9kZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gUGFyZW50IG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIENoaWxkIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gQ2hpbGQgbm9kZS5cbiAqL1xuZnVuY3Rpb24gcmVxdWlyZWRDaGlsZChub2RlLCBuYW1lLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGNoaWxkID0gbm9kZS5nZXRDaGlsZChuYW1lKVxuXG4gIGlmICghY2hpbGQpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgYCR7bm9kZS5uYW1lfSB3aXRob3V0ICR7bmFtZX1gLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgcmV0dXJuIGNoaWxkXG59XG5cbi8qKlxuICogUmV0dXJucyBhIG5vcm1hbGl6ZWQgTGV6ZXIgbm9kZSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gTGV6ZXIgbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IFNvdXJjZSBsb2NhdGlvbi5cbiAqL1xuZnVuY3Rpb24gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgcmV0dXJuIGxvY2F0aW9uRnJvbU9mZnNldHMoZmlsZW5hbWUsIHNvdXJjZSwgbm9kZS5mcm9tLCBub2RlLnRvKVxufVxuXG4vKipcbiAqIFJldHVybnMgc291cmNlIHRleHQgYmVsb25naW5nIHRvIGEgc3ludGF4IG5vZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIExlemVyIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3N0cmluZ30gTm9kZSB0ZXh0LlxuICovXG5mdW5jdGlvbiBub2RlVGV4dChub2RlLCBzb3VyY2UpIHtcbiAgcmV0dXJuIHNvdXJjZS5zbGljZShub2RlLmZyb20sIG5vZGUudG8pXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBzdXBwb3J0ZWQgSmF2YSBleHByZXNzaW9uIG5vZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIExlemVyIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259IFNlbWFudGljIGV4cHJlc3Npb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRFeHByZXNzaW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobm9kZS5uYW1lID09IFwiUGFyZW50aGVzaXplZEV4cHJlc3Npb25cIikge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gc3RydWN0dXJhbENoaWxkcmVuKG5vZGUpXG5cbiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoICE9IDEpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJ1bnN1cHBvcnRlZCBwYXJlbnRoZXNpemVkIGV4cHJlc3Npb25cIiwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnZlcnRFeHByZXNzaW9uKGNoaWxkcmVuWzBdLCBmaWxlbmFtZSwgc291cmNlKVxuICB9XG5cbiAgaWYgKG5vZGUubmFtZSA9PSBcIklkZW50aWZpZXJcIikge1xuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJJZGVudGlmaWVyRXhwcmVzc2lvblwiKSwgbG9jYXRpb24sIG5hbWU6IG5vZGVUZXh0KG5vZGUsIHNvdXJjZSl9LCB7bmFtZTogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUubmFtZSA9PSBcIkludGVnZXJMaXRlcmFsXCIpIHtcbiAgICBjb25zdCB2YWx1ZSA9IE51bWJlcihub2RlVGV4dChub2RlLCBzb3VyY2UpKVxuXG4gICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWx1ZSkpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJub24tc2FmZSBpbnRlZ2VyIGxpdGVyYWxcIiwgbG9jYXRpb24pXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSW50ZWdlckxpdGVyYWxcIiksIGxvY2F0aW9uLCB2YWx1ZX0sIHtsaXRlcmFsOiBsb2NhdGlvbn0pXG4gIH1cblxuICBpZiAobm9kZS5uYW1lID09IFwiQm9vbGVhbkxpdGVyYWxcIikge1xuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJCb29sZWFuTGl0ZXJhbFwiKSwgbG9jYXRpb24sIHZhbHVlOiBub2RlVGV4dChub2RlLCBzb3VyY2UpID09IFwidHJ1ZVwifSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlLm5hbWUgPT0gXCJTdHJpbmdMaXRlcmFsXCIpIHtcbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiU3RyaW5nTGl0ZXJhbFwiKSwgbG9jYXRpb24sIHZhbHVlOiBkZWNvZGVTdHJpbmdMaXRlcmFsKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpfSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlLm5hbWUgPT0gXCJVbmFyeUV4cHJlc3Npb25cIikge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gc3RydWN0dXJhbENoaWxkcmVuKG5vZGUpXG4gICAgY29uc3Qgb3BlcmF0b3JOb2RlID0gbm9kZS5nZXRDaGlsZChcIkxvZ2ljT3BcIikgPz8gbm9kZS5nZXRDaGlsZChcIkFyaXRoT3BcIilcbiAgICBjb25zdCBvcGVyYW5kID0gY2hpbGRyZW4uZmluZCgoY2hpbGQpID0+IGNoaWxkLm5hbWUgIT0gXCJMb2dpY09wXCIgJiYgY2hpbGQubmFtZSAhPSBcIkFyaXRoT3BcIilcbiAgICBjb25zdCBvcGVyYXRvciA9IG9wZXJhdG9yTm9kZSA/IG5vZGVUZXh0KG9wZXJhdG9yTm9kZSwgc291cmNlKSA6IHVuZGVmaW5lZFxuXG4gICAgaWYgKCFvcGVyYXRvck5vZGUgfHwgIW9wZXJhbmQgfHwgY2hpbGRyZW4ubGVuZ3RoICE9IDIgfHwgKG9wZXJhdG9yICE9IFwiIVwiICYmIG9wZXJhdG9yICE9IFwiLVwiKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuYXJ5IGV4cHJlc3Npb25cIiwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgaWYgKG9wZXJhdG9yID09IFwiIVwiICYmIG9wZXJhbmQubmFtZSA9PSBcIk1ldGhvZEludm9jYXRpb25cIiAmJiBpc0VxdWFsc0ludm9jYXRpb24ob3BlcmFuZCwgc291cmNlKSkge1xuICAgICAgcmV0dXJuIGNvbnZlcnRTdHJpbmdFcXVhbGl0eShvcGVyYW5kLCB0cnVlLCBsb2NhdGlvbiwgbm9kZUxvY2F0aW9uKG9wZXJhdG9yTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfVxuXG4gICAgY29uc3Qgc2VtYW50aWMgPSB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IFwiVW5hcnlFeHByZXNzaW9uXCIsXG4gICAgICBsb2NhdGlvbixcbiAgICAgIG9wZXJhbmQ6IGNvbnZlcnRFeHByZXNzaW9uKG9wZXJhbmQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSwge29wZXJhdG9yOiBub2RlTG9jYXRpb24ob3BlcmF0b3JOb2RlLCBmaWxlbmFtZSwgc291cmNlKX0pLCBvcGVyYXRvciA9PSBcIiFcIiA/IFwiTm90XCIgOiBcIk5lZ2F0ZVwiKVxuXG4gICAgcmV0dXJuIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gKi8gKC8qKiBAdHlwZSB7dW5rbm93bn0gKi8gKHNlbWFudGljKSlcbiAgfVxuXG4gIGlmIChub2RlLm5hbWUgPT0gXCJCaW5hcnlFeHByZXNzaW9uXCIpIHtcbiAgICBjb25zdCBuYW1lZCA9IHN0cnVjdHVyYWxDaGlsZHJlbihub2RlKVxuICAgIGNvbnN0IG9wZXJhdG9yTm9kZSA9IG5vZGUuZ2V0Q2hpbGQoXCJDb21wYXJlT3BcIikgPz8gbm9kZS5nZXRDaGlsZChcIkFyaXRoT3BcIikgPz8gbm9kZS5nZXRDaGlsZChcIkxvZ2ljT3BcIikgPz8gbm9kZS5nZXRDaGlsZChcIkJpdE9wXCIpXG5cbiAgICBpZiAoIW9wZXJhdG9yTm9kZSB8fCBuYW1lZC5sZW5ndGggIT0gMykgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcImJpbmFyeSBleHByZXNzaW9uXCIsIGxvY2F0aW9uKVxuXG4gICAgY29uc3Qgb3BlcmFuZHMgPSBbbmFtZWRbMF0sIG5hbWVkWzJdXVxuICAgIGNvbnN0IHVuc3VwcG9ydGVkT3BlcmFuZCA9IG9wZXJhbmRzLmZpbmQoKG9wZXJhbmQpID0+ICFpc1N1cHBvcnRlZEV4cHJlc3Npb25Ob2RlKG9wZXJhbmQpKVxuXG4gICAgaWYgKHVuc3VwcG9ydGVkT3BlcmFuZCkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCB1bnN1cHBvcnRlZE9wZXJhbmQubmFtZSwgbm9kZUxvY2F0aW9uKHVuc3VwcG9ydGVkT3BlcmFuZCwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgICBjb25zdCBvcGVyYXRvciA9IG5vZGVUZXh0KG9wZXJhdG9yTm9kZSwgc291cmNlKVxuXG4gICAgaWYgKCFqYXZhQmluYXJ5T3BlcmF0aW9ucy5oYXMob3BlcmF0b3IpKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIGBiaW5hcnkgJHtvcGVyYXRvcn1gLCBsb2NhdGlvbilcblxuICAgIGNvbnN0IHNlbWFudGljID0gd2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiBcIkJpbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxlZnQ6IGNvbnZlcnRFeHByZXNzaW9uKG9wZXJhbmRzWzBdLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmlnaHQ6IGNvbnZlcnRFeHByZXNzaW9uKG9wZXJhbmRzWzFdLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0sIHtvcGVyYXRvcjogbm9kZUxvY2F0aW9uKG9wZXJhdG9yTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSl9KSwgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy9vcGVyYXRvcnMuanNcIikuQWRhcHRlZE9wZXJhdGlvbn0gKi8gKGphdmFCaW5hcnlPcGVyYXRpb25zLmdldChvcGVyYXRvcikpKVxuXG4gICAgcmV0dXJuIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gKi8gKC8qKiBAdHlwZSB7dW5rbm93bn0gKi8gKHNlbWFudGljKSlcbiAgfVxuXG4gIGlmIChub2RlLm5hbWUgPT0gXCJNZXRob2RJbnZvY2F0aW9uXCIpIHtcbiAgICBpZiAoaXNFcXVhbHNJbnZvY2F0aW9uKG5vZGUsIHNvdXJjZSkpIHtcbiAgICAgIGNvbnN0IG1ldGhvZE5hbWUgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiTWV0aG9kTmFtZVwiLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gICAgICByZXR1cm4gY29udmVydFN0cmluZ0VxdWFsaXR5KG5vZGUsIGZhbHNlLCBsb2NhdGlvbiwgbm9kZUxvY2F0aW9uKG1ldGhvZE5hbWUsIGZpbGVuYW1lLCBzb3VyY2UpLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH1cblxuICAgIGNvbnN0IHVuc3VwcG9ydGVkUmVjZWl2ZXIgPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4obm9kZSkuZmluZCgoY2hpbGQpID0+IGNoaWxkLm5hbWUgIT0gXCJNZXRob2ROYW1lXCIgJiYgY2hpbGQubmFtZSAhPSBcIkFyZ3VtZW50TGlzdFwiKVxuXG4gICAgaWYgKHVuc3VwcG9ydGVkUmVjZWl2ZXIpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJtZXRob2QgaW52b2NhdGlvbiByZWNlaXZlclwiLCBub2RlTG9jYXRpb24odW5zdXBwb3J0ZWRSZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgICBjb25zdCBtZXRob2ROYW1lID0gcmVxdWlyZWRDaGlsZChub2RlLCBcIk1ldGhvZE5hbWVcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBjb25zdCBhcmd1bWVudExpc3QgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiQXJndW1lbnRMaXN0XCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgY29uc3QgYXJndW1lbnROb2RlcyA9IHN0cnVjdHVyYWxDaGlsZHJlbihhcmd1bWVudExpc3QpXG4gICAgY29uc3QgdW5zdXBwb3J0ZWRBcmd1bWVudCA9IGFyZ3VtZW50Tm9kZXMuZmluZCgoY2hpbGQpID0+ICFpc1N1cHBvcnRlZEV4cHJlc3Npb25Ob2RlKGNoaWxkKSlcblxuICAgIGlmICh1bnN1cHBvcnRlZEFyZ3VtZW50KSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIGBtZXRob2QgYXJndW1lbnQgJHt1bnN1cHBvcnRlZEFyZ3VtZW50Lm5hbWV9YCwgbm9kZUxvY2F0aW9uKHVuc3VwcG9ydGVkQXJndW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuXG4gICAgY29uc3QgYXJndW1lbnRzXyA9IGFyZ3VtZW50Tm9kZXMubWFwKChjaGlsZCkgPT4gY29udmVydEV4cHJlc3Npb24oY2hpbGQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2FyZ3VtZW50czogYXJndW1lbnRzXywgY2FsbGVlOiBub2RlVGV4dChtZXRob2ROYW1lLCBzb3VyY2UpLCBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJDYWxsRXhwcmVzc2lvblwiKSwgbG9jYXRpb259LCB7XG4gICAgICBjYWxsZWU6IG5vZGVMb2NhdGlvbihtZXRob2ROYW1lLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0pXG4gIH1cblxuICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIG5vZGUubmFtZSwgbG9jYXRpb24pXG59XG5cbi8qKlxuICogQ2hlY2tzIHRoZSBvbmUgcGFyc2VyLW5hdGl2ZSBKYXZhIHN0cmluZyBlcXVhbGl0eSBpbnZvY2F0aW9uIGZvcm0uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIE1ldGhvZCBpbnZvY2F0aW9uIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGludm9jYXRpb24gc3BlbGxzIGAuZXF1YWxzYCB3aXRoIGEgcmVjZWl2ZXIuXG4gKi9cbmZ1bmN0aW9uIGlzRXF1YWxzSW52b2NhdGlvbihub2RlLCBzb3VyY2UpIHtcbiAgY29uc3QgbWV0aG9kTmFtZSA9IG5vZGUuZ2V0Q2hpbGQoXCJNZXRob2ROYW1lXCIpXG4gIGNvbnN0IHJlY2VpdmVycyA9IHN0cnVjdHVyYWxDaGlsZHJlbihub2RlKS5maWx0ZXIoKGNoaWxkKSA9PiBjaGlsZC5uYW1lICE9IFwiTWV0aG9kTmFtZVwiICYmIGNoaWxkLm5hbWUgIT0gXCJBcmd1bWVudExpc3RcIilcblxuICByZXR1cm4gbWV0aG9kTmFtZSAhPSBudWxsICYmIG5vZGVUZXh0KG1ldGhvZE5hbWUsIHNvdXJjZSkgPT0gXCJlcXVhbHNcIiAmJiByZWNlaXZlcnMubGVuZ3RoID09IDFcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBKYXZhIGAuZXF1YWxzYCBvciBpdHMgZGlyZWN0bHkgbmVnYXRlZCBmb3JtIHdpdGhvdXQgc291cmNlLXRleHQgaW5mZXJlbmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBQYXJzZXIgbWV0aG9kIGludm9jYXRpb24uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG5lZ2F0ZWQgLSBXaGV0aGVyIGEgcGFyc2VyLW93bmVkIHVuYXJ5IG5vdCB3cmFwcyB0aGUgaW52b2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gV2hvbGUgZXF1YWxpdHkgZXhwcmVzc2lvbiBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IG9wZXJhdG9yTG9jYXRpb24gLSBQYXJzZXItb3duZWQgb3BlcmF0b3IvbWV0aG9kIGxvY2F0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSBBZGFwdGVkIGVxdWFsaXR5IGV4cHJlc3Npb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRTdHJpbmdFcXVhbGl0eShub2RlLCBuZWdhdGVkLCBsb2NhdGlvbiwgb3BlcmF0b3JMb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBhcmd1bWVudExpc3QgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiQXJndW1lbnRMaXN0XCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGFyZ3VtZW50c18gPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4oYXJndW1lbnRMaXN0KVxuICBjb25zdCByZWNlaXZlcnMgPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4obm9kZSkuZmlsdGVyKChjaGlsZCkgPT4gY2hpbGQubmFtZSAhPSBcIk1ldGhvZE5hbWVcIiAmJiBjaGlsZC5uYW1lICE9IFwiQXJndW1lbnRMaXN0XCIpXG4gIGNvbnN0IHVuc3VwcG9ydGVkQXJndW1lbnQgPSBhcmd1bWVudHNfLmZpbmQoKGNoaWxkKSA9PiAhaXNTdXBwb3J0ZWRFeHByZXNzaW9uTm9kZShjaGlsZCkpXG5cbiAgaWYgKHJlY2VpdmVycy5sZW5ndGggIT0gMSB8fCBhcmd1bWVudHNfLmxlbmd0aCAhPSAxIHx8IHVuc3VwcG9ydGVkQXJndW1lbnQpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwic3RyaW5nIGVxdWFscyBpbnZvY2F0aW9uXCIsIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24+fSAqL1xuICBjb25zdCByYW5nZXMgPSB7b3BlcmF0b3I6IG9wZXJhdG9yTG9jYXRpb259XG5cbiAgaWYgKG5lZ2F0ZWQpIHtcbiAgICByYW5nZXMuZXF1YWxpdHlPcGVyYXRvciA9IG5vZGVMb2NhdGlvbihyZXF1aXJlZENoaWxkKG5vZGUsIFwiTWV0aG9kTmFtZVwiLCBmaWxlbmFtZSwgc291cmNlKSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfVxuXG4gIGNvbnN0IHNlbWFudGljID0gd2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAga2luZDogXCJCaW5hcnlFeHByZXNzaW9uXCIsXG4gICAgbGVmdDogY29udmVydEV4cHJlc3Npb24ocmVjZWl2ZXJzWzBdLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBsb2NhdGlvbixcbiAgICByaWdodDogY29udmVydEV4cHJlc3Npb24oYXJndW1lbnRzX1swXSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfSwgcmFuZ2VzKSwgbmVnYXRlZCA/IFwiU3RyaW5nTm90RXF1YWxcIiA6IFwiU3RyaW5nRXF1YWxcIilcblxuICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgTGV6ZXIgbm9kZSBpcyBpbiB0aGUgZXhwcmVzc2lvbiBzdWJzZXQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIEphdmEgc3ludGF4IG5vZGUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgbm9kZSBpcyBzdXBwb3J0ZWQuXG4gKi9cbmZ1bmN0aW9uIGlzU3VwcG9ydGVkRXhwcmVzc2lvbk5vZGUobm9kZSkge1xuICByZXR1cm4gW1xuICAgIFwiSWRlbnRpZmllclwiLFxuICAgIFwiSW50ZWdlckxpdGVyYWxcIixcbiAgICBcIkJvb2xlYW5MaXRlcmFsXCIsXG4gICAgXCJTdHJpbmdMaXRlcmFsXCIsXG4gICAgXCJVbmFyeUV4cHJlc3Npb25cIixcbiAgICBcIkJpbmFyeUV4cHJlc3Npb25cIixcbiAgICBcIk1ldGhvZEludm9jYXRpb25cIixcbiAgICBcIlBhcmVudGhlc2l6ZWRFeHByZXNzaW9uXCJcbiAgXS5pbmNsdWRlcyhub2RlLm5hbWUpXG59XG5cbi8qKlxuICogQXBwbGllcyBKYXZhIFVuaWNvZGUgdHJhbnNsYXRpb24gYmVmb3JlIHRva2VuLWxldmVsIHN0cmluZyBlc2NhcGUgZGVjb2RpbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGl0ZXJhbCAtIFBhcnNlci1jb25maXJtZWQgSmF2YSBzdHJpbmcgbGl0ZXJhbC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gTGl0ZXJhbCBzb3VyY2UgbG9jYXRpb24uXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBVbmljb2RlLXRyYW5zbGF0ZWQgbGl0ZXJhbC5cbiAqL1xuZnVuY3Rpb24gdHJhbnNsYXRlVW5pY29kZUVzY2FwZXMobGl0ZXJhbCwgbG9jYXRpb24pIHtcbiAgbGV0IHRyYW5zbGF0ZWQgPSBcIlwiXG4gIGxldCBjb25zZWN1dGl2ZUJhY2tzbGFzaGVzID0gMFxuICBsZXQgcHJldmlvdXNXYXNVbmljb2RlRXNjYXBlID0gZmFsc2VcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgbGl0ZXJhbC5sZW5ndGg7IGluZGV4KyspIHtcbiAgICBjb25zdCBjaGFyYWN0ZXIgPSBsaXRlcmFsW2luZGV4XVxuICAgIGNvbnN0IGVsaWdpYmxlID0gY2hhcmFjdGVyID09IFwiXFxcXFwiICYmIChwcmV2aW91c1dhc1VuaWNvZGVFc2NhcGUgfHwgY29uc2VjdXRpdmVCYWNrc2xhc2hlcyAlIDIgPT0gMClcblxuICAgIGlmIChlbGlnaWJsZSAmJiBsaXRlcmFsW2luZGV4ICsgMV0gPT0gXCJ1XCIpIHtcbiAgICAgIGxldCBkaWdpdHNTdGFydCA9IGluZGV4ICsgMlxuXG4gICAgICB3aGlsZSAobGl0ZXJhbFtkaWdpdHNTdGFydF0gPT0gXCJ1XCIpIGRpZ2l0c1N0YXJ0KytcblxuICAgICAgY29uc3QgaGV4YWRlY2ltYWwgPSBsaXRlcmFsLnNsaWNlKGRpZ2l0c1N0YXJ0LCBkaWdpdHNTdGFydCArIDQpXG4gICAgICBjb25zdCBpc0hleGFkZWNpbWFsID0gaGV4YWRlY2ltYWwubGVuZ3RoID09IDQgJiYgWy4uLmhleGFkZWNpbWFsXS5ldmVyeSgoZGlnaXQpID0+XG4gICAgICAgIChkaWdpdCA+PSBcIjBcIiAmJiBkaWdpdCA8PSBcIjlcIikgfHwgKGRpZ2l0ID49IFwiQVwiICYmIGRpZ2l0IDw9IFwiRlwiKSB8fCAoZGlnaXQgPj0gXCJhXCIgJiYgZGlnaXQgPD0gXCJmXCIpXG4gICAgICApXG5cbiAgICAgIGlmICghaXNIZXhhZGVjaW1hbCkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuc3VwcG9ydGVkIHN0cmluZyBlc2NhcGVcIiwgbG9jYXRpb24pXG5cbiAgICAgIGNvbnN0IHRyYW5zbGF0ZWRDaGFyYWN0ZXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKE51bWJlci5wYXJzZUludChoZXhhZGVjaW1hbCwgMTYpKVxuXG4gICAgICB0cmFuc2xhdGVkICs9IHRyYW5zbGF0ZWRDaGFyYWN0ZXJcbiAgICAgIGNvbnNlY3V0aXZlQmFja3NsYXNoZXMgPSB0cmFuc2xhdGVkQ2hhcmFjdGVyID09IFwiXFxcXFwiID8gY29uc2VjdXRpdmVCYWNrc2xhc2hlcyArIDEgOiAwXG4gICAgICBwcmV2aW91c1dhc1VuaWNvZGVFc2NhcGUgPSB0cnVlXG4gICAgICBpbmRleCA9IGRpZ2l0c1N0YXJ0ICsgM1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICB0cmFuc2xhdGVkICs9IGNoYXJhY3RlclxuICAgIGNvbnNlY3V0aXZlQmFja3NsYXNoZXMgPSBjaGFyYWN0ZXIgPT0gXCJcXFxcXCIgPyBjb25zZWN1dGl2ZUJhY2tzbGFzaGVzICsgMSA6IDBcbiAgICBwcmV2aW91c1dhc1VuaWNvZGVFc2NhcGUgPSBmYWxzZVxuICB9XG5cbiAgcmV0dXJuIHRyYW5zbGF0ZWRcbn1cblxuLyoqXG4gKiBEZWNvZGVzIHRoZSBhY2NlcHRlZCBlc2NhcGVzIGZyb20gb25lIHBhcnNlci1jb25maXJtZWQgSmF2YSBzdHJpbmcgbGl0ZXJhbC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gSmF2YSBTdHJpbmdMaXRlcmFsIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3N0cmluZ30gRGVjb2RlZCBVbmljb2RlIHN0cmluZy5cbiAqL1xuZnVuY3Rpb24gZGVjb2RlU3RyaW5nTGl0ZXJhbChub2RlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGxpdGVyYWwgPSB0cmFuc2xhdGVVbmljb2RlRXNjYXBlcyhub2RlVGV4dChub2RlLCBzb3VyY2UpLCBsb2NhdGlvbilcbiAgbGV0IHZhbHVlID0gXCJcIlxuXG4gIGZvciAobGV0IGluZGV4ID0gMTsgaW5kZXggPCBsaXRlcmFsLmxlbmd0aCAtIDE7IGluZGV4KyspIHtcbiAgICBjb25zdCBjaGFyYWN0ZXIgPSBsaXRlcmFsW2luZGV4XVxuXG4gICAgaWYgKGNoYXJhY3RlciA9PSBcIlxcXCJcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXG5cIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHJcIikge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcImludmFsaWQgc3RyaW5nIGxpdGVyYWxcIiwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgaWYgKGNoYXJhY3RlciAhPSBcIlxcXFxcIikge1xuICAgICAgdmFsdWUgKz0gY2hhcmFjdGVyXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGlmIChpbmRleCArIDEgPj0gbGl0ZXJhbC5sZW5ndGggLSAxKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwiaW52YWxpZCBzdHJpbmcgbGl0ZXJhbFwiLCBsb2NhdGlvbilcblxuICAgIGNvbnN0IGVzY2FwZWQgPSBsaXRlcmFsWysraW5kZXhdXG4gICAgY29uc3Qgc2ltcGxlID0gc2ltcGxlU3RyaW5nRXNjYXBlc1tlc2NhcGVkXVxuXG4gICAgaWYgKHNpbXBsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB2YWx1ZSArPSBzaW1wbGVcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgaWYgKGVzY2FwZWQgPj0gXCIwXCIgJiYgZXNjYXBlZCA8PSBcIjdcIikge1xuICAgICAgbGV0IG9jdGFsID0gZXNjYXBlZFxuICAgICAgY29uc3QgbWF4aW11bUxlbmd0aCA9IGVzY2FwZWQgPD0gXCIzXCIgPyAzIDogMlxuXG4gICAgICB3aGlsZSAob2N0YWwubGVuZ3RoIDwgbWF4aW11bUxlbmd0aCAmJiBsaXRlcmFsW2luZGV4ICsgMV0gPj0gXCIwXCIgJiYgbGl0ZXJhbFtpbmRleCArIDFdIDw9IFwiN1wiKSB7XG4gICAgICAgIG9jdGFsICs9IGxpdGVyYWxbKytpbmRleF1cbiAgICAgIH1cblxuICAgICAgdmFsdWUgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShOdW1iZXIucGFyc2VJbnQob2N0YWwsIDgpKVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwidW5zdXBwb3J0ZWQgc3RyaW5nIGVzY2FwZVwiLCBsb2NhdGlvbilcbiAgfVxuXG4gIGlmICghaGFzT25seVVuaWNvZGVTY2FsYXJzKHZhbHVlKSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcImludmFsaWQgVW5pY29kZSBzdHJpbmcgbGl0ZXJhbFwiLCBsb2NhdGlvbilcblxuICByZXR1cm4gdmFsdWVcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhwbGljaXQgSmF2YSByZXR1cm4gc3RhdGVtZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IHN0YXRlbWVudCAtIEphdmEgc3RhdGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5SZXR1cm5TdGF0ZW1lbnR9IFNlbWFudGljIHJldHVybi5cbiAqL1xuZnVuY3Rpb24gY29udmVydFJldHVybihzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24oc3RhdGVtZW50LCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChzdGF0ZW1lbnQubmFtZSAhPSBcIlJldHVyblN0YXRlbWVudFwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIHN0YXRlbWVudC5uYW1lLCBsb2NhdGlvbilcblxuICBjb25zdCBleHByZXNzaW9uTm9kZXMgPSBkaXJlY3RDaGlsZHJlbihzdGF0ZW1lbnQpLmZpbHRlcigoY2hpbGQpID0+IGNoaWxkLm5hbWUgIT0gXCJyZXR1cm5cIiAmJiBjaGlsZC5uYW1lICE9IFwiO1wiKVxuICBjb25zdCBleHByZXNzaW9uID0gZXhwcmVzc2lvbk5vZGVzLmxlbmd0aCA9PSAxID8gZXhwcmVzc2lvbk5vZGVzWzBdIDogdW5kZWZpbmVkXG5cbiAgaWYgKCFleHByZXNzaW9uKSB7XG4gICAgY29uc3QgdW5zdXBwb3J0ZWQgPSBleHByZXNzaW9uTm9kZXNbMF1cblxuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcbiAgICAgIFwiamF2YVwiLFxuICAgICAgdW5zdXBwb3J0ZWQ/Lm5hbWUgPz8gXCJlbXB0eSByZXR1cm5cIixcbiAgICAgIHVuc3VwcG9ydGVkID8gbm9kZUxvY2F0aW9uKHVuc3VwcG9ydGVkLCBmaWxlbmFtZSwgc291cmNlKSA6IGxvY2F0aW9uXG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihleHByZXNzaW9uLCBmaWxlbmFtZSwgc291cmNlKSwga2luZDogXCJSZXR1cm5TdGF0ZW1lbnRcIiwgbG9jYXRpb259XG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIEphdmEgbG9jYWwgZGVjbGFyYXRpb24gb3IgYXNzaWdubWVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBzdGF0ZW1lbnQgLSBKYXZhIHN0YXRlbWVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuTG9jYWxTdGF0ZW1lbnR9IFNlbWFudGljIGxvY2FsIHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydExvY2FsU3RhdGVtZW50KHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiTG9jYWxWYXJpYWJsZURlY2xhcmF0aW9uXCIpIHtcbiAgICBjb25zdCBkZWNsYXJhdG9ycyA9IHN0YXRlbWVudC5nZXRDaGlsZHJlbihcIlZhcmlhYmxlRGVjbGFyYXRvclwiKVxuICAgIGNvbnN0IHR5cGVOb2RlID0gZGVjbGFyYXRpb25UeXBlKHN0YXRlbWVudClcbiAgICBjb25zdCB2YXJOb2RlID0gc3RhdGVtZW50LmdldENoaWxkKFwidmFyXCIpXG4gICAgY29uc3QgbW9kaWZpZXJzID0gc3RhdGVtZW50LmdldENoaWxkKFwiTW9kaWZpZXJzXCIpXG4gICAgY29uc3QgbW9kaWZpZXJDaGlsZHJlbiA9IG1vZGlmaWVycyA/IHN0cnVjdHVyYWxDaGlsZHJlbihtb2RpZmllcnMpIDogW11cblxuICAgIGlmICh2YXJOb2RlKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwidmFyIGxvY2FsIGRlY2xhcmF0aW9uXCIsIG5vZGVMb2NhdGlvbih2YXJOb2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICBpZiAoZGVjbGFyYXRvcnMubGVuZ3RoICE9IDEpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJtdWx0aXBsZSBsb2NhbCBkZWNsYXJhdG9yc1wiLCBsb2NhdGlvbilcbiAgICBpZiAoIXR5cGVOb2RlIHx8IHR5cGVOb2RlLm5hbWUgPT0gXCJBcnJheVR5cGVcIikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuc3VwcG9ydGVkIGxvY2FsIHR5cGVcIiwgbG9jYXRpb24pXG4gICAgaWYgKG1vZGlmaWVyQ2hpbGRyZW4uc29tZSgoY2hpbGQpID0+IGNoaWxkLm5hbWUgIT0gXCJmaW5hbFwiKSB8fCBtb2RpZmllckNoaWxkcmVuLmxlbmd0aCA+IDEpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJ1bnN1cHBvcnRlZCBsb2NhbCBtb2RpZmllcnNcIiwgbW9kaWZpZXJzID8gbm9kZUxvY2F0aW9uKG1vZGlmaWVycywgZmlsZW5hbWUsIHNvdXJjZSkgOiBsb2NhdGlvbilcbiAgICB9XG5cbiAgICBjb25zdCBkZWNsYXJhdG9yID0gZGVjbGFyYXRvcnNbMF1cbiAgICBjb25zdCBkZWZpbml0aW9uID0gcmVxdWlyZWRDaGlsZChkZWNsYXJhdG9yLCBcIkRlZmluaXRpb25cIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBjb25zdCBhc3NpZ25tZW50ID0gZGVjbGFyYXRvci5nZXRDaGlsZChcIkFzc2lnbk9wXCIpXG4gICAgY29uc3QgZGltZW5zaW9ucyA9IGRlY2xhcmF0b3IuZ2V0Q2hpbGRyZW4oXCJEaW1lbnNpb25cIilcbiAgICBjb25zdCBpbml0aWFsaXplck5vZGVzID0gZGlyZWN0Q2hpbGRyZW4oZGVjbGFyYXRvcikuZmlsdGVyKChjaGlsZCkgPT4gY2hpbGQubmFtZSAhPSBcIkRlZmluaXRpb25cIiAmJiBjaGlsZC5uYW1lICE9IFwiQXNzaWduT3BcIilcblxuICAgIGlmIChkaW1lbnNpb25zLmxlbmd0aCA+IDApIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJhcnJheSBsb2NhbCBkZWNsYXJhdGlvblwiLCBub2RlTG9jYXRpb24oZGVjbGFyYXRvciwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgaWYgKCFhc3NpZ25tZW50IHx8IG5vZGVUZXh0KGFzc2lnbm1lbnQsIHNvdXJjZSkgIT0gXCI9XCIgfHwgaW5pdGlhbGl6ZXJOb2Rlcy5sZW5ndGggIT0gMSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuaW5pdGlhbGl6ZWQgbG9jYWwgZGVjbGFyYXRpb25cIiwgbm9kZUxvY2F0aW9uKGRlY2xhcmF0b3IsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cblxuICAgIGNvbnN0IG5hbWUgPSBub2RlVGV4dChkZWZpbml0aW9uLCBzb3VyY2UpXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBpbml0aWFsaXplcjogY29udmVydEV4cHJlc3Npb24oaW5pdGlhbGl6ZXJOb2Rlc1swXSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBraW5kOiBcIkxvY2FsRGVjbGFyYXRpb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgbXV0YWJsZTogbW9kaWZpZXJDaGlsZHJlbi5sZW5ndGggPT0gMCxcbiAgICAgIG5hbWUsXG4gICAgICB0eXBlOiBjb252ZXJ0VHlwZSh0eXBlTm9kZSwgYExvY2FsICcke25hbWV9J2AsIGxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0sIHtuYW1lOiBub2RlTG9jYXRpb24oZGVmaW5pdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSksIG9wZXJhdG9yOiBub2RlTG9jYXRpb24oYXNzaWdubWVudCwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9XG5cbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiRXhwcmVzc2lvblN0YXRlbWVudFwiKSB7XG4gICAgY29uc3QgYXNzaWdubWVudCA9IHN0YXRlbWVudC5nZXRDaGlsZChcIkFzc2lnbm1lbnRFeHByZXNzaW9uXCIpXG5cbiAgICBpZiAoIWFzc2lnbm1lbnQpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgc3RhdGVtZW50Lm5hbWUsIGxvY2F0aW9uKVxuXG4gICAgY29uc3QgY2hpbGRyZW4gPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4oYXNzaWdubWVudClcbiAgICBjb25zdCBvcGVyYXRvciA9IGFzc2lnbm1lbnQuZ2V0Q2hpbGQoXCJBc3NpZ25PcFwiKVxuICAgIGNvbnN0IHRhcmdldCA9IGNoaWxkcmVuWzBdXG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGNoaWxkcmVuLmF0KC0xKVxuXG4gICAgaWYgKCFvcGVyYXRvciB8fCBub2RlVGV4dChvcGVyYXRvciwgc291cmNlKSAhPSBcIj1cIikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcImNvbXBvdW5kIGFzc2lnbm1lbnRcIiwgbm9kZUxvY2F0aW9uKGFzc2lnbm1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIGlmICghdGFyZ2V0IHx8IHRhcmdldC5uYW1lICE9IFwiSWRlbnRpZmllclwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIHRhcmdldD8ubmFtZSA/PyBcImFzc2lnbm1lbnQgdGFyZ2V0XCIsIHRhcmdldCA/IG5vZGVMb2NhdGlvbih0YXJnZXQsIGZpbGVuYW1lLCBzb3VyY2UpIDogbG9jYXRpb24pXG4gICAgaWYgKCFleHByZXNzaW9uIHx8IGV4cHJlc3Npb24gPT0gdGFyZ2V0IHx8IGV4cHJlc3Npb24gPT0gb3BlcmF0b3IpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJhc3NpZ25tZW50IGV4cHJlc3Npb25cIiwgbm9kZUxvY2F0aW9uKGFzc2lnbm1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuXG4gICAgY29uc3QgdGFyZ2V0RXhwcmVzc2lvbiA9IHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSWRlbnRpZmllckV4cHJlc3Npb25cIiksXG4gICAgICBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKHRhcmdldCwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBuYW1lOiBub2RlVGV4dCh0YXJnZXQsIHNvdXJjZSlcbiAgICB9LCB7bmFtZTogbm9kZUxvY2F0aW9uKHRhcmdldCwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgZXhwcmVzc2lvbjogY29udmVydEV4cHJlc3Npb24oZXhwcmVzc2lvbiwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBraW5kOiBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgdGFyZ2V0OiB0YXJnZXRFeHByZXNzaW9uXG4gICAgfSwge29wZXJhdG9yOiBub2RlTG9jYXRpb24ob3BlcmF0b3IsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgfVxuXG4gIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgc3RhdGVtZW50Lm5hbWUsIGxvY2F0aW9uKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBleGhhdXN0aXZlIGRpcmVjdCBKYXZhIGJsb2NrIGNoaWxkLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IHN0YXRlbWVudCAtIEphdmEgc3RhdGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TdGF0ZW1lbnR9IFNlbWFudGljIHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydFN0YXRlbWVudChzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiUmV0dXJuU3RhdGVtZW50XCIpIHJldHVybiBjb252ZXJ0UmV0dXJuKHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiSWZTdGF0ZW1lbnRcIikgcmV0dXJuIGNvbnZlcnRJZihzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGlmIChzdGF0ZW1lbnQubmFtZSA9PSBcIkxvY2FsVmFyaWFibGVEZWNsYXJhdGlvblwiKSByZXR1cm4gY29udmVydExvY2FsU3RhdGVtZW50KHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiRXhwcmVzc2lvblN0YXRlbWVudFwiKSB7XG4gICAgaWYgKHN0YXRlbWVudC5nZXRDaGlsZChcIkFzc2lnbm1lbnRFeHByZXNzaW9uXCIpKSByZXR1cm4gY29udmVydExvY2FsU3RhdGVtZW50KHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBpZiAoIXN0YXRlbWVudC5nZXRDaGlsZChcIk1ldGhvZEludm9jYXRpb25cIikpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgc3RhdGVtZW50Lm5hbWUsIG5vZGVMb2NhdGlvbihzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cblxuICAgIHJldHVybiBjb252ZXJ0UHJpbnQoc3RhdGVtZW50LCBmaWxlbmFtZSwgc291cmNlKVxuICB9XG5cbiAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBzdGF0ZW1lbnQubmFtZSwgbm9kZUxvY2F0aW9uKHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSkpXG59XG5cbi8qKlxuICogQ29udmVydHMgZGlyZWN0IHN0cnVjdHVyYWwgY2hpbGRyZW4gb2Ygb25lIEphdmEgYmxvY2sgaW4gc291cmNlIG9yZGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBKYXZhIEJsb2NrIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkJsb2NrfSBTZW1hbnRpYyBibG9jay5cbiAqL1xuZnVuY3Rpb24gY29udmVydEJsb2NrKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgaWYgKG5vZGUubmFtZSAhPSBcIkJsb2NrXCIpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgYGV4cGVjdGVkIGJsb2NrLCByZWNlaXZlZCAke25vZGUubmFtZX1gLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgcmV0dXJuIHtcbiAgICBraW5kOiBcIkJsb2NrXCIsXG4gICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBzdGF0ZW1lbnRzOiBzdHJ1Y3R1cmFsQ2hpbGRyZW4obm9kZSkubWFwKChzdGF0ZW1lbnQpID0+IGNvbnZlcnRTdGF0ZW1lbnQoc3RhdGVtZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxufVxuXG4vKipcbiAqIFJlcXVpcmVzIGFuIGV4YWN0IEphdmEgc2NhbGFyIHR5cGUgbm9kZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlIHwgbnVsbH0gc291cmNlVHlwZSAtIEphdmEgdHlwZSBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IHN1YmplY3QgLSBUeXBlZCBzdWJqZWN0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBTb3VyY2UgbG9jYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlR5cGVSZWZlcmVuY2V9IFNlbWFudGljIHR5cGUuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRUeXBlKHNvdXJjZVR5cGUsIHN1YmplY3QsIGxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGlmICghc291cmNlVHlwZSkgcmV0dXJuIG1pc3NpbmdUeXBlKFwiamF2YVwiLCBzdWJqZWN0LCBsb2NhdGlvbilcbiAgaWYgKCFbXCJQcmltaXRpdmVUeXBlXCIsIFwiVHlwZU5hbWVcIiwgXCJTY29wZWRUeXBlTmFtZVwiXS5pbmNsdWRlcyhzb3VyY2VUeXBlLm5hbWUpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuc3VwcG9ydGVkIHNjYWxhciB0eXBlXCIsIGxvY2F0aW9uKVxuICB9XG5cbiAgY29uc3QgdHlwZSA9IHNvdXJjZVNjYWxhclR5cGUoXCJqYXZhXCIsIG5vZGVUZXh0KHNvdXJjZVR5cGUsIHNvdXJjZSksIG5vZGVMb2NhdGlvbihzb3VyY2VUeXBlLCBmaWxlbmFtZSwgc291cmNlKSlcblxuICBpZiAoIXR5cGUpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJ1bnN1cHBvcnRlZCBzY2FsYXIgdHlwZVwiLCBub2RlTG9jYXRpb24oc291cmNlVHlwZSwgbG9jYXRpb24uZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgcmV0dXJuIHR5cGVcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBkaXJlY3QgSmF2YSBkZWNsYXJhdGlvbiB0eXBlIG5vZGUgc3VwcG9ydGVkIGJ5IHNjYWxhciBjb252ZXJzaW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBEZWNsYXJhdGlvbiBub2RlLlxuICogQHJldHVybnMge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZSB8IG51bGx9IFR5cGUgc3ludGF4IG5vZGUuXG4gKi9cbmZ1bmN0aW9uIGRlY2xhcmF0aW9uVHlwZShub2RlKSB7XG4gIHJldHVybiBub2RlLmdldENoaWxkKFwiUHJpbWl0aXZlVHlwZVwiKSA/PyBub2RlLmdldENoaWxkKFwiVHlwZU5hbWVcIikgPz8gbm9kZS5nZXRDaGlsZChcIlNjb3BlZFR5cGVOYW1lXCIpXG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIHN1cHBvcnRlZCBKYXZhIGZ1bmN0aW9uIG1ldGhvZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gTWV0aG9kIGRlY2xhcmF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9ufSBTZW1hbnRpYyBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY29udmVydEZ1bmN0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgZGVmaW5pdGlvbiA9IHJlcXVpcmVkQ2hpbGQobm9kZSwgXCJEZWZpbml0aW9uXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IG5hbWUgPSBub2RlVGV4dChkZWZpbml0aW9uLCBzb3VyY2UpXG4gIGNvbnN0IHBhcmFtZXRlcnNOb2RlID0gcmVxdWlyZWRDaGlsZChub2RlLCBcIkZvcm1hbFBhcmFtZXRlcnNcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgcGFyYW1ldGVycyA9IHBhcmFtZXRlcnNOb2RlLmdldENoaWxkcmVuKFwiRm9ybWFsUGFyYW1ldGVyXCIpLm1hcCgocGFyYW1ldGVyKSA9PiB7XG4gICAgY29uc3QgcGFyYW1ldGVyTG9jYXRpb24gPSBub2RlTG9jYXRpb24ocGFyYW1ldGVyLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IHBhcmFtZXRlck5hbWVOb2RlID0gcmVxdWlyZWRDaGlsZChwYXJhbWV0ZXIsIFwiRGVmaW5pdGlvblwiLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IHBhcmFtZXRlck5hbWUgPSBub2RlVGV4dChwYXJhbWV0ZXJOYW1lTm9kZSwgc291cmNlKVxuXG4gICAgY29uc3Qgc2VtYW50aWNQYXJhbWV0ZXIgPSB7XG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJQYXJhbWV0ZXJcIiksXG4gICAgICBsb2NhdGlvbjogcGFyYW1ldGVyTG9jYXRpb24sXG4gICAgICBuYW1lOiBwYXJhbWV0ZXJOYW1lLFxuICAgICAgdHlwZTogY29udmVydFR5cGUoZGVjbGFyYXRpb25UeXBlKHBhcmFtZXRlciksIGBQYXJhbWV0ZXIgJyR7cGFyYW1ldGVyTmFtZX0nYCwgcGFyYW1ldGVyTG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoc2VtYW50aWNQYXJhbWV0ZXIsIHtuYW1lOiBub2RlTG9jYXRpb24ocGFyYW1ldGVyTmFtZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgfSlcbiAgY29uc3QgYmxvY2sgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiQmxvY2tcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYm9keSA9IGNvbnZlcnRCbG9jayhibG9jaywgZmlsZW5hbWUsIHNvdXJjZSlcblxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgYm9keSxcbiAgICBraW5kOiBcIkZ1bmN0aW9uRGVjbGFyYXRpb25cIixcbiAgICBsb2NhdGlvbixcbiAgICBuYW1lLFxuICAgIHBhcmFtZXRlcnMsXG4gICAgcmV0dXJuVHlwZTogY29udmVydFR5cGUoZGVjbGFyYXRpb25UeXBlKG5vZGUpLCBgRnVuY3Rpb24gJyR7bmFtZX0nIHJldHVybmAsIGxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuICB9LCB7bmFtZTogbm9kZUxvY2F0aW9uKGRlZmluaXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpfSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZXhpc3RpbmcgZXhhY3QgSmF2YSBpZi9lbHNlIHRlcm1pbmFsIHdpdGggcmVzdHJpY3RlZCBicmFuY2ggcHJlZml4ZXMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIEphdmEgaWYgc3RhdGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5JZlN0YXRlbWVudH0gU2VtYW50aWMgYnJhbmNoLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0SWYobm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBjb25kaXRpb25Db250YWluZXIgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiUGFyZW50aGVzaXplZEV4cHJlc3Npb25cIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgY29uZGl0aW9uTm9kZXMgPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4oY29uZGl0aW9uQ29udGFpbmVyKVxuICBjb25zdCBjb25kaXRpb24gPSBjb25kaXRpb25Ob2Rlcy5sZW5ndGggPT0gMSA/IGNvbmRpdGlvbk5vZGVzWzBdIDogdW5kZWZpbmVkXG4gIGNvbnN0IGRpcmVjdCA9IGRpcmVjdENoaWxkcmVuKG5vZGUpXG4gIGNvbnN0IGNvbmRpdGlvbkluZGV4ID0gZGlyZWN0LmZpbmRJbmRleCgoY2hpbGQpID0+IGNoaWxkLm5hbWUgPT0gY29uZGl0aW9uQ29udGFpbmVyLm5hbWUgJiZcbiAgICBjaGlsZC5mcm9tID09IGNvbmRpdGlvbkNvbnRhaW5lci5mcm9tICYmIGNoaWxkLnRvID09IGNvbmRpdGlvbkNvbnRhaW5lci50bylcbiAgY29uc3QgY29uc2VxdWVudE5vZGUgPSBkaXJlY3RbY29uZGl0aW9uSW5kZXggKyAxXVxuICBjb25zdCBhbHRlcm5hdGVOb2RlID0gZGlyZWN0LmF0KC0xKSA9PSBjb25zZXF1ZW50Tm9kZSA/IHVuZGVmaW5lZCA6IGRpcmVjdC5hdCgtMSlcblxuICBpZiAoIWNvbmRpdGlvbiB8fCAhY29uc2VxdWVudE5vZGUgfHwgY29uc2VxdWVudE5vZGUubmFtZSAhPSBcIkJsb2NrXCIpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwiaWYgd2l0aG91dCBibG9jayBjb25zZXF1ZW50XCIsIGxvY2F0aW9uKVxuICB9XG5cbiAgbGV0IGFsdGVybmF0ZVxuXG4gIGlmIChhbHRlcm5hdGVOb2RlPy5uYW1lID09IFwiQmxvY2tcIikgYWx0ZXJuYXRlID0gY29udmVydEJsb2NrKGFsdGVybmF0ZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGVsc2UgaWYgKGFsdGVybmF0ZU5vZGU/Lm5hbWUgPT0gXCJJZlN0YXRlbWVudFwiKSB7XG4gICAgYWx0ZXJuYXRlID0ge1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQmxvY2tcIiksXG4gICAgICBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKGFsdGVybmF0ZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgc3RhdGVtZW50czogW2NvbnZlcnRJZihhbHRlcm5hdGVOb2RlLCBmaWxlbmFtZSwgc291cmNlKV1cbiAgICB9XG4gIH0gZWxzZSBpZiAoYWx0ZXJuYXRlTm9kZSAmJiBhbHRlcm5hdGVOb2RlLm5hbWUgIT0gXCJlbHNlXCIpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIGBpZiBhbHRlcm5hdGUgJHthbHRlcm5hdGVOb2RlLm5hbWV9YCwgbm9kZUxvY2F0aW9uKGFsdGVybmF0ZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICAuLi4oYWx0ZXJuYXRlID8ge2FsdGVybmF0ZX0gOiB7fSksXG4gICAgY29uZGl0aW9uOiBjb252ZXJ0RXhwcmVzc2lvbihjb25kaXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIGNvbnNlcXVlbnQ6IGNvbnZlcnRCbG9jayhjb25zZXF1ZW50Tm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAga2luZDogXCJJZlN0YXRlbWVudFwiLFxuICAgIGxvY2F0aW9uXG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBKYXZhJ3Mgc3VwcG9ydGVkIG1haW4gbWV0aG9kLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBNYWluIG1ldGhvZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRW50cnlQb2ludH0gU2VtYW50aWMgZW50cnkgcG9pbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRFbnRyeVBvaW50KG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYmxvY2sgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiQmxvY2tcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYm9keSA9IGNvbnZlcnRCbG9jayhibG9jaywgZmlsZW5hbWUsIHNvdXJjZSlcblxuICByZXR1cm4ge2JvZHksIGtpbmQ6IFwiRW50cnlQb2ludFwiLCBsb2NhdGlvbn1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgc3VwcG9ydGVkIEphdmEgcHJpbnQgc3RhdGVtZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IHN0YXRlbWVudCAtIEV4cHJlc3Npb24gc3RhdGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QcmludFN0YXRlbWVudH0gU2VtYW50aWMgcHJpbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRQcmludChzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24oc3RhdGVtZW50LCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGNvbnN0IHByaW50SW52b2NhdGlvbiA9IHN0YXRlbWVudC5nZXRDaGlsZChcIk1ldGhvZEludm9jYXRpb25cIilcblxuICBpZiAoIXByaW50SW52b2NhdGlvbikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcIm1haW4gd2l0aG91dCBTeXN0ZW0ub3V0LnByaW50bG5cIiwgbG9jYXRpb24pXG5cbiAgY29uc3QgZmllbGRBY2Nlc3MgPSBwcmludEludm9jYXRpb24uZ2V0Q2hpbGQoXCJGaWVsZEFjY2Vzc1wiKVxuICBjb25zdCBtZXRob2ROYW1lID0gcHJpbnRJbnZvY2F0aW9uLmdldENoaWxkKFwiTWV0aG9kTmFtZVwiKVxuXG4gIGlmICghZmllbGRBY2Nlc3MgfHwgIW1ldGhvZE5hbWUgfHwgbm9kZVRleHQoZmllbGRBY2Nlc3MsIHNvdXJjZSkgIT0gXCJTeXN0ZW0ub3V0XCIgfHwgbm9kZVRleHQobWV0aG9kTmFtZSwgc291cmNlKSAhPSBcInByaW50bG5cIikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJtYWluIHdpdGhvdXQgU3lzdGVtLm91dC5wcmludGxuXCIsIG5vZGVMb2NhdGlvbihwcmludEludm9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG5cbiAgY29uc3QgYXJndW1lbnRMaXN0ID0gcmVxdWlyZWRDaGlsZChwcmludEludm9jYXRpb24sIFwiQXJndW1lbnRMaXN0XCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGFyZ3VtZW50c18gPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4oYXJndW1lbnRMaXN0KVxuXG4gIGlmIChhcmd1bWVudHNfLmxlbmd0aCAhPSAxKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInByaW50bG4gd2l0aG91dCBvbmUgc3VwcG9ydGVkIGFyZ3VtZW50XCIsIG5vZGVMb2NhdGlvbihhcmd1bWVudExpc3QsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG5cbiAgY29uc3QgcHJpbnRMb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihwcmludEludm9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihhcmd1bWVudHNfWzBdLCBmaWxlbmFtZSwgc291cmNlKSwga2luZDogXCJQcmludFN0YXRlbWVudFwiLCBsb2NhdGlvbjogcHJpbnRMb2NhdGlvbn1cbn1cblxuLyoqXG4gKiBQYXJzZXMgSmF2YSBpbnRvIHRoZSBzaGFyZWQgc2VtYW50aWMgbW9kdWxlLlxuICogQHBhcmFtIHtvYmplY3R9IGlucHV0IC0gUGFyc2VyIGlucHV0LlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0LmZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0LnNvdXJjZSAtIFNvdXJjZSB0ZXh0LlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBTZW1hbnRpYyBtb2R1bGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUphdmEoe2ZpbGVuYW1lLCBzb3VyY2V9KSB7XG4gIGNvbnN0IHRyZWUgPSBwYXJzZXIucGFyc2Uoc291cmNlKVxuICBjb25zdCBlcnJvciA9IGRlc2NlbmRhbnRzKHRyZWUudG9wTm9kZSwgXCLimqBcIilbMF1cblxuICBpZiAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtcbiAgICAgIGNvZGU6IFwiUEFSU0VfRVJST1JcIixcbiAgICAgIGxhbmd1YWdlOiBcImphdmFcIixcbiAgICAgIGxvY2F0aW9uOiBub2RlTG9jYXRpb24oZXJyb3IsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgbWVzc2FnZTogXCJKYXZhIHBhcnNlciByZXBvcnRlZCBpbnZhbGlkIHN5bnRheC5cIlxuICAgIH0pXG4gIH1cblxuICBjb25zdCBtZXRob2RzID0gZGVzY2VuZGFudHModHJlZS50b3BOb2RlLCBcIk1ldGhvZERlY2xhcmF0aW9uXCIpXG4gIGNvbnN0IG1haW5NZXRob2QgPSBtZXRob2RzLmZpbmQoKG1ldGhvZCkgPT4gbm9kZVRleHQocmVxdWlyZWRDaGlsZChtZXRob2QsIFwiRGVmaW5pdGlvblwiLCBmaWxlbmFtZSwgc291cmNlKSwgc291cmNlKSA9PSBcIm1haW5cIilcbiAgY29uc3QgZnVuY3Rpb25NZXRob2RzID0gbWV0aG9kcy5maWx0ZXIoKG1ldGhvZCkgPT4gbWV0aG9kICE9IG1haW5NZXRob2QpXG4gIGNvbnN0IGxvY2F0aW9uID0gbW9kdWxlTG9jYXRpb24oZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoZnVuY3Rpb25NZXRob2RzLmxlbmd0aCA9PSAwKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwiY2xhc3Mgd2l0aG91dCBhIHNlbWFudGljIGZ1bmN0aW9uXCIsIGxvY2F0aW9uKVxuICBpZiAoIW1haW5NZXRob2QpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJjbGFzcyB3aXRob3V0IG1haW5cIiwgbG9jYXRpb24pXG5cbiAgY29uc3QgZnVuY3Rpb25zID0gZnVuY3Rpb25NZXRob2RzLm1hcCgobWV0aG9kKSA9PiBjb252ZXJ0RnVuY3Rpb24obWV0aG9kLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgY29uc3QgZW50cnlQb2ludCA9IGNvbnZlcnRFbnRyeVBvaW50KG1haW5NZXRob2QsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgcmV0dXJuIHtlbnRyeVBvaW50LCBmdW5jdGlvbnMsIGtpbmQ6IFwiTW9kdWxlXCIsIGxvY2F0aW9ufVxufVxuIl19