semantifold 0.5.0 → 0.7.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 (201) hide show
  1. package/README.md +15 -9
  2. package/build/index.d.ts +8 -8
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +6 -6
  5. package/build/src/backends/android.js +8 -4
  6. package/build/src/backends/dart.d.ts +19 -0
  7. package/build/src/backends/dart.d.ts.map +1 -1
  8. package/build/src/backends/dart.js +28 -16
  9. package/build/src/backends/flutter.d.ts +51 -0
  10. package/build/src/backends/flutter.d.ts.map +1 -0
  11. package/build/src/backends/flutter.js +1362 -0
  12. package/build/src/backends/identifiers.d.ts +6 -0
  13. package/build/src/backends/identifiers.d.ts.map +1 -1
  14. package/build/src/backends/identifiers.js +28 -5
  15. package/build/src/backends/ios.js +2 -2
  16. package/build/src/backends/native-validation.d.ts +2 -2
  17. package/build/src/backends/native-validation.d.ts.map +1 -1
  18. package/build/src/backends/native-validation.js +2 -2
  19. package/build/src/backends/program.d.ts +4 -4
  20. package/build/src/backends/program.d.ts.map +1 -1
  21. package/build/src/backends/program.js +4 -4
  22. package/build/src/backends/scalars.d.ts.map +1 -1
  23. package/build/src/backends/scalars.js +2 -1
  24. package/build/src/backends/shared.d.ts +7 -0
  25. package/build/src/backends/shared.d.ts.map +1 -1
  26. package/build/src/backends/shared.js +14 -9
  27. package/build/src/backends/zig-runtime.d.ts +5 -0
  28. package/build/src/backends/zig-runtime.d.ts.map +1 -0
  29. package/build/src/backends/zig-runtime.js +92 -0
  30. package/build/src/backends/zig-validation.d.ts +9 -0
  31. package/build/src/backends/zig-validation.d.ts.map +1 -0
  32. package/build/src/backends/zig-validation.js +73 -0
  33. package/build/src/backends/zig.d.ts +42 -0
  34. package/build/src/backends/zig.d.ts.map +1 -0
  35. package/build/src/backends/zig.js +584 -0
  36. package/build/src/frontends/scalars.d.ts.map +1 -1
  37. package/build/src/frontends/scalars.js +2 -1
  38. package/build/src/frontends/zig-parser.d.ts +31 -0
  39. package/build/src/frontends/zig-parser.d.ts.map +1 -0
  40. package/build/src/frontends/zig-parser.js +17 -0
  41. package/build/src/frontends/zig.d.ts +14 -0
  42. package/build/src/frontends/zig.d.ts.map +1 -0
  43. package/build/src/frontends/zig.js +970 -0
  44. package/build/src/language-registry.d.ts.map +1 -1
  45. package/build/src/language-registry.js +40 -1
  46. package/build/src/mapping.js +2 -2
  47. package/build/src/semantic/provenance.js +3 -3
  48. package/build/src/semantic/types.d.ts +154 -4
  49. package/build/src/semantic/types.d.ts.map +1 -1
  50. package/build/src/semantic/types.js +39 -3
  51. package/build/src/semantic/validate.js +2 -2
  52. package/build/src/toolchains.d.ts +6 -0
  53. package/build/src/toolchains.d.ts.map +1 -1
  54. package/build/src/toolchains.js +2 -1
  55. package/build/src/zig-bindings.d.ts +10 -0
  56. package/build/src/zig-bindings.d.ts.map +1 -0
  57. package/build/src/zig-bindings.js +54 -0
  58. package/docs/android.md +7 -3
  59. package/docs/architecture.md +13 -5
  60. package/docs/flutter.md +47 -0
  61. package/docs/goals.md +1 -1
  62. package/docs/language-support.md +16 -5
  63. package/docs/parser-qualification.md +31 -1
  64. package/docs/source-maps.md +7 -3
  65. package/docs/testing.md +47 -4
  66. package/docs/zig.md +33 -0
  67. package/index.js +5 -5
  68. package/node_modules/semantifold-tree-sitter-zig-internal/LICENSE +15 -0
  69. package/node_modules/semantifold-tree-sitter-zig-internal/README.md +5 -0
  70. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/LICENSE +21 -0
  71. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/README.md +21 -0
  72. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/binding.gyp +29 -0
  73. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/bindings/node/binding.cc +20 -0
  74. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/bindings/node/binding_test.js +9 -0
  75. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/bindings/node/index.d.ts +28 -0
  76. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/bindings/node/index.js +11 -0
  77. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/grammar.js +900 -0
  78. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/package.json +57 -0
  79. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/prebuilds/darwin-arm64/@tree-sitter-grammars+tree-sitter-zig.node +0 -0
  80. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/prebuilds/darwin-x64/@tree-sitter-grammars+tree-sitter-zig.node +0 -0
  81. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/prebuilds/linux-arm64/@tree-sitter-grammars+tree-sitter-zig.node +0 -0
  82. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/prebuilds/linux-x64/@tree-sitter-grammars+tree-sitter-zig.node +0 -0
  83. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/prebuilds/win32-arm64/@tree-sitter-grammars+tree-sitter-zig.node +0 -0
  84. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/prebuilds/win32-x64/@tree-sitter-grammars+tree-sitter-zig.node +0 -0
  85. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/queries/folds.scm +23 -0
  86. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/queries/highlights.scm +291 -0
  87. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/queries/indents.scm +22 -0
  88. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/queries/injections.scm +10 -0
  89. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/grammar.json +6570 -0
  90. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/node-types.json +3178 -0
  91. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/parser.c +169829 -0
  92. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/tree_sitter/alloc.h +54 -0
  93. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/tree_sitter/array.h +291 -0
  94. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/tree_sitter/parser.h +266 -0
  95. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/tree-sitter-zig.wasm +0 -0
  96. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/tree-sitter.json +38 -0
  97. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/LICENSE +21 -0
  98. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/README.md +128 -0
  99. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/binding.gyp +80 -0
  100. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/index.js +916 -0
  101. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/package.json +76 -0
  102. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
  103. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
  104. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/linux-arm64/tree-sitter.node +0 -0
  105. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
  106. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/win32-arm64/tree-sitter.node +0 -0
  107. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
  108. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/addon_data.h +47 -0
  109. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/binding.cc +35 -0
  110. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/conversions.cc +140 -0
  111. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/conversions.h +22 -0
  112. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/language.cc +106 -0
  113. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/language.h +17 -0
  114. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/logger.cc +70 -0
  115. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/logger.h +19 -0
  116. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
  117. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
  118. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/node.cc +1088 -0
  119. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/node.h +30 -0
  120. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/parser.cc +306 -0
  121. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/parser.h +35 -0
  122. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/query.cc +397 -0
  123. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/query.h +40 -0
  124. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/tree.cc +316 -0
  125. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/tree.h +45 -0
  126. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
  127. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/tree_cursor.h +52 -0
  128. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/tree-sitter.d.ts +1042 -0
  129. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1318 -0
  130. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
  131. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
  132. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +291 -0
  133. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
  134. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
  135. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
  136. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +501 -0
  137. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
  138. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
  139. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +223 -0
  140. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +297 -0
  141. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
  142. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +435 -0
  143. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +49 -0
  144. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +12 -0
  145. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +920 -0
  146. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2165 -0
  147. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +266 -0
  148. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +62 -0
  149. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/portable/endian.h +206 -0
  150. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4187 -0
  151. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
  152. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
  153. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +899 -0
  154. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +130 -0
  155. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1066 -0
  156. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +399 -0
  157. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +170 -0
  158. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
  159. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +712 -0
  160. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
  161. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/ts_assert.h +11 -0
  162. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
  163. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
  164. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
  165. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
  166. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
  167. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
  168. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
  169. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
  170. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
  171. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +83 -0
  172. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +24 -0
  173. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +109 -0
  174. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1302 -0
  175. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1859 -0
  176. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
  177. package/node_modules/semantifold-tree-sitter-zig-internal/package.json +21 -0
  178. package/node_modules/semantifold-tree-sitter-zig-internal/src/zig.js +134 -0
  179. package/package.json +11 -6
  180. package/src/backends/android.js +7 -3
  181. package/src/backends/dart.js +28 -15
  182. package/src/backends/flutter.js +1465 -0
  183. package/src/backends/identifiers.js +28 -4
  184. package/src/backends/ios.js +1 -1
  185. package/src/backends/native-validation.js +1 -1
  186. package/src/backends/program.js +3 -3
  187. package/src/backends/scalars.js +1 -0
  188. package/src/backends/shared.js +15 -11
  189. package/src/backends/zig-runtime.js +93 -0
  190. package/src/backends/zig-validation.js +68 -0
  191. package/src/backends/zig.js +579 -0
  192. package/src/frontends/scalars.js +1 -0
  193. package/src/frontends/zig-parser.js +20 -0
  194. package/src/frontends/zig.js +994 -0
  195. package/src/language-registry.js +40 -0
  196. package/src/mapping.js +1 -1
  197. package/src/semantic/provenance.js +2 -2
  198. package/src/semantic/types.js +41 -2
  199. package/src/semantic/validate.js +1 -1
  200. package/src/toolchains.js +1 -0
  201. package/src/zig-bindings.js +46 -0
@@ -0,0 +1,1362 @@
1
+ // @ts-check
2
+ import { createHash } from "node:crypto";
3
+ import { isDenseArray } from "../array.js";
4
+ import { findPortableArtifactPathConflict, isSafeArtifactPath } from "../artifact-path.js";
5
+ import { createByteMapping } from "../binary-mapping.js";
6
+ import { SemantifoldDiagnostic, unsupportedCapability } from "../diagnostic.js";
7
+ import { finalizeMapping, toSourceMapV3 } from "../mapping.js";
8
+ import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
9
+ import { dartRuntime } from "./dart-runtime.js";
10
+ import { emitDartBlock, findUnreadDartLocals } from "./dart.js";
11
+ import { preflightSemanticProgram } from "./program.js";
12
+ import { emitScalarType } from "./scalars.js";
13
+ import { SourceWriter } from "./writer.js";
14
+ const projectRoot = "generated/flutter-app";
15
+ const generatorVersion = "0.6.0";
16
+ const flutterToolchain = Object.freeze({
17
+ archive: "flutter_linux_3.47.4-stable.tar.xz",
18
+ archiveSha256: "5b45f0ceda99b9bebdc873e7e69f6450aeb4c30f454b505e2e62fc9255a907d3",
19
+ dart: "3.13.3",
20
+ revision: "9584c6713b324636289d067944a46fd6b49df14b",
21
+ version: "3.47.4"
22
+ });
23
+ const androidToolchain = Object.freeze({
24
+ androidGradlePlugin: "8.11.1",
25
+ buildTools: "35.0.0",
26
+ cmake: "3.22.1",
27
+ compileSdk: 35,
28
+ gradle: "8.14",
29
+ java: "21.0.8",
30
+ kotlinGradlePlugin: "2.2.20",
31
+ minimumSdk: 23,
32
+ ndk: "27.0.12077973",
33
+ targetSdk: 35
34
+ });
35
+ /** @type {readonly (readonly [string, string, string])[]} */
36
+ const flutterLockedHostedPackages = Object.freeze([
37
+ ["async", "2.13.1", "e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37"],
38
+ ["boolean_selector", "2.1.2", "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"],
39
+ ["characters", "1.4.1", "faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b"],
40
+ ["clock", "1.1.3", "e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e"],
41
+ ["collection", "1.19.1", "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"],
42
+ ["fake_async", "1.3.3", "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"],
43
+ ["leak_tracker", "11.0.2", "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"],
44
+ ["leak_tracker_flutter_testing", "3.0.10", "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"],
45
+ ["leak_tracker_testing", "3.0.2", "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"],
46
+ ["matcher", "0.12.20", "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"],
47
+ ["material_color_utilities", "0.13.0", "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"],
48
+ ["meta", "1.19.0", "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9"],
49
+ ["path", "1.9.1", "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"],
50
+ ["source_span", "1.10.2", "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"],
51
+ ["stack_trace", "1.12.2", "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490"],
52
+ ["stream_channel", "2.1.4", "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"],
53
+ ["string_scanner", "1.4.1", "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"],
54
+ ["term_glyph", "1.2.2", "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"],
55
+ ["test_api", "0.7.12", "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"],
56
+ ["vector_math", "2.4.2", "f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47"],
57
+ ["vm_service", "15.3.0", "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0"]
58
+ ]);
59
+ /** @type {readonly (readonly [string, "direct main" | "direct dev" | "transitive"])[]} */
60
+ const flutterLockedSdkPackages = Object.freeze([
61
+ ["flutter", "direct main"],
62
+ ["flutter_test", "direct dev"],
63
+ ["sky_engine", "transitive"]
64
+ ]);
65
+ /** @type {Readonly<Set<import("../semantic/types.js").SemanticLanguage>>} */
66
+ const flutterSourceLanguages = new Set([
67
+ "php", "ruby", "javascript", "typescript", "java", "kotlin", "python", "csharp", "go", "c", "cpp", "rust", "swift", "dart", "zig"
68
+ ]);
69
+ const requestFields = new Set(["assets", "configuration", "language", "module", "program", "role"]);
70
+ const configurationFields = new Set([
71
+ "activityClassName", "applicationId", "buildToolsVersion", "compileSdk", "displayName", "minimumSdk", "organization",
72
+ "packageName", "permissions", "targetSdk", "versionCode", "versionName"
73
+ ]);
74
+ const assetFields = new Set(["content", "mediaType", "path", "sha256"]);
75
+ const dartKeywords = new Set([
76
+ "abstract", "as", "assert", "async", "await", "base", "break", "case", "catch", "class", "const", "continue",
77
+ "covariant", "default", "deferred", "do", "dynamic", "else", "enum", "export", "extends", "extension", "external",
78
+ "factory", "false", "final", "finally", "for", "Function", "get", "hide", "if", "implements", "import", "in",
79
+ "interface", "is", "late", "library", "mixin", "new", "null", "of", "on", "operator", "part", "required",
80
+ "rethrow", "return", "sealed", "set", "show", "static", "super", "switch", "sync", "this", "throw", "true",
81
+ "try", "typedef", "var", "void", "when", "while", "with", "yield"
82
+ ]);
83
+ const javaKeywords = new Set([
84
+ "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default",
85
+ "do", "double", "else", "enum", "extends", "final", "finally", "float", "for", "goto", "if", "implements",
86
+ "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected", "public",
87
+ "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient",
88
+ "try", "void", "volatile", "while"
89
+ ]);
90
+ const forbiddenPackageNames = new Set([
91
+ ...flutterLockedHostedPackages.map(([name]) => name),
92
+ ...flutterLockedSdkPackages.map(([name]) => name),
93
+ "integration_test",
94
+ "semantifold"
95
+ ]);
96
+ const androidRunnerBaseClassNames = new Set(["FlutterActivity"]);
97
+ const semanticVersionPattern = /^(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-(?:0|[1-9][0-9]*|[A-Za-z-][A-Za-z0-9-]*)(?:\.(?:0|[1-9][0-9]*|[A-Za-z-][A-Za-z0-9-]*))*)?(?:\+[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*)?$/u;
98
+ const mediaTypePattern = /^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+(?:[\u0020-\u007e]+)?$/u;
99
+ const excludedPathPatterns = Object.freeze([
100
+ ".dart_tool/**", ".flutter-plugins", ".flutter-plugins-dependencies", "android/.gradle/**", "android/app/build/**",
101
+ "android/local.properties", "build/**"
102
+ ]);
103
+ const outputSinkRuntime = `
104
+ final class _SemantifoldOutputSink {
105
+ final List<String> _values = <String>[];
106
+
107
+ void write(Object value) {
108
+ if (value is! int && value is! bool && value is! String) {
109
+ throw StateError('Unsupported Semantifold output value');
110
+ }
111
+ _values.add(value.toString());
112
+ }
113
+
114
+ List<String> snapshot() => List<String>.unmodifiable(_values);
115
+ }
116
+ `;
117
+ /** @typedef {{content: string | Uint8Array, contentKind: "binary" | "text", fullPath: string, mediaType: string, path: string, sha256: string}} FlutterAsset */
118
+ /** @typedef {{end: number, field: string, path: string, start: number}} ConfigurationSpan */
119
+ /**
120
+ * Preflights a complete Flutter application request before rendering any artifact.
121
+ * @param {Record<string, unknown>} input - Candidate application request.
122
+ * @returns {{assets: FlutterAsset[], configuration: import("../semantic/types.js").FlutterApplicationConfiguration, modulePaths: Map<string, string>, modules: import("../semantic/types.js").SemanticModule[], packagePath: string, program: import("../semantic/types.js").SemanticProgram, sources: {content: string, filename: string, language?: import("../semantic/types.js").SemanticLanguage}[]}} Prepared application.
123
+ */
124
+ export function preflightFlutterApplication(input) {
125
+ if (!isPlainObject(input) || Object.keys(input).some(key => !requestFields.has(key)) ||
126
+ Boolean(input.module) == Boolean(input.program)) {
127
+ invalidInput("Flutter application generation requires a closed request with exactly one semantic module or program.");
128
+ }
129
+ if (input.language !== undefined && input.language != "flutter" || input.role !== undefined && input.role != "application") {
130
+ invalidInput("Flutter application generation accepts only the Flutter application role.");
131
+ }
132
+ const configuration = normalizeConfiguration(input.configuration);
133
+ const program = input.program ?? normalizeSingleModule(
134
+ /** @type {import("../semantic/types.js").SemanticModule | undefined} */ (input.module));
135
+ const prepared = preflightSemanticProgram({
136
+ backendLanguage: "dart",
137
+ diagnosticLanguage: "flutter",
138
+ program: /** @type {import("../semantic/types.js").SemanticProgram} */ (program),
139
+ sourceLanguages: flutterSourceLanguages
140
+ });
141
+ const entryModule = prepared.modules.find(module => Reflect.get(module, "id") == prepared.program.entryModule);
142
+ const entryCollision = entryModule?.functions.find(({ name }) => name == "semantifoldEntry");
143
+ if (entryCollision)
144
+ unsupportedCapability("flutter", "reserved generated semantic entry function 'semantifoldEntry'", entryCollision.location);
145
+ const packagePath = configuration.applicationId.replaceAll(".", "/");
146
+ const modulePaths = new Map(prepared.modules.map(module => {
147
+ const moduleId = /** @type {string} */ (Reflect.get(module, "id"));
148
+ return [moduleId, `${projectRoot}/lib/src/semantic/${moduleFileName(moduleId)}.dart`];
149
+ }));
150
+ const assets = normalizeAssets(input.assets);
151
+ const completePaths = [...applicationPaths(configuration, modulePaths), ...assets.map(({ fullPath }) => fullPath)];
152
+ const conflict = findPortableArtifactPathConflict(completePaths);
153
+ if (conflict) {
154
+ invalidPath(`Application artifact path '${conflict.path}' has a ${conflict.kind} conflict${conflict.other ? ` with '${conflict.other}'` : ""}.`);
155
+ }
156
+ const semanticNames = new Map();
157
+ for (const module of prepared.modules) {
158
+ const moduleId = /** @type {string} */ (Reflect.get(module, "id"));
159
+ const name = moduleName(moduleId);
160
+ const previous = semanticNames.get(name);
161
+ if (previous)
162
+ invalidPath(`Semantic modules '${previous}' and '${moduleId}' collide at generated Dart class '${name}'.`);
163
+ semanticNames.set(name, moduleId);
164
+ }
165
+ return { ...prepared, assets, configuration, modulePaths, packagePath };
166
+ }
167
+ /**
168
+ * Generates one deterministic SDK-only Flutter project for the qualified Android lane.
169
+ * @param {Record<string, unknown>} input - Application generation request.
170
+ * @returns {{artifacts: import("../semantic/types.js").GeneratedSetArtifact[], metadata: {applicationManifest: string, platformQualification: {android: string, ios: string}}, target: "flutter"}} Candidate artifact set.
171
+ */
172
+ export function generateFlutterApplication(input) {
173
+ const prepared = preflightFlutterApplication(input);
174
+ const configurationSpans = /** @type {ConfigurationSpan[]} */ ([]);
175
+ const configuration = prepared.configuration;
176
+ const semanticArtifacts = renderSemanticArtifacts(prepared);
177
+ const artifacts = /** @type {import("../semantic/types.js").GeneratedSetArtifact[]} */ ([
178
+ syntheticText(`${projectRoot}/.metadata`, "manifest", renderMetadata(), "Exact Flutter 3.47.4 project-template identity; generated migration is disabled."),
179
+ syntheticText(`${projectRoot}/analysis_options.yaml`, "support", renderAnalysisOptions(), "Closed analyzer configuration without external lint packages."),
180
+ configuredText(`${projectRoot}/android/app/build.gradle.kts`, "manifest", renderAndroidAppBuild(configuration, configurationSpans), "Task 028-compatible Android build and isolated debug-signing configuration."),
181
+ configuredText(`${projectRoot}/android/app/src/main/AndroidManifest.xml`, "manifest", renderAndroidManifest(configuration, configurationSpans), "Closed permission-free Flutter Android application manifest."),
182
+ configuredText(`${projectRoot}/android/app/src/main/java/${prepared.packagePath}/${configuration.activityClassName}.java`, "support", renderAndroidActivity(configuration, configurationSpans), "Synthetic Flutter Android embedding launcher."),
183
+ syntheticText(`${projectRoot}/android/app/src/main/res/drawable/launch_background.xml`, "resource", renderLaunchBackground(), "Synthetic minimum-SDK-qualified Flutter launch background."),
184
+ syntheticText(`${projectRoot}/android/app/src/main/res/values-night/styles.xml`, "resource", renderAndroidStyles(true), "Synthetic dark platform launch and Flutter host themes."),
185
+ syntheticText(`${projectRoot}/android/app/src/main/res/values/styles.xml`, "resource", renderAndroidStyles(false), "Synthetic light platform launch and Flutter host themes."),
186
+ syntheticText(`${projectRoot}/android/app/src/main/res/xml/backup_rules.xml`, "resource", renderBackupRules(), "Closed API 23-30 full-backup exclusions reused from the Android safety contract."),
187
+ syntheticText(`${projectRoot}/android/app/src/main/res/xml/data_extraction_rules.xml`, "resource", renderDataExtractionRules(), "Closed Android 12+ backup and transfer exclusions reused from the Android safety contract."),
188
+ syntheticText(`${projectRoot}/android/build.gradle.kts`, "manifest", renderAndroidRootBuild(), "Task 028-compatible deterministic Android root build."),
189
+ syntheticText(`${projectRoot}/android/gradle.properties`, "support", renderAndroidGradleProperties(), "Pinned isolated Gradle properties for the qualified Android lane."),
190
+ configuredText(`${projectRoot}/android/settings.gradle.kts`, "manifest", renderAndroidSettings(configuration, configurationSpans), "Exact Flutter Gradle plugin loader with the pinned Task 028 Android plugin matrix."),
191
+ configuredText(`${projectRoot}/lib/main.dart`, "entry", renderWidgetApplication(prepared, configurationSpans), "Synthetic stateless Material application and labelled output widget."),
192
+ ...semanticArtifacts,
193
+ syntheticText(`${projectRoot}/pubspec.lock`, "manifest", renderPubspecLock(), "Exact Flutter 3.47.4 SDK dependency resolution; no caller package resolution."),
194
+ configuredText(`${projectRoot}/pubspec.yaml`, "manifest", renderPubspec(prepared, configurationSpans), "Closed SDK-only Flutter package and asset manifest."),
195
+ configuredText(`${projectRoot}/test/semantic_logic_test.dart`, "support", renderLogicTest(prepared, configurationSpans), "SDK-owned Flutter test for fresh deterministic semantic entry execution."),
196
+ configuredText(`${projectRoot}/test/widget_test.dart`, "support", renderWidgetTest(prepared, configurationSpans), "SDK-owned Flutter widget test for exact text, key, and semantics label."),
197
+ ...prepared.assets.map(assetArtifact)
198
+ ]);
199
+ artifacts.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
200
+ const manifestPath = `${projectRoot}/semantifold-project.json`;
201
+ artifacts.push(syntheticText(manifestPath, "manifest", renderProjectManifest(prepared, artifacts, manifestPath, configurationSpans), "Versioned Flutter project ownership, toolchain, provenance, and platform-status manifest."));
202
+ return {
203
+ artifacts,
204
+ metadata: {
205
+ applicationManifest: manifestPath,
206
+ platformQualification: { android: "tensorbuzz-kvm", ios: "deferred-owner-direction" }
207
+ },
208
+ target: "flutter"
209
+ };
210
+ }
211
+ /**
212
+ * Emits mapped application-owned Dart semantic modules.
213
+ * @param {ReturnType<typeof preflightFlutterApplication>} prepared - Prepared application.
214
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact[]} Semantic Dart artifacts.
215
+ */
216
+ function renderSemanticArtifacts(prepared) {
217
+ const declarations = new Map();
218
+ for (const module of prepared.modules) {
219
+ for (const declaration of module.functions)
220
+ declarations.set(declaration.id, {
221
+ declaration,
222
+ moduleId: /** @type {string} */ (Reflect.get(module, "id"))
223
+ });
224
+ }
225
+ /** @type {import("../semantic/types.js").GeneratedSetArtifact[]} */
226
+ const artifacts = [syntheticText(`${projectRoot}/lib/src/semantic/semantifold.dart`, "support", renderSemanticLibrary(prepared), "Shared checked Dart scalar/output runtime and deterministic part ownership.")];
227
+ for (const module of prepared.modules) {
228
+ const moduleId = /** @type {string} */ (Reflect.get(module, "id"));
229
+ const filename = /** @type {string} */ (prepared.modulePaths.get(moduleId));
230
+ const sinkName = outputSinkName(module);
231
+ const writer = new SourceWriter({
232
+ callArgumentSuffix: sinkName,
233
+ callNameResolver: expression => {
234
+ const resolved = declarations.get(expression.resolution?.declarationId);
235
+ if (!resolved)
236
+ throw new TypeError(`Unknown validated Flutter function '${expression.resolution?.declarationId}'.`);
237
+ return `SemantifoldModule${moduleName(resolved.moduleId)}.${resolved.declaration.name}`;
238
+ },
239
+ filename,
240
+ language: "dart",
241
+ module,
242
+ program: prepared.program,
243
+ programPaths: prepared.modulePaths,
244
+ sources: prepared.sources
245
+ });
246
+ writer.synthetic("part of 'semantifold.dart';\n\n", "Flutter semantic library part directive", [module], [""]);
247
+ emitSemanticModule(writer, module, moduleId, moduleId == prepared.program.entryModule, sinkName);
248
+ const mapping = finalizeMapping(writer.finish());
249
+ artifacts.push({
250
+ content: mapping.generated.content,
251
+ contentKind: "text",
252
+ mediaType: "text/x-dart",
253
+ ownership: "generated",
254
+ path: filename,
255
+ provenance: { kind: "text", mapping, sourceMap: toSourceMapV3(mapping), sourceMapFilename: `${filename}.map` },
256
+ role: "source"
257
+ });
258
+ }
259
+ return artifacts;
260
+ }
261
+ /**
262
+ * Emits one namespaced semantic Dart part.
263
+ * @param {SourceWriter} writer - Mapped source writer.
264
+ * @param {import("../semantic/types.js").SemanticModule} module - Prepared semantic module.
265
+ * @param {string} moduleId - Stable semantic module identity.
266
+ * @param {boolean} entry - Whether this module owns the application entry.
267
+ * @param {string} sinkName - Collision-safe output sink binding.
268
+ */
269
+ function emitSemanticModule(writer, module, moduleId, entry, sinkName) {
270
+ const unreadLocals = findUnreadDartLocals(module);
271
+ writer.synthetic(`abstract final class SemantifoldModule${moduleName(moduleId)} {\n`, "Flutter semantic module namespace", [module], [""]);
272
+ module.functions.forEach((declaration, functionIndex) => {
273
+ const path = `/functions/${functionIndex}`;
274
+ writer.synthetic(" static ", "Flutter namespaced function scaffold", [declaration], [path]);
275
+ writer.mapped(emitScalarType("dart", declaration.returnType), {
276
+ mappingKind: "exact", node: declaration.returnType, path: `${path}/returnType`, role: "type"
277
+ });
278
+ writer.synthetic(" ", "declaration spacing", [declaration], [path]);
279
+ writer.mapped(declaration.name, { mappingKind: "exact", node: declaration, path, role: "name" });
280
+ const parameterTexts = declaration.parameters.map(parameter => `${emitScalarType("dart", parameter.type)} ${parameter.name}`);
281
+ parameterTexts.push(`_SemantifoldOutputSink ${sinkName}`);
282
+ const multiline = writer.column - 1 + `(${parameterTexts.join(", ")}) {`.length > 80;
283
+ writer.mapped("(", { mappingKind: "anchor", node: declaration, path });
284
+ declaration.parameters.forEach((parameter, parameterIndex) => {
285
+ const parameterPath = `${path}/parameters/${parameterIndex}`;
286
+ if (multiline)
287
+ writer.synthetic(`${parameterIndex ? "" : "\n"} `, "Dart application parameter indentation", [parameter], [parameterPath]);
288
+ else if (parameterIndex)
289
+ writer.synthetic(", ", "parameter separator", [parameter], [parameterPath]);
290
+ writer.mapped(emitScalarType("dart", parameter.type), {
291
+ mappingKind: "exact", node: parameter.type, path: `${parameterPath}/type`, role: "type"
292
+ });
293
+ writer.synthetic(" ", "parameter spacing", [parameter], [parameterPath]);
294
+ writer.mapped(parameter.name, { mappingKind: "exact", node: parameter, path: parameterPath, role: "name" });
295
+ if (multiline)
296
+ writer.synthetic(",\n", "Dart formatter parameter separator", [parameter], [parameterPath]);
297
+ });
298
+ if (multiline)
299
+ writer.synthetic(`${declaration.parameters.length ? "" : "\n"} _SemantifoldOutputSink ${sinkName},\n `, "Flutter output sink parameter", [declaration], [path]);
300
+ else
301
+ writer.synthetic(`${declaration.parameters.length ? ", " : ""}_SemantifoldOutputSink ${sinkName}`, "Flutter output sink parameter", [declaration], [path]);
302
+ writer.mapped(")", { mappingKind: "anchor", node: declaration, path });
303
+ writer.synthetic(" {\n", "Dart function body scaffold", [declaration], [path]);
304
+ emitDartBlock(writer, declaration.body, " ", `${path}/body`, unreadLocals, `${sinkName}.write`, true);
305
+ writer.synthetic(" }\n", "Dart function body scaffold", [declaration], [path]);
306
+ if (functionIndex + 1 < module.functions.length || entry) {
307
+ writer.synthetic("\n", "Dart formatter declaration separator", [declaration], [path]);
308
+ }
309
+ });
310
+ if (entry) {
311
+ writer.synthetic(" static List<String> semantifoldEntry() {\n", "Flutter semantic entry scaffold", [module.entryPoint], ["/entryPoint"]);
312
+ writer.synthetic(` final _SemantifoldOutputSink ${sinkName} = _SemantifoldOutputSink();\n`, "Flutter output sink allocation", [module.entryPoint], ["/entryPoint"]);
313
+ emitDartBlock(writer, module.entryPoint.body, " ", "/entryPoint/body", unreadLocals, `${sinkName}.write`, true);
314
+ writer.synthetic(` return ${sinkName}.snapshot();\n`, "Flutter semantic output return", [module.entryPoint], ["/entryPoint"]);
315
+ writer.synthetic(" }\n", "Flutter semantic entry scaffold", [module.entryPoint], ["/entryPoint"]);
316
+ }
317
+ writer.synthetic("}\n", "Flutter semantic module namespace", [module], [""]);
318
+ }
319
+ /**
320
+ * Renders the shared semantic Dart library.
321
+ * @param {ReturnType<typeof preflightFlutterApplication>} prepared - Prepared project.
322
+ * @returns {string} Dart library source.
323
+ */
324
+ function renderSemanticLibrary(prepared) {
325
+ const parts = prepared.modules.map(module => `part '${moduleFileName(/** @type {string} */ (Reflect.get(module, "id")))}.dart';`).join("\n");
326
+ return `${parts}\n\n${dartRuntime}${outputSinkRuntime}`;
327
+ }
328
+ /**
329
+ * Renders exact Flutter template identity metadata.
330
+ * @returns {string} Metadata YAML.
331
+ */
332
+ function renderMetadata() {
333
+ return `# This file tracks properties of this Semantifold-owned Flutter project.
334
+ version:
335
+ revision: ${flutterToolchain.revision}
336
+ channel: stable
337
+ project_type: app
338
+ `;
339
+ }
340
+ /**
341
+ * Renders the closed analyzer configuration.
342
+ * @returns {string} Analyzer YAML.
343
+ */
344
+ function renderAnalysisOptions() {
345
+ return `analyzer:
346
+ language:
347
+ strict-casts: true
348
+ strict-raw-types: true
349
+ `;
350
+ }
351
+ /**
352
+ * Renders the SDK-only package manifest.
353
+ * @param {ReturnType<typeof preflightFlutterApplication>} prepared - Prepared project.
354
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
355
+ * @returns {string} Pubspec YAML.
356
+ */
357
+ function renderPubspec(prepared, spans) {
358
+ const configuration = prepared.configuration;
359
+ const assetLines = prepared.assets.length == 0 ? "" : `\n assets:\n${prepared.assets.map(({ path }) => ` - ${path}`).join("\n")}\n`;
360
+ return configured(`${projectRoot}/pubspec.yaml`, spans, [
361
+ "name: ", field("packageName", configuration.packageName), "\npublish_to: none\nversion: ",
362
+ field("versionName", configuration.versionName), "+", field("versionCode", String(configuration.versionCode)),
363
+ "\nenvironment:\n sdk: 3.13.3\n flutter: 3.47.4\ndependencies:\n flutter:\n sdk: flutter\ndev_dependencies:\n flutter_test:\n sdk: flutter\nflutter:\n uses-material-design: true\n",
364
+ assetLines
365
+ ]);
366
+ }
367
+ /**
368
+ * Renders the exact Flutter SDK dependency lock.
369
+ * @returns {string} Pub lock YAML.
370
+ */
371
+ function renderPubspecLock() {
372
+ const hosted = new Map(flutterLockedHostedPackages.map(package_ => [package_[0], package_]));
373
+ const sdk = new Map(flutterLockedSdkPackages);
374
+ const packageNames = [...hosted.keys(), ...sdk.keys()].sort();
375
+ const packages = packageNames.map(name => {
376
+ const sdkDependency = sdk.get(name);
377
+ if (sdkDependency)
378
+ return ` ${name}:
379
+ dependency: ${sdkDependency == "transitive" ? sdkDependency : `"${sdkDependency}"`}
380
+ description: flutter
381
+ source: sdk
382
+ version: "0.0.0"`;
383
+ const locked = hosted.get(name);
384
+ if (!locked)
385
+ throw new TypeError(`Missing validated Flutter lock entry '${name}'.`);
386
+ const [, version, sha256] = locked;
387
+ const renderedHash = /^[0-9]/u.test(sha256) ? `"${sha256}"` : sha256;
388
+ return ` ${name}:
389
+ dependency: transitive
390
+ description:
391
+ name: ${name}
392
+ sha256: ${renderedHash}
393
+ url: "https://pub.dev"
394
+ source: hosted
395
+ version: "${version}"`;
396
+ }).join("\n");
397
+ return `# Generated by pub
398
+ # See https://dart.dev/tools/pub/glossary#lockfile
399
+ packages:
400
+ ${packages}
401
+ sdks:
402
+ dart: "3.13.3"
403
+ flutter: "3.47.4"
404
+ `;
405
+ }
406
+ /**
407
+ * Renders the synthetic Material widget shell.
408
+ * @param {ReturnType<typeof preflightFlutterApplication>} prepared - Prepared project.
409
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
410
+ * @returns {string} Flutter entry source.
411
+ */
412
+ function renderWidgetApplication(prepared, spans) {
413
+ const entryClass = `SemantifoldModule${moduleName(prepared.program.entryModule)}`;
414
+ return configured(`${projectRoot}/lib/main.dart`, spans, [
415
+ `import 'package:flutter/material.dart';
416
+
417
+ import 'src/semantic/semantifold.dart';
418
+
419
+ void main() {
420
+ runApp(const SemantifoldApplication());
421
+ }
422
+
423
+ class SemantifoldApplication extends StatelessWidget {
424
+ const SemantifoldApplication({super.key});
425
+
426
+ @override
427
+ Widget build(BuildContext context) {
428
+ final List<String> lines = ${entryClass}.semantifoldEntry();
429
+
430
+ return MaterialApp(
431
+ debugShowCheckedModeBanner: false,
432
+ title: '`, field("displayName", dartEscape(prepared.configuration.displayName)), `',
433
+ home: Scaffold(
434
+ body: Center(
435
+ child: Semantics(
436
+ key: const Key('semantifold-output'),
437
+ container: true,
438
+ explicitChildNodes: true,
439
+ label: 'semantifold-output',
440
+ child: Text(lines.join('\\n')),
441
+ ),
442
+ ),
443
+ ),
444
+ );
445
+ }
446
+ }
447
+ `
448
+ ]);
449
+ }
450
+ /**
451
+ * Renders the semantic-entry determinism test.
452
+ * @param {ReturnType<typeof preflightFlutterApplication>} prepared - Prepared project.
453
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
454
+ * @returns {string} Flutter test source.
455
+ */
456
+ function renderLogicTest(prepared, spans) {
457
+ const entryClass = `SemantifoldModule${moduleName(prepared.program.entryModule)}`;
458
+ return configured(`${projectRoot}/test/semantic_logic_test.dart`, spans, [
459
+ "import 'package:flutter_test/flutter_test.dart';\nimport 'package:", field("packageName", prepared.configuration.packageName),
460
+ `/src/semantic/semantifold.dart';
461
+
462
+ void main() {
463
+ test('semantic entry is deterministic across fresh runs', () {
464
+ expect(
465
+ ${entryClass}.semantifoldEntry(),
466
+ ${entryClass}.semantifoldEntry(),
467
+ );
468
+ });
469
+ }
470
+ `
471
+ ]);
472
+ }
473
+ /**
474
+ * Renders the exact labelled widget test.
475
+ * @param {ReturnType<typeof preflightFlutterApplication>} prepared - Prepared project.
476
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
477
+ * @returns {string} Flutter widget test source.
478
+ */
479
+ function renderWidgetTest(prepared, spans) {
480
+ const entryClass = `SemantifoldModule${moduleName(prepared.program.entryModule)}`;
481
+ return configured(`${projectRoot}/test/widget_test.dart`, spans, [
482
+ "import 'package:flutter/material.dart';\nimport 'package:flutter_test/flutter_test.dart';\nimport 'package:",
483
+ field("packageName", prepared.configuration.packageName), `/main.dart';
484
+ import 'package:`, field("packageName", prepared.configuration.packageName), `/src/semantic/semantifold.dart';
485
+
486
+ void main() {
487
+ testWidgets('renders exact labelled semantic output', (
488
+ WidgetTester tester,
489
+ ) async {
490
+ final String expected = ${entryClass}.semantifoldEntry().join('\\n');
491
+
492
+ await tester.pumpWidget(const SemantifoldApplication());
493
+ final Finder output = find.byKey(const Key('semantifold-output'));
494
+
495
+ expect(output, findsOneWidget);
496
+ expect(
497
+ tester.widget<Semantics>(output).properties.label,
498
+ 'semantifold-output',
499
+ );
500
+ expect(
501
+ find.descendant(of: output, matching: find.text(expected)),
502
+ findsOneWidget,
503
+ );
504
+ });
505
+ }
506
+ `
507
+ ]);
508
+ }
509
+ /**
510
+ * Renders the shared Android root build.
511
+ * @returns {string} Gradle Kotlin source.
512
+ */
513
+ function renderAndroidRootBuild() {
514
+ return `allprojects {
515
+ repositories {
516
+ google()
517
+ mavenCentral()
518
+ }
519
+ }
520
+
521
+ val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
522
+ rootProject.layout.buildDirectory.value(newBuildDir)
523
+
524
+ subprojects {
525
+ project.layout.buildDirectory.value(newBuildDir.dir(project.name))
526
+ project.evaluationDependsOn(":app")
527
+ }
528
+
529
+ tasks.register<Delete>("clean") {
530
+ delete(rootProject.layout.buildDirectory)
531
+ }
532
+ `;
533
+ }
534
+ /**
535
+ * Renders Flutter plugin and Android plugin ownership.
536
+ * @param {import("../semantic/types.js").FlutterApplicationConfiguration} configuration - Normalized configuration.
537
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
538
+ * @returns {string} Gradle settings source.
539
+ */
540
+ function renderAndroidSettings(configuration, spans) {
541
+ return configured(`${projectRoot}/android/settings.gradle.kts`, spans, [`pluginManagement {
542
+ val flutterSdkPath = run {
543
+ val properties = java.util.Properties()
544
+ file("local.properties").inputStream().use { properties.load(it) }
545
+ requireNotNull(properties.getProperty("flutter.sdk")) { "flutter.sdk not set in local.properties" }
546
+ }
547
+
548
+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
549
+
550
+ repositories {
551
+ google()
552
+ mavenCentral()
553
+ gradlePluginPortal()
554
+ }
555
+ }
556
+
557
+ plugins {
558
+ id("dev.flutter.flutter-plugin-loader") version "1.0.0"
559
+ id("com.android.application") version "${androidToolchain.androidGradlePlugin}" apply false
560
+ id("org.jetbrains.kotlin.android") version "${androidToolchain.kotlinGradlePlugin}" apply false
561
+ }
562
+
563
+ rootProject.name = "`, field("packageName", configuration.packageName), `"
564
+ include(":app")
565
+ `]);
566
+ }
567
+ /**
568
+ * Renders deterministic Android Gradle properties.
569
+ * @returns {string} Gradle properties.
570
+ */
571
+ function renderAndroidGradleProperties() {
572
+ return `android.builtInKotlin=false
573
+ android.newDsl=false
574
+ android.useAndroidX=true
575
+ kotlin.stdlib.default.dependency=false
576
+ org.gradle.caching=false
577
+ org.gradle.configuration-cache=false
578
+ org.gradle.daemon=false
579
+ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -Duser.language=en -Duser.country=US -Duser.timezone=UTC
580
+ org.gradle.parallel=false
581
+ `;
582
+ }
583
+ /**
584
+ * Renders the Flutter Android application build.
585
+ * @param {import("../semantic/types.js").FlutterApplicationConfiguration} configuration - Normalized configuration.
586
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
587
+ * @returns {string} Application Gradle source.
588
+ */
589
+ function renderAndroidAppBuild(configuration, spans) {
590
+ return configured(`${projectRoot}/android/app/build.gradle.kts`, spans, [`plugins {
591
+ id("com.android.application")
592
+ id("org.jetbrains.kotlin.android")
593
+ id("dev.flutter.flutter-gradle-plugin")
594
+ }
595
+
596
+ val semantifoldAcceptanceRoot = providers.environmentVariable("SEMANTIFOLD_FLUTTER_ACCEPTANCE_ROOT").orNull
597
+ ?: throw GradleException("SEMANTIFOLD_FLUTTER_INFRASTRUCTURE: SEMANTIFOLD_FLUTTER_ACCEPTANCE_ROOT is required")
598
+ val semantifoldDebugKeystore = file("$semantifoldAcceptanceRoot/debug.keystore")
599
+ if (!semantifoldDebugKeystore.isFile) {
600
+ throw GradleException("SEMANTIFOLD_FLUTTER_INFRASTRUCTURE: ephemeral debug keystore is missing")
601
+ }
602
+
603
+ configurations.configureEach {
604
+ exclude(group = "androidx.profileinstaller", module = "profileinstaller")
605
+ }
606
+
607
+ android {
608
+ namespace = "`, field("applicationId", configuration.applicationId), `"
609
+ compileSdk = `, field("compileSdk", String(configuration.compileSdk)), `
610
+ buildToolsVersion = "`, field("buildToolsVersion", configuration.buildToolsVersion), `"
611
+ ndkVersion = "${androidToolchain.ndk}"
612
+
613
+ defaultConfig {
614
+ applicationId = "`, field("applicationId", configuration.applicationId), `"
615
+ minSdk = `, field("minimumSdk", String(configuration.minimumSdk)), `
616
+ targetSdk = `, field("targetSdk", String(configuration.targetSdk)), `
617
+ versionCode = `, field("versionCode", String(configuration.versionCode)), `
618
+ versionName = "`, field("versionName", configuration.versionName), `"
619
+ }
620
+
621
+ signingConfigs {
622
+ getByName("debug") {
623
+ storeFile = semantifoldDebugKeystore
624
+ storePassword = "android"
625
+ keyAlias = "androiddebugkey"
626
+ keyPassword = "android"
627
+ }
628
+ }
629
+
630
+ buildTypes {
631
+ getByName("debug") {
632
+ signingConfig = signingConfigs.getByName("debug")
633
+ }
634
+ }
635
+
636
+ buildFeatures {
637
+ buildConfig = false
638
+ }
639
+
640
+ compileOptions {
641
+ sourceCompatibility = JavaVersion.VERSION_17
642
+ targetCompatibility = JavaVersion.VERSION_17
643
+ }
644
+
645
+ lint {
646
+ abortOnError = true
647
+ checkDependencies = true
648
+ disable += "MissingApplicationIcon"
649
+ disable += "OldTargetApi"
650
+ disable += "GradleDependency"
651
+ warningsAsErrors = true
652
+ }
653
+ }
654
+
655
+ flutter {
656
+ source = "../.."
657
+ }
658
+ `]);
659
+ }
660
+ /**
661
+ * Renders the permission-free Android manifest.
662
+ * @param {import("../semantic/types.js").FlutterApplicationConfiguration} configuration - Normalized configuration.
663
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
664
+ * @returns {string} Android manifest XML.
665
+ */
666
+ function renderAndroidManifest(configuration, spans) {
667
+ return configured(`${projectRoot}/android/app/src/main/AndroidManifest.xml`, spans, [
668
+ `<manifest
669
+ xmlns:android="http://schemas.android.com/apk/res/android"
670
+ xmlns:tools="http://schemas.android.com/tools">
671
+ <permission tools:node="removeAll" />
672
+ <uses-permission tools:node="removeAll" />
673
+ <application
674
+ android:allowBackup="false"
675
+ android:dataExtractionRules="@xml/data_extraction_rules"
676
+ android:fullBackupContent="@xml/backup_rules"
677
+ android:label="`, field("displayName", xmlEscape(configuration.displayName)), `"
678
+ android:name="\${applicationName}"
679
+ android:supportsRtl="true">
680
+ <activity
681
+ android:name=".`, field("activityClassName", configuration.activityClassName), `"
682
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
683
+ android:exported="true"
684
+ android:hardwareAccelerated="true"
685
+ android:launchMode="singleTop"
686
+ android:taskAffinity=""
687
+ android:theme="@style/LaunchTheme"
688
+ android:windowSoftInputMode="adjustResize">
689
+ <meta-data
690
+ android:name="io.flutter.embedding.android.NormalTheme"
691
+ android:resource="@style/NormalTheme" />
692
+ <intent-filter>
693
+ <action android:name="android.intent.action.MAIN" />
694
+ <category android:name="android.intent.category.LAUNCHER" />
695
+ </intent-filter>
696
+ </activity>
697
+ <meta-data android:name="flutterEmbedding" android:value="2" />
698
+ <provider android:name="androidx.startup.InitializationProvider" tools:node="remove" />
699
+ </application>
700
+ </manifest>
701
+ `
702
+ ]);
703
+ }
704
+ /**
705
+ * Renders the Java Flutter activity launcher.
706
+ * @param {import("../semantic/types.js").FlutterApplicationConfiguration} configuration - Normalized configuration.
707
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
708
+ * @returns {string} Java source.
709
+ */
710
+ function renderAndroidActivity(configuration, spans) {
711
+ return configured(`${projectRoot}/android/app/src/main/java/${configuration.applicationId.replaceAll(".", "/")}/${configuration.activityClassName}.java`, spans, [
712
+ "package ", field("applicationId", configuration.applicationId), `;
713
+
714
+ import io.flutter.embedding.android.FlutterActivity;
715
+
716
+ public final class `, field("activityClassName", configuration.activityClassName), ` extends FlutterActivity {
717
+ }
718
+ `
719
+ ]);
720
+ }
721
+ /**
722
+ * Renders platform launch and host styles.
723
+ * @param {boolean} night - Whether to render the night theme.
724
+ * @returns {string} Android resource XML.
725
+ */
726
+ function renderAndroidStyles(night) {
727
+ return `<?xml version="1.0" encoding="utf-8"?>
728
+ <resources>
729
+ <style name="LaunchTheme" parent="@android:style/Theme.${night ? "Black" : "Light"}.NoTitleBar">
730
+ <item name="android:windowBackground">@drawable/launch_background</item>
731
+ </style>
732
+ <style name="NormalTheme" parent="@android:style/Theme.${night ? "Black" : "Light"}.NoTitleBar">
733
+ <item name="android:windowBackground">?android:colorBackground</item>
734
+ </style>
735
+ </resources>
736
+ `;
737
+ }
738
+ /**
739
+ * Renders a platform launch background.
740
+ * @returns {string} Android resource XML.
741
+ */
742
+ function renderLaunchBackground() {
743
+ return `<?xml version="1.0" encoding="utf-8"?>
744
+ <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
745
+ <item android:drawable="?android:colorBackground" />
746
+ </layer-list>
747
+ `;
748
+ }
749
+ /**
750
+ * Renders complete legacy backup exclusions.
751
+ * @returns {string} Android resource XML.
752
+ */
753
+ function renderBackupRules() {
754
+ return `<?xml version="1.0" encoding="utf-8"?>
755
+ <full-backup-content>
756
+ <exclude domain="root" path="." />
757
+ <exclude domain="file" path="." />
758
+ <exclude domain="database" path="." />
759
+ <exclude domain="sharedpref" path="." />
760
+ <exclude domain="external" path="." />
761
+ <exclude domain="device_root" path="." />
762
+ <exclude domain="device_file" path="." />
763
+ <exclude domain="device_database" path="." />
764
+ <exclude domain="device_sharedpref" path="." />
765
+ </full-backup-content>
766
+ `;
767
+ }
768
+ /**
769
+ * Renders complete Android 12+ backup exclusions.
770
+ * @returns {string} Android resource XML.
771
+ */
772
+ function renderDataExtractionRules() {
773
+ const exclusions = ["root", "file", "database", "sharedpref", "external", "device_root", "device_file", "device_database", "device_sharedpref"]
774
+ .map(domain => ` <exclude domain="${domain}" path="." />`).join("\n");
775
+ return `<?xml version="1.0" encoding="utf-8"?>
776
+ <data-extraction-rules>
777
+ <cloud-backup>
778
+ ${exclusions}
779
+ </cloud-backup>
780
+ <device-transfer>
781
+ ${exclusions}
782
+ </device-transfer>
783
+ </data-extraction-rules>
784
+ `;
785
+ }
786
+ /**
787
+ * Renders the ownership, toolchain, provenance, and platform-status manifest.
788
+ * @param {ReturnType<typeof preflightFlutterApplication>} prepared - Prepared application.
789
+ * @param {import("../semantic/types.js").GeneratedSetArtifact[]} artifacts - Owned artifacts except this manifest.
790
+ * @param {string} manifestPath - Manifest artifact path.
791
+ * @param {ConfigurationSpan[]} spans - Configuration provenance spans.
792
+ * @returns {string} Canonical manifest JSON.
793
+ */
794
+ function renderProjectManifest(prepared, artifacts, manifestPath, spans) {
795
+ const inputPaths = new Set(prepared.assets.map(({ fullPath }) => fullPath));
796
+ const semanticArtifacts = artifacts.filter(artifact => artifact.provenance.kind == "text");
797
+ return stringifyCanonicalJson({
798
+ configuration: prepared.configuration,
799
+ generator: { name: "semantifold", version: generatorVersion },
800
+ ownership: {
801
+ excludedPathPatterns,
802
+ ownedPaths: [...artifacts.map(({ path }) => path), manifestPath],
803
+ ownedRoot: projectRoot,
804
+ sha256: artifacts.map(artifact => ({ path: artifact.path, sha256: hashContent(artifact.content) }))
805
+ },
806
+ platforms: {
807
+ android: { acceptance: "tensorbuzz-kvm", artifacts: "generated" },
808
+ ios: {
809
+ acceptance: "deferred",
810
+ artifacts: "omitted",
811
+ reason: "Owner direction defers macOS, Xcode, Apple SDK, signing, and iOS Simulator qualification."
812
+ }
813
+ },
814
+ provenance: {
815
+ configuration: Object.keys(prepared.configuration).sort().map(fieldName => ({
816
+ field: fieldName,
817
+ manifestPointer: `/configuration/${fieldName}`,
818
+ outputs: configurationOutputs(spans, fieldName)
819
+ })),
820
+ inputs: prepared.assets.map(asset => ({
821
+ contentKind: asset.contentKind,
822
+ mediaType: asset.mediaType,
823
+ path: asset.fullPath,
824
+ sha256: asset.sha256
825
+ })),
826
+ semanticSources: prepared.sources.map(source => ({
827
+ artifacts: semanticArtifacts.filter(artifact => artifact.provenance.kind == "text" &&
828
+ artifact.provenance.mapping.spans.some(({ origin }) => originReferencesFilename(origin, source.filename)))
829
+ .map(({ path }) => path),
830
+ filename: source.filename,
831
+ ...(source.language === undefined ? {} : { language: source.language }),
832
+ sha256: createHash("sha256").update(source.content).digest("hex")
833
+ })),
834
+ syntheticScaffolding: [...artifacts.filter(artifact => artifact.provenance.kind == "synthetic" &&
835
+ !inputPaths.has(artifact.path)).map(({ path }) => path), manifestPath]
836
+ },
837
+ schema: "SemantifoldFlutterProject",
838
+ semanticProgram: semanticProgramManifest(prepared),
839
+ target: "flutter",
840
+ toolchain: { android: androidToolchain, flutter: flutterToolchain },
841
+ version: 1
842
+ });
843
+ }
844
+ /**
845
+ * Describes the complete semantic program inside the application manifest.
846
+ * @param {ReturnType<typeof preflightFlutterApplication>} prepared - Prepared project.
847
+ * @returns {Record<string, unknown>} Semantic program manifest.
848
+ */
849
+ function semanticProgramManifest(prepared) {
850
+ const sourceContent = new Map(prepared.sources.map(source => [source.filename, source.content]));
851
+ const order = new Map(prepared.program.modules.map((module, index) => [module.id, index]));
852
+ const modules = prepared.program.modules.map(module => {
853
+ const source = prepared.program.sources.find(candidate => candidate.filename == module.sourceFilename);
854
+ const content = sourceContent.get(module.sourceFilename);
855
+ if (!source || content === undefined)
856
+ throw new TypeError(`Preflighted Flutter module '${module.id}' lost source ownership.`);
857
+ return {
858
+ dependencies: [...new Set(module.imports.map(({ moduleId }) => moduleId))]
859
+ .sort((left, right) => /** @type {number} */ (order.get(left)) - /** @type {number} */ (order.get(right))),
860
+ generatedArtifacts: [prepared.modulePaths.get(module.id)],
861
+ id: module.id,
862
+ namespace: `SemantifoldModule${moduleName(module.id)}`,
863
+ source: { filename: source.filename, id: source.id, sha256: createHash("sha256").update(content).digest("hex") }
864
+ };
865
+ });
866
+ const entryId = prepared.program.entryModule;
867
+ return {
868
+ entry: {
869
+ generatedArtifact: prepared.modulePaths.get(entryId),
870
+ generatedFunctionIdentity: `SemantifoldModule${moduleName(entryId)}.semantifoldEntry`,
871
+ moduleId: entryId,
872
+ widgetArtifact: `${projectRoot}/lib/main.dart`
873
+ },
874
+ modules,
875
+ schema: "SemantifoldFlutterSemanticProgram",
876
+ sources: prepared.program.sources.map(source => ({
877
+ filename: source.filename,
878
+ id: source.id,
879
+ language: source.language,
880
+ moduleIds: modules.filter(module => module.source.filename == source.filename).map(({ id }) => id),
881
+ ownership: source.ownership ?? "application",
882
+ sha256: createHash("sha256").update(/** @type {string} */ (sourceContent.get(source.filename))).digest("hex")
883
+ })),
884
+ version: 1
885
+ };
886
+ }
887
+ /**
888
+ * Normalizes and validates the closed application configuration.
889
+ * @param {unknown} candidate - Candidate configuration.
890
+ * @returns {import("../semantic/types.js").FlutterApplicationConfiguration} Normalized configuration.
891
+ */
892
+ function normalizeConfiguration(candidate) {
893
+ if (candidate === undefined)
894
+ candidate = {};
895
+ if (!isPlainObject(candidate) || Object.keys(candidate).some(key => !configurationFields.has(key))) {
896
+ invalidConfiguration("Flutter application configuration must be a closed plain object.");
897
+ }
898
+ const configuration = /** @type {import("../semantic/types.js").FlutterApplicationConfigurationInput} */ (candidate);
899
+ const packageName = configuration.packageName ?? "semantifold_generated";
900
+ const organization = configuration.organization ?? "dev.semantifold";
901
+ const applicationId = configuration.applicationId ?? `${organization}.generated`;
902
+ const activityClassName = configuration.activityClassName ?? "MainActivity";
903
+ const displayName = configuration.displayName ?? "Semantifold";
904
+ const minimumSdk = configuration.minimumSdk ?? 23;
905
+ const targetSdk = configuration.targetSdk ?? 35;
906
+ const compileSdk = configuration.compileSdk ?? 35;
907
+ const buildToolsVersion = configuration.buildToolsVersion ?? "35.0.0";
908
+ const versionCode = configuration.versionCode ?? 1;
909
+ const versionName = configuration.versionName ?? "1.0.0";
910
+ if (typeof packageName != "string" || !/^[a-z][a-z0-9_]*$/u.test(packageName) || dartKeywords.has(packageName) ||
911
+ forbiddenPackageNames.has(packageName))
912
+ invalidConfiguration("Dart package name must be a non-reserved lowercase underscore identifier.");
913
+ if (typeof organization != "string" || !isReverseDns(organization, 2)) {
914
+ invalidConfiguration("Organization must be a lowercase reverse-DNS identity with at least two segments.");
915
+ }
916
+ if (typeof applicationId != "string" || !isReverseDns(applicationId, 3) || !applicationId.startsWith(`${organization}.`)) {
917
+ invalidConfiguration("Application ID must extend the exact organization as lowercase reverse DNS.");
918
+ }
919
+ if (typeof activityClassName != "string" || !/^[A-Z][A-Za-z0-9]*$/u.test(activityClassName) ||
920
+ javaKeywords.has(activityClassName))
921
+ invalidConfiguration("Activity class name must be an ASCII upper-camel Java identifier.");
922
+ if (androidRunnerBaseClassNames.has(activityClassName)) {
923
+ invalidConfiguration("Activity class name must not collide with the imported Flutter launcher base class.");
924
+ }
925
+ if (typeof displayName != "string" || displayName.length == 0 || displayName.trim() != displayName ||
926
+ [...displayName].length > 64 || !hasOnlyUnicodeScalars(displayName) || /[\p{Cc}\p{Zl}\p{Zp}\uFFFE\uFFFF]/u.test(displayName)) {
927
+ invalidConfiguration("Display name must be a non-empty single-line Unicode scalar string of at most 64 characters.");
928
+ }
929
+ if (minimumSdk !== 23 || targetSdk !== 35 || compileSdk !== 35) {
930
+ invalidConfiguration("SDK levels must reuse the qualified minimum 23, target 35, and compile 35 Android matrix.");
931
+ }
932
+ if (buildToolsVersion != "35.0.0")
933
+ invalidConfiguration("Build Tools version must be exactly '35.0.0'.");
934
+ if (!Number.isSafeInteger(versionCode) || versionCode < 1 || versionCode > 2_100_000_000) {
935
+ invalidConfiguration("Version code must be a positive Android-safe integer.");
936
+ }
937
+ if (typeof versionName != "string" || !semanticVersionPattern.test(versionName) || versionName.includes("+")) {
938
+ invalidConfiguration("Version name must be a canonical semantic version without build metadata.");
939
+ }
940
+ if (configuration.permissions !== undefined &&
941
+ (!isDenseArray(configuration.permissions) || configuration.permissions.length != 0)) {
942
+ invalidConfiguration("The baseline Flutter permission set must be empty.");
943
+ }
944
+ return { activityClassName, applicationId, buildToolsVersion, compileSdk, displayName, minimumSdk, organization,
945
+ packageName, targetSdk, versionCode, versionName };
946
+ }
947
+ /**
948
+ * Snapshots and validates exact caller assets.
949
+ * @param {unknown} candidate - Candidate asset collection.
950
+ * @returns {FlutterAsset[]} Normalized assets.
951
+ */
952
+ function normalizeAssets(candidate) {
953
+ if (candidate === undefined)
954
+ return [];
955
+ if (!isDenseArray(candidate))
956
+ invalidAsset("Flutter assets must be a dense array.");
957
+ /** @type {FlutterAsset[]} */
958
+ const assets = [];
959
+ for (let index = 0; index < candidate.length; index += 1) {
960
+ const item = candidate[index];
961
+ if (!isPlainObject(item) || Object.keys(item).length != assetFields.size ||
962
+ Object.keys(item).some(key => !assetFields.has(key)))
963
+ invalidAsset(`Asset ${index} must use the closed input schema.`);
964
+ const path = item.path;
965
+ const content = item.content;
966
+ const mediaType = item.mediaType;
967
+ const sha256 = item.sha256;
968
+ if (!isSafeArtifactPath(path) || !String(path).startsWith("assets/")) {
969
+ invalidAsset(`Asset ${index} requires a safe portable path below 'assets'.`);
970
+ }
971
+ if (typeof content != "string" && !(content instanceof Uint8Array) || typeof content == "string" &&
972
+ (content.length == 0 || !hasOnlyUnicodeScalars(content)) || content instanceof Uint8Array && content.byteLength == 0) {
973
+ invalidAsset(`Asset '${path}' requires non-empty exact content.`);
974
+ }
975
+ if (typeof mediaType != "string" || !mediaTypePattern.test(mediaType) || /[\r\n]/u.test(mediaType)) {
976
+ invalidAsset(`Asset '${path}' requires an explicit valid media type.`);
977
+ }
978
+ const snapshot = typeof content == "string" ? content : new Uint8Array(content);
979
+ const actualHash = createHash("sha256").update(snapshot).digest("hex");
980
+ if (typeof sha256 != "string" || !/^[0-9a-f]{64}$/u.test(sha256) || sha256 != actualHash) {
981
+ invalidAsset(`Asset '${path}' SHA-256 does not match its exact content.`);
982
+ }
983
+ assets.push({ content: snapshot, contentKind: typeof snapshot == "string" ? "text" : "binary",
984
+ fullPath: `${projectRoot}/${path}`, mediaType, path, sha256 });
985
+ }
986
+ assets.sort((left, right) => left.fullPath < right.fullPath ? -1 : left.fullPath > right.fullPath ? 1 : 0);
987
+ const conflict = findPortableArtifactPathConflict(assets.map(({ fullPath }) => fullPath));
988
+ if (conflict)
989
+ invalidAsset(`Asset path '${conflict.path}' has a ${conflict.kind} conflict.`);
990
+ return assets;
991
+ }
992
+ /**
993
+ * Enumerates every generator-owned application path.
994
+ * @param {import("../semantic/types.js").FlutterApplicationConfiguration} configuration - Normalized configuration.
995
+ * @param {Map<string, string>} modulePaths - Semantic module paths.
996
+ * @returns {string[]} Complete paths.
997
+ */
998
+ function applicationPaths(configuration, modulePaths) {
999
+ const packagePath = configuration.applicationId.replaceAll(".", "/");
1000
+ return [
1001
+ `${projectRoot}/.metadata`,
1002
+ `${projectRoot}/analysis_options.yaml`,
1003
+ `${projectRoot}/android/app/build.gradle.kts`,
1004
+ `${projectRoot}/android/app/src/main/AndroidManifest.xml`,
1005
+ `${projectRoot}/android/app/src/main/java/${packagePath}/${configuration.activityClassName}.java`,
1006
+ `${projectRoot}/android/app/src/main/res/drawable/launch_background.xml`,
1007
+ `${projectRoot}/android/app/src/main/res/values-night/styles.xml`,
1008
+ `${projectRoot}/android/app/src/main/res/values/styles.xml`,
1009
+ `${projectRoot}/android/app/src/main/res/xml/backup_rules.xml`,
1010
+ `${projectRoot}/android/app/src/main/res/xml/data_extraction_rules.xml`,
1011
+ `${projectRoot}/android/build.gradle.kts`,
1012
+ `${projectRoot}/android/gradle.properties`,
1013
+ `${projectRoot}/android/settings.gradle.kts`,
1014
+ `${projectRoot}/lib/main.dart`,
1015
+ ...modulePaths.values(),
1016
+ `${projectRoot}/lib/src/semantic/semantifold.dart`,
1017
+ `${projectRoot}/pubspec.lock`,
1018
+ `${projectRoot}/pubspec.yaml`,
1019
+ `${projectRoot}/test/semantic_logic_test.dart`,
1020
+ `${projectRoot}/test/widget_test.dart`,
1021
+ `${projectRoot}/semantifold-project.json`
1022
+ ];
1023
+ }
1024
+ /**
1025
+ * Converts one normalized asset to an owned artifact.
1026
+ * @param {FlutterAsset} asset - Normalized asset.
1027
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Generated asset.
1028
+ */
1029
+ function assetArtifact(asset) {
1030
+ const reason = `Exact caller-provided Flutter asset (sha256:${asset.sha256}).`;
1031
+ if (typeof asset.content == "string")
1032
+ return { ...syntheticText(asset.fullPath, "resource", asset.content, reason), mediaType: asset.mediaType };
1033
+ const content = new Uint8Array(asset.content);
1034
+ return {
1035
+ content,
1036
+ contentKind: "binary",
1037
+ mediaType: asset.mediaType,
1038
+ ownership: "generated",
1039
+ path: asset.fullPath,
1040
+ provenance: { kind: "bytes", mapping: createByteMapping({
1041
+ byteLength: content.byteLength,
1042
+ path: asset.fullPath,
1043
+ ranges: [{ generated: { end: content.byteLength, start: 0 },
1044
+ origin: { kind: "synthetic", reason, relatedOrigins: [] }, role: "asset" }]
1045
+ }) },
1046
+ role: "resource"
1047
+ };
1048
+ }
1049
+ /**
1050
+ * Creates a synthetic text artifact.
1051
+ * @param {string} path - Artifact path.
1052
+ * @param {import("../semantic/types.js").GeneratedArtifactRole} role - Artifact role.
1053
+ * @param {string} content - Exact content.
1054
+ * @param {string} reason - Synthetic provenance reason.
1055
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Generated artifact.
1056
+ */
1057
+ function syntheticText(path, role, content, reason) {
1058
+ return { content, contentKind: "text", mediaType: mediaTypeFor(path), ownership: "generated", path,
1059
+ provenance: { kind: "synthetic", reason, relatedOrigins: [] }, role };
1060
+ }
1061
+ /**
1062
+ * Creates text whose configuration spans are recorded separately.
1063
+ * @param {string} path - Artifact path.
1064
+ * @param {import("../semantic/types.js").GeneratedArtifactRole} role - Artifact role.
1065
+ * @param {string} content - Exact content.
1066
+ * @param {string} reason - Synthetic provenance reason.
1067
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Generated artifact.
1068
+ */
1069
+ function configuredText(path, role, content, reason) {
1070
+ return syntheticText(path, role, content, reason);
1071
+ }
1072
+ /**
1073
+ * Selects an exact media type from an owned path.
1074
+ * @param {string} path - Artifact path.
1075
+ * @returns {string} Media type.
1076
+ */
1077
+ function mediaTypeFor(path) {
1078
+ if (path.endsWith(".dart"))
1079
+ return "text/x-dart";
1080
+ if (path.endsWith(".json"))
1081
+ return "application/json";
1082
+ if (path.endsWith(".yaml") || path.endsWith(".lock"))
1083
+ return "application/yaml";
1084
+ if (path.endsWith(".xml"))
1085
+ return "application/xml";
1086
+ if (path.endsWith(".java"))
1087
+ return "text/x-java-source";
1088
+ if (path.endsWith(".kts"))
1089
+ return "text/x-kotlin";
1090
+ return "text/plain";
1091
+ }
1092
+ /**
1093
+ * Marks one rendered value as configuration-derived.
1094
+ * @param {string} fieldName - Configuration field.
1095
+ * @param {string} value - Rendered value.
1096
+ * @returns {{field: string, value: string}} Marked value.
1097
+ */
1098
+ function field(fieldName, value) {
1099
+ return { field: fieldName, value };
1100
+ }
1101
+ /**
1102
+ * Joins configured parts while recording exact output spans.
1103
+ * @param {string} path - Artifact path.
1104
+ * @param {ConfigurationSpan[]} spans - Configuration provenance sink.
1105
+ * @param {(string | {field: string, value: string})[]} parts - Literal and configured parts.
1106
+ * @returns {string} Rendered content.
1107
+ */
1108
+ function configured(path, spans, parts) {
1109
+ let content = "";
1110
+ for (const part of parts) {
1111
+ if (typeof part == "string")
1112
+ content += part;
1113
+ else {
1114
+ const start = content.length;
1115
+ content += part.value;
1116
+ spans.push({ end: content.length, field: part.field, path, start });
1117
+ }
1118
+ }
1119
+ return content;
1120
+ }
1121
+ /**
1122
+ * Groups exact generated ranges for one configuration field.
1123
+ * @param {ConfigurationSpan[]} spans - Recorded spans.
1124
+ * @param {string} fieldName - Configuration field.
1125
+ * @returns {{path: string, ranges: {end: number, start: number}[]}[]} Grouped output ranges.
1126
+ */
1127
+ function configurationOutputs(spans, fieldName) {
1128
+ const grouped = new Map();
1129
+ for (const span of spans) {
1130
+ if (span.field != fieldName)
1131
+ continue;
1132
+ const ranges = grouped.get(span.path) ?? [];
1133
+ ranges.push({ end: span.end, start: span.start });
1134
+ grouped.set(span.path, ranges);
1135
+ }
1136
+ return [...grouped].map(([path, ranges]) => ({ path, ranges }));
1137
+ }
1138
+ /**
1139
+ * Checks whether provenance refers to one source file.
1140
+ * @param {import("../semantic/types.js").SemanticOrigin} origin - Semantic origin.
1141
+ * @param {string} filename - Source filename.
1142
+ * @returns {boolean} Whether the origin references the source.
1143
+ */
1144
+ function originReferencesFilename(origin, filename) {
1145
+ if (origin.kind == "source")
1146
+ return origin.location.filename == filename;
1147
+ if (origin.kind == "derived")
1148
+ return origin.origins.some(({ location }) => location.filename == filename);
1149
+ return origin.relatedOrigins.some(({ location }) => location.filename == filename);
1150
+ }
1151
+ /**
1152
+ * Hashes exact artifact content.
1153
+ * @param {string | Uint8Array} content - Artifact content.
1154
+ * @returns {string} Lowercase SHA-256.
1155
+ */
1156
+ function hashContent(content) {
1157
+ return createHash("sha256").update(content).digest("hex");
1158
+ }
1159
+ /**
1160
+ * Serializes a recursively sorted JSON value.
1161
+ * @param {unknown} value - JSON-compatible value.
1162
+ * @returns {string} Canonical indented JSON.
1163
+ */
1164
+ function stringifyCanonicalJson(value) {
1165
+ return `${JSON.stringify(sortJson(value), null, 2)}\n`;
1166
+ }
1167
+ /**
1168
+ * Recursively sorts object keys without reordering arrays.
1169
+ * @param {unknown} value - JSON-compatible value.
1170
+ * @returns {unknown} Sorted value.
1171
+ */
1172
+ function sortJson(value) {
1173
+ if (Array.isArray(value))
1174
+ return value.map(sortJson);
1175
+ if (!isPlainObject(value))
1176
+ return value;
1177
+ return Object.fromEntries(Object.keys(value).sort().map(key => [key, sortJson(value[key])]));
1178
+ }
1179
+ /**
1180
+ * Validates a lowercase reverse-DNS identity.
1181
+ * @param {string} value - Candidate identity.
1182
+ * @param {number} segments - Required minimum segment count.
1183
+ * @returns {boolean} Whether the identity is valid.
1184
+ */
1185
+ function isReverseDns(value, segments) {
1186
+ const parts = value.split(".");
1187
+ return parts.length >= segments && parts.every(part => /^[a-z][a-z0-9_]*$/u.test(part) && !javaKeywords.has(part));
1188
+ }
1189
+ /**
1190
+ * Derives one stable Dart class suffix.
1191
+ * @param {string} id - Semantic module identity.
1192
+ * @returns {string} Dart class suffix.
1193
+ */
1194
+ function moduleName(id) {
1195
+ return id.split(/[._-]+/u).map(part => `${part[0].toUpperCase()}${part.slice(1)}`).join("");
1196
+ }
1197
+ /**
1198
+ * Derives one stable semantic part filename.
1199
+ * @param {string} id - Semantic module identity.
1200
+ * @returns {string} Dart filename.
1201
+ */
1202
+ function moduleFileName(id) {
1203
+ return id.replaceAll(/[.-]/gu, "_");
1204
+ }
1205
+ /**
1206
+ * Allocates a collision-free private output sink binding.
1207
+ * @param {import("../semantic/types.js").SemanticModule} module - Semantic module.
1208
+ * @returns {string} Dart binding name.
1209
+ */
1210
+ function outputSinkName(module) {
1211
+ const bindings = new Set(module.functions.flatMap(declaration => declaration.parameters.map(({ name }) => name)));
1212
+ for (const declaration of module.functions)
1213
+ collectBlockBindingNames(declaration.body, bindings);
1214
+ collectBlockBindingNames(module.entryPoint.body, bindings);
1215
+ let candidate = "semantifoldOutput";
1216
+ while (bindings.has(candidate))
1217
+ candidate += "_";
1218
+ return candidate;
1219
+ }
1220
+ /**
1221
+ * Collects every block-owned binding name.
1222
+ * @param {import("../semantic/types.js").Block} block - Semantic block.
1223
+ * @param {Set<string>} bindings - Mutable name set.
1224
+ * @returns {void}
1225
+ */
1226
+ function collectBlockBindingNames(block, bindings) {
1227
+ for (const statement of block.statements) {
1228
+ if (statement.kind == "LocalDeclaration")
1229
+ bindings.add(statement.name);
1230
+ else if (statement.kind == "IfStatement") {
1231
+ collectBlockBindingNames(statement.consequent, bindings);
1232
+ if (statement.alternate)
1233
+ collectBlockBindingNames(statement.alternate, bindings);
1234
+ }
1235
+ }
1236
+ }
1237
+ /**
1238
+ * Wraps one module in an explicit semantic project.
1239
+ * @param {import("../semantic/types.js").SemanticModule | undefined} candidate - Candidate module.
1240
+ * @returns {import("../semantic/types.js").SemanticProgram} Normalized project.
1241
+ */
1242
+ function normalizeSingleModule(candidate) {
1243
+ if (!isPlainObject(candidate))
1244
+ unsupportedCapability("flutter", "missing or invalid module", undefined);
1245
+ const module = structuredClone(candidate);
1246
+ const sources = module.provenance?.sources;
1247
+ if (!Array.isArray(sources) || sources.length != 1 || sources[0].content === null ||
1248
+ sources[0].filename != module.location?.filename || typeof sources[0].language != "string") {
1249
+ unsupportedCapability("flutter", "single-module source ownership", module.location);
1250
+ }
1251
+ rekeyModuleDeclarations(module, "main");
1252
+ const exports = [
1253
+ ...(module.records ?? []).map(declaration => applicationExport(declaration, "record")),
1254
+ ...(module.classes ?? []).map(declaration => applicationExport(declaration, "class")),
1255
+ ...(module.errors ?? []).map(declaration => applicationExport(declaration, "error")),
1256
+ ...module.functions.map(declaration => applicationExport(declaration, "function"))
1257
+ ];
1258
+ const programModule = { ...module, exports, id: "main", imports: [], sourceFilename: sources[0].filename };
1259
+ return { entryModule: "main", kind: "Program", modules: [programModule], sources: structuredClone(sources) };
1260
+ }
1261
+ /**
1262
+ * Converts one module declaration to an explicit application export.
1263
+ * @param {{id?: string, location: import("../semantic/types.js").SourceLocation, name: string}} declaration - Declaration.
1264
+ * @param {import("../semantic/types.js").SemanticDeclarationKind} symbolKind - Declaration kind.
1265
+ * @returns {import("../semantic/types.js").SemanticExport} Semantic export.
1266
+ */
1267
+ function applicationExport(declaration, symbolKind) {
1268
+ return { declarationId: /** @type {string} */ (declaration.id), exportedName: declaration.name,
1269
+ kind: "Export", location: declaration.location, symbolKind };
1270
+ }
1271
+ /**
1272
+ * Re-keys one standalone module for application-project ownership.
1273
+ * @param {import("../semantic/types.js").SemanticModule} module - Standalone module.
1274
+ * @param {string} moduleId - Stable application module identity.
1275
+ * @returns {void}
1276
+ */
1277
+ function rekeyModuleDeclarations(module, moduleId) {
1278
+ const declarations = [...module.records ?? [], ...module.classes ?? [], ...module.errors ?? [], ...module.functions];
1279
+ const replacements = new Map(declarations.filter(declaration => typeof declaration.id == "string")
1280
+ .map(declaration => [declaration.id, `${moduleId}#${declaration.id}`]));
1281
+ for (const declaration of declarations)
1282
+ if (typeof declaration.id == "string")
1283
+ declaration.id = replacements.get(declaration.id);
1284
+ const seen = new Set();
1285
+ const identityFields = new Set(["classId", "declarationId", "field", "method", "parameterId"]);
1286
+ /**
1287
+ * Rewrites semantic declaration identities recursively.
1288
+ * @param {unknown} value - Candidate semantic value.
1289
+ * @returns {void}
1290
+ */
1291
+ const visit = value => {
1292
+ if (!value || typeof value != "object" || seen.has(value))
1293
+ return;
1294
+ seen.add(value);
1295
+ for (const [key, nested] of Object.entries(value)) {
1296
+ if (!Array.isArray(value) && identityFields.has(key) && typeof nested == "string" && replacements.has(nested)) {
1297
+ Reflect.set(value, key, replacements.get(nested));
1298
+ }
1299
+ else
1300
+ visit(nested);
1301
+ }
1302
+ };
1303
+ visit(module);
1304
+ }
1305
+ /**
1306
+ * Escapes an XML attribute value.
1307
+ * @param {string} value - Raw value.
1308
+ * @returns {string} Escaped value.
1309
+ */
1310
+ function xmlEscape(value) {
1311
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")
1312
+ .replaceAll('"', "&quot;").replaceAll("'", "&apos;");
1313
+ }
1314
+ /**
1315
+ * Escapes a single-quoted Dart literal body.
1316
+ * @param {string} value - Raw value.
1317
+ * @returns {string} Escaped value.
1318
+ */
1319
+ function dartEscape(value) {
1320
+ return value.replaceAll("\\", "\\\\").replaceAll("'", "\\'").replaceAll("$", "\\$");
1321
+ }
1322
+ /**
1323
+ * Checks for a plain string-keyed object.
1324
+ * @param {unknown} value - Candidate value.
1325
+ * @returns {value is Record<string, unknown>} Whether the value is plain.
1326
+ */
1327
+ function isPlainObject(value) {
1328
+ return Boolean(value) && typeof value == "object" && !Array.isArray(value) && Object.getPrototypeOf(value) == Object.prototype;
1329
+ }
1330
+ /**
1331
+ * Throws a stable invalid-input diagnostic.
1332
+ * @param {string} message - Diagnostic detail.
1333
+ * @returns {never} Never returns.
1334
+ */
1335
+ function invalidInput(message) {
1336
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_INPUT", language: "flutter", message });
1337
+ }
1338
+ /**
1339
+ * Throws a stable invalid-configuration diagnostic.
1340
+ * @param {string} message - Diagnostic detail.
1341
+ * @returns {never} Never returns.
1342
+ */
1343
+ function invalidConfiguration(message) {
1344
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_CONFIGURATION", language: "flutter", message });
1345
+ }
1346
+ /**
1347
+ * Throws a stable invalid-asset diagnostic.
1348
+ * @param {string} message - Diagnostic detail.
1349
+ * @returns {never} Never returns.
1350
+ */
1351
+ function invalidAsset(message) {
1352
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_ASSET", language: "flutter", message });
1353
+ }
1354
+ /**
1355
+ * Throws a stable invalid-path diagnostic.
1356
+ * @param {string} message - Diagnostic detail.
1357
+ * @returns {never} Never returns.
1358
+ */
1359
+ function invalidPath(message) {
1360
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_PATH", language: "flutter", message });
1361
+ }
1362
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmx1dHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZW5kcy9mbHV0dGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sYUFBYSxDQUFBO0FBQ3RDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxhQUFhLENBQUE7QUFDeEMsT0FBTyxFQUFDLGdDQUFnQyxFQUFFLGtCQUFrQixFQUFDLE1BQU0scUJBQXFCLENBQUE7QUFDeEYsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sc0JBQXNCLENBQUE7QUFDdEQsT0FBTyxFQUFDLHFCQUFxQixFQUFFLHFCQUFxQixFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDN0UsT0FBTyxFQUFDLGVBQWUsRUFBRSxhQUFhLEVBQUMsTUFBTSxlQUFlLENBQUE7QUFDNUQsT0FBTyxFQUFDLHFCQUFxQixFQUFDLE1BQU0sd0JBQXdCLENBQUE7QUFDNUQsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLG1CQUFtQixDQUFBO0FBQzdDLE9BQU8sRUFBQyxhQUFhLEVBQUUsb0JBQW9CLEVBQUMsTUFBTSxXQUFXLENBQUE7QUFDN0QsT0FBTyxFQUFDLHdCQUF3QixFQUFDLE1BQU0sY0FBYyxDQUFBO0FBQ3JELE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFDM0MsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGFBQWEsQ0FBQTtBQUV4QyxNQUFNLFdBQVcsR0FBRyx1QkFBdUIsQ0FBQTtBQUMzQyxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQTtBQUNoQyxNQUFNLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDckMsT0FBTyxFQUFFLG9DQUFvQztJQUM3QyxhQUFhLEVBQUUsa0VBQWtFO0lBQ2pGLElBQUksRUFBRSxRQUFRO0lBQ2QsUUFBUSxFQUFFLDBDQUEwQztJQUNwRCxPQUFPLEVBQUUs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QUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxZQUFZLENBQUMsT0FBTztJQUMzQixNQUFNLElBQUkscUJBQXFCLENBQUMsRUFBQyxJQUFJLEVBQUUsMkJBQTJCLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUMsQ0FBQyxDQUFBO0FBQ3BHLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxvQkFBb0IsQ0FBQyxPQUFPO0lBQ25DLE1BQU0sSUFBSSxxQkFBcUIsQ0FBQyxFQUFDLElBQUksRUFBRSxtQ0FBbUMsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBQyxDQUFDLENBQUE7QUFDNUcsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLFlBQVksQ0FBQyxPQUFPO0lBQzNCLE1BQU0sSUFBSSxxQkFBcUIsQ0FBQyxFQUFDLElBQUksRUFBRSwyQkFBMkIsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBQyxDQUFDLENBQUE7QUFDcEcsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLFdBQVcsQ0FBQyxPQUFPO0lBQzFCLE1BQU0sSUFBSSxxQkFBcUIsQ0FBQyxFQUFDLElBQUksRUFBRSwwQkFBMEIsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBQyxDQUFDLENBQUE7QUFDbkcsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQge2NyZWF0ZUhhc2h9IGZyb20gXCJub2RlOmNyeXB0b1wiXG5pbXBvcnQge2lzRGVuc2VBcnJheX0gZnJvbSBcIi4uL2FycmF5LmpzXCJcbmltcG9ydCB7ZmluZFBvcnRhYmxlQXJ0aWZhY3RQYXRoQ29uZmxpY3QsIGlzU2FmZUFydGlmYWN0UGF0aH0gZnJvbSBcIi4uL2FydGlmYWN0LXBhdGguanNcIlxuaW1wb3J0IHtjcmVhdGVCeXRlTWFwcGluZ30gZnJvbSBcIi4uL2JpbmFyeS1tYXBwaW5nLmpzXCJcbmltcG9ydCB7U2VtYW50aWZvbGREaWFnbm9zdGljLCB1bnN1cHBvcnRlZENhcGFiaWxpdHl9IGZyb20gXCIuLi9kaWFnbm9zdGljLmpzXCJcbmltcG9ydCB7ZmluYWxpemVNYXBwaW5nLCB0b1NvdXJjZU1hcFYzfSBmcm9tIFwiLi4vbWFwcGluZy5qc1wiXG5pbXBvcnQge2hhc09ubHlVbmljb2RlU2NhbGFyc30gZnJvbSBcIi4uL3NlbWFudGljL3NjYWxhcnMuanNcIlxuaW1wb3J0IHtkYXJ0UnVudGltZX0gZnJvbSBcIi4vZGFydC1ydW50aW1lLmpzXCJcbmltcG9ydCB7ZW1pdERhcnRCbG9jaywgZmluZFVucmVhZERhcnRMb2NhbHN9IGZyb20gXCIuL2RhcnQuanNcIlxuaW1wb3J0IHtwcmVmbGlnaHRTZW1hbnRpY1Byb2dyYW19IGZyb20gXCIuL3Byb2dyYW0uanNcIlxuaW1wb3J0IHtlbWl0U2NhbGFyVHlwZX0gZnJvbSBcIi4vc2NhbGFycy5qc1wiXG5pbXBvcnQge1NvdXJjZVdyaXRlcn0gZnJvbSBcIi4vd3JpdGVyLmpzXCJcblxuY29uc3QgcHJvamVjdFJvb3QgPSBcImdlbmVyYXRlZC9mbHV0dGVyLWFwcFwiXG5jb25zdCBnZW5lcmF0b3JWZXJzaW9uID0gXCIwLjYuMFwiXG5jb25zdCBmbHV0dGVyVG9vbGNoYWluID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGFyY2hpdmU6IFwiZmx1dHRlcl9saW51eF8zLjQ3LjQtc3RhYmxlLnRhci54elwiLFxuICBhcmNoaXZlU2hhMjU2OiBcIjViNDVmMGNlZGE5OWI5YmViZGM4NzNlN2U2OWY2NDUwYWViNGMzMGY0NTRiNTA1ZTJlNjJmYzkyNTVhOTA3ZDNcIixcbiAgZGFydDogXCIzLjEzLjNcIixcbiAgcmV2aXNpb246IFwiOTU4NGM2NzEzYjMyNDYzNjI4OWQwNjc5NDRhNDZmZDZiNDlkZjE0YlwiLFxuICB2ZXJzaW9uOiBcIjMuNDcuNFwiXG59KVxuY29uc3QgYW5kcm9pZFRvb2xjaGFpbiA9IE9iamVjdC5mcmVlemUoe1xuICBhbmRyb2lkR3JhZGxlUGx1Z2luOiBcIjguMTEuMVwiLFxuICBidWlsZFRvb2xzOiBcIjM1LjAuMFwiLFxuICBjbWFrZTogXCIzLjIyLjFcIixcbiAgY29tcGlsZVNkazogMzUsXG4gIGdyYWRsZTogXCI4LjE0XCIsXG4gIGphdmE6IFwiMjEuMC44XCIsXG4gIGtvdGxpbkdyYWRsZVBsdWdpbjogXCIyLjIuMjBcIixcbiAgbWluaW11bVNkazogMjMsXG4gIG5kazogXCIyNy4wLjEyMDc3OTczXCIsXG4gIHRhcmdldFNkazogMzVcbn0pXG4vKiogQHR5cGUge3JlYWRvbmx5IChyZWFkb25seSBbc3RyaW5nLCBzdHJpbmcsIHN0cmluZ10pW119ICovXG5jb25zdCBmbHV0dGVyTG9ja2VkSG9zdGVkUGFja2FnZXMgPSBPYmplY3QuZnJlZXplKFtcbiAgW1wiYXN5bmNcIiwgXCIyLjEzLjFcIiwgXCJlMmViMDQ5MWJhNWRkYjYxNzc3NDJkMmRhMjM5MDQ1NzQwODIxMzliMDdjMWUzM2I4NTAzYjlmNDZmM2UxYTM3XCJdLFxuICBbXCJib29sZWFuX3NlbGVjdG9yXCIsIFwiMi4xLjJcIiwgXCI4YWFiMTc3MWUxMjQzYTUwNjNiOGIwZmY2ODA0MmQ2NzMzNGUzZmVhYjllOTViOTQ5MGY5YTZlYmY3M2I0MmVhXCJdLFxuICBbXCJjaGFyYWN0ZXJzXCIsIFwiMS40LjFcIiwgXCJmYWYzODQ5N2JkYTVlYWQyYThjNzYxNWY0Zjc5MzlkZjA0MzMzNDc4YmYzMmU0MTczZmNiMDZkNDI4YjU3MTZiXCJdLFxuICBbXCJjbG9ja1wiLCBcIjEuMS4zXCIsIFwiZTUxZDUwYmNhMzIxN2M5YTlmYTJiNDFhMzBlNGEzODk3MTEzM2Y1ZjllYzdhM2Q1N2JhZTA5NTAwN2YxZDI4ZVwiXSxcbiAgW1wiY29sbGVjdGlvblwiLCBcIjEuMTkuMVwiLCBcIjJmNTcwOWFlNGQzZDU5ZGQ4ZjdjZDMwOWI0ZTAyMzA0NmI1N2Q4YTZjODIxMzA3ODVkMmIwZTU4NjgwODRlNzZcIl0sXG4gIFtcImZha2VfYXN5bmNcIiwgXCIxLjMuM1wiLCBcIjUzNjhmMjI0YTc0NTIzZThkMmU3Mzk5ZWExNjM4YjM3YWVjZmNhODI0YTNjYzRkZmRmNzdiZjFmYTkwNWFjNDRcIl0sXG4gIFtcImxlYWtfdHJhY2tlclwiLCBcIjExLjAuMlwiLCBcIjMzZTJlMjZiZGQ4NWEwMTEyZWMxNTQwMGM4Y2JmZmVhNzBkMGY5YzM0MDc0OTFmNjcyYTJmYWQ0NzkxNWUyZGVcIl0sXG4gIFtcImxlYWtfdHJhY2tlcl9mbHV0dGVyX3Rlc3RpbmdcIiwgXCIzLjAuMTBcIiwgXCIxZGJjMTQwYmI1YTIzYzc1ZWE5YzQ4MTEyMjI3NTYxMDRmYmNkMWEyNzE3M2YwYzM0Y2EwMWUxNmJlYTQ3M2MxXCJdLFxuICBbXCJsZWFrX3RyYWNrZXJfdGVzdGluZ1wiLCBcIjMuMC4yXCIsIFwiOGQ1YTJkNDlmNGE2NmI0OTc0NGIyM2IwMTg4NDg0MDBkMjNlNTRjYWY5NDYzZjRlYjIwZGYzZWI4YWNiMmViMVwiXSxcbiAgW1wibWF0Y2hlclwiLCBcIjAuMTIuMjBcIiwgXCIzMWJkMDk5YjQ3YzEwY2QxYWViNTUxNDZhMmQ0NmNlMDI3NzYzMGVjZWYzZjdkYWU1NGFkNzg3M2YzNjY5NmNkXCJdLFxuICBbXCJtYXRlcmlhbF9jb2xvcl91dGlsaXRpZXNcIiwgXCIwLjEzLjBcIiwgXCI5YzMzNzAwN2U4MmIxODg5MTQ5YzgyZWQyNDJlZDFjYjI0YTY2MDQ0ZTMwOTc5YzQ0OTEyMzgxZTliZTRjNDhiXCJdLFxuICBbXCJtZXRhXCIsIFwiMS4xOS4wXCIsIFwiMzA3MjQ5Y2U0ZmYyOWQ1OGExOGU5N2Y2MzQ1ZjUzOTM4MmViOWM5YzI5ZWNkYTYyODkwMGYzMWRlMDQ0M2RkOVwiXSxcbiAgW1wicGF0aFwiLCBcIjEuOS4xXCIsIFwiNzVjY2E2OWQxNDkwOTY1YmU5OGM3M2NlYWVhMTE3ZThhMDRkZDIxMjE3YjM3YjI5MmM5ZGRiZWMwZDk1NWJjNVwiXSxcbiAgW1wic291cmNlX3NwYW5cIiwgXCIxLjEwLjJcIiwgXCI1NmEwMmYxZjRjZDFhMmQ5NjMwM2MwMTQ0YzkzYmQ2ZDkwOWVlYTZiZWU2YmY1YTBlMGI2ODVlZGJkNGM0N2FiXCJdLFxuICBbXCJzdGFja190cmFjZVwiLCBcIjEuMTIuMlwiLCBcIjI3NzY1NGIzMDM0ZDE3YWM2ZjlmMWNiNTU5NWRiMDExYjFkNWQ0MWU4ODA2ODY2ZGIyOGUwYWJhYTEwMWM0OTBcIl0sXG4gIFtcInN0cmVhbV9jaGFubmVsXCIsIFwiMi4xLjRcIiwgXCI5NjllMDRjODBiOGJjZGY4MjZmOGYxNjU3OWM3YjE0ZDc4MDQ1OGJkOTdmNTZkMTA3ZDM5NTBmZGJlZWYwNTlkXCJdLFxuICBbXCJzdHJpbmdfc2Nhbm5lclwiLCBcIjEuNC4xXCIsIFwiOTIxY2QzMTcyNWI3MmZlMTgxOTA2YzZhOTRkOTg3Yzc4ZTNiOThjMmUyMDViMzk3ZWEzOTlkNDA1NDg3MmI0M1wiXSxcbiAgW1widGVybV9nbHlwaFwiLCBcIjEuMi4yXCIsIFwiN2Y1NTQ3OTg2MjVlYTc2OGE3NTE4MzEzZTU4ZjgzODkxYzdmNTAyNGY4OGU0NmU3MTgyYTQ1NTg4NTBhNGI4ZVwiXSxcbiAgW1widGVzdF9hcGlcIiwgXCIwLjcuMTJcIiwgXCIyYTEyMmNiZTA1OWY4YjYxMGQzYTU0MTVmNDJlMjU1YjZjMTdiMWYyMWVlZTFkOTYwZjMxMDgwMjM3ZmI0ZjExXCJdLFxuICBbXCJ2ZWN0b3JfbWF0aFwiLCBcIjIuNC4yXCIsIFwiZjM2ZjlmM2JlNjRjNjE5ODcxNDQ5MmJiNDU1YzExMDU2ZTMzZTJmODVkOWEwYjY3NmE0ODMwMWU0NGZkY2Y0N1wiXSxcbiAgW1widm1fc2VydmljZVwiLCBcIjE1LjMuMFwiLCBcIjVmMzcyMzljNDg1MWVmY2VmOTI5Y2VhNzgyNGU3NmRmN2YyZjA5NzBhZWY4NWQ2NmJiYzQzMGFmYTQwZTcyZjBcIl1cbl0pXG4vKiogQHR5cGUge3JlYWRvbmx5IChyZWFkb25seSBbc3RyaW5nLCBcImRpcmVjdCBtYWluXCIgfCBcImRpcmVjdCBkZXZcIiB8IFwidHJhbnNpdGl2ZVwiXSlbXX0gKi9cbmNvbnN0IGZsdXR0ZXJMb2NrZWRTZGtQYWNrYWdlcyA9IE9iamVjdC5mcmVlemUoW1xuICBbXCJmbHV0dGVyXCIsIFwiZGlyZWN0IG1haW5cIl0sXG4gIFtcImZsdXR0ZXJfdGVzdFwiLCBcImRpcmVjdCBkZXZcIl0sXG4gIFtcInNreV9lbmdpbmVcIiwgXCJ0cmFuc2l0aXZlXCJdXG5dKVxuLyoqIEB0eXBlIHtSZWFkb25seTxTZXQ8aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNMYW5ndWFnZT4+fSAqL1xuY29uc3QgZmx1dHRlclNvdXJjZUxhbmd1YWdlcyA9IG5ldyBTZXQoW1xuICBcInBocFwiLCBcInJ1YnlcIiwgXCJqYXZhc2NyaXB0XCIsIFwidHlwZXNjcmlwdFwiLCBcImphdmFcIiwgXCJrb3RsaW5cIiwgXCJweXRob25cIiwgXCJjc2hhcnBcIiwgXCJnb1wiLCBcImNcIiwgXCJjcHBcIiwgXCJydXN0XCIsIFwic3dpZnRcIiwgXCJkYXJ0XCIsIFwiemlnXCJcbl0pXG5jb25zdCByZXF1ZXN0RmllbGRzID0gbmV3IFNldChbXCJhc3NldHNcIiwgXCJjb25maWd1cmF0aW9uXCIsIFwibGFuZ3VhZ2VcIiwgXCJtb2R1bGVcIiwgXCJwcm9ncmFtXCIsIFwicm9sZVwiXSlcbmNvbnN0IGNvbmZpZ3VyYXRpb25GaWVsZHMgPSBuZXcgU2V0KFtcbiAgXCJhY3Rpdml0eUNsYXNzTmFtZVwiLCBcImFwcGxpY2F0aW9uSWRcIiwgXCJidWlsZFRvb2xzVmVyc2lvblwiLCBcImNvbXBpbGVTZGtcIiwgXCJkaXNwbGF5TmFtZVwiLCBcIm1pbmltdW1TZGtcIiwgXCJvcmdhbml6YXRpb25cIixcbiAgXCJwYWNrYWdlTmFtZVwiLCBcInBlcm1pc3Npb25zXCIsIFwidGFyZ2V0U2RrXCIsIFwidmVyc2lvbkNvZGVcIiwgXCJ2ZXJzaW9uTmFtZVwiXG5dKVxuY29uc3QgYXNzZXRGaWVsZHMgPSBuZXcgU2V0KFtcImNvbnRlbnRcIiwgXCJtZWRpYVR5cGVcIiwgXCJwYXRoXCIsIFwic2hhMjU2XCJdKVxuY29uc3QgZGFydEtleXdvcmRzID0gbmV3IFNldChbXG4gIFwiYWJzdHJhY3RcIiwgXCJhc1wiLCBcImFzc2VydFwiLCBcImFzeW5jXCIsIFwiYXdhaXRcIiwgXCJiYXNlXCIsIFwiYnJlYWtcIiwgXCJjYXNlXCIsIFwiY2F0Y2hcIiwgXCJjbGFzc1wiLCBcImNvbnN0XCIsIFwiY29udGludWVcIixcbiAgXCJjb3ZhcmlhbnRcIiwgXCJkZWZhdWx0XCIsIFwiZGVmZXJyZWRcIiwgXCJkb1wiLCBcImR5bmFtaWNcIiwgXCJlbHNlXCIsIFwiZW51bVwiLCBcImV4cG9ydFwiLCBcImV4dGVuZHNcIiwgXCJleHRlbnNpb25cIiwgXCJleHRlcm5hbFwiLFxuICBcImZhY3RvcnlcIiwgXCJmYWxzZVwiLCBcImZpbmFsXCIsIFwiZmluYWxseVwiLCBcImZvclwiLCBcIkZ1bmN0aW9uXCIsIFwiZ2V0XCIsIFwiaGlkZVwiLCBcImlmXCIsIFwiaW1wbGVtZW50c1wiLCBcImltcG9ydFwiLCBcImluXCIsXG4gIFwiaW50ZXJmYWNlXCIsIFwiaXNcIiwgXCJsYXRlXCIsIFwibGlicmFyeVwiLCBcIm1peGluXCIsIFwibmV3XCIsIFwibnVsbFwiLCBcIm9mXCIsIFwib25cIiwgXCJvcGVyYXRvclwiLCBcInBhcnRcIiwgXCJyZXF1aXJlZFwiLFxuICBcInJldGhyb3dcIiwgXCJyZXR1cm5cIiwgXCJzZWFsZWRcIiwgXCJzZXRcIiwgXCJzaG93XCIsIFwic3RhdGljXCIsIFwic3VwZXJcIiwgXCJzd2l0Y2hcIiwgXCJzeW5jXCIsIFwidGhpc1wiLCBcInRocm93XCIsIFwidHJ1ZVwiLFxuICBcInRyeVwiLCBcInR5cGVkZWZcIiwgXCJ2YXJcIiwgXCJ2b2lkXCIsIFwid2hlblwiLCBcIndoaWxlXCIsIFwid2l0aFwiLCBcInlpZWxkXCJcbl0pXG5jb25zdCBqYXZhS2V5d29yZHMgPSBuZXcgU2V0KFtcbiAgXCJhYnN0cmFjdFwiLCBcImFzc2VydFwiLCBcImJvb2xlYW5cIiwgXCJicmVha1wiLCBcImJ5dGVcIiwgXCJjYXNlXCIsIFwiY2F0Y2hcIiwgXCJjaGFyXCIsIFwiY2xhc3NcIiwgXCJjb25zdFwiLCBcImNvbnRpbnVlXCIsIFwiZGVmYXVsdFwiLFxuICBcImRvXCIsIFwiZG91YmxlXCIsIFwiZWxzZVwiLCBcImVudW1cIiwgXCJleHRlbmRzXCIsIFwiZmluYWxcIiwgXCJmaW5hbGx5XCIsIFwiZmxvYXRcIiwgXCJmb3JcIiwgXCJnb3RvXCIsIFwiaWZcIiwgXCJpbXBsZW1lbnRzXCIsXG4gIFwiaW1wb3J0XCIsIFwiaW5zdGFuY2VvZlwiLCBcImludFwiLCBcImludGVyZmFjZVwiLCBcImxvbmdcIiwgXCJuYXRpdmVcIiwgXCJuZXdcIiwgXCJwYWNrYWdlXCIsIFwicHJpdmF0ZVwiLCBcInByb3RlY3RlZFwiLCBcInB1YmxpY1wiLFxuICBcInJldHVyblwiLCBcInNob3J0XCIsIFwic3RhdGljXCIsIFwic3RyaWN0ZnBcIiwgXCJzdXBlclwiLCBcInN3aXRjaFwiLCBcInN5bmNocm9uaXplZFwiLCBcInRoaXNcIiwgXCJ0aHJvd1wiLCBcInRocm93c1wiLCBcInRyYW5zaWVudFwiLFxuICBcInRyeVwiLCBcInZvaWRcIiwgXCJ2b2xhdGlsZVwiLCBcIndoaWxlXCJcbl0pXG5jb25zdCBmb3JiaWRkZW5QYWNrYWdlTmFtZXMgPSBuZXcgU2V0KFtcbiAgLi4uZmx1dHRlckxvY2tlZEhvc3RlZFBhY2thZ2VzLm1hcCgoW25hbWVdKSA9PiBuYW1lKSxcbiAgLi4uZmx1dHRlckxvY2tlZFNka1BhY2thZ2VzLm1hcCgoW25hbWVdKSA9PiBuYW1lKSxcbiAgXCJpbnRlZ3JhdGlvbl90ZXN0XCIsXG4gIFwic2VtYW50aWZvbGRcIlxuXSlcbmNvbnN0IGFuZHJvaWRSdW5uZXJCYXNlQ2xhc3NOYW1lcyA9IG5ldyBTZXQoW1wiRmx1dHRlckFjdGl2aXR5XCJdKVxuY29uc3Qgc2VtYW50aWNWZXJzaW9uUGF0dGVybiA9IC9eKD86MHxbMS05XVswLTldKilcXC4oPzowfFsxLTldWzAtOV0qKVxcLig/OjB8WzEtOV1bMC05XSopKD86LSg/OjB8WzEtOV1bMC05XSp8W0EtWmEtei1dW0EtWmEtejAtOS1dKikoPzpcXC4oPzowfFsxLTldWzAtOV0qfFtBLVphLXotXVtBLVphLXowLTktXSopKSopPyg/OlxcK1tBLVphLXowLTktXSsoPzpcXC5bQS1aYS16MC05LV0rKSopPyQvdVxuY29uc3QgbWVkaWFUeXBlUGF0dGVybiA9IC9eW0EtWmEtejAtOSEjJCZeXy4rLV0rXFwvW0EtWmEtejAtOSEjJCZeXy4rLV0rKD86W1xcdTAwMjAtXFx1MDA3ZV0rKT8kL3VcbmNvbnN0IGV4Y2x1ZGVkUGF0aFBhdHRlcm5zID0gT2JqZWN0LmZyZWV6ZShbXG4gIFwiLmRhcnRfdG9vbC8qKlwiLCBcIi5mbHV0dGVyLXBsdWdpbnNcIiwgXCIuZmx1dHRlci1wbHVnaW5zLWRlcGVuZGVuY2llc1wiLCBcImFuZHJvaWQvLmdyYWRsZS8qKlwiLCBcImFuZHJvaWQvYXBwL2J1aWxkLyoqXCIsXG4gIFwiYW5kcm9pZC9sb2NhbC5wcm9wZXJ0aWVzXCIsIFwiYnVpbGQvKipcIlxuXSlcbmNvbnN0IG91dHB1dFNpbmtSdW50aW1lID0gYFxuZmluYWwgY2xhc3MgX1NlbWFudGlmb2xkT3V0cHV0U2luayB7XG4gIGZpbmFsIExpc3Q8U3RyaW5nPiBfdmFsdWVzID0gPFN0cmluZz5bXTtcblxuICB2b2lkIHdyaXRlKE9iamVjdCB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSBpcyEgaW50ICYmIHZhbHVlIGlzISBib29sICYmIHZhbHVlIGlzISBTdHJpbmcpIHtcbiAgICAgIHRocm93IFN0YXRlRXJyb3IoJ1Vuc3VwcG9ydGVkIFNlbWFudGlmb2xkIG91dHB1dCB2YWx1ZScpO1xuICAgIH1cbiAgICBfdmFsdWVzLmFkZCh2YWx1ZS50b1N0cmluZygpKTtcbiAgfVxuXG4gIExpc3Q8U3RyaW5nPiBzbmFwc2hvdCgpID0+IExpc3Q8U3RyaW5nPi51bm1vZGlmaWFibGUoX3ZhbHVlcyk7XG59XG5gXG5cbi8qKiBAdHlwZWRlZiB7e2NvbnRlbnQ6IHN0cmluZyB8IFVpbnQ4QXJyYXksIGNvbnRlbnRLaW5kOiBcImJpbmFyeVwiIHwgXCJ0ZXh0XCIsIGZ1bGxQYXRoOiBzdHJpbmcsIG1lZGlhVHlwZTogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIHNoYTI1Njogc3RyaW5nfX0gRmx1dHRlckFzc2V0ICovXG4vKiogQHR5cGVkZWYge3tlbmQ6IG51bWJlciwgZmllbGQ6IHN0cmluZywgcGF0aDogc3RyaW5nLCBzdGFydDogbnVtYmVyfX0gQ29uZmlndXJhdGlvblNwYW4gKi9cblxuLyoqXG4gKiBQcmVmbGlnaHRzIGEgY29tcGxldGUgRmx1dHRlciBhcHBsaWNhdGlvbiByZXF1ZXN0IGJlZm9yZSByZW5kZXJpbmcgYW55IGFydGlmYWN0LlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gaW5wdXQgLSBDYW5kaWRhdGUgYXBwbGljYXRpb24gcmVxdWVzdC5cbiAqIEByZXR1cm5zIHt7YXNzZXRzOiBGbHV0dGVyQXNzZXRbXSwgY29uZmlndXJhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRmx1dHRlckFwcGxpY2F0aW9uQ29uZmlndXJhdGlvbiwgbW9kdWxlUGF0aHM6IE1hcDxzdHJpbmcsIHN0cmluZz4sIG1vZHVsZXM6IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlW10sIHBhY2thZ2VQYXRoOiBzdHJpbmcsIHByb2dyYW06IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljUHJvZ3JhbSwgc291cmNlczoge2NvbnRlbnQ6IHN0cmluZywgZmlsZW5hbWU6IHN0cmluZywgbGFuZ3VhZ2U/OiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY0xhbmd1YWdlfVtdfX0gUHJlcGFyZWQgYXBwbGljYXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmVmbGlnaHRGbHV0dGVyQXBwbGljYXRpb24oaW5wdXQpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KGlucHV0KSB8fCBPYmplY3Qua2V5cyhpbnB1dCkuc29tZShrZXkgPT4gIXJlcXVlc3RGaWVsZHMuaGFzKGtleSkpIHx8XG4gICAgQm9vbGVhbihpbnB1dC5tb2R1bGUpID09IEJvb2xlYW4oaW5wdXQucHJvZ3JhbSkpIHtcbiAgICBpbnZhbGlkSW5wdXQoXCJGbHV0dGVyIGFwcGxpY2F0aW9uIGdlbmVyYXRpb24gcmVxdWlyZXMgYSBjbG9zZWQgcmVxdWVzdCB3aXRoIGV4YWN0bHkgb25lIHNlbWFudGljIG1vZHVsZSBvciBwcm9ncmFtLlwiKVxuICB9XG4gIGlmIChpbnB1dC5sYW5ndWFnZSAhPT0gdW5kZWZpbmVkICYmIGlucHV0Lmxhbmd1YWdlICE9IFwiZmx1dHRlclwiIHx8IGlucHV0LnJvbGUgIT09IHVuZGVmaW5lZCAmJiBpbnB1dC5yb2xlICE9IFwiYXBwbGljYXRpb25cIikge1xuICAgIGludmFsaWRJbnB1dChcIkZsdXR0ZXIgYXBwbGljYXRpb24gZ2VuZXJhdGlvbiBhY2NlcHRzIG9ubHkgdGhlIEZsdXR0ZXIgYXBwbGljYXRpb24gcm9sZS5cIilcbiAgfVxuICBjb25zdCBjb25maWd1cmF0aW9uID0gbm9ybWFsaXplQ29uZmlndXJhdGlvbihpbnB1dC5jb25maWd1cmF0aW9uKVxuICBjb25zdCBwcm9ncmFtID0gaW5wdXQucHJvZ3JhbSA/PyBub3JtYWxpemVTaW5nbGVNb2R1bGUoXG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZSB8IHVuZGVmaW5lZH0gKi8gKGlucHV0Lm1vZHVsZSkpXG4gIGNvbnN0IHByZXBhcmVkID0gcHJlZmxpZ2h0U2VtYW50aWNQcm9ncmFtKHtcbiAgICBiYWNrZW5kTGFuZ3VhZ2U6IFwiZGFydFwiLFxuICAgIGRpYWdub3N0aWNMYW5ndWFnZTogXCJmbHV0dGVyXCIsXG4gICAgcHJvZ3JhbTogLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY1Byb2dyYW19ICovIChwcm9ncmFtKSxcbiAgICBzb3VyY2VMYW5ndWFnZXM6IGZsdXR0ZXJTb3VyY2VMYW5ndWFnZXNcbiAgfSlcbiAgY29uc3QgZW50cnlNb2R1bGUgPSBwcmVwYXJlZC5tb2R1bGVzLmZpbmQobW9kdWxlID0+IFJlZmxlY3QuZ2V0KG1vZHVsZSwgXCJpZFwiKSA9PSBwcmVwYXJlZC5wcm9ncmFtLmVudHJ5TW9kdWxlKVxuICBjb25zdCBlbnRyeUNvbGxpc2lvbiA9IGVudHJ5TW9kdWxlPy5mdW5jdGlvbnMuZmluZCgoe25hbWV9KSA9PiBuYW1lID09IFwic2VtYW50aWZvbGRFbnRyeVwiKVxuXG4gIGlmIChlbnRyeUNvbGxpc2lvbikgdW5zdXBwb3J0ZWRDYXBhYmlsaXR5KFwiZmx1dHRlclwiLCBcInJlc2VydmVkIGdlbmVyYXRlZCBzZW1hbnRpYyBlbnRyeSBmdW5jdGlvbiAnc2VtYW50aWZvbGRFbnRyeSdcIiwgZW50cnlDb2xsaXNpb24ubG9jYXRpb24pXG4gIGNvbnN0IHBhY2thZ2VQYXRoID0gY29uZmlndXJhdGlvbi5hcHBsaWNhdGlvbklkLnJlcGxhY2VBbGwoXCIuXCIsIFwiL1wiKVxuICBjb25zdCBtb2R1bGVQYXRocyA9IG5ldyBNYXAocHJlcGFyZWQubW9kdWxlcy5tYXAobW9kdWxlID0+IHtcbiAgICBjb25zdCBtb2R1bGVJZCA9IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoUmVmbGVjdC5nZXQobW9kdWxlLCBcImlkXCIpKVxuXG4gICAgcmV0dXJuIFttb2R1bGVJZCwgYCR7cHJvamVjdFJvb3R9L2xpYi9zcmMvc2VtYW50aWMvJHttb2R1bGVGaWxlTmFtZShtb2R1bGVJZCl9LmRhcnRgXVxuICB9KSlcbiAgY29uc3QgYXNzZXRzID0gbm9ybWFsaXplQXNzZXRzKGlucHV0LmFzc2V0cylcbiAgY29uc3QgY29tcGxldGVQYXRocyA9IFsuLi5hcHBsaWNhdGlvblBhdGhzKGNvbmZpZ3VyYXRpb24sIG1vZHVsZVBhdGhzKSwgLi4uYXNzZXRzLm1hcCgoe2Z1bGxQYXRofSkgPT4gZnVsbFBhdGgpXVxuICBjb25zdCBjb25mbGljdCA9IGZpbmRQb3J0YWJsZUFydGlmYWN0UGF0aENvbmZsaWN0KGNvbXBsZXRlUGF0aHMpXG5cbiAgaWYgKGNvbmZsaWN0KSB7XG4gICAgaW52YWxpZFBhdGgoYEFwcGxpY2F0aW9uIGFydGlmYWN0IHBhdGggJyR7Y29uZmxpY3QucGF0aH0nIGhhcyBhICR7Y29uZmxpY3Qua2luZH0gY29uZmxpY3Qke2NvbmZsaWN0Lm90aGVyID8gYCB3aXRoICcke2NvbmZsaWN0Lm90aGVyfSdgIDogXCJcIn0uYClcbiAgfVxuICBjb25zdCBzZW1hbnRpY05hbWVzID0gbmV3IE1hcCgpXG5cbiAgZm9yIChjb25zdCBtb2R1bGUgb2YgcHJlcGFyZWQubW9kdWxlcykge1xuICAgIGNvbnN0IG1vZHVsZUlkID0gLyoqIEB0eXBlIHtzdHJpbmd9ICovIChSZWZsZWN0LmdldChtb2R1bGUsIFwiaWRcIikpXG4gICAgY29uc3QgbmFtZSA9IG1vZHVsZU5hbWUobW9kdWxlSWQpXG4gICAgY29uc3QgcHJldmlvdXMgPSBzZW1hbnRpY05hbWVzLmdldChuYW1lKVxuXG4gICAgaWYgKHByZXZpb3VzKSBpbnZhbGlkUGF0aChgU2VtYW50aWMgbW9kdWxlcyAnJHtwcmV2aW91c30nIGFuZCAnJHttb2R1bGVJZH0nIGNvbGxpZGUgYXQgZ2VuZXJhdGVkIERhcnQgY2xhc3MgJyR7bmFtZX0nLmApXG4gICAgc2VtYW50aWNOYW1lcy5zZXQobmFtZSwgbW9kdWxlSWQpXG4gIH1cblxuICByZXR1cm4gey4uLnByZXBhcmVkLCBhc3NldHMsIGNvbmZpZ3VyYXRpb24sIG1vZHVsZVBhdGhzLCBwYWNrYWdlUGF0aH1cbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgb25lIGRldGVybWluaXN0aWMgU0RLLW9ubHkgRmx1dHRlciBwcm9qZWN0IGZvciB0aGUgcXVhbGlmaWVkIEFuZHJvaWQgbGFuZS5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IGlucHV0IC0gQXBwbGljYXRpb24gZ2VuZXJhdGlvbiByZXF1ZXN0LlxuICogQHJldHVybnMge3thcnRpZmFjdHM6IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0W10sIG1ldGFkYXRhOiB7YXBwbGljYXRpb25NYW5pZmVzdDogc3RyaW5nLCBwbGF0Zm9ybVF1YWxpZmljYXRpb246IHthbmRyb2lkOiBzdHJpbmcsIGlvczogc3RyaW5nfX0sIHRhcmdldDogXCJmbHV0dGVyXCJ9fSBDYW5kaWRhdGUgYXJ0aWZhY3Qgc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVGbHV0dGVyQXBwbGljYXRpb24oaW5wdXQpIHtcbiAgY29uc3QgcHJlcGFyZWQgPSBwcmVmbGlnaHRGbHV0dGVyQXBwbGljYXRpb24oaW5wdXQpXG4gIGNvbnN0IGNvbmZpZ3VyYXRpb25TcGFucyA9IC8qKiBAdHlwZSB7Q29uZmlndXJhdGlvblNwYW5bXX0gKi8gKFtdKVxuICBjb25zdCBjb25maWd1cmF0aW9uID0gcHJlcGFyZWQuY29uZmlndXJhdGlvblxuICBjb25zdCBzZW1hbnRpY0FydGlmYWN0cyA9IHJlbmRlclNlbWFudGljQXJ0aWZhY3RzKHByZXBhcmVkKVxuICBjb25zdCBhcnRpZmFjdHMgPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0W119ICovIChbXG4gICAgc3ludGhldGljVGV4dChgJHtwcm9qZWN0Um9vdH0vLm1ldGFkYXRhYCwgXCJtYW5pZmVzdFwiLCByZW5kZXJNZXRhZGF0YSgpLFxuICAgICAgXCJFeGFjdCBGbHV0dGVyIDMuNDcuNCBwcm9qZWN0LXRlbXBsYXRlIGlkZW50aXR5OyBnZW5lcmF0ZWQgbWlncmF0aW9uIGlzIGRpc2FibGVkLlwiKSxcbiAgICBzeW50aGV0aWNUZXh0KGAke3Byb2plY3RSb290fS9hbmFseXNpc19vcHRpb25zLnlhbWxgLCBcInN1cHBvcnRcIiwgcmVuZGVyQW5hbHlzaXNPcHRpb25zKCksXG4gICAgICBcIkNsb3NlZCBhbmFseXplciBjb25maWd1cmF0aW9uIHdpdGhvdXQgZXh0ZXJuYWwgbGludCBwYWNrYWdlcy5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL2J1aWxkLmdyYWRsZS5rdHNgLCBcIm1hbmlmZXN0XCIsIHJlbmRlckFuZHJvaWRBcHBCdWlsZChjb25maWd1cmF0aW9uLCBjb25maWd1cmF0aW9uU3BhbnMpLFxuICAgICAgXCJUYXNrIDAyOC1jb21wYXRpYmxlIEFuZHJvaWQgYnVpbGQgYW5kIGlzb2xhdGVkIGRlYnVnLXNpZ25pbmcgY29uZmlndXJhdGlvbi5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL0FuZHJvaWRNYW5pZmVzdC54bWxgLCBcIm1hbmlmZXN0XCIsXG4gICAgICByZW5kZXJBbmRyb2lkTWFuaWZlc3QoY29uZmlndXJhdGlvbiwgY29uZmlndXJhdGlvblNwYW5zKSwgXCJDbG9zZWQgcGVybWlzc2lvbi1mcmVlIEZsdXR0ZXIgQW5kcm9pZCBhcHBsaWNhdGlvbiBtYW5pZmVzdC5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL2phdmEvJHtwcmVwYXJlZC5wYWNrYWdlUGF0aH0vJHtjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lfS5qYXZhYCwgXCJzdXBwb3J0XCIsXG4gICAgICByZW5kZXJBbmRyb2lkQWN0aXZpdHkoY29uZmlndXJhdGlvbiwgY29uZmlndXJhdGlvblNwYW5zKSwgXCJTeW50aGV0aWMgRmx1dHRlciBBbmRyb2lkIGVtYmVkZGluZyBsYXVuY2hlci5cIiksXG4gICAgc3ludGhldGljVGV4dChgJHtwcm9qZWN0Um9vdH0vYW5kcm9pZC9hcHAvc3JjL21haW4vcmVzL2RyYXdhYmxlL2xhdW5jaF9iYWNrZ3JvdW5kLnhtbGAsIFwicmVzb3VyY2VcIiwgcmVuZGVyTGF1bmNoQmFja2dyb3VuZCgpLFxuICAgICAgXCJTeW50aGV0aWMgbWluaW11bS1TREstcXVhbGlmaWVkIEZsdXR0ZXIgbGF1bmNoIGJhY2tncm91bmQuXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL3Jlcy92YWx1ZXMtbmlnaHQvc3R5bGVzLnhtbGAsIFwicmVzb3VyY2VcIiwgcmVuZGVyQW5kcm9pZFN0eWxlcyh0cnVlKSxcbiAgICAgIFwiU3ludGhldGljIGRhcmsgcGxhdGZvcm0gbGF1bmNoIGFuZCBGbHV0dGVyIGhvc3QgdGhlbWVzLlwiKSxcbiAgICBzeW50aGV0aWNUZXh0KGAke3Byb2plY3RSb290fS9hbmRyb2lkL2FwcC9zcmMvbWFpbi9yZXMvdmFsdWVzL3N0eWxlcy54bWxgLCBcInJlc291cmNlXCIsIHJlbmRlckFuZHJvaWRTdHlsZXMoZmFsc2UpLFxuICAgICAgXCJTeW50aGV0aWMgbGlnaHQgcGxhdGZvcm0gbGF1bmNoIGFuZCBGbHV0dGVyIGhvc3QgdGhlbWVzLlwiKSxcbiAgICBzeW50aGV0aWNUZXh0KGAke3Byb2plY3RSb290fS9hbmRyb2lkL2FwcC9zcmMvbWFpbi9yZXMveG1sL2JhY2t1cF9ydWxlcy54bWxgLCBcInJlc291cmNlXCIsIHJlbmRlckJhY2t1cFJ1bGVzKCksXG4gICAgICBcIkNsb3NlZCBBUEkgMjMtMzAgZnVsbC1iYWNrdXAgZXhjbHVzaW9ucyByZXVzZWQgZnJvbSB0aGUgQW5kcm9pZCBzYWZldHkgY29udHJhY3QuXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL3Jlcy94bWwvZGF0YV9leHRyYWN0aW9uX3J1bGVzLnhtbGAsIFwicmVzb3VyY2VcIiwgcmVuZGVyRGF0YUV4dHJhY3Rpb25SdWxlcygpLFxuICAgICAgXCJDbG9zZWQgQW5kcm9pZCAxMisgYmFja3VwIGFuZCB0cmFuc2ZlciBleGNsdXNpb25zIHJldXNlZCBmcm9tIHRoZSBBbmRyb2lkIHNhZmV0eSBjb250cmFjdC5cIiksXG4gICAgc3ludGhldGljVGV4dChgJHtwcm9qZWN0Um9vdH0vYW5kcm9pZC9idWlsZC5ncmFkbGUua3RzYCwgXCJtYW5pZmVzdFwiLCByZW5kZXJBbmRyb2lkUm9vdEJ1aWxkKCksXG4gICAgICBcIlRhc2sgMDI4LWNvbXBhdGlibGUgZGV0ZXJtaW5pc3RpYyBBbmRyb2lkIHJvb3QgYnVpbGQuXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvZ3JhZGxlLnByb3BlcnRpZXNgLCBcInN1cHBvcnRcIiwgcmVuZGVyQW5kcm9pZEdyYWRsZVByb3BlcnRpZXMoKSxcbiAgICAgIFwiUGlubmVkIGlzb2xhdGVkIEdyYWRsZSBwcm9wZXJ0aWVzIGZvciB0aGUgcXVhbGlmaWVkIEFuZHJvaWQgbGFuZS5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvc2V0dGluZ3MuZ3JhZGxlLmt0c2AsIFwibWFuaWZlc3RcIiwgcmVuZGVyQW5kcm9pZFNldHRpbmdzKGNvbmZpZ3VyYXRpb24sIGNvbmZpZ3VyYXRpb25TcGFucyksXG4gICAgICBcIkV4YWN0IEZsdXR0ZXIgR3JhZGxlIHBsdWdpbiBsb2FkZXIgd2l0aCB0aGUgcGlubmVkIFRhc2sgMDI4IEFuZHJvaWQgcGx1Z2luIG1hdHJpeC5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L2xpYi9tYWluLmRhcnRgLCBcImVudHJ5XCIsIHJlbmRlcldpZGdldEFwcGxpY2F0aW9uKHByZXBhcmVkLCBjb25maWd1cmF0aW9uU3BhbnMpLFxuICAgICAgXCJTeW50aGV0aWMgc3RhdGVsZXNzIE1hdGVyaWFsIGFwcGxpY2F0aW9uIGFuZCBsYWJlbGxlZCBvdXRwdXQgd2lkZ2V0LlwiKSxcbiAgICAuLi5zZW1hbnRpY0FydGlmYWN0cyxcbiAgICBzeW50aGV0aWNUZXh0KGAke3Byb2plY3RSb290fS9wdWJzcGVjLmxvY2tgLCBcIm1hbmlmZXN0XCIsIHJlbmRlclB1YnNwZWNMb2NrKCksXG4gICAgICBcIkV4YWN0IEZsdXR0ZXIgMy40Ny40IFNESyBkZXBlbmRlbmN5IHJlc29sdXRpb247IG5vIGNhbGxlciBwYWNrYWdlIHJlc29sdXRpb24uXCIpLFxuICAgIGNvbmZpZ3VyZWRUZXh0KGAke3Byb2plY3RSb290fS9wdWJzcGVjLnlhbWxgLCBcIm1hbmlmZXN0XCIsIHJlbmRlclB1YnNwZWMocHJlcGFyZWQsIGNvbmZpZ3VyYXRpb25TcGFucyksXG4gICAgICBcIkNsb3NlZCBTREstb25seSBGbHV0dGVyIHBhY2thZ2UgYW5kIGFzc2V0IG1hbmlmZXN0LlwiKSxcbiAgICBjb25maWd1cmVkVGV4dChgJHtwcm9qZWN0Um9vdH0vdGVzdC9zZW1hbnRpY19sb2dpY190ZXN0LmRhcnRgLCBcInN1cHBvcnRcIiwgcmVuZGVyTG9naWNUZXN0KHByZXBhcmVkLCBjb25maWd1cmF0aW9uU3BhbnMpLFxuICAgICAgXCJTREstb3duZWQgRmx1dHRlciB0ZXN0IGZvciBmcmVzaCBkZXRlcm1pbmlzdGljIHNlbWFudGljIGVudHJ5IGV4ZWN1dGlvbi5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L3Rlc3Qvd2lkZ2V0X3Rlc3QuZGFydGAsIFwic3VwcG9ydFwiLCByZW5kZXJXaWRnZXRUZXN0KHByZXBhcmVkLCBjb25maWd1cmF0aW9uU3BhbnMpLFxuICAgICAgXCJTREstb3duZWQgRmx1dHRlciB3aWRnZXQgdGVzdCBmb3IgZXhhY3QgdGV4dCwga2V5LCBhbmQgc2VtYW50aWNzIGxhYmVsLlwiKSxcbiAgICAuLi5wcmVwYXJlZC5hc3NldHMubWFwKGFzc2V0QXJ0aWZhY3QpXG4gIF0pXG5cbiAgYXJ0aWZhY3RzLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0LnBhdGggPCByaWdodC5wYXRoID8gLTEgOiBsZWZ0LnBhdGggPiByaWdodC5wYXRoID8gMSA6IDApXG4gIGNvbnN0IG1hbmlmZXN0UGF0aCA9IGAke3Byb2plY3RSb290fS9zZW1hbnRpZm9sZC1wcm9qZWN0Lmpzb25gXG5cbiAgYXJ0aWZhY3RzLnB1c2goc3ludGhldGljVGV4dChtYW5pZmVzdFBhdGgsIFwibWFuaWZlc3RcIixcbiAgICByZW5kZXJQcm9qZWN0TWFuaWZlc3QocHJlcGFyZWQsIGFydGlmYWN0cywgbWFuaWZlc3RQYXRoLCBjb25maWd1cmF0aW9uU3BhbnMpLFxuICAgIFwiVmVyc2lvbmVkIEZsdXR0ZXIgcHJvamVjdCBvd25lcnNoaXAsIHRvb2xjaGFpbiwgcHJvdmVuYW5jZSwgYW5kIHBsYXRmb3JtLXN0YXR1cyBtYW5pZmVzdC5cIikpXG5cbiAgcmV0dXJuIHtcbiAgICBhcnRpZmFjdHMsXG4gICAgbWV0YWRhdGE6IHtcbiAgICAgIGFwcGxpY2F0aW9uTWFuaWZlc3Q6IG1hbmlmZXN0UGF0aCxcbiAgICAgIHBsYXRmb3JtUXVhbGlmaWNhdGlvbjoge2FuZHJvaWQ6IFwidGVuc29yYnV6ei1rdm1cIiwgaW9zOiBcImRlZmVycmVkLW93bmVyLWRpcmVjdGlvblwifVxuICAgIH0sXG4gICAgdGFyZ2V0OiBcImZsdXR0ZXJcIlxuICB9XG59XG5cbi8qKlxuICogRW1pdHMgbWFwcGVkIGFwcGxpY2F0aW9uLW93bmVkIERhcnQgc2VtYW50aWMgbW9kdWxlcy5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgcHJlZmxpZ2h0Rmx1dHRlckFwcGxpY2F0aW9uPn0gcHJlcGFyZWQgLSBQcmVwYXJlZCBhcHBsaWNhdGlvbi5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0ZWRTZXRBcnRpZmFjdFtdfSBTZW1hbnRpYyBEYXJ0IGFydGlmYWN0cy5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyU2VtYW50aWNBcnRpZmFjdHMocHJlcGFyZWQpIHtcbiAgY29uc3QgZGVjbGFyYXRpb25zID0gbmV3IE1hcCgpXG5cbiAgZm9yIChjb25zdCBtb2R1bGUgb2YgcHJlcGFyZWQubW9kdWxlcykge1xuICAgIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgbW9kdWxlLmZ1bmN0aW9ucykgZGVjbGFyYXRpb25zLnNldChkZWNsYXJhdGlvbi5pZCwge1xuICAgICAgZGVjbGFyYXRpb24sXG4gICAgICBtb2R1bGVJZDogLyoqIEB0eXBlIHtzdHJpbmd9ICovIChSZWZsZWN0LmdldChtb2R1bGUsIFwiaWRcIikpXG4gICAgfSlcbiAgfVxuICAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0W119ICovXG4gIGNvbnN0IGFydGlmYWN0cyA9IFtzeW50aGV0aWNUZXh0KGAke3Byb2plY3RSb290fS9saWIvc3JjL3NlbWFudGljL3NlbWFudGlmb2xkLmRhcnRgLCBcInN1cHBvcnRcIixcbiAgICByZW5kZXJTZW1hbnRpY0xpYnJhcnkocHJlcGFyZWQpLCBcIlNoYXJlZCBjaGVja2VkIERhcnQgc2NhbGFyL291dHB1dCBydW50aW1lIGFuZCBkZXRlcm1pbmlzdGljIHBhcnQgb3duZXJzaGlwLlwiKV1cblxuICBmb3IgKGNvbnN0IG1vZHVsZSBvZiBwcmVwYXJlZC5tb2R1bGVzKSB7XG4gICAgY29uc3QgbW9kdWxlSWQgPSAvKiogQHR5cGUge3N0cmluZ30gKi8gKFJlZmxlY3QuZ2V0KG1vZHVsZSwgXCJpZFwiKSlcbiAgICBjb25zdCBmaWxlbmFtZSA9IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAocHJlcGFyZWQubW9kdWxlUGF0aHMuZ2V0KG1vZHVsZUlkKSlcbiAgICBjb25zdCBzaW5rTmFtZSA9IG91dHB1dFNpbmtOYW1lKG1vZHVsZSlcbiAgICBjb25zdCB3cml0ZXIgPSBuZXcgU291cmNlV3JpdGVyKHtcbiAgICAgIGNhbGxBcmd1bWVudFN1ZmZpeDogc2lua05hbWUsXG4gICAgICBjYWxsTmFtZVJlc29sdmVyOiBleHByZXNzaW9uID0+IHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSBkZWNsYXJhdGlvbnMuZ2V0KGV4cHJlc3Npb24ucmVzb2x1dGlvbj8uZGVjbGFyYXRpb25JZClcblxuICAgICAgICBpZiAoIXJlc29sdmVkKSB0aHJvdyBuZXcgVHlwZUVycm9yKGBVbmtub3duIHZhbGlkYXRlZCBGbHV0dGVyIGZ1bmN0aW9uICcke2V4cHJlc3Npb24ucmVzb2x1dGlvbj8uZGVjbGFyYXRpb25JZH0nLmApXG5cbiAgICAgICAgcmV0dXJuIGBTZW1hbnRpZm9sZE1vZHVsZSR7bW9kdWxlTmFtZShyZXNvbHZlZC5tb2R1bGVJZCl9LiR7cmVzb2x2ZWQuZGVjbGFyYXRpb24ubmFtZX1gXG4gICAgICB9LFxuICAgICAgZmlsZW5hbWUsXG4gICAgICBsYW5ndWFnZTogXCJkYXJ0XCIsXG4gICAgICBtb2R1bGUsXG4gICAgICBwcm9ncmFtOiBwcmVwYXJlZC5wcm9ncmFtLFxuICAgICAgcHJvZ3JhbVBhdGhzOiBwcmVwYXJlZC5tb2R1bGVQYXRocyxcbiAgICAgIHNvdXJjZXM6IHByZXBhcmVkLnNvdXJjZXNcbiAgICB9KVxuXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcInBhcnQgb2YgJ3NlbWFudGlmb2xkLmRhcnQnO1xcblxcblwiLCBcIkZsdXR0ZXIgc2VtYW50aWMgbGlicmFyeSBwYXJ0IGRpcmVjdGl2ZVwiLCBbbW9kdWxlXSwgW1wiXCJdKVxuICAgIGVtaXRTZW1hbnRpY01vZHVsZSh3cml0ZXIsIG1vZHVsZSwgbW9kdWxlSWQsIG1vZHVsZUlkID09IHByZXBhcmVkLnByb2dyYW0uZW50cnlNb2R1bGUsIHNpbmtOYW1lKVxuICAgIGNvbnN0IG1hcHBpbmcgPSBmaW5hbGl6ZU1hcHBpbmcod3JpdGVyLmZpbmlzaCgpKVxuXG4gICAgYXJ0aWZhY3RzLnB1c2goe1xuICAgICAgY29udGVudDogbWFwcGluZy5nZW5lcmF0ZWQuY29udGVudCxcbiAgICAgIGNvbnRlbnRLaW5kOiBcInRleHRcIixcbiAgICAgIG1lZGlhVHlwZTogXCJ0ZXh0L3gtZGFydFwiLFxuICAgICAgb3duZXJzaGlwOiBcImdlbmVyYXRlZFwiLFxuICAgICAgcGF0aDogZmlsZW5hbWUsXG4gICAgICBwcm92ZW5hbmNlOiB7a2luZDogXCJ0ZXh0XCIsIG1hcHBpbmcsIHNvdXJjZU1hcDogdG9Tb3VyY2VNYXBWMyhtYXBwaW5nKSwgc291cmNlTWFwRmlsZW5hbWU6IGAke2ZpbGVuYW1lfS5tYXBgfSxcbiAgICAgIHJvbGU6IFwic291cmNlXCJcbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIGFydGlmYWN0c1xufVxuXG4vKipcbiAqIEVtaXRzIG9uZSBuYW1lc3BhY2VkIHNlbWFudGljIERhcnQgcGFydC5cbiAqIEBwYXJhbSB7U291cmNlV3JpdGVyfSB3cml0ZXIgLSBNYXBwZWQgc291cmNlIHdyaXRlci5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFByZXBhcmVkIHNlbWFudGljIG1vZHVsZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtb2R1bGVJZCAtIFN0YWJsZSBzZW1hbnRpYyBtb2R1bGUgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGVudHJ5IC0gV2hldGhlciB0aGlzIG1vZHVsZSBvd25zIHRoZSBhcHBsaWNhdGlvbiBlbnRyeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzaW5rTmFtZSAtIENvbGxpc2lvbi1zYWZlIG91dHB1dCBzaW5rIGJpbmRpbmcuXG4gKi9cbmZ1bmN0aW9uIGVtaXRTZW1hbnRpY01vZHVsZSh3cml0ZXIsIG1vZHVsZSwgbW9kdWxlSWQsIGVudHJ5LCBzaW5rTmFtZSkge1xuICBjb25zdCB1bnJlYWRMb2NhbHMgPSBmaW5kVW5yZWFkRGFydExvY2Fscyhtb2R1bGUpXG5cbiAgd3JpdGVyLnN5bnRoZXRpYyhgYWJzdHJhY3QgZmluYWwgY2xhc3MgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUobW9kdWxlSWQpfSB7XFxuYCxcbiAgICBcIkZsdXR0ZXIgc2VtYW50aWMgbW9kdWxlIG5hbWVzcGFjZVwiLCBbbW9kdWxlXSwgW1wiXCJdKVxuICBtb2R1bGUuZnVuY3Rpb25zLmZvckVhY2goKGRlY2xhcmF0aW9uLCBmdW5jdGlvbkluZGV4KSA9PiB7XG4gICAgY29uc3QgcGF0aCA9IGAvZnVuY3Rpb25zLyR7ZnVuY3Rpb25JbmRleH1gXG5cbiAgICB3cml0ZXIuc3ludGhldGljKFwiICBzdGF0aWMgXCIsIFwiRmx1dHRlciBuYW1lc3BhY2VkIGZ1bmN0aW9uIHNjYWZmb2xkXCIsIFtkZWNsYXJhdGlvbl0sIFtwYXRoXSlcbiAgICB3cml0ZXIubWFwcGVkKGVtaXRTY2FsYXJUeXBlKFwiZGFydFwiLCBkZWNsYXJhdGlvbi5yZXR1cm5UeXBlKSwge1xuICAgICAgbWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogZGVjbGFyYXRpb24ucmV0dXJuVHlwZSwgcGF0aDogYCR7cGF0aH0vcmV0dXJuVHlwZWAsIHJvbGU6IFwidHlwZVwiXG4gICAgfSlcbiAgICB3cml0ZXIuc3ludGhldGljKFwiIFwiLCBcImRlY2xhcmF0aW9uIHNwYWNpbmdcIiwgW2RlY2xhcmF0aW9uXSwgW3BhdGhdKVxuICAgIHdyaXRlci5tYXBwZWQoZGVjbGFyYXRpb24ubmFtZSwge21hcHBpbmdLaW5kOiBcImV4YWN0XCIsIG5vZGU6IGRlY2xhcmF0aW9uLCBwYXRoLCByb2xlOiBcIm5hbWVcIn0pXG4gICAgY29uc3QgcGFyYW1ldGVyVGV4dHMgPSBkZWNsYXJhdGlvbi5wYXJhbWV0ZXJzLm1hcChwYXJhbWV0ZXIgPT4gYCR7ZW1pdFNjYWxhclR5cGUoXCJkYXJ0XCIsIHBhcmFtZXRlci50eXBlKX0gJHtwYXJhbWV0ZXIubmFtZX1gKVxuXG4gICAgcGFyYW1ldGVyVGV4dHMucHVzaChgX1NlbWFudGlmb2xkT3V0cHV0U2luayAke3NpbmtOYW1lfWApXG4gICAgY29uc3QgbXVsdGlsaW5lID0gd3JpdGVyLmNvbHVtbiAtIDEgKyBgKCR7cGFyYW1ldGVyVGV4dHMuam9pbihcIiwgXCIpfSkge2AubGVuZ3RoID4gODBcblxuICAgIHdyaXRlci5tYXBwZWQoXCIoXCIsIHttYXBwaW5nS2luZDogXCJhbmNob3JcIiwgbm9kZTogZGVjbGFyYXRpb24sIHBhdGh9KVxuICAgIGRlY2xhcmF0aW9uLnBhcmFtZXRlcnMuZm9yRWFjaCgocGFyYW1ldGVyLCBwYXJhbWV0ZXJJbmRleCkgPT4ge1xuICAgICAgY29uc3QgcGFyYW1ldGVyUGF0aCA9IGAke3BhdGh9L3BhcmFtZXRlcnMvJHtwYXJhbWV0ZXJJbmRleH1gXG5cbiAgICAgIGlmIChtdWx0aWxpbmUpIHdyaXRlci5zeW50aGV0aWMoYCR7cGFyYW1ldGVySW5kZXggPyBcIlwiIDogXCJcXG5cIn0gICAgYCxcbiAgICAgICAgXCJEYXJ0IGFwcGxpY2F0aW9uIHBhcmFtZXRlciBpbmRlbnRhdGlvblwiLCBbcGFyYW1ldGVyXSwgW3BhcmFtZXRlclBhdGhdKVxuICAgICAgZWxzZSBpZiAocGFyYW1ldGVySW5kZXgpIHdyaXRlci5zeW50aGV0aWMoXCIsIFwiLCBcInBhcmFtZXRlciBzZXBhcmF0b3JcIiwgW3BhcmFtZXRlcl0sIFtwYXJhbWV0ZXJQYXRoXSlcbiAgICAgIHdyaXRlci5tYXBwZWQoZW1pdFNjYWxhclR5cGUoXCJkYXJ0XCIsIHBhcmFtZXRlci50eXBlKSwge1xuICAgICAgICBtYXBwaW5nS2luZDogXCJleGFjdFwiLCBub2RlOiBwYXJhbWV0ZXIudHlwZSwgcGF0aDogYCR7cGFyYW1ldGVyUGF0aH0vdHlwZWAsIHJvbGU6IFwidHlwZVwiXG4gICAgICB9KVxuICAgICAgd3JpdGVyLnN5bnRoZXRpYyhcIiBcIiwgXCJwYXJhbWV0ZXIgc3BhY2luZ1wiLCBbcGFyYW1ldGVyXSwgW3BhcmFtZXRlclBhdGhdKVxuICAgICAgd3JpdGVyLm1hcHBlZChwYXJhbWV0ZXIubmFtZSwge21hcHBpbmdLaW5kOiBcImV4YWN0XCIsIG5vZGU6IHBhcmFtZXRlciwgcGF0aDogcGFyYW1ldGVyUGF0aCwgcm9sZTogXCJuYW1lXCJ9KVxuICAgICAgaWYgKG11bHRpbGluZSkgd3JpdGVyLnN5bnRoZXRpYyhcIixcXG5cIiwgXCJEYXJ0IGZvcm1hdHRlciBwYXJhbWV0ZXIgc2VwYXJhdG9yXCIsIFtwYXJhbWV0ZXJdLCBbcGFyYW1ldGVyUGF0aF0pXG4gICAgfSlcbiAgICBpZiAobXVsdGlsaW5lKSB3cml0ZXIuc3ludGhldGljKGAke2RlY2xhcmF0aW9uLnBhcmFtZXRlcnMubGVuZ3RoID8gXCJcIiA6IFwiXFxuXCJ9ICAgIF9TZW1hbnRpZm9sZE91dHB1dFNpbmsgJHtzaW5rTmFtZX0sXFxuICBgLFxuICAgICAgXCJGbHV0dGVyIG91dHB1dCBzaW5rIHBhcmFtZXRlclwiLCBbZGVjbGFyYXRpb25dLCBbcGF0aF0pXG4gICAgZWxzZSB3cml0ZXIuc3ludGhldGljKGAke2RlY2xhcmF0aW9uLnBhcmFtZXRlcnMubGVuZ3RoID8gXCIsIFwiIDogXCJcIn1fU2VtYW50aWZvbGRPdXRwdXRTaW5rICR7c2lua05hbWV9YCxcbiAgICAgIFwiRmx1dHRlciBvdXRwdXQgc2luayBwYXJhbWV0ZXJcIiwgW2RlY2xhcmF0aW9uXSwgW3BhdGhdKVxuICAgIHdyaXRlci5tYXBwZWQoXCIpXCIsIHttYXBwaW5nS2luZDogXCJhbmNob3JcIiwgbm9kZTogZGVjbGFyYXRpb24sIHBhdGh9KVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIge1xcblwiLCBcIkRhcnQgZnVuY3Rpb24gYm9keSBzY2FmZm9sZFwiLCBbZGVjbGFyYXRpb25dLCBbcGF0aF0pXG4gICAgZW1pdERhcnRCbG9jayh3cml0ZXIsIGRlY2xhcmF0aW9uLmJvZHksIFwiICAgIFwiLCBgJHtwYXRofS9ib2R5YCwgdW5yZWFkTG9jYWxzLCBgJHtzaW5rTmFtZX0ud3JpdGVgLCB0cnVlKVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgIH1cXG5cIiwgXCJEYXJ0IGZ1bmN0aW9uIGJvZHkgc2NhZmZvbGRcIiwgW2RlY2xhcmF0aW9uXSwgW3BhdGhdKVxuICAgIGlmIChmdW5jdGlvbkluZGV4ICsgMSA8IG1vZHVsZS5mdW5jdGlvbnMubGVuZ3RoIHx8IGVudHJ5KSB7XG4gICAgICB3cml0ZXIuc3ludGhldGljKFwiXFxuXCIsIFwiRGFydCBmb3JtYXR0ZXIgZGVjbGFyYXRpb24gc2VwYXJhdG9yXCIsIFtkZWNsYXJhdGlvbl0sIFtwYXRoXSlcbiAgICB9XG4gIH0pXG4gIGlmIChlbnRyeSkge1xuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgIHN0YXRpYyBMaXN0PFN0cmluZz4gc2VtYW50aWZvbGRFbnRyeSgpIHtcXG5cIiwgXCJGbHV0dGVyIHNlbWFudGljIGVudHJ5IHNjYWZmb2xkXCIsXG4gICAgICBbbW9kdWxlLmVudHJ5UG9pbnRdLCBbXCIvZW50cnlQb2ludFwiXSlcbiAgICB3cml0ZXIuc3ludGhldGljKGAgICAgZmluYWwgX1NlbWFudGlmb2xkT3V0cHV0U2luayAke3NpbmtOYW1lfSA9IF9TZW1hbnRpZm9sZE91dHB1dFNpbmsoKTtcXG5gLFxuICAgICAgXCJGbHV0dGVyIG91dHB1dCBzaW5rIGFsbG9jYXRpb25cIiwgW21vZHVsZS5lbnRyeVBvaW50XSwgW1wiL2VudHJ5UG9pbnRcIl0pXG4gICAgZW1pdERhcnRCbG9jayh3cml0ZXIsIG1vZHVsZS5lbnRyeVBvaW50LmJvZHksIFwiICAgIFwiLCBcIi9lbnRyeVBvaW50L2JvZHlcIiwgdW5yZWFkTG9jYWxzLCBgJHtzaW5rTmFtZX0ud3JpdGVgLCB0cnVlKVxuICAgIHdyaXRlci5zeW50aGV0aWMoYCAgICByZXR1cm4gJHtzaW5rTmFtZX0uc25hcHNob3QoKTtcXG5gLCBcIkZsdXR0ZXIgc2VtYW50aWMgb3V0cHV0IHJldHVyblwiLFxuICAgICAgW21vZHVsZS5lbnRyeVBvaW50XSwgW1wiL2VudHJ5UG9pbnRcIl0pXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIiAgfVxcblwiLCBcIkZsdXR0ZXIgc2VtYW50aWMgZW50cnkgc2NhZmZvbGRcIiwgW21vZHVsZS5lbnRyeVBvaW50XSwgW1wiL2VudHJ5UG9pbnRcIl0pXG4gIH1cbiAgd3JpdGVyLnN5bnRoZXRpYyhcIn1cXG5cIiwgXCJGbHV0dGVyIHNlbWFudGljIG1vZHVsZSBuYW1lc3BhY2VcIiwgW21vZHVsZV0sIFtcIlwiXSlcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBzaGFyZWQgc2VtYW50aWMgRGFydCBsaWJyYXJ5LlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBwcmVmbGlnaHRGbHV0dGVyQXBwbGljYXRpb24+fSBwcmVwYXJlZCAtIFByZXBhcmVkIHByb2plY3QuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBEYXJ0IGxpYnJhcnkgc291cmNlLlxuICovXG5mdW5jdGlvbiByZW5kZXJTZW1hbnRpY0xpYnJhcnkocHJlcGFyZWQpIHtcbiAgY29uc3QgcGFydHMgPSBwcmVwYXJlZC5tb2R1bGVzLm1hcChtb2R1bGUgPT4gYHBhcnQgJyR7bW9kdWxlRmlsZU5hbWUoLyoqIEB0eXBlIHtzdHJpbmd9ICovIChSZWZsZWN0LmdldChtb2R1bGUsIFwiaWRcIikpKX0uZGFydCc7YCkuam9pbihcIlxcblwiKVxuXG4gIHJldHVybiBgJHtwYXJ0c31cXG5cXG4ke2RhcnRSdW50aW1lfSR7b3V0cHV0U2lua1J1bnRpbWV9YFxufVxuXG4vKipcbiAqIFJlbmRlcnMgZXhhY3QgRmx1dHRlciB0ZW1wbGF0ZSBpZGVudGl0eSBtZXRhZGF0YS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IE1ldGFkYXRhIFlBTUwuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlck1ldGFkYXRhKCkge1xuICByZXR1cm4gYCMgVGhpcyBmaWxlIHRyYWNrcyBwcm9wZXJ0aWVzIG9mIHRoaXMgU2VtYW50aWZvbGQtb3duZWQgRmx1dHRlciBwcm9qZWN0LlxudmVyc2lvbjpcbiAgcmV2aXNpb246ICR7Zmx1dHRlclRvb2xjaGFpbi5yZXZpc2lvbn1cbiAgY2hhbm5lbDogc3RhYmxlXG5wcm9qZWN0X3R5cGU6IGFwcFxuYFxufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIGNsb3NlZCBhbmFseXplciBjb25maWd1cmF0aW9uLlxuICogQHJldHVybnMge3N0cmluZ30gQW5hbHl6ZXIgWUFNTC5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyQW5hbHlzaXNPcHRpb25zKCkge1xuICByZXR1cm4gYGFuYWx5emVyOlxuICBsYW5ndWFnZTpcbiAgICBzdHJpY3QtY2FzdHM6IHRydWVcbiAgICBzdHJpY3QtcmF3LXR5cGVzOiB0cnVlXG5gXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgU0RLLW9ubHkgcGFja2FnZSBtYW5pZmVzdC5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgcHJlZmxpZ2h0Rmx1dHRlckFwcGxpY2F0aW9uPn0gcHJlcGFyZWQgLSBQcmVwYXJlZCBwcm9qZWN0LlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uU3BhbltdfSBzcGFucyAtIENvbmZpZ3VyYXRpb24gcHJvdmVuYW5jZSBzaW5rLlxuICogQHJldHVybnMge3N0cmluZ30gUHVic3BlYyBZQU1MLlxuICovXG5mdW5jdGlvbiByZW5kZXJQdWJzcGVjKHByZXBhcmVkLCBzcGFucykge1xuICBjb25zdCBjb25maWd1cmF0aW9uID0gcHJlcGFyZWQuY29uZmlndXJhdGlvblxuICBjb25zdCBhc3NldExpbmVzID0gcHJlcGFyZWQuYXNzZXRzLmxlbmd0aCA9PSAwID8gXCJcIiA6IGBcXG4gIGFzc2V0czpcXG4ke3ByZXBhcmVkLmFzc2V0cy5tYXAoKHtwYXRofSkgPT4gYCAgICAtICR7cGF0aH1gKS5qb2luKFwiXFxuXCIpfVxcbmBcblxuICByZXR1cm4gY29uZmlndXJlZChgJHtwcm9qZWN0Um9vdH0vcHVic3BlYy55YW1sYCwgc3BhbnMsIFtcbiAgICBcIm5hbWU6IFwiLCBmaWVsZChcInBhY2thZ2VOYW1lXCIsIGNvbmZpZ3VyYXRpb24ucGFja2FnZU5hbWUpLCBcIlxcbnB1Ymxpc2hfdG86IG5vbmVcXG52ZXJzaW9uOiBcIixcbiAgICBmaWVsZChcInZlcnNpb25OYW1lXCIsIGNvbmZpZ3VyYXRpb24udmVyc2lvbk5hbWUpLCBcIitcIiwgZmllbGQoXCJ2ZXJzaW9uQ29kZVwiLCBTdHJpbmcoY29uZmlndXJhdGlvbi52ZXJzaW9uQ29kZSkpLFxuICAgIFwiXFxuZW52aXJvbm1lbnQ6XFxuICBzZGs6IDMuMTMuM1xcbiAgZmx1dHRlcjogMy40Ny40XFxuZGVwZW5kZW5jaWVzOlxcbiAgZmx1dHRlcjpcXG4gICAgc2RrOiBmbHV0dGVyXFxuZGV2X2RlcGVuZGVuY2llczpcXG4gIGZsdXR0ZXJfdGVzdDpcXG4gICAgc2RrOiBmbHV0dGVyXFxuZmx1dHRlcjpcXG4gIHVzZXMtbWF0ZXJpYWwtZGVzaWduOiB0cnVlXFxuXCIsXG4gICAgYXNzZXRMaW5lc1xuICBdKVxufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIGV4YWN0IEZsdXR0ZXIgU0RLIGRlcGVuZGVuY3kgbG9jay5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IFB1YiBsb2NrIFlBTUwuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclB1YnNwZWNMb2NrKCkge1xuICBjb25zdCBob3N0ZWQgPSBuZXcgTWFwKGZsdXR0ZXJMb2NrZWRIb3N0ZWRQYWNrYWdlcy5tYXAocGFja2FnZV8gPT4gW3BhY2thZ2VfWzBdLCBwYWNrYWdlX10pKVxuICBjb25zdCBzZGsgPSBuZXcgTWFwKGZsdXR0ZXJMb2NrZWRTZGtQYWNrYWdlcylcbiAgY29uc3QgcGFja2FnZU5hbWVzID0gWy4uLmhvc3RlZC5rZXlzKCksIC4uLnNkay5rZXlzKCldLnNvcnQoKVxuICBjb25zdCBwYWNrYWdlcyA9IHBhY2thZ2VOYW1lcy5tYXAobmFtZSA9PiB7XG4gICAgY29uc3Qgc2RrRGVwZW5kZW5jeSA9IHNkay5nZXQobmFtZSlcblxuICAgIGlmIChzZGtEZXBlbmRlbmN5KSByZXR1cm4gYCAgJHtuYW1lfTpcbiAgICBkZXBlbmRlbmN5OiAke3Nka0RlcGVuZGVuY3kgPT0gXCJ0cmFuc2l0aXZlXCIgPyBzZGtEZXBlbmRlbmN5IDogYFwiJHtzZGtEZXBlbmRlbmN5fVwiYH1cbiAgICBkZXNjcmlwdGlvbjogZmx1dHRlclxuICAgIHNvdXJjZTogc2RrXG4gICAgdmVyc2lvbjogXCIwLjAuMFwiYFxuICAgIGNvbnN0IGxvY2tlZCA9IGhvc3RlZC5nZXQobmFtZSlcblxuICAgIGlmICghbG9ja2VkKSB0aHJvdyBuZXcgVHlwZUVycm9yKGBNaXNzaW5nIHZhbGlkYXRlZCBGbHV0dGVyIGxvY2sgZW50cnkgJyR7bmFtZX0nLmApXG4gICAgY29uc3QgWywgdmVyc2lvbiwgc2hhMjU2XSA9IGxvY2tlZFxuICAgIGNvbnN0IHJlbmRlcmVkSGFzaCA9IC9eWzAtOV0vdS50ZXN0KHNoYTI1NikgPyBgXCIke3NoYTI1Nn1cImAgOiBzaGEyNTZcblxuICAgIHJldHVybiBgICAke25hbWV9OlxuICAgIGRlcGVuZGVuY3k6IHRyYW5zaXRpdmVcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIG5hbWU6ICR7bmFtZX1cbiAgICAgIHNoYTI1NjogJHtyZW5kZXJlZEhhc2h9XG4gICAgICB1cmw6IFwiaHR0cHM6Ly9wdWIuZGV2XCJcbiAgICBzb3VyY2U6IGhvc3RlZFxuICAgIHZlcnNpb246IFwiJHt2ZXJzaW9ufVwiYFxuICB9KS5qb2luKFwiXFxuXCIpXG5cbiAgcmV0dXJuIGAjIEdlbmVyYXRlZCBieSBwdWJcbiMgU2VlIGh0dHBzOi8vZGFydC5kZXYvdG9vbHMvcHViL2dsb3NzYXJ5I2xvY2tmaWxlXG5wYWNrYWdlczpcbiR7cGFja2FnZXN9XG5zZGtzOlxuICBkYXJ0OiBcIjMuMTMuM1wiXG4gIGZsdXR0ZXI6IFwiMy40Ny40XCJcbmBcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBzeW50aGV0aWMgTWF0ZXJpYWwgd2lkZ2V0IHNoZWxsLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBwcmVmbGlnaHRGbHV0dGVyQXBwbGljYXRpb24+fSBwcmVwYXJlZCAtIFByZXBhcmVkIHByb2plY3QuXG4gKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb25TcGFuW119IHNwYW5zIC0gQ29uZmlndXJhdGlvbiBwcm92ZW5hbmNlIHNpbmsuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBGbHV0dGVyIGVudHJ5IHNvdXJjZS5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyV2lkZ2V0QXBwbGljYXRpb24ocHJlcGFyZWQsIHNwYW5zKSB7XG4gIGNvbnN0IGVudHJ5Q2xhc3MgPSBgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUocHJlcGFyZWQucHJvZ3JhbS5lbnRyeU1vZHVsZSl9YFxuXG4gIHJldHVybiBjb25maWd1cmVkKGAke3Byb2plY3RSb290fS9saWIvbWFpbi5kYXJ0YCwgc3BhbnMsIFtcbiAgICBgaW1wb3J0ICdwYWNrYWdlOmZsdXR0ZXIvbWF0ZXJpYWwuZGFydCc7XG5cbmltcG9ydCAnc3JjL3NlbWFudGljL3NlbWFudGlmb2xkLmRhcnQnO1xuXG52b2lkIG1haW4oKSB7XG4gIHJ1bkFwcChjb25zdCBTZW1hbnRpZm9sZEFwcGxpY2F0aW9uKCkpO1xufVxuXG5jbGFzcyBTZW1hbnRpZm9sZEFwcGxpY2F0aW9uIGV4dGVuZHMgU3RhdGVsZXNzV2lkZ2V0IHtcbiAgY29uc3QgU2VtYW50aWZvbGRBcHBsaWNhdGlvbih7c3VwZXIua2V5fSk7XG5cbiAgQG92ZXJyaWRlXG4gIFdpZGdldCBidWlsZChCdWlsZENvbnRleHQgY29udGV4dCkge1xuICAgIGZpbmFsIExpc3Q8U3RyaW5nPiBsaW5lcyA9ICR7ZW50cnlDbGFzc30uc2VtYW50aWZvbGRFbnRyeSgpO1xuXG4gICAgcmV0dXJuIE1hdGVyaWFsQXBwKFxuICAgICAgZGVidWdTaG93Q2hlY2tlZE1vZGVCYW5uZXI6IGZhbHNlLFxuICAgICAgdGl0bGU6ICdgLCBmaWVsZChcImRpc3BsYXlOYW1lXCIsIGRhcnRFc2NhcGUocHJlcGFyZWQuY29uZmlndXJhdGlvbi5kaXNwbGF5TmFtZSkpLCBgJyxcbiAgICAgIGhvbWU6IFNjYWZmb2xkKFxuICAgICAgICBib2R5OiBDZW50ZXIoXG4gICAgICAgICAgY2hpbGQ6IFNlbWFudGljcyhcbiAgICAgICAgICAgIGtleTogY29uc3QgS2V5KCdzZW1hbnRpZm9sZC1vdXRwdXQnKSxcbiAgICAgICAgICAgIGNvbnRhaW5lcjogdHJ1ZSxcbiAgICAgICAgICAgIGV4cGxpY2l0Q2hpbGROb2RlczogdHJ1ZSxcbiAgICAgICAgICAgIGxhYmVsOiAnc2VtYW50aWZvbGQtb3V0cHV0JyxcbiAgICAgICAgICAgIGNoaWxkOiBUZXh0KGxpbmVzLmpvaW4oJ1xcXFxuJykpLFxuICAgICAgICAgICksXG4gICAgICAgICksXG4gICAgICApLFxuICAgICk7XG4gIH1cbn1cbmBcbiAgXSlcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBzZW1hbnRpYy1lbnRyeSBkZXRlcm1pbmlzbSB0ZXN0LlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBwcmVmbGlnaHRGbHV0dGVyQXBwbGljYXRpb24+fSBwcmVwYXJlZCAtIFByZXBhcmVkIHByb2plY3QuXG4gKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb25TcGFuW119IHNwYW5zIC0gQ29uZmlndXJhdGlvbiBwcm92ZW5hbmNlIHNpbmsuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBGbHV0dGVyIHRlc3Qgc291cmNlLlxuICovXG5mdW5jdGlvbiByZW5kZXJMb2dpY1Rlc3QocHJlcGFyZWQsIHNwYW5zKSB7XG4gIGNvbnN0IGVudHJ5Q2xhc3MgPSBgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUocHJlcGFyZWQucHJvZ3JhbS5lbnRyeU1vZHVsZSl9YFxuXG4gIHJldHVybiBjb25maWd1cmVkKGAke3Byb2plY3RSb290fS90ZXN0L3NlbWFudGljX2xvZ2ljX3Rlc3QuZGFydGAsIHNwYW5zLCBbXG4gICAgXCJpbXBvcnQgJ3BhY2thZ2U6Zmx1dHRlcl90ZXN0L2ZsdXR0ZXJfdGVzdC5kYXJ0JztcXG5pbXBvcnQgJ3BhY2thZ2U6XCIsIGZpZWxkKFwicGFja2FnZU5hbWVcIiwgcHJlcGFyZWQuY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZSksXG4gICAgYC9zcmMvc2VtYW50aWMvc2VtYW50aWZvbGQuZGFydCc7XG5cbnZvaWQgbWFpbigpIHtcbiAgdGVzdCgnc2VtYW50aWMgZW50cnkgaXMgZGV0ZXJtaW5pc3RpYyBhY3Jvc3MgZnJlc2ggcnVucycsICgpIHtcbiAgICBleHBlY3QoXG4gICAgICAke2VudHJ5Q2xhc3N9LnNlbWFudGlmb2xkRW50cnkoKSxcbiAgICAgICR7ZW50cnlDbGFzc30uc2VtYW50aWZvbGRFbnRyeSgpLFxuICAgICk7XG4gIH0pO1xufVxuYFxuICBdKVxufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIGV4YWN0IGxhYmVsbGVkIHdpZGdldCB0ZXN0LlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBwcmVmbGlnaHRGbHV0dGVyQXBwbGljYXRpb24+fSBwcmVwYXJlZCAtIFByZXBhcmVkIHByb2plY3QuXG4gKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb25TcGFuW119IHNwYW5zIC0gQ29uZmlndXJhdGlvbiBwcm92ZW5hbmNlIHNpbmsuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBGbHV0dGVyIHdpZGdldCB0ZXN0IHNvdXJjZS5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyV2lkZ2V0VGVzdChwcmVwYXJlZCwgc3BhbnMpIHtcbiAgY29uc3QgZW50cnlDbGFzcyA9IGBTZW1hbnRpZm9sZE1vZHVsZSR7bW9kdWxlTmFtZShwcmVwYXJlZC5wcm9ncmFtLmVudHJ5TW9kdWxlKX1gXG5cbiAgcmV0dXJuIGNvbmZpZ3VyZWQoYCR7cHJvamVjdFJvb3R9L3Rlc3Qvd2lkZ2V0X3Rlc3QuZGFydGAsIHNwYW5zLCBbXG4gICAgXCJpbXBvcnQgJ3BhY2thZ2U6Zmx1dHRlci9tYXRlcmlhbC5kYXJ0JztcXG5pbXBvcnQgJ3BhY2thZ2U6Zmx1dHRlcl90ZXN0L2ZsdXR0ZXJfdGVzdC5kYXJ0JztcXG5pbXBvcnQgJ3BhY2thZ2U6XCIsXG4gICAgZmllbGQoXCJwYWNrYWdlTmFtZVwiLCBwcmVwYXJlZC5jb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lKSwgYC9tYWluLmRhcnQnO1xuaW1wb3J0ICdwYWNrYWdlOmAsIGZpZWxkKFwicGFja2FnZU5hbWVcIiwgcHJlcGFyZWQuY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZSksIGAvc3JjL3NlbWFudGljL3NlbWFudGlmb2xkLmRhcnQnO1xuXG52b2lkIG1haW4oKSB7XG4gIHRlc3RXaWRnZXRzKCdyZW5kZXJzIGV4YWN0IGxhYmVsbGVkIHNlbWFudGljIG91dHB1dCcsIChcbiAgICBXaWRnZXRUZXN0ZXIgdGVzdGVyLFxuICApIGFzeW5jIHtcbiAgICBmaW5hbCBTdHJpbmcgZXhwZWN0ZWQgPSAke2VudHJ5Q2xhc3N9LnNlbWFudGlmb2xkRW50cnkoKS5qb2luKCdcXFxcbicpO1xuXG4gICAgYXdhaXQgdGVzdGVyLnB1bXBXaWRnZXQoY29uc3QgU2VtYW50aWZvbGRBcHBsaWNhdGlvbigpKTtcbiAgICBmaW5hbCBGaW5kZXIgb3V0cHV0ID0gZmluZC5ieUtleShjb25zdCBLZXkoJ3NlbWFudGlmb2xkLW91dHB1dCcpKTtcblxuICAgIGV4cGVjdChvdXRwdXQsIGZpbmRzT25lV2lkZ2V0KTtcbiAgICBleHBlY3QoXG4gICAgICB0ZXN0ZXIud2lkZ2V0PFNlbWFudGljcz4ob3V0cHV0KS5wcm9wZXJ0aWVzLmxhYmVsLFxuICAgICAgJ3NlbWFudGlmb2xkLW91dHB1dCcsXG4gICAgKTtcbiAgICBleHBlY3QoXG4gICAgICBmaW5kLmRlc2NlbmRhbnQob2Y6IG91dHB1dCwgbWF0Y2hpbmc6IGZpbmQudGV4dChleHBlY3RlZCkpLFxuICAgICAgZmluZHNPbmVXaWRnZXQsXG4gICAgKTtcbiAgfSk7XG59XG5gXG4gIF0pXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgc2hhcmVkIEFuZHJvaWQgcm9vdCBidWlsZC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEdyYWRsZSBLb3RsaW4gc291cmNlLlxuICovXG5mdW5jdGlvbiByZW5kZXJBbmRyb2lkUm9vdEJ1aWxkKCkge1xuICByZXR1cm4gYGFsbHByb2plY3RzIHtcbiAgcmVwb3NpdG9yaWVzIHtcbiAgICBnb29nbGUoKVxuICAgIG1hdmVuQ2VudHJhbCgpXG4gIH1cbn1cblxudmFsIG5ld0J1aWxkRGlyOiBEaXJlY3RvcnkgPSByb290UHJvamVjdC5sYXlvdXQuYnVpbGREaXJlY3RvcnkuZGlyKFwiLi4vLi4vYnVpbGRcIikuZ2V0KClcbnJvb3RQcm9qZWN0LmxheW91dC5idWlsZERpcmVjdG9yeS52YWx1ZShuZXdCdWlsZERpcilcblxuc3VicHJvamVjdHMge1xuICBwcm9qZWN0LmxheW91dC5idWlsZERpcmVjdG9yeS52YWx1ZShuZXdCdWlsZERpci5kaXIocHJvamVjdC5uYW1lKSlcbiAgcHJvamVjdC5ldmFsdWF0aW9uRGVwZW5kc09uKFwiOmFwcFwiKVxufVxuXG50YXNrcy5yZWdpc3RlcjxEZWxldGU+KFwiY2xlYW5cIikge1xuICBkZWxldGUocm9vdFByb2plY3QubGF5b3V0LmJ1aWxkRGlyZWN0b3J5KVxufVxuYFxufVxuXG4vKipcbiAqIFJlbmRlcnMgRmx1dHRlciBwbHVnaW4gYW5kIEFuZHJvaWQgcGx1Z2luIG93bmVyc2hpcC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRmx1dHRlckFwcGxpY2F0aW9uQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIE5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7Q29uZmlndXJhdGlvblNwYW5bXX0gc3BhbnMgLSBDb25maWd1cmF0aW9uIHByb3ZlbmFuY2Ugc2luay5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEdyYWRsZSBzZXR0aW5ncyBzb3VyY2UuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckFuZHJvaWRTZXR0aW5ncyhjb25maWd1cmF0aW9uLCBzcGFucykge1xuICByZXR1cm4gY29uZmlndXJlZChgJHtwcm9qZWN0Um9vdH0vYW5kcm9pZC9zZXR0aW5ncy5ncmFkbGUua3RzYCwgc3BhbnMsIFtgcGx1Z2luTWFuYWdlbWVudCB7XG4gIHZhbCBmbHV0dGVyU2RrUGF0aCA9IHJ1biB7XG4gICAgdmFsIHByb3BlcnRpZXMgPSBqYXZhLnV0aWwuUHJvcGVydGllcygpXG4gICAgZmlsZShcImxvY2FsLnByb3BlcnRpZXNcIikuaW5wdXRTdHJlYW0oKS51c2UgeyBwcm9wZXJ0aWVzLmxvYWQoaXQpIH1cbiAgICByZXF1aXJlTm90TnVsbChwcm9wZXJ0aWVzLmdldFByb3BlcnR5KFwiZmx1dHRlci5zZGtcIikpIHsgXCJmbHV0dGVyLnNkayBub3Qgc2V0IGluIGxvY2FsLnByb3BlcnRpZXNcIiB9XG4gIH1cblxuICBpbmNsdWRlQnVpbGQoXCIkZmx1dHRlclNka1BhdGgvcGFja2FnZXMvZmx1dHRlcl90b29scy9ncmFkbGVcIilcblxuICByZXBvc2l0b3JpZXMge1xuICAgIGdvb2dsZSgpXG4gICAgbWF2ZW5DZW50cmFsKClcbiAgICBncmFkbGVQbHVnaW5Qb3J0YWwoKVxuICB9XG59XG5cbnBsdWdpbnMge1xuICBpZChcImRldi5mbHV0dGVyLmZsdXR0ZXItcGx1Z2luLWxvYWRlclwiKSB2ZXJzaW9uIFwiMS4wLjBcIlxuICBpZChcImNvbS5hbmRyb2lkLmFwcGxpY2F0aW9uXCIpIHZlcnNpb24gXCIke2FuZHJvaWRUb29sY2hhaW4uYW5kcm9pZEdyYWRsZVBsdWdpbn1cIiBhcHBseSBmYWxzZVxuICBpZChcIm9yZy5qZXRicmFpbnMua290bGluLmFuZHJvaWRcIikgdmVyc2lvbiBcIiR7YW5kcm9pZFRvb2xjaGFpbi5rb3RsaW5HcmFkbGVQbHVnaW59XCIgYXBwbHkgZmFsc2Vcbn1cblxucm9vdFByb2plY3QubmFtZSA9IFwiYCwgZmllbGQoXCJwYWNrYWdlTmFtZVwiLCBjb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lKSwgYFwiXG5pbmNsdWRlKFwiOmFwcFwiKVxuYF0pXG59XG5cbi8qKlxuICogUmVuZGVycyBkZXRlcm1pbmlzdGljIEFuZHJvaWQgR3JhZGxlIHByb3BlcnRpZXMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBHcmFkbGUgcHJvcGVydGllcy5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyQW5kcm9pZEdyYWRsZVByb3BlcnRpZXMoKSB7XG4gIHJldHVybiBgYW5kcm9pZC5idWlsdEluS290bGluPWZhbHNlXG5hbmRyb2lkLm5ld0RzbD1mYWxzZVxuYW5kcm9pZC51c2VBbmRyb2lkWD10cnVlXG5rb3RsaW4uc3RkbGliLmRlZmF1bHQuZGVwZW5kZW5jeT1mYWxzZVxub3JnLmdyYWRsZS5jYWNoaW5nPWZhbHNlXG5vcmcuZ3JhZGxlLmNvbmZpZ3VyYXRpb24tY2FjaGU9ZmFsc2Vcbm9yZy5ncmFkbGUuZGFlbW9uPWZhbHNlXG5vcmcuZ3JhZGxlLmp2bWFyZ3M9LVhteDIwNDhtIC1EZmlsZS5lbmNvZGluZz1VVEYtOCAtRHVzZXIubGFuZ3VhZ2U9ZW4gLUR1c2VyLmNvdW50cnk9VVMgLUR1c2VyLnRpbWV6b25lPVVUQ1xub3JnLmdyYWRsZS5wYXJhbGxlbD1mYWxzZVxuYFxufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEZsdXR0ZXIgQW5kcm9pZCBhcHBsaWNhdGlvbiBidWlsZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRmx1dHRlckFwcGxpY2F0aW9uQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIE5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7Q29uZmlndXJhdGlvblNwYW5bXX0gc3BhbnMgLSBDb25maWd1cmF0aW9uIHByb3ZlbmFuY2Ugc2luay5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEFwcGxpY2F0aW9uIEdyYWRsZSBzb3VyY2UuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckFuZHJvaWRBcHBCdWlsZChjb25maWd1cmF0aW9uLCBzcGFucykge1xuICByZXR1cm4gY29uZmlndXJlZChgJHtwcm9qZWN0Um9vdH0vYW5kcm9pZC9hcHAvYnVpbGQuZ3JhZGxlLmt0c2AsIHNwYW5zLCBbYHBsdWdpbnMge1xuICBpZChcImNvbS5hbmRyb2lkLmFwcGxpY2F0aW9uXCIpXG4gIGlkKFwib3JnLmpldGJyYWlucy5rb3RsaW4uYW5kcm9pZFwiKVxuICBpZChcImRldi5mbHV0dGVyLmZsdXR0ZXItZ3JhZGxlLXBsdWdpblwiKVxufVxuXG52YWwgc2VtYW50aWZvbGRBY2NlcHRhbmNlUm9vdCA9IHByb3ZpZGVycy5lbnZpcm9ubWVudFZhcmlhYmxlKFwiU0VNQU5USUZPTERfRkxVVFRFUl9BQ0NFUFRBTkNFX1JPT1RcIikub3JOdWxsXG4gID86IHRocm93IEdyYWRsZUV4Y2VwdGlvbihcIlNFTUFOVElGT0xEX0ZMVVRURVJfSU5GUkFTVFJVQ1RVUkU6IFNFTUFOVElGT0xEX0ZMVVRURVJfQUNDRVBUQU5DRV9ST09UIGlzIHJlcXVpcmVkXCIpXG52YWwgc2VtYW50aWZvbGREZWJ1Z0tleXN0b3JlID0gZmlsZShcIiRzZW1hbnRpZm9sZEFjY2VwdGFuY2VSb290L2RlYnVnLmtleXN0b3JlXCIpXG5pZiAoIXNlbWFudGlmb2xkRGVidWdLZXlzdG9yZS5pc0ZpbGUpIHtcbiAgdGhyb3cgR3JhZGxlRXhjZXB0aW9uKFwiU0VNQU5USUZPTERfRkxVVFRFUl9JTkZSQVNUUlVDVFVSRTogZXBoZW1lcmFsIGRlYnVnIGtleXN0b3JlIGlzIG1pc3NpbmdcIilcbn1cblxuY29uZmlndXJhdGlvbnMuY29uZmlndXJlRWFjaCB7XG4gIGV4Y2x1ZGUoZ3JvdXAgPSBcImFuZHJvaWR4LnByb2ZpbGVpbnN0YWxsZXJcIiwgbW9kdWxlID0gXCJwcm9maWxlaW5zdGFsbGVyXCIpXG59XG5cbmFuZHJvaWQge1xuICBuYW1lc3BhY2UgPSBcImAsIGZpZWxkKFwiYXBwbGljYXRpb25JZFwiLCBjb25maWd1cmF0aW9uLmFwcGxpY2F0aW9uSWQpLCBgXCJcbiAgY29tcGlsZVNkayA9IGAsIGZpZWxkKFwiY29tcGlsZVNka1wiLCBTdHJpbmcoY29uZmlndXJhdGlvbi5jb21waWxlU2RrKSksIGBcbiAgYnVpbGRUb29sc1ZlcnNpb24gPSBcImAsIGZpZWxkKFwiYnVpbGRUb29sc1ZlcnNpb25cIiwgY29uZmlndXJhdGlvbi5idWlsZFRvb2xzVmVyc2lvbiksIGBcIlxuICBuZGtWZXJzaW9uID0gXCIke2FuZHJvaWRUb29sY2hhaW4ubmRrfVwiXG5cbiAgZGVmYXVsdENvbmZpZyB7XG4gICAgYXBwbGljYXRpb25JZCA9IFwiYCwgZmllbGQoXCJhcHBsaWNhdGlvbklkXCIsIGNvbmZpZ3VyYXRpb24uYXBwbGljYXRpb25JZCksIGBcIlxuICAgIG1pblNkayA9IGAsIGZpZWxkKFwibWluaW11bVNka1wiLCBTdHJpbmcoY29uZmlndXJhdGlvbi5taW5pbXVtU2RrKSksIGBcbiAgICB0YXJnZXRTZGsgPSBgLCBmaWVsZChcInRhcmdldFNka1wiLCBTdHJpbmcoY29uZmlndXJhdGlvbi50YXJnZXRTZGspKSwgYFxuICAgIHZlcnNpb25Db2RlID0gYCwgZmllbGQoXCJ2ZXJzaW9uQ29kZVwiLCBTdHJpbmcoY29uZmlndXJhdGlvbi52ZXJzaW9uQ29kZSkpLCBgXG4gICAgdmVyc2lvbk5hbWUgPSBcImAsIGZpZWxkKFwidmVyc2lvbk5hbWVcIiwgY29uZmlndXJhdGlvbi52ZXJzaW9uTmFtZSksIGBcIlxuICB9XG5cbiAgc2lnbmluZ0NvbmZpZ3Mge1xuICAgIGdldEJ5TmFtZShcImRlYnVnXCIpIHtcbiAgICAgIHN0b3JlRmlsZSA9IHNlbWFudGlmb2xkRGVidWdLZXlzdG9yZVxuICAgICAgc3RvcmVQYXNzd29yZCA9IFwiYW5kcm9pZFwiXG4gICAgICBrZXlBbGlhcyA9IFwiYW5kcm9pZGRlYnVna2V5XCJcbiAgICAgIGtleVBhc3N3b3JkID0gXCJhbmRyb2lkXCJcbiAgICB9XG4gIH1cblxuICBidWlsZFR5cGVzIHtcbiAgICBnZXRCeU5hbWUoXCJkZWJ1Z1wiKSB7XG4gICAgICBzaWduaW5nQ29uZmlnID0gc2lnbmluZ0NvbmZpZ3MuZ2V0QnlOYW1lKFwiZGVidWdcIilcbiAgICB9XG4gIH1cblxuICBidWlsZEZlYXR1cmVzIHtcbiAgICBidWlsZENvbmZpZyA9IGZhbHNlXG4gIH1cblxuICBjb21waWxlT3B0aW9ucyB7XG4gICAgc291cmNlQ29tcGF0aWJpbGl0eSA9IEphdmFWZXJzaW9uLlZFUlNJT05fMTdcbiAgICB0YXJnZXRDb21wYXRpYmlsaXR5ID0gSmF2YVZlcnNpb24uVkVSU0lPTl8xN1xuICB9XG5cbiAgbGludCB7XG4gICAgYWJvcnRPbkVycm9yID0gdHJ1ZVxuICAgIGNoZWNrRGVwZW5kZW5jaWVzID0gdHJ1ZVxuICAgIGRpc2FibGUgKz0gXCJNaXNzaW5nQXBwbGljYXRpb25JY29uXCJcbiAgICBkaXNhYmxlICs9IFwiT2xkVGFyZ2V0QXBpXCJcbiAgICBkaXNhYmxlICs9IFwiR3JhZGxlRGVwZW5kZW5jeVwiXG4gICAgd2FybmluZ3NBc0Vycm9ycyA9IHRydWVcbiAgfVxufVxuXG5mbHV0dGVyIHtcbiAgc291cmNlID0gXCIuLi8uLlwiXG59XG5gXSlcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBwZXJtaXNzaW9uLWZyZWUgQW5kcm9pZCBtYW5pZmVzdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRmx1dHRlckFwcGxpY2F0aW9uQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIE5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7Q29uZmlndXJhdGlvblNwYW5bXX0gc3BhbnMgLSBDb25maWd1cmF0aW9uIHByb3ZlbmFuY2Ugc2luay5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEFuZHJvaWQgbWFuaWZlc3QgWE1MLlxuICovXG5mdW5jdGlvbiByZW5kZXJBbmRyb2lkTWFuaWZlc3QoY29uZmlndXJhdGlvbiwgc3BhbnMpIHtcbiAgcmV0dXJuIGNvbmZpZ3VyZWQoYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL0FuZHJvaWRNYW5pZmVzdC54bWxgLCBzcGFucywgW1xuICAgIGA8bWFuaWZlc3RcbiAgeG1sbnM6YW5kcm9pZD1cImh0dHA6Ly9zY2hlbWFzLmFuZHJvaWQuY29tL2Fway9yZXMvYW5kcm9pZFwiXG4gIHhtbG5zOnRvb2xzPVwiaHR0cDovL3NjaGVtYXMuYW5kcm9pZC5jb20vdG9vbHNcIj5cbiAgPHBlcm1pc3Npb24gdG9vbHM6bm9kZT1cInJlbW92ZUFsbFwiIC8+XG4gIDx1c2VzLXBlcm1pc3Npb24gdG9vbHM6bm9kZT1cInJlbW92ZUFsbFwiIC8+XG4gIDxhcHBsaWNhdGlvblxuICAgIGFuZHJvaWQ6YWxsb3dCYWNrdXA9XCJmYWxzZVwiXG4gICAgYW5kcm9pZDpkYXRhRXh0cmFjdGlvblJ1bGVzPVwiQHhtbC9kYXRhX2V4dHJhY3Rpb25fcnVsZXNcIlxuICAgIGFuZHJvaWQ6ZnVsbEJhY2t1cENvbnRlbnQ9XCJAeG1sL2JhY2t1cF9ydWxlc1wiXG4gICAgYW5kcm9pZDpsYWJlbD1cImAsIGZpZWxkKFwiZGlzcGxheU5hbWVcIiwgeG1sRXNjYXBlKGNvbmZpZ3VyYXRpb24uZGlzcGxheU5hbWUpKSwgYFwiXG4gICAgYW5kcm9pZDpuYW1lPVwiXFwke2FwcGxpY2F0aW9uTmFtZX1cIlxuICAgIGFuZHJvaWQ6c3VwcG9ydHNSdGw9XCJ0cnVlXCI+XG4gICAgPGFjdGl2aXR5XG4gICAgICBhbmRyb2lkOm5hbWU9XCIuYCwgZmllbGQoXCJhY3Rpdml0eUNsYXNzTmFtZVwiLCBjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lKSwgYFwiXG4gICAgICBhbmRyb2lkOmNvbmZpZ0NoYW5nZXM9XCJvcmllbnRhdGlvbnxrZXlib2FyZEhpZGRlbnxrZXlib2FyZHxzY3JlZW5TaXplfHNtYWxsZXN0U2NyZWVuU2l6ZXxsb2NhbGV8bGF5b3V0RGlyZWN0aW9ufGZvbnRTY2FsZXxzY3JlZW5MYXlvdXR8ZGVuc2l0eXx1aU1vZGVcIlxuICAgICAgYW5kcm9pZDpleHBvcnRlZD1cInRydWVcIlxuICAgICAgYW5kcm9pZDpoYXJkd2FyZUFjY2VsZXJhdGVkPVwidHJ1ZVwiXG4gICAgICBhbmRyb2lkOmxhdW5jaE1vZGU9XCJzaW5nbGVUb3BcIlxuICAgICAgYW5kcm9pZDp0YXNrQWZmaW5pdHk9XCJcIlxuICAgICAgYW5kcm9pZDp0aGVtZT1cIkBzdHlsZS9MYXVuY2hUaGVtZVwiXG4gICAgICBhbmRyb2lkOndpbmRvd1NvZnRJbnB1dE1vZGU9XCJhZGp1c3RSZXNpemVcIj5cbiAgICAgIDxtZXRhLWRhdGFcbiAgICAgICAgYW5kcm9pZDpuYW1lPVwiaW8uZmx1dHRlci5lbWJlZGRpbmcuYW5kcm9pZC5Ob3JtYWxUaGVtZVwiXG4gICAgICAgIGFuZHJvaWQ6cmVzb3VyY2U9XCJAc3R5bGUvTm9ybWFsVGhlbWVcIiAvPlxuICAgICAgPGludGVudC1maWx0ZXI+XG4gICAgICAgIDxhY3Rpb24gYW5kcm9pZDpuYW1lPVwiYW5kcm9pZC5pbnRlbnQuYWN0aW9uLk1BSU5cIiAvPlxuICAgICAgICA8Y2F0ZWdvcnkgYW5kcm9pZDpuYW1lPVwiYW5kcm9pZC5pbnRlbnQuY2F0ZWdvcnkuTEFVTkNIRVJcIiAvPlxuICAgICAgPC9pbnRlbnQtZmlsdGVyPlxuICAgIDwvYWN0aXZpdHk+XG4gICAgPG1ldGEtZGF0YSBhbmRyb2lkOm5hbWU9XCJmbHV0dGVyRW1iZWRkaW5nXCIgYW5kcm9pZDp2YWx1ZT1cIjJcIiAvPlxuICAgIDxwcm92aWRlciBhbmRyb2lkOm5hbWU9XCJhbmRyb2lkeC5zdGFydHVwLkluaXRpYWxpemF0aW9uUHJvdmlkZXJcIiB0b29sczpub2RlPVwicmVtb3ZlXCIgLz5cbiAgPC9hcHBsaWNhdGlvbj5cbjwvbWFuaWZlc3Q+XG5gXG4gIF0pXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgSmF2YSBGbHV0dGVyIGFjdGl2aXR5IGxhdW5jaGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5GbHV0dGVyQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gTm9ybWFsaXplZCBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uU3BhbltdfSBzcGFucyAtIENvbmZpZ3VyYXRpb24gcHJvdmVuYW5jZSBzaW5rLlxuICogQHJldHVybnMge3N0cmluZ30gSmF2YSBzb3VyY2UuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckFuZHJvaWRBY3Rpdml0eShjb25maWd1cmF0aW9uLCBzcGFucykge1xuICByZXR1cm4gY29uZmlndXJlZChgJHtwcm9qZWN0Um9vdH0vYW5kcm9pZC9hcHAvc3JjL21haW4vamF2YS8ke2NvbmZpZ3VyYXRpb24uYXBwbGljYXRpb25JZC5yZXBsYWNlQWxsKFwiLlwiLCBcIi9cIil9LyR7Y29uZmlndXJhdGlvbi5hY3Rpdml0eUNsYXNzTmFtZX0uamF2YWAsIHNwYW5zLCBbXG4gICAgXCJwYWNrYWdlIFwiLCBmaWVsZChcImFwcGxpY2F0aW9uSWRcIiwgY29uZmlndXJhdGlvbi5hcHBsaWNhdGlvbklkKSwgYDtcblxuaW1wb3J0IGlvLmZsdXR0ZXIuZW1iZWRkaW5nLmFuZHJvaWQuRmx1dHRlckFjdGl2aXR5O1xuXG5wdWJsaWMgZmluYWwgY2xhc3MgYCwgZmllbGQoXCJhY3Rpdml0eUNsYXNzTmFtZVwiLCBjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lKSwgYCBleHRlbmRzIEZsdXR0ZXJBY3Rpdml0eSB7XG59XG5gXG4gIF0pXG59XG5cbi8qKlxuICogUmVuZGVycyBwbGF0Zm9ybSBsYXVuY2ggYW5kIGhvc3Qgc3R5bGVzLlxuICogQHBhcmFtIHtib29sZWFufSBuaWdodCAtIFdoZXRoZXIgdG8gcmVuZGVyIHRoZSBuaWdodCB0aGVtZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEFuZHJvaWQgcmVzb3VyY2UgWE1MLlxuICovXG5mdW5jdGlvbiByZW5kZXJBbmRyb2lkU3R5bGVzKG5pZ2h0KSB7XG4gIHJldHVybiBgPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwidXRmLThcIj8+XG48cmVzb3VyY2VzPlxuICA8c3R5bGUgbmFtZT1cIkxhdW5jaFRoZW1lXCIgcGFyZW50PVwiQGFuZHJvaWQ6c3R5bGUvVGhlbWUuJHtuaWdodCA/IFwiQmxhY2tcIiA6IFwiTGlnaHRcIn0uTm9UaXRsZUJhclwiPlxuICAgIDxpdGVtIG5hbWU9XCJhbmRyb2lkOndpbmRvd0JhY2tncm91bmRcIj5AZHJhd2FibGUvbGF1bmNoX2JhY2tncm91bmQ8L2l0ZW0+XG4gIDwvc3R5bGU+XG4gIDxzdHlsZSBuYW1lPVwiTm9ybWFsVGhlbWVcIiBwYXJlbnQ9XCJAYW5kcm9pZDpzdHlsZS9UaGVtZS4ke25pZ2h0ID8gXCJCbGFja1wiIDogXCJMaWdodFwifS5Ob1RpdGxlQmFyXCI+XG4gICAgPGl0ZW0gbmFtZT1cImFuZHJvaWQ6d2luZG93QmFja2dyb3VuZFwiPj9hbmRyb2lkOmNvbG9yQmFja2dyb3VuZDwvaXRlbT5cbiAgPC9zdHlsZT5cbjwvcmVzb3VyY2VzPlxuYFxufVxuXG4vKipcbiAqIFJlbmRlcnMgYSBwbGF0Zm9ybSBsYXVuY2ggYmFja2dyb3VuZC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEFuZHJvaWQgcmVzb3VyY2UgWE1MLlxuICovXG5mdW5jdGlvbiByZW5kZXJMYXVuY2hCYWNrZ3JvdW5kKCkge1xuICByZXR1cm4gYDw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cInV0Zi04XCI/PlxuPGxheWVyLWxpc3QgeG1sbnM6YW5kcm9pZD1cImh0dHA6Ly9zY2hlbWFzLmFuZHJvaWQuY29tL2Fway9yZXMvYW5kcm9pZFwiPlxuICA8aXRlbSBhbmRyb2lkOmRyYXdhYmxlPVwiP2FuZHJvaWQ6Y29sb3JCYWNrZ3JvdW5kXCIgLz5cbjwvbGF5ZXItbGlzdD5cbmBcbn1cblxuLyoqXG4gKiBSZW5kZXJzIGNvbXBsZXRlIGxlZ2FjeSBiYWNrdXAgZXhjbHVzaW9ucy5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEFuZHJvaWQgcmVzb3VyY2UgWE1MLlxuICovXG5mdW5jdGlvbiByZW5kZXJCYWNrdXBSdWxlcygpIHtcbiAgcmV0dXJuIGA8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJ1dGYtOFwiPz5cbjxmdWxsLWJhY2t1cC1jb250ZW50PlxuICA8ZXhjbHVkZSBkb21haW49XCJyb290XCIgcGF0aD1cIi5cIiAvPlxuICA8ZXhjbHVkZSBkb21haW49XCJmaWxlXCIgcGF0aD1cIi5cIiAvPlxuICA8ZXhjbHVkZSBkb21haW49XCJkYXRhYmFzZVwiIHBhdGg9XCIuXCIgLz5cbiAgPGV4Y2x1ZGUgZG9tYWluPVwic2hhcmVkcHJlZlwiIHBhdGg9XCIuXCIgLz5cbiAgPGV4Y2x1ZGUgZG9tYWluPVwiZXh0ZXJuYWxcIiBwYXRoPVwiLlwiIC8+XG4gIDxleGNsdWRlIGRvbWFpbj1cImRldmljZV9yb290XCIgcGF0aD1cIi5cIiAvPlxuICA8ZXhjbHVkZSBkb21haW49XCJkZXZpY2VfZmlsZVwiIHBhdGg9XCIuXCIgLz5cbiAgPGV4Y2x1ZGUgZG9tYWluPVwiZGV2aWNlX2RhdGFiYXNlXCIgcGF0aD1cIi5cIiAvPlxuICA8ZXhjbHVkZSBkb21haW49XCJkZXZpY2Vfc2hhcmVkcHJlZlwiIHBhdGg9XCIuXCIgLz5cbjwvZnVsbC1iYWNrdXAtY29udGVudD5cbmBcbn1cblxuLyoqXG4gKiBSZW5kZXJzIGNvbXBsZXRlIEFuZHJvaWQgMTIrIGJhY2t1cCBleGNsdXNpb25zLlxuICogQHJldHVybnMge3N0cmluZ30gQW5kcm9pZCByZXNvdXJjZSBYTUwuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckRhdGFFeHRyYWN0aW9uUnVsZXMoKSB7XG4gIGNvbnN0IGV4Y2x1c2lvbnMgPSBbXCJyb290XCIsIFwiZmlsZVwiLCBcImRhdGFiYXNlXCIsIFwic2hhcmVkcHJlZlwiLCBcImV4dGVybmFsXCIsIFwiZGV2aWNlX3Jvb3RcIiwgXCJkZXZpY2VfZmlsZVwiLCBcImRldmljZV9kYXRhYmFzZVwiLCBcImRldmljZV9zaGFyZWRwcmVmXCJdXG4gICAgLm1hcChkb21haW4gPT4gYCAgICA8ZXhjbHVkZSBkb21haW49XCIke2RvbWFpbn1cIiBwYXRoPVwiLlwiIC8+YCkuam9pbihcIlxcblwiKVxuXG4gIHJldHVybiBgPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwidXRmLThcIj8+XG48ZGF0YS1leHRyYWN0aW9uLXJ1bGVzPlxuICA8Y2xvdWQtYmFja3VwPlxuJHtleGNsdXNpb25zfVxuICA8L2Nsb3VkLWJhY2t1cD5cbiAgPGRldmljZS10cmFuc2Zlcj5cbiR7ZXhjbHVzaW9uc31cbiAgPC9kZXZpY2UtdHJhbnNmZXI+XG48L2RhdGEtZXh0cmFjdGlvbi1ydWxlcz5cbmBcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBvd25lcnNoaXAsIHRvb2xjaGFpbiwgcHJvdmVuYW5jZSwgYW5kIHBsYXRmb3JtLXN0YXR1cyBtYW5pZmVzdC5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgcHJlZmxpZ2h0Rmx1dHRlckFwcGxpY2F0aW9uPn0gcHJlcGFyZWQgLSBQcmVwYXJlZCBhcHBsaWNhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3RbXX0gYXJ0aWZhY3RzIC0gT3duZWQgYXJ0aWZhY3RzIGV4Y2VwdCB0aGlzIG1hbmlmZXN0LlxuICogQHBhcmFtIHtzdHJpbmd9IG1hbmlmZXN0UGF0aCAtIE1hbmlmZXN0IGFydGlmYWN0IHBhdGguXG4gKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb25TcGFuW119IHNwYW5zIC0gQ29uZmlndXJhdGlvbiBwcm92ZW5hbmNlIHNwYW5zLlxuICogQHJldHVybnMge3N0cmluZ30gQ2Fub25pY2FsIG1hbmlmZXN0IEpTT04uXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclByb2plY3RNYW5pZmVzdChwcmVwYXJlZCwgYXJ0aWZhY3RzLCBtYW5pZmVzdFBhdGgsIHNwYW5zKSB7XG4gIGNvbnN0IGlucHV0UGF0aHMgPSBuZXcgU2V0KHByZXBhcmVkLmFzc2V0cy5tYXAoKHtmdWxsUGF0aH0pID0+IGZ1bGxQYXRoKSlcbiAgY29uc3Qgc2VtYW50aWNBcnRpZmFjdHMgPSBhcnRpZmFjdHMuZmlsdGVyKGFydGlmYWN0ID0+IGFydGlmYWN0LnByb3ZlbmFuY2Uua2luZCA9PSBcInRleHRcIilcblxuICByZXR1cm4gc3RyaW5naWZ5Q2Fub25pY2FsSnNvbih7XG4gICAgY29uZmlndXJhdGlvbjogcHJlcGFyZWQuY29uZmlndXJhdGlvbixcbiAgICBnZW5lcmF0b3I6IHtuYW1lOiBcInNlbWFudGlmb2xkXCIsIHZlcnNpb246IGdlbmVyYXRvclZlcnNpb259LFxuICAgIG93bmVyc2hpcDoge1xuICAgICAgZXhjbHVkZWRQYXRoUGF0dGVybnMsXG4gICAgICBvd25lZFBhdGhzOiBbLi4uYXJ0aWZhY3RzLm1hcCgoe3BhdGh9KSA9PiBwYXRoKSwgbWFuaWZlc3RQYXRoXSxcbiAgICAgIG93bmVkUm9vdDogcHJvamVjdFJvb3QsXG4gICAgICBzaGEyNTY6IGFydGlmYWN0cy5tYXAoYXJ0aWZhY3QgPT4gKHtwYXRoOiBhcnRpZmFjdC5wYXRoLCBzaGEyNTY6IGhhc2hDb250ZW50KGFydGlmYWN0LmNvbnRlbnQpfSkpXG4gICAgfSxcbiAgICBwbGF0Zm9ybXM6IHtcbiAgICAgIGFuZHJvaWQ6IHthY2NlcHRhbmNlOiBcInRlbnNvcmJ1enota3ZtXCIsIGFydGlmYWN0czogXCJnZW5lcmF0ZWRcIn0sXG4gICAgICBpb3M6IHtcbiAgICAgICAgYWNjZXB0YW5jZTogXCJkZWZlcnJlZFwiLFxuICAgICAgICBhcnRpZmFjdHM6IFwib21pdHRlZFwiLFxuICAgICAgICByZWFzb246IFwiT3duZXIgZGlyZWN0aW9uIGRlZmVycyBtYWNPUywgWGNvZGUsIEFwcGxlIFNESywgc2lnbmluZywgYW5kIGlPUyBTaW11bGF0b3IgcXVhbGlmaWNhdGlvbi5cIlxuICAgICAgfVxuICAgIH0sXG4gICAgcHJvdmVuYW5jZToge1xuICAgICAgY29uZmlndXJhdGlvbjogT2JqZWN0LmtleXMocHJlcGFyZWQuY29uZmlndXJhdGlvbikuc29ydCgpLm1hcChmaWVsZE5hbWUgPT4gKHtcbiAgICAgICAgZmllbGQ6IGZpZWxkTmFtZSxcbiAgICAgICAgbWFuaWZlc3RQb2ludGVyOiBgL2NvbmZpZ3VyYXRpb24vJHtmaWVsZE5hbWV9YCxcbiAgICAgICAgb3V0cHV0czogY29uZmlndXJhdGlvbk91dHB1dHMoc3BhbnMsIGZpZWxkTmFtZSlcbiAgICAgIH0pKSxcbiAgICAgIGlucHV0czogcHJlcGFyZWQuYXNzZXRzLm1hcChhc3NldCA9PiAoe1xuICAgICAgICBjb250ZW50S2luZDogYXNzZXQuY29udGVudEtpbmQsXG4gICAgICAgIG1lZGlhVHlwZTogYXNzZXQubWVkaWFUeXBlLFxuICAgICAgICBwYXRoOiBhc3NldC5mdWxsUGF0aCxcbiAgICAgICAgc2hhMjU2OiBhc3NldC5zaGEyNTZcbiAgICAgIH0pKSxcbiAgICAgIHNlbWFudGljU291cmNlczogcHJlcGFyZWQuc291cmNlcy5tYXAoc291cmNlID0+ICh7XG4gICAgICAgIGFydGlmYWN0czogc2VtYW50aWNBcnRpZmFjdHMuZmlsdGVyKGFydGlmYWN0ID0+IGFydGlmYWN0LnByb3ZlbmFuY2Uua2luZCA9PSBcInRleHRcIiAmJlxuICAgICAgICAgIGFydGlmYWN0LnByb3ZlbmFuY2UubWFwcGluZy5zcGFucy5zb21lKCh7b3JpZ2lufSkgPT4gb3JpZ2luUmVmZXJlbmNlc0ZpbGVuYW1lKG9yaWdpbiwgc291cmNlLmZpbGVuYW1lKSkpXG4gICAgICAgICAgLm1hcCgoe3BhdGh9KSA9PiBwYXRoKSxcbiAgICAgICAgZmlsZW5hbWU6IHNvdXJjZS5maWxlbmFtZSxcbiAgICAgICAgLi4uKHNvdXJjZS5sYW5ndWFnZSA9PT0gdW5kZWZpbmVkID8ge30gOiB7bGFuZ3VhZ2U6IHNvdXJjZS5sYW5ndWFnZX0pLFxuICAgICAgICBzaGEyNTY6IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHNvdXJjZS5jb250ZW50KS5kaWdlc3QoXCJoZXhcIilcbiAgICAgIH0pKSxcbiAgICAgIHN5bnRoZXRpY1NjYWZmb2xkaW5nOiBbLi4uYXJ0aWZhY3RzLmZpbHRlcihhcnRpZmFjdCA9PiBhcnRpZmFjdC5wcm92ZW5hbmNlLmtpbmQgPT0gXCJzeW50aGV0aWNcIiAmJlxuICAgICAgICAhaW5wdXRQYXRocy5oYXMoYXJ0aWZhY3QucGF0aCkpLm1hcCgoe3BhdGh9KSA9PiBwYXRoKSwgbWFuaWZlc3RQYXRoXVxuICAgIH0sXG4gICAgc2NoZW1hOiBcIlNlbWFudGlmb2xkRmx1dHRlclByb2plY3RcIixcbiAgICBzZW1hbnRpY1Byb2dyYW06IHNlbWFudGljUHJvZ3JhbU1hbmlmZXN0KHByZXBhcmVkKSxcbiAgICB0YXJnZXQ6IFwiZmx1dHRlclwiLFxuICAgIHRvb2xjaGFpbjoge2FuZHJvaWQ6IGFuZHJvaWRUb29sY2hhaW4sIGZsdXR0ZXI6IGZsdXR0ZXJUb29sY2hhaW59LFxuICAgIHZlcnNpb246IDFcbiAgfSlcbn1cblxuLyoqXG4gKiBEZXNjcmliZXMgdGhlIGNvbXBsZXRlIHNlbWFudGljIHByb2dyYW0gaW5zaWRlIHRoZSBhcHBsaWNhdGlvbiBtYW5pZmVzdC5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgcHJlZmxpZ2h0Rmx1dHRlckFwcGxpY2F0aW9uPn0gcHJlcGFyZWQgLSBQcmVwYXJlZCBwcm9qZWN0LlxuICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSBTZW1hbnRpYyBwcm9ncmFtIG1hbmlmZXN0LlxuICovXG5mdW5jdGlvbiBzZW1hbnRpY1Byb2dyYW1NYW5pZmVzdChwcmVwYXJlZCkge1xuICBjb25zdCBzb3VyY2VDb250ZW50ID0gbmV3IE1hcChwcmVwYXJlZC5zb3VyY2VzLm1hcChzb3VyY2UgPT4gW3NvdXJjZS5maWxlbmFtZSwgc291cmNlLmNvbnRlbnRdKSlcbiAgY29uc3Qgb3JkZXIgPSBuZXcgTWFwKHByZXBhcmVkLnByb2dyYW0ubW9kdWxlcy5tYXAoKG1vZHVsZSwgaW5kZXgpID0+IFttb2R1bGUuaWQsIGluZGV4XSkpXG4gIGNvbnN0IG1vZHVsZXMgPSBwcmVwYXJlZC5wcm9ncmFtLm1vZHVsZXMubWFwKG1vZHVsZSA9PiB7XG4gICAgY29uc3Qgc291cmNlID0gcHJlcGFyZWQucHJvZ3JhbS5zb3VyY2VzLmZpbmQoY2FuZGlkYXRlID0+IGNhbmRpZGF0ZS5maWxlbmFtZSA9PSBtb2R1bGUuc291cmNlRmlsZW5hbWUpXG4gICAgY29uc3QgY29udGVudCA9IHNvdXJjZUNvbnRlbnQuZ2V0KG1vZHVsZS5zb3VyY2VGaWxlbmFtZSlcblxuICAgIGlmICghc291cmNlIHx8IGNvbnRlbnQgPT09IHVuZGVmaW5lZCkgdGhyb3cgbmV3IFR5cGVFcnJvcihgUHJlZmxpZ2h0ZWQgRmx1dHRlciBtb2R1bGUgJyR7bW9kdWxlLmlkfScgbG9zdCBzb3VyY2Ugb3duZXJzaGlwLmApXG5cbiAgICByZXR1cm4ge1xuICAgICAgZGVwZW5kZW5jaWVzOiBbLi4ubmV3IFNldChtb2R1bGUuaW1wb3J0cy5tYXAoKHttb2R1bGVJZH0pID0+IG1vZHVsZUlkKSldXG4gICAgICAgIC5zb3J0KChsZWZ0LCByaWdodCkgPT4gLyoqIEB0eXBlIHtudW1iZXJ9ICovIChvcmRlci5nZXQobGVmdCkpIC0gLyoqIEB0eXBlIHtudW1iZXJ9ICovIChvcmRlci5nZXQocmlnaHQpKSksXG4gICAgICBnZW5lcmF0ZWRBcnRpZmFjdHM6IFtwcmVwYXJlZC5tb2R1bGVQYXRocy5nZXQobW9kdWxlLmlkKV0sXG4gICAgICBpZDogbW9kdWxlLmlkLFxuICAgICAgbmFtZXNwYWNlOiBgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUobW9kdWxlLmlkKX1gLFxuICAgICAgc291cmNlOiB7ZmlsZW5hbWU6IHNvdXJjZS5maWxlbmFtZSwgaWQ6IHNvdXJjZS5pZCwgc2hhMjU2OiBjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShjb250ZW50KS5kaWdlc3QoXCJoZXhcIil9XG4gICAgfVxuICB9KVxuICBjb25zdCBlbnRyeUlkID0gcHJlcGFyZWQucHJvZ3JhbS5lbnRyeU1vZHVsZVxuXG4gIHJldHVybiB7XG4gICAgZW50cnk6IHtcbiAgICAgIGdlbmVyYXRlZEFydGlmYWN0OiBwcmVwYXJlZC5tb2R1bGVQYXRocy5nZXQoZW50cnlJZCksXG4gICAgICBnZW5lcmF0ZWRGdW5jdGlvbklkZW50aXR5OiBgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUoZW50cnlJZCl9LnNlbWFudGlmb2xkRW50cnlgLFxuICAgICAgbW9kdWxlSWQ6IGVudHJ5SWQsXG4gICAgICB3aWRnZXRBcnRpZmFjdDogYCR7cHJvamVjdFJvb3R9L2xpYi9tYWluLmRhcnRgXG4gICAgfSxcbiAgICBtb2R1bGVzLFxuICAgIHNjaGVtYTogXCJTZW1hbnRpZm9sZEZsdXR0ZXJTZW1hbnRpY1Byb2dyYW1cIixcbiAgICBzb3VyY2VzOiBwcmVwYXJlZC5wcm9ncmFtLnNvdXJjZXMubWFwKHNvdXJjZSA9PiAoe1xuICAgICAgZmlsZW5hbWU6IHNvdXJjZS5maWxlbmFtZSxcbiAgICAgIGlkOiBzb3VyY2UuaWQsXG4gICAgICBsYW5ndWFnZTogc291cmNlLmxhbmd1YWdlLFxuICAgICAgbW9kdWxlSWRzOiBtb2R1bGVzLmZpbHRlcihtb2R1bGUgPT4gbW9kdWxlLnNvdXJjZS5maWxlbmFtZSA9PSBzb3VyY2UuZmlsZW5hbWUpLm1hcCgoe2lkfSkgPT4gaWQpLFxuICAgICAgb3duZXJzaGlwOiBzb3VyY2Uub3duZXJzaGlwID8/IFwiYXBwbGljYXRpb25cIixcbiAgICAgIHNoYTI1NjogY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUoLyoqIEB0eXBlIHtzdHJpbmd9ICovIChzb3VyY2VDb250ZW50LmdldChzb3VyY2UuZmlsZW5hbWUpKSkuZGlnZXN0KFwiaGV4XCIpXG4gICAgfSkpLFxuICAgIHZlcnNpb246IDFcbiAgfVxufVxuXG4vKipcbiAqIE5vcm1hbGl6ZXMgYW5kIHZhbGlkYXRlcyB0aGUgY2xvc2VkIGFwcGxpY2F0aW9uIGNvbmZpZ3VyYXRpb24uXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSBjb25maWd1cmF0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkZsdXR0ZXJBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb259IE5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbi5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplQ29uZmlndXJhdGlvbihjYW5kaWRhdGUpIHtcbiAgaWYgKGNhbmRpZGF0ZSA9PT0gdW5kZWZpbmVkKSBjYW5kaWRhdGUgPSB7fVxuICBpZiAoIWlzUGxhaW5PYmplY3QoY2FuZGlkYXRlKSB8fCBPYmplY3Qua2V5cyhjYW5kaWRhdGUpLnNvbWUoa2V5ID0+ICFjb25maWd1cmF0aW9uRmllbGRzLmhhcyhrZXkpKSkge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiRmx1dHRlciBhcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uIG11c3QgYmUgYSBjbG9zZWQgcGxhaW4gb2JqZWN0LlwiKVxuICB9XG4gIGNvbnN0IGNvbmZpZ3VyYXRpb24gPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkZsdXR0ZXJBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb25JbnB1dH0gKi8gKGNhbmRpZGF0ZSlcbiAgY29uc3QgcGFja2FnZU5hbWUgPSBjb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lID8/IFwic2VtYW50aWZvbGRfZ2VuZXJhdGVkXCJcbiAgY29uc3Qgb3JnYW5pemF0aW9uID0gY29uZmlndXJhdGlvbi5vcmdhbml6YXRpb24gPz8gXCJkZXYuc2VtYW50aWZvbGRcIlxuICBjb25zdCBhcHBsaWNhdGlvbklkID0gY29uZmlndXJhdGlvbi5hcHBsaWNhdGlvbklkID8/IGAke29yZ2FuaXphdGlvbn0uZ2VuZXJhdGVkYFxuICBjb25zdCBhY3Rpdml0eUNsYXNzTmFtZSA9IGNvbmZpZ3VyYXRpb24uYWN0aXZpdHlDbGFzc05hbWUgPz8gXCJNYWluQWN0aXZpdHlcIlxuICBjb25zdCBkaXNwbGF5TmFtZSA9IGNvbmZpZ3VyYXRpb24uZGlzcGxheU5hbWUgPz8gXCJTZW1hbnRpZm9sZFwiXG4gIGNvbnN0IG1pbmltdW1TZGsgPSBjb25maWd1cmF0aW9uLm1pbmltdW1TZGsgPz8gMjNcbiAgY29uc3QgdGFyZ2V0U2RrID0gY29uZmlndXJhdGlvbi50YXJnZXRTZGsgPz8gMzVcbiAgY29uc3QgY29tcGlsZVNkayA9IGNvbmZpZ3VyYXRpb24uY29tcGlsZVNkayA/PyAzNVxuICBjb25zdCBidWlsZFRvb2xzVmVyc2lvbiA9IGNvbmZpZ3VyYXRpb24uYnVpbGRUb29sc1ZlcnNpb24gPz8gXCIzNS4wLjBcIlxuICBjb25zdCB2ZXJzaW9uQ29kZSA9IGNvbmZpZ3VyYXRpb24udmVyc2lvbkNvZGUgPz8gMVxuICBjb25zdCB2ZXJzaW9uTmFtZSA9IGNvbmZpZ3VyYXRpb24udmVyc2lvbk5hbWUgPz8gXCIxLjAuMFwiXG5cbiAgaWYgKHR5cGVvZiBwYWNrYWdlTmFtZSAhPSBcInN0cmluZ1wiIHx8ICEvXlthLXpdW2EtejAtOV9dKiQvdS50ZXN0KHBhY2thZ2VOYW1lKSB8fCBkYXJ0S2V5d29yZHMuaGFzKHBhY2thZ2VOYW1lKSB8fFxuICAgIGZvcmJpZGRlblBhY2thZ2VOYW1lcy5oYXMocGFja2FnZU5hbWUpKSBpbnZhbGlkQ29uZmlndXJhdGlvbihcIkRhcnQgcGFja2FnZSBuYW1lIG11c3QgYmUgYSBub24tcmVzZXJ2ZWQgbG93ZXJjYXNlIHVuZGVyc2NvcmUgaWRlbnRpZmllci5cIilcbiAgaWYgKHR5cGVvZiBvcmdhbml6YXRpb24gIT0gXCJzdHJpbmdcIiB8fCAhaXNSZXZlcnNlRG5zKG9yZ2FuaXphdGlvbiwgMikpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIk9yZ2FuaXphdGlvbiBtdXN0IGJlIGEgbG93ZXJjYXNlIHJldmVyc2UtRE5TIGlkZW50aXR5IHdpdGggYXQgbGVhc3QgdHdvIHNlZ21lbnRzLlwiKVxuICB9XG4gIGlmICh0eXBlb2YgYXBwbGljYXRpb25JZCAhPSBcInN0cmluZ1wiIHx8ICFpc1JldmVyc2VEbnMoYXBwbGljYXRpb25JZCwgMykgfHwgIWFwcGxpY2F0aW9uSWQuc3RhcnRzV2l0aChgJHtvcmdhbml6YXRpb259LmApKSB7XG4gICAgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJBcHBsaWNhdGlvbiBJRCBtdXN0IGV4dGVuZCB0aGUgZXhhY3Qgb3JnYW5pemF0aW9uIGFzIGxvd2VyY2FzZSByZXZlcnNlIEROUy5cIilcbiAgfVxuICBpZiAodHlwZW9mIGFjdGl2aXR5Q2xhc3NOYW1lICE9IFwic3RyaW5nXCIgfHwgIS9eW0EtWl1bQS1aYS16MC05XSokL3UudGVzdChhY3Rpdml0eUNsYXNzTmFtZSkgfHxcbiAgICBqYXZhS2V5d29yZHMuaGFzKGFjdGl2aXR5Q2xhc3NOYW1lKSkgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJBY3Rpdml0eSBjbGFzcyBuYW1lIG11c3QgYmUgYW4gQVNDSUkgdXBwZXItY2FtZWwgSmF2YSBpZGVudGlmaWVyLlwiKVxuICBpZiAoYW5kcm9pZFJ1bm5lckJhc2VDbGFzc05hbWVzLmhhcyhhY3Rpdml0eUNsYXNzTmFtZSkpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIkFjdGl2aXR5IGNsYXNzIG5hbWUgbXVzdCBub3QgY29sbGlkZSB3aXRoIHRoZSBpbXBvcnRlZCBGbHV0dGVyIGxhdW5jaGVyIGJhc2UgY2xhc3MuXCIpXG4gIH1cbiAgaWYgKHR5cGVvZiBkaXNwbGF5TmFtZSAhPSBcInN0cmluZ1wiIHx8IGRpc3BsYXlOYW1lLmxlbmd0aCA9PSAwIHx8IGRpc3BsYXlOYW1lLnRyaW0oKSAhPSBkaXNwbGF5TmFtZSB8fFxuICAgIFsuLi5kaXNwbGF5TmFtZV0ubGVuZ3RoID4gNjQgfHwgIWhhc09ubHlVbmljb2RlU2NhbGFycyhkaXNwbGF5TmFtZSkgfHwgL1tcXHB7Q2N9XFxwe1psfVxccHtacH1cXHVGRkZFXFx1RkZGRl0vdS50ZXN0KGRpc3BsYXlOYW1lKSkge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiRGlzcGxheSBuYW1lIG11c3QgYmUgYSBub24tZW1wdHkgc2luZ2xlLWxpbmUgVW5pY29kZSBzY2FsYXIgc3RyaW5nIG9mIGF0IG1vc3QgNjQgY2hhcmFjdGVycy5cIilcbiAgfVxuICBpZiAobWluaW11bVNkayAhPT0gMjMgfHwgdGFyZ2V0U2RrICE9PSAzNSB8fCBjb21waWxlU2RrICE9PSAzNSkge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiU0RLIGxldmVscyBtdXN0IHJldXNlIHRoZSBxdWFsaWZpZWQgbWluaW11bSAyMywgdGFyZ2V0IDM1LCBhbmQgY29tcGlsZSAzNSBBbmRyb2lkIG1hdHJpeC5cIilcbiAgfVxuICBpZiAoYnVpbGRUb29sc1ZlcnNpb24gIT0gXCIzNS4wLjBcIikgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJCdWlsZCBUb29scyB2ZXJzaW9uIG11c3QgYmUgZXhhY3RseSAnMzUuMC4wJy5cIilcbiAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih2ZXJzaW9uQ29kZSkgfHwgdmVyc2lvbkNvZGUgPCAxIHx8IHZlcnNpb25Db2RlID4gMl8xMDBfMDAwXzAwMCkge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiVmVyc2lvbiBjb2RlIG11c3QgYmUgYSBwb3NpdGl2ZSBBbmRyb2lkLXNhZmUgaW50ZWdlci5cIilcbiAgfVxuICBpZiAodHlwZW9mIHZlcnNpb25OYW1lICE9IFwic3RyaW5nXCIgfHwgIXNlbWFudGljVmVyc2lvblBhdHRlcm4udGVzdCh2ZXJzaW9uTmFtZSkgfHwgdmVyc2lvbk5hbWUuaW5jbHVkZXMoXCIrXCIpKSB7XG4gICAgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJWZXJzaW9uIG5hbWUgbXVzdCBiZSBhIGNhbm9uaWNhbCBzZW1hbnRpYyB2ZXJzaW9uIHdpdGhvdXQgYnVpbGQgbWV0YWRhdGEuXCIpXG4gIH1cbiAgaWYgKGNvbmZpZ3VyYXRpb24ucGVybWlzc2lvbnMgIT09IHVuZGVmaW5lZCAmJlxuICAgICghaXNEZW5zZUFycmF5KGNvbmZpZ3VyYXRpb24ucGVybWlzc2lvbnMpIHx8IGNvbmZpZ3VyYXRpb24ucGVybWlzc2lvbnMubGVuZ3RoICE9IDApKSB7XG4gICAgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJUaGUgYmFzZWxpbmUgRmx1dHRlciBwZXJtaXNzaW9uIHNldCBtdXN0IGJlIGVtcHR5LlwiKVxuICB9XG5cbiAgcmV0dXJuIHthY3Rpdml0eUNsYXNzTmFtZSwgYXBwbGljYXRpb25JZCwgYnVpbGRUb29sc1ZlcnNpb24sIGNvbXBpbGVTZGssIGRpc3BsYXlOYW1lLCBtaW5pbXVtU2RrLCBvcmdhbml6YXRpb24sXG4gICAgcGFja2FnZU5hbWUsIHRhcmdldFNkaywgdmVyc2lvbkNvZGUsIHZlcnNpb25OYW1lfVxufVxuXG4vKipcbiAqIFNuYXBzaG90cyBhbmQgdmFsaWRhdGVzIGV4YWN0IGNhbGxlciBhc3NldHMuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSBhc3NldCBjb2xsZWN0aW9uLlxuICogQHJldHVybnMge0ZsdXR0ZXJBc3NldFtdfSBOb3JtYWxpemVkIGFzc2V0cy5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplQXNzZXRzKGNhbmRpZGF0ZSkge1xuICBpZiAoY2FuZGlkYXRlID09PSB1bmRlZmluZWQpIHJldHVybiBbXVxuICBpZiAoIWlzRGVuc2VBcnJheShjYW5kaWRhdGUpKSBpbnZhbGlkQXNzZXQoXCJGbHV0dGVyIGFzc2V0cyBtdXN0IGJlIGEgZGVuc2UgYXJyYXkuXCIpXG4gIC8qKiBAdHlwZSB7Rmx1dHRlckFzc2V0W119ICovXG4gIGNvbnN0IGFzc2V0cyA9IFtdXG5cbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGNhbmRpZGF0ZS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICBjb25zdCBpdGVtID0gY2FuZGlkYXRlW2luZGV4XVxuXG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KGl0ZW0pIHx8IE9iamVjdC5rZXlzKGl0ZW0pLmxlbmd0aCAhPSBhc3NldEZpZWxkcy5zaXplIHx8XG4gICAgICBPYmplY3Qua2V5cyhpdGVtKS5zb21lKGtleSA9PiAhYXNzZXRGaWVsZHMuaGFzKGtleSkpKSBpbnZhbGlkQXNzZXQoYEFzc2V0ICR7aW5kZXh9IG11c3QgdXNlIHRoZSBjbG9zZWQgaW5wdXQgc2NoZW1hLmApXG4gICAgY29uc3QgcGF0aCA9IGl0ZW0ucGF0aFxuICAgIGNvbnN0IGNvbnRlbnQgPSBpdGVtLmNvbnRlbnRcbiAgICBjb25zdCBtZWRpYVR5cGUgPSBpdGVtLm1lZGlhVHlwZVxuICAgIGNvbnN0IHNoYTI1NiA9IGl0ZW0uc2hhMjU2XG5cbiAgICBpZiAoIWlzU2FmZUFydGlmYWN0UGF0aChwYXRoKSB8fCAhU3RyaW5nKHBhdGgpLnN0YXJ0c1dpdGgoXCJhc3NldHMvXCIpKSB7XG4gICAgICBpbnZhbGlkQXNzZXQoYEFzc2V0ICR7aW5kZXh9IHJlcXVpcmVzIGEgc2FmZSBwb3J0YWJsZSBwYXRoIGJlbG93ICdhc3NldHMnLmApXG4gICAgfVxuICAgIGlmICh0eXBlb2YgY29udGVudCAhPSBcInN0cmluZ1wiICYmICEoY29udGVudCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHx8IHR5cGVvZiBjb250ZW50ID09IFwic3RyaW5nXCIgJiZcbiAgICAgIChjb250ZW50Lmxlbmd0aCA9PSAwIHx8ICFoYXNPbmx5VW5pY29kZVNjYWxhcnMoY29udGVudCkpIHx8IGNvbnRlbnQgaW5zdGFuY2VvZiBVaW50OEFycmF5ICYmIGNvbnRlbnQuYnl0ZUxlbmd0aCA9PSAwKSB7XG4gICAgICBpbnZhbGlkQXNzZXQoYEFzc2V0ICcke3BhdGh9JyByZXF1aXJlcyBub24tZW1wdHkgZXhhY3QgY29udGVudC5gKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIG1lZGlhVHlwZSAhPSBcInN0cmluZ1wiIHx8ICFtZWRpYVR5cGVQYXR0ZXJuLnRlc3QobWVkaWFUeXBlKSB8fCAvW1xcclxcbl0vdS50ZXN0KG1lZGlhVHlwZSkpIHtcbiAgICAgIGludmFsaWRBc3NldChgQXNzZXQgJyR7cGF0aH0nIHJlcXVpcmVzIGFuIGV4cGxpY2l0IHZhbGlkIG1lZGlhIHR5cGUuYClcbiAgICB9XG4gICAgY29uc3Qgc25hcHNob3QgPSB0eXBlb2YgY29udGVudCA9PSBcInN0cmluZ1wiID8gY29udGVudCA6IG5ldyBVaW50OEFycmF5KGNvbnRlbnQpXG4gICAgY29uc3QgYWN0dWFsSGFzaCA9IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHNuYXBzaG90KS5kaWdlc3QoXCJoZXhcIilcblxuICAgIGlmICh0eXBlb2Ygc2hhMjU2ICE9IFwic3RyaW5nXCIgfHwgIS9eWzAtOWEtZl17NjR9JC91LnRlc3Qoc2hhMjU2KSB8fCBzaGEyNTYgIT0gYWN0dWFsSGFzaCkge1xuICAgICAgaW52YWxpZEFzc2V0KGBBc3NldCAnJHtwYXRofScgU0hBLTI1NiBkb2VzIG5vdCBtYXRjaCBpdHMgZXhhY3QgY29udGVudC5gKVxuICAgIH1cbiAgICBhc3NldHMucHVzaCh7Y29udGVudDogc25hcHNob3QsIGNvbnRlbnRLaW5kOiB0eXBlb2Ygc25hcHNob3QgPT0gXCJzdHJpbmdcIiA/IFwidGV4dFwiIDogXCJiaW5hcnlcIixcbiAgICAgIGZ1bGxQYXRoOiBgJHtwcm9qZWN0Um9vdH0vJHtwYXRofWAsIG1lZGlhVHlwZSwgcGF0aCwgc2hhMjU2fSlcbiAgfVxuICBhc3NldHMuc29ydCgobGVmdCwgcmlnaHQpID0+IGxlZnQuZnVsbFBhdGggPCByaWdodC5mdWxsUGF0aCA/IC0xIDogbGVmdC5mdWxsUGF0aCA+IHJpZ2h0LmZ1bGxQYXRoID8gMSA6IDApXG4gIGNvbnN0IGNvbmZsaWN0ID0gZmluZFBvcnRhYmxlQXJ0aWZhY3RQYXRoQ29uZmxpY3QoYXNzZXRzLm1hcCgoe2Z1bGxQYXRofSkgPT4gZnVsbFBhdGgpKVxuXG4gIGlmIChjb25mbGljdCkgaW52YWxpZEFzc2V0KGBBc3NldCBwYXRoICcke2NvbmZsaWN0LnBhdGh9JyBoYXMgYSAke2NvbmZsaWN0LmtpbmR9IGNvbmZsaWN0LmApXG5cbiAgcmV0dXJuIGFzc2V0c1xufVxuXG4vKipcbiAqIEVudW1lcmF0ZXMgZXZlcnkgZ2VuZXJhdG9yLW93bmVkIGFwcGxpY2F0aW9uIHBhdGguXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkZsdXR0ZXJBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb259IGNvbmZpZ3VyYXRpb24gLSBOb3JtYWxpemVkIGNvbmZpZ3VyYXRpb24uXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIHN0cmluZz59IG1vZHVsZVBhdGhzIC0gU2VtYW50aWMgbW9kdWxlIHBhdGhzLlxuICogQHJldHVybnMge3N0cmluZ1tdfSBDb21wbGV0ZSBwYXRocy5cbiAqL1xuZnVuY3Rpb24gYXBwbGljYXRpb25QYXRocyhjb25maWd1cmF0aW9uLCBtb2R1bGVQYXRocykge1xuICBjb25zdCBwYWNrYWdlUGF0aCA9IGNvbmZpZ3VyYXRpb24uYXBwbGljYXRpb25JZC5yZXBsYWNlQWxsKFwiLlwiLCBcIi9cIilcblxuICByZXR1cm4gW1xuICAgIGAke3Byb2plY3RSb290fS8ubWV0YWRhdGFgLFxuICAgIGAke3Byb2plY3RSb290fS9hbmFseXNpc19vcHRpb25zLnlhbWxgLFxuICAgIGAke3Byb2plY3RSb290fS9hbmRyb2lkL2FwcC9idWlsZC5ncmFkbGUua3RzYCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vYW5kcm9pZC9hcHAvc3JjL21haW4vQW5kcm9pZE1hbmlmZXN0LnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL2phdmEvJHtwYWNrYWdlUGF0aH0vJHtjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lfS5qYXZhYCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vYW5kcm9pZC9hcHAvc3JjL21haW4vcmVzL2RyYXdhYmxlL2xhdW5jaF9iYWNrZ3JvdW5kLnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL3Jlcy92YWx1ZXMtbmlnaHQvc3R5bGVzLnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL3Jlcy92YWx1ZXMvc3R5bGVzLnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL3Jlcy94bWwvYmFja3VwX3J1bGVzLnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYXBwL3NyYy9tYWluL3Jlcy94bWwvZGF0YV9leHRyYWN0aW9uX3J1bGVzLnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvYnVpbGQuZ3JhZGxlLmt0c2AsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FuZHJvaWQvZ3JhZGxlLnByb3BlcnRpZXNgLFxuICAgIGAke3Byb2plY3RSb290fS9hbmRyb2lkL3NldHRpbmdzLmdyYWRsZS5rdHNgLFxuICAgIGAke3Byb2plY3RSb290fS9saWIvbWFpbi5kYXJ0YCxcbiAgICAuLi5tb2R1bGVQYXRocy52YWx1ZXMoKSxcbiAgICBgJHtwcm9qZWN0Um9vdH0vbGliL3NyYy9zZW1hbnRpYy9zZW1hbnRpZm9sZC5kYXJ0YCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vcHVic3BlYy5sb2NrYCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vcHVic3BlYy55YW1sYCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vdGVzdC9zZW1hbnRpY19sb2dpY190ZXN0LmRhcnRgLFxuICAgIGAke3Byb2plY3RSb290fS90ZXN0L3dpZGdldF90ZXN0LmRhcnRgLFxuICAgIGAke3Byb2plY3RSb290fS9zZW1hbnRpZm9sZC1wcm9qZWN0Lmpzb25gXG4gIF1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgbm9ybWFsaXplZCBhc3NldCB0byBhbiBvd25lZCBhcnRpZmFjdC5cbiAqIEBwYXJhbSB7Rmx1dHRlckFzc2V0fSBhc3NldCAtIE5vcm1hbGl6ZWQgYXNzZXQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3R9IEdlbmVyYXRlZCBhc3NldC5cbiAqL1xuZnVuY3Rpb24gYXNzZXRBcnRpZmFjdChhc3NldCkge1xuICBjb25zdCByZWFzb24gPSBgRXhhY3QgY2FsbGVyLXByb3ZpZGVkIEZsdXR0ZXIgYXNzZXQgKHNoYTI1Njoke2Fzc2V0LnNoYTI1Nn0pLmBcblxuICBpZiAodHlwZW9mIGFzc2V0LmNvbnRlbnQgPT0gXCJzdHJpbmdcIikgcmV0dXJuIHsuLi5zeW50aGV0aWNUZXh0KGFzc2V0LmZ1bGxQYXRoLCBcInJlc291cmNlXCIsIGFzc2V0LmNvbnRlbnQsIHJlYXNvbiksIG1lZGlhVHlwZTogYXNzZXQubWVkaWFUeXBlfVxuICBjb25zdCBjb250ZW50ID0gbmV3IFVpbnQ4QXJyYXkoYXNzZXQuY29udGVudClcblxuICByZXR1cm4ge1xuICAgIGNvbnRlbnQsXG4gICAgY29udGVudEtpbmQ6IFwiYmluYXJ5XCIsXG4gICAgbWVkaWFUeXBlOiBhc3NldC5tZWRpYVR5cGUsXG4gICAgb3duZXJzaGlwOiBcImdlbmVyYXRlZFwiLFxuICAgIHBhdGg6IGFzc2V0LmZ1bGxQYXRoLFxuICAgIHByb3ZlbmFuY2U6IHtraW5kOiBcImJ5dGVzXCIsIG1hcHBpbmc6IGNyZWF0ZUJ5dGVNYXBwaW5nKHtcbiAgICAgIGJ5dGVMZW5ndGg6IGNvbnRlbnQuYnl0ZUxlbmd0aCxcbiAgICAgIHBhdGg6IGFzc2V0LmZ1bGxQYXRoLFxuICAgICAgcmFuZ2VzOiBbe2dlbmVyYXRlZDoge2VuZDogY29udGVudC5ieXRlTGVuZ3RoLCBzdGFydDogMH0sXG4gICAgICAgIG9yaWdpbjoge2tpbmQ6IFwic3ludGhldGljXCIsIHJlYXNvbiwgcmVsYXRlZE9yaWdpbnM6IFtdfSwgcm9sZTogXCJhc3NldFwifV1cbiAgICB9KX0sXG4gICAgcm9sZTogXCJyZXNvdXJjZVwiXG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc3ludGhldGljIHRleHQgYXJ0aWZhY3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIEFydGlmYWN0IHBhdGguXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZEFydGlmYWN0Um9sZX0gcm9sZSAtIEFydGlmYWN0IHJvbGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGVudCAtIEV4YWN0IGNvbnRlbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVhc29uIC0gU3ludGhldGljIHByb3ZlbmFuY2UgcmVhc29uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0fSBHZW5lcmF0ZWQgYXJ0aWZhY3QuXG4gKi9cbmZ1bmN0aW9uIHN5bnRoZXRpY1RleHQocGF0aCwgcm9sZSwgY29udGVudCwgcmVhc29uKSB7XG4gIHJldHVybiB7Y29udGVudCwgY29udGVudEtpbmQ6IFwidGV4dFwiLCBtZWRpYVR5cGU6IG1lZGlhVHlwZUZvcihwYXRoKSwgb3duZXJzaGlwOiBcImdlbmVyYXRlZFwiLCBwYXRoLFxuICAgIHByb3ZlbmFuY2U6IHtraW5kOiBcInN5bnRoZXRpY1wiLCByZWFzb24sIHJlbGF0ZWRPcmlnaW5zOiBbXX0sIHJvbGV9XG59XG5cbi8qKlxuICogQ3JlYXRlcyB0ZXh0IHdob3NlIGNvbmZpZ3VyYXRpb24gc3BhbnMgYXJlIHJlY29yZGVkIHNlcGFyYXRlbHkuXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIEFydGlmYWN0IHBhdGguXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZEFydGlmYWN0Um9sZX0gcm9sZSAtIEFydGlmYWN0IHJvbGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGVudCAtIEV4YWN0IGNvbnRlbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVhc29uIC0gU3ludGhldGljIHByb3ZlbmFuY2UgcmVhc29uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0fSBHZW5lcmF0ZWQgYXJ0aWZhY3QuXG4gKi9cbmZ1bmN0aW9uIGNvbmZpZ3VyZWRUZXh0KHBhdGgsIHJvbGUsIGNvbnRlbnQsIHJlYXNvbikge1xuICByZXR1cm4gc3ludGhldGljVGV4dChwYXRoLCByb2xlLCBjb250ZW50LCByZWFzb24pXG59XG5cbi8qKlxuICogU2VsZWN0cyBhbiBleGFjdCBtZWRpYSB0eXBlIGZyb20gYW4gb3duZWQgcGF0aC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gQXJ0aWZhY3QgcGF0aC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IE1lZGlhIHR5cGUuXG4gKi9cbmZ1bmN0aW9uIG1lZGlhVHlwZUZvcihwYXRoKSB7XG4gIGlmIChwYXRoLmVuZHNXaXRoKFwiLmRhcnRcIikpIHJldHVybiBcInRleHQveC1kYXJ0XCJcbiAgaWYgKHBhdGguZW5kc1dpdGgoXCIuanNvblwiKSkgcmV0dXJuIFwiYXBwbGljYXRpb24vanNvblwiXG4gIGlmIChwYXRoLmVuZHNXaXRoKFwiLnlhbWxcIikgfHwgcGF0aC5lbmRzV2l0aChcIi5sb2NrXCIpKSByZXR1cm4gXCJhcHBsaWNhdGlvbi95YW1sXCJcbiAgaWYgKHBhdGguZW5kc1dpdGgoXCIueG1sXCIpKSByZXR1cm4gXCJhcHBsaWNhdGlvbi94bWxcIlxuICBpZiAocGF0aC5lbmRzV2l0aChcIi5qYXZhXCIpKSByZXR1cm4gXCJ0ZXh0L3gtamF2YS1zb3VyY2VcIlxuICBpZiAocGF0aC5lbmRzV2l0aChcIi5rdHNcIikpIHJldHVybiBcInRleHQveC1rb3RsaW5cIlxuXG4gIHJldHVybiBcInRleHQvcGxhaW5cIlxufVxuXG4vKipcbiAqIE1hcmtzIG9uZSByZW5kZXJlZCB2YWx1ZSBhcyBjb25maWd1cmF0aW9uLWRlcml2ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmllbGROYW1lIC0gQ29uZmlndXJhdGlvbiBmaWVsZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFJlbmRlcmVkIHZhbHVlLlxuICogQHJldHVybnMge3tmaWVsZDogc3RyaW5nLCB2YWx1ZTogc3RyaW5nfX0gTWFya2VkIHZhbHVlLlxuICovXG5mdW5jdGlvbiBmaWVsZChmaWVsZE5hbWUsIHZhbHVlKSB7XG4gIHJldHVybiB7ZmllbGQ6IGZpZWxkTmFtZSwgdmFsdWV9XG59XG5cbi8qKlxuICogSm9pbnMgY29uZmlndXJlZCBwYXJ0cyB3aGlsZSByZWNvcmRpbmcgZXhhY3Qgb3V0cHV0IHNwYW5zLlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBBcnRpZmFjdCBwYXRoLlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uU3BhbltdfSBzcGFucyAtIENvbmZpZ3VyYXRpb24gcHJvdmVuYW5jZSBzaW5rLlxuICogQHBhcmFtIHsoc3RyaW5nIHwge2ZpZWxkOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmd9KVtdfSBwYXJ0cyAtIExpdGVyYWwgYW5kIGNvbmZpZ3VyZWQgcGFydHMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBSZW5kZXJlZCBjb250ZW50LlxuICovXG5mdW5jdGlvbiBjb25maWd1cmVkKHBhdGgsIHNwYW5zLCBwYXJ0cykge1xuICBsZXQgY29udGVudCA9IFwiXCJcblxuICBmb3IgKGNvbnN0IHBhcnQgb2YgcGFydHMpIHtcbiAgICBpZiAodHlwZW9mIHBhcnQgPT0gXCJzdHJpbmdcIikgY29udGVudCArPSBwYXJ0XG4gICAgZWxzZSB7XG4gICAgICBjb25zdCBzdGFydCA9IGNvbnRlbnQubGVuZ3RoXG5cbiAgICAgIGNvbnRlbnQgKz0gcGFydC52YWx1ZVxuICAgICAgc3BhbnMucHVzaCh7ZW5kOiBjb250ZW50Lmxlbmd0aCwgZmllbGQ6IHBhcnQuZmllbGQsIHBhdGgsIHN0YXJ0fSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gY29udGVudFxufVxuXG4vKipcbiAqIEdyb3VwcyBleGFjdCBnZW5lcmF0ZWQgcmFuZ2VzIGZvciBvbmUgY29uZmlndXJhdGlvbiBmaWVsZC5cbiAqIEBwYXJhbSB7Q29uZmlndXJhdGlvblNwYW5bXX0gc3BhbnMgLSBSZWNvcmRlZCBzcGFucy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWVsZE5hbWUgLSBDb25maWd1cmF0aW9uIGZpZWxkLlxuICogQHJldHVybnMge3twYXRoOiBzdHJpbmcsIHJhbmdlczoge2VuZDogbnVtYmVyLCBzdGFydDogbnVtYmVyfVtdfVtdfSBHcm91cGVkIG91dHB1dCByYW5nZXMuXG4gKi9cbmZ1bmN0aW9uIGNvbmZpZ3VyYXRpb25PdXRwdXRzKHNwYW5zLCBmaWVsZE5hbWUpIHtcbiAgY29uc3QgZ3JvdXBlZCA9IG5ldyBNYXAoKVxuXG4gIGZvciAoY29uc3Qgc3BhbiBvZiBzcGFucykge1xuICAgIGlmIChzcGFuLmZpZWxkICE9IGZpZWxkTmFtZSkgY29udGludWVcbiAgICBjb25zdCByYW5nZXMgPSBncm91cGVkLmdldChzcGFuLnBhdGgpID8/IFtdXG5cbiAgICByYW5nZXMucHVzaCh7ZW5kOiBzcGFuLmVuZCwgc3RhcnQ6IHNwYW4uc3RhcnR9KVxuICAgIGdyb3VwZWQuc2V0KHNwYW4ucGF0aCwgcmFuZ2VzKVxuICB9XG5cbiAgcmV0dXJuIFsuLi5ncm91cGVkXS5tYXAoKFtwYXRoLCByYW5nZXNdKSA9PiAoe3BhdGgsIHJhbmdlc30pKVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHByb3ZlbmFuY2UgcmVmZXJzIHRvIG9uZSBzb3VyY2UgZmlsZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNPcmlnaW59IG9yaWdpbiAtIFNlbWFudGljIG9yaWdpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBvcmlnaW4gcmVmZXJlbmNlcyB0aGUgc291cmNlLlxuICovXG5mdW5jdGlvbiBvcmlnaW5SZWZlcmVuY2VzRmlsZW5hbWUob3JpZ2luLCBmaWxlbmFtZSkge1xuICBpZiAob3JpZ2luLmtpbmQgPT0gXCJzb3VyY2VcIikgcmV0dXJuIG9yaWdpbi5sb2NhdGlvbi5maWxlbmFtZSA9PSBmaWxlbmFtZVxuICBpZiAob3JpZ2luLmtpbmQgPT0gXCJkZXJpdmVkXCIpIHJldHVybiBvcmlnaW4ub3JpZ2lucy5zb21lKCh7bG9jYXRpb259KSA9PiBsb2NhdGlvbi5maWxlbmFtZSA9PSBmaWxlbmFtZSlcblxuICByZXR1cm4gb3JpZ2luLnJlbGF0ZWRPcmlnaW5zLnNvbWUoKHtsb2NhdGlvbn0pID0+IGxvY2F0aW9uLmZpbGVuYW1lID09IGZpbGVuYW1lKVxufVxuXG4vKipcbiAqIEhhc2hlcyBleGFjdCBhcnRpZmFjdCBjb250ZW50LlxuICogQHBhcmFtIHtzdHJpbmcgfCBVaW50OEFycmF5fSBjb250ZW50IC0gQXJ0aWZhY3QgY29udGVudC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IExvd2VyY2FzZSBTSEEtMjU2LlxuICovXG5mdW5jdGlvbiBoYXNoQ29udGVudChjb250ZW50KSB7XG4gIHJldHVybiBjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShjb250ZW50KS5kaWdlc3QoXCJoZXhcIilcbn1cblxuLyoqXG4gKiBTZXJpYWxpemVzIGEgcmVjdXJzaXZlbHkgc29ydGVkIEpTT04gdmFsdWUuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gSlNPTi1jb21wYXRpYmxlIHZhbHVlLlxuICogQHJldHVybnMge3N0cmluZ30gQ2Fub25pY2FsIGluZGVudGVkIEpTT04uXG4gKi9cbmZ1bmN0aW9uIHN0cmluZ2lmeUNhbm9uaWNhbEpzb24odmFsdWUpIHtcbiAgcmV0dXJuIGAke0pTT04uc3RyaW5naWZ5KHNvcnRKc29uKHZhbHVlKSwgbnVsbCwgMil9XFxuYFxufVxuXG4vKipcbiAqIFJlY3Vyc2l2ZWx5IHNvcnRzIG9iamVjdCBrZXlzIHdpdGhvdXQgcmVvcmRlcmluZyBhcnJheXMuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gSlNPTi1jb21wYXRpYmxlIHZhbHVlLlxuICogQHJldHVybnMge3Vua25vd259IFNvcnRlZCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gc29ydEpzb24odmFsdWUpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSByZXR1cm4gdmFsdWUubWFwKHNvcnRKc29uKVxuICBpZiAoIWlzUGxhaW5PYmplY3QodmFsdWUpKSByZXR1cm4gdmFsdWVcblxuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKE9iamVjdC5rZXlzKHZhbHVlKS5zb3J0KCkubWFwKGtleSA9PiBba2V5LCBzb3J0SnNvbih2YWx1ZVtrZXldKV0pKVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBhIGxvd2VyY2FzZSByZXZlcnNlLUROUyBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIENhbmRpZGF0ZSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzZWdtZW50cyAtIFJlcXVpcmVkIG1pbmltdW0gc2VnbWVudCBjb3VudC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBpZGVudGl0eSBpcyB2YWxpZC5cbiAqL1xuZnVuY3Rpb24gaXNSZXZlcnNlRG5zKHZhbHVlLCBzZWdtZW50cykge1xuICBjb25zdCBwYXJ0cyA9IHZhbHVlLnNwbGl0KFwiLlwiKVxuXG4gIHJldHVybiBwYXJ0cy5sZW5ndGggPj0gc2VnbWVudHMgJiYgcGFydHMuZXZlcnkocGFydCA9PiAvXlthLXpdW2EtejAtOV9dKiQvdS50ZXN0KHBhcnQpICYmICFqYXZhS2V5d29yZHMuaGFzKHBhcnQpKVxufVxuXG4vKipcbiAqIERlcml2ZXMgb25lIHN0YWJsZSBEYXJ0IGNsYXNzIHN1ZmZpeC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFNlbWFudGljIG1vZHVsZSBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IERhcnQgY2xhc3Mgc3VmZml4LlxuICovXG5mdW5jdGlvbiBtb2R1bGVOYW1lKGlkKSB7XG4gIHJldHVybiBpZC5zcGxpdCgvWy5fLV0rL3UpLm1hcChwYXJ0ID0+IGAke3BhcnRbMF0udG9VcHBlckNhc2UoKX0ke3BhcnQuc2xpY2UoMSl9YCkuam9pbihcIlwiKVxufVxuXG4vKipcbiAqIERlcml2ZXMgb25lIHN0YWJsZSBzZW1hbnRpYyBwYXJ0IGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gU2VtYW50aWMgbW9kdWxlIGlkZW50aXR5LlxuICogQHJldHVybnMge3N0cmluZ30gRGFydCBmaWxlbmFtZS5cbiAqL1xuZnVuY3Rpb24gbW9kdWxlRmlsZU5hbWUoaWQpIHtcbiAgcmV0dXJuIGlkLnJlcGxhY2VBbGwoL1suLV0vZ3UsIFwiX1wiKVxufVxuXG4vKipcbiAqIEFsbG9jYXRlcyBhIGNvbGxpc2lvbi1mcmVlIHByaXZhdGUgb3V0cHV0IHNpbmsgYmluZGluZy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFNlbWFudGljIG1vZHVsZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IERhcnQgYmluZGluZyBuYW1lLlxuICovXG5mdW5jdGlvbiBvdXRwdXRTaW5rTmFtZShtb2R1bGUpIHtcbiAgY29uc3QgYmluZGluZ3MgPSBuZXcgU2V0KG1vZHVsZS5mdW5jdGlvbnMuZmxhdE1hcChkZWNsYXJhdGlvbiA9PiBkZWNsYXJhdGlvbi5wYXJhbWV0ZXJzLm1hcCgoe25hbWV9KSA9PiBuYW1lKSkpXG5cbiAgZm9yIChjb25zdCBkZWNsYXJhdGlvbiBvZiBtb2R1bGUuZnVuY3Rpb25zKSBjb2xsZWN0QmxvY2tCaW5kaW5nTmFtZXMoZGVjbGFyYXRpb24uYm9keSwgYmluZGluZ3MpXG4gIGNvbGxlY3RCbG9ja0JpbmRpbmdOYW1lcyhtb2R1bGUuZW50cnlQb2ludC5ib2R5LCBiaW5kaW5ncylcbiAgbGV0IGNhbmRpZGF0ZSA9IFwic2VtYW50aWZvbGRPdXRwdXRcIlxuXG4gIHdoaWxlIChiaW5kaW5ncy5oYXMoY2FuZGlkYXRlKSkgY2FuZGlkYXRlICs9IFwiX1wiXG5cbiAgcmV0dXJuIGNhbmRpZGF0ZVxufVxuXG4vKipcbiAqIENvbGxlY3RzIGV2ZXJ5IGJsb2NrLW93bmVkIGJpbmRpbmcgbmFtZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQmxvY2t9IGJsb2NrIC0gU2VtYW50aWMgYmxvY2suXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSBiaW5kaW5ncyAtIE11dGFibGUgbmFtZSBzZXQuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gY29sbGVjdEJsb2NrQmluZGluZ05hbWVzKGJsb2NrLCBiaW5kaW5ncykge1xuICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiBibG9jay5zdGF0ZW1lbnRzKSB7XG4gICAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiTG9jYWxEZWNsYXJhdGlvblwiKSBiaW5kaW5ncy5hZGQoc3RhdGVtZW50Lm5hbWUpXG4gICAgZWxzZSBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJJZlN0YXRlbWVudFwiKSB7XG4gICAgICBjb2xsZWN0QmxvY2tCaW5kaW5nTmFtZXMoc3RhdGVtZW50LmNvbnNlcXVlbnQsIGJpbmRpbmdzKVxuICAgICAgaWYgKHN0YXRlbWVudC5hbHRlcm5hdGUpIGNvbGxlY3RCbG9ja0JpbmRpbmdOYW1lcyhzdGF0ZW1lbnQuYWx0ZXJuYXRlLCBiaW5kaW5ncylcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBXcmFwcyBvbmUgbW9kdWxlIGluIGFuIGV4cGxpY2l0IHNlbWFudGljIHByb2plY3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlIHwgdW5kZWZpbmVkfSBjYW5kaWRhdGUgLSBDYW5kaWRhdGUgbW9kdWxlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljUHJvZ3JhbX0gTm9ybWFsaXplZCBwcm9qZWN0LlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVTaW5nbGVNb2R1bGUoY2FuZGlkYXRlKSB7XG4gIGlmICghaXNQbGFpbk9iamVjdChjYW5kaWRhdGUpKSB1bnN1cHBvcnRlZENhcGFiaWxpdHkoXCJmbHV0dGVyXCIsIFwibWlzc2luZyBvciBpbnZhbGlkIG1vZHVsZVwiLCB1bmRlZmluZWQpXG4gIGNvbnN0IG1vZHVsZSA9IHN0cnVjdHVyZWRDbG9uZShjYW5kaWRhdGUpXG4gIGNvbnN0IHNvdXJjZXMgPSBtb2R1bGUucHJvdmVuYW5jZT8uc291cmNlc1xuXG4gIGlmICghQXJyYXkuaXNBcnJheShzb3VyY2VzKSB8fCBzb3VyY2VzLmxlbmd0aCAhPSAxIHx8IHNvdXJjZXNbMF0uY29udGVudCA9PT0gbnVsbCB8fFxuICAgIHNvdXJjZXNbMF0uZmlsZW5hbWUgIT0gbW9kdWxlLmxvY2F0aW9uPy5maWxlbmFtZSB8fCB0eXBlb2Ygc291cmNlc1swXS5sYW5ndWFnZSAhPSBcInN0cmluZ1wiKSB7XG4gICAgdW5zdXBwb3J0ZWRDYXBhYmlsaXR5KFwiZmx1dHRlclwiLCBcInNpbmdsZS1tb2R1bGUgc291cmNlIG93bmVyc2hpcFwiLCBtb2R1bGUubG9jYXRpb24pXG4gIH1cbiAgcmVrZXlNb2R1bGVEZWNsYXJhdGlvbnMobW9kdWxlLCBcIm1haW5cIilcbiAgY29uc3QgZXhwb3J0cyA9IFtcbiAgICAuLi4obW9kdWxlLnJlY29yZHMgPz8gW10pLm1hcChkZWNsYXJhdGlvbiA9PiBhcHBsaWNhdGlvbkV4cG9ydChkZWNsYXJhdGlvbiwgXCJyZWNvcmRcIikpLFxuICAgIC4uLihtb2R1bGUuY2xhc3NlcyA/PyBbXSkubWFwKGRlY2xhcmF0aW9uID0+IGFwcGxpY2F0aW9uRXhwb3J0KGRlY2xhcmF0aW9uLCBcImNsYXNzXCIpKSxcbiAgICAuLi4obW9kdWxlLmVycm9ycyA/PyBbXSkubWFwKGRlY2xhcmF0aW9uID0+IGFwcGxpY2F0aW9uRXhwb3J0KGRlY2xhcmF0aW9uLCBcImVycm9yXCIpKSxcbiAgICAuLi5tb2R1bGUuZnVuY3Rpb25zLm1hcChkZWNsYXJhdGlvbiA9PiBhcHBsaWNhdGlvbkV4cG9ydChkZWNsYXJhdGlvbiwgXCJmdW5jdGlvblwiKSlcbiAgXVxuICBjb25zdCBwcm9ncmFtTW9kdWxlID0gey4uLm1vZHVsZSwgZXhwb3J0cywgaWQ6IFwibWFpblwiLCBpbXBvcnRzOiBbXSwgc291cmNlRmlsZW5hbWU6IHNvdXJjZXNbMF0uZmlsZW5hbWV9XG5cbiAgcmV0dXJuIHtlbnRyeU1vZHVsZTogXCJtYWluXCIsIGtpbmQ6IFwiUHJvZ3JhbVwiLCBtb2R1bGVzOiBbcHJvZ3JhbU1vZHVsZV0sIHNvdXJjZXM6IHN0cnVjdHVyZWRDbG9uZShzb3VyY2VzKX1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgbW9kdWxlIGRlY2xhcmF0aW9uIHRvIGFuIGV4cGxpY2l0IGFwcGxpY2F0aW9uIGV4cG9ydC5cbiAqIEBwYXJhbSB7e2lkPzogc3RyaW5nLCBsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIG5hbWU6IHN0cmluZ319IGRlY2xhcmF0aW9uIC0gRGVjbGFyYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljRGVjbGFyYXRpb25LaW5kfSBzeW1ib2xLaW5kIC0gRGVjbGFyYXRpb24ga2luZC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY0V4cG9ydH0gU2VtYW50aWMgZXhwb3J0LlxuICovXG5mdW5jdGlvbiBhcHBsaWNhdGlvbkV4cG9ydChkZWNsYXJhdGlvbiwgc3ltYm9sS2luZCkge1xuICByZXR1cm4ge2RlY2xhcmF0aW9uSWQ6IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoZGVjbGFyYXRpb24uaWQpLCBleHBvcnRlZE5hbWU6IGRlY2xhcmF0aW9uLm5hbWUsXG4gICAga2luZDogXCJFeHBvcnRcIiwgbG9jYXRpb246IGRlY2xhcmF0aW9uLmxvY2F0aW9uLCBzeW1ib2xLaW5kfVxufVxuXG4vKipcbiAqIFJlLWtleXMgb25lIHN0YW5kYWxvbmUgbW9kdWxlIGZvciBhcHBsaWNhdGlvbi1wcm9qZWN0IG93bmVyc2hpcC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFN0YW5kYWxvbmUgbW9kdWxlLlxuICogQHBhcmFtIHtzdHJpbmd9IG1vZHVsZUlkIC0gU3RhYmxlIGFwcGxpY2F0aW9uIG1vZHVsZSBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiByZWtleU1vZHVsZURlY2xhcmF0aW9ucyhtb2R1bGUsIG1vZHVsZUlkKSB7XG4gIGNvbnN0IGRlY2xhcmF0aW9ucyA9IFsuLi5tb2R1bGUucmVjb3JkcyA/PyBbXSwgLi4ubW9kdWxlLmNsYXNzZXMgPz8gW10sIC4uLm1vZHVsZS5lcnJvcnMgPz8gW10sIC4uLm1vZHVsZS5mdW5jdGlvbnNdXG4gIGNvbnN0IHJlcGxhY2VtZW50cyA9IG5ldyBNYXAoZGVjbGFyYXRpb25zLmZpbHRlcihkZWNsYXJhdGlvbiA9PiB0eXBlb2YgZGVjbGFyYXRpb24uaWQgPT0gXCJzdHJpbmdcIilcbiAgICAubWFwKGRlY2xhcmF0aW9uID0+IFtkZWNsYXJhdGlvbi5pZCwgYCR7bW9kdWxlSWR9IyR7ZGVjbGFyYXRpb24uaWR9YF0pKVxuXG4gIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgZGVjbGFyYXRpb25zKSBpZiAodHlwZW9mIGRlY2xhcmF0aW9uLmlkID09IFwic3RyaW5nXCIpIGRlY2xhcmF0aW9uLmlkID0gcmVwbGFjZW1lbnRzLmdldChkZWNsYXJhdGlvbi5pZClcbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQoKVxuICBjb25zdCBpZGVudGl0eUZpZWxkcyA9IG5ldyBTZXQoW1wiY2xhc3NJZFwiLCBcImRlY2xhcmF0aW9uSWRcIiwgXCJmaWVsZFwiLCBcIm1ldGhvZFwiLCBcInBhcmFtZXRlcklkXCJdKVxuICAvKipcbiAgICogUmV3cml0ZXMgc2VtYW50aWMgZGVjbGFyYXRpb24gaWRlbnRpdGllcyByZWN1cnNpdmVseS5cbiAgICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIENhbmRpZGF0ZSBzZW1hbnRpYyB2YWx1ZS5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBjb25zdCB2aXNpdCA9IHZhbHVlID0+IHtcbiAgICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPSBcIm9iamVjdFwiIHx8IHNlZW4uaGFzKHZhbHVlKSkgcmV0dXJuXG4gICAgc2Vlbi5hZGQodmFsdWUpXG4gICAgZm9yIChjb25zdCBba2V5LCBuZXN0ZWRdIG9mIE9iamVjdC5lbnRyaWVzKHZhbHVlKSkge1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBpZGVudGl0eUZpZWxkcy5oYXMoa2V5KSAmJiB0eXBlb2YgbmVzdGVkID09IFwic3RyaW5nXCIgJiYgcmVwbGFjZW1lbnRzLmhhcyhuZXN0ZWQpKSB7XG4gICAgICAgIFJlZmxlY3Quc2V0KHZhbHVlLCBrZXksIHJlcGxhY2VtZW50cy5nZXQobmVzdGVkKSlcbiAgICAgIH0gZWxzZSB2aXNpdChuZXN0ZWQpXG4gICAgfVxuICB9XG5cbiAgdmlzaXQobW9kdWxlKVxufVxuXG4vKipcbiAqIEVzY2FwZXMgYW4gWE1MIGF0dHJpYnV0ZSB2YWx1ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFJhdyB2YWx1ZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEVzY2FwZWQgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIHhtbEVzY2FwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUucmVwbGFjZUFsbChcIiZcIiwgXCImYW1wO1wiKS5yZXBsYWNlQWxsKFwiPFwiLCBcIiZsdDtcIikucmVwbGFjZUFsbChcIj5cIiwgXCImZ3Q7XCIpXG4gICAgLnJlcGxhY2VBbGwoJ1wiJywgXCImcXVvdDtcIikucmVwbGFjZUFsbChcIidcIiwgXCImYXBvcztcIilcbn1cblxuLyoqXG4gKiBFc2NhcGVzIGEgc2luZ2xlLXF1b3RlZCBEYXJ0IGxpdGVyYWwgYm9keS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFJhdyB2YWx1ZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEVzY2FwZWQgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIGRhcnRFc2NhcGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlLnJlcGxhY2VBbGwoXCJcXFxcXCIsIFwiXFxcXFxcXFxcIikucmVwbGFjZUFsbChcIidcIiwgXCJcXFxcJ1wiKS5yZXBsYWNlQWxsKFwiJFwiLCBcIlxcXFwkXCIpXG59XG5cbi8qKlxuICogQ2hlY2tzIGZvciBhIHBsYWluIHN0cmluZy1rZXllZCBvYmplY3QuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gQ2FuZGlkYXRlIHZhbHVlLlxuICogQHJldHVybnMge3ZhbHVlIGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+fSBXaGV0aGVyIHRoZSB2YWx1ZSBpcyBwbGFpbi5cbiAqL1xuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gQm9vbGVhbih2YWx1ZSkgJiYgdHlwZW9mIHZhbHVlID09IFwib2JqZWN0XCIgJiYgIUFycmF5LmlzQXJyYXkodmFsdWUpICYmIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSkgPT0gT2JqZWN0LnByb3RvdHlwZVxufVxuXG4vKipcbiAqIFRocm93cyBhIHN0YWJsZSBpbnZhbGlkLWlucHV0IGRpYWdub3N0aWMuXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIERpYWdub3N0aWMgZGV0YWlsLlxuICogQHJldHVybnMge25ldmVyfSBOZXZlciByZXR1cm5zLlxuICovXG5mdW5jdGlvbiBpbnZhbGlkSW5wdXQobWVzc2FnZSkge1xuICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtjb2RlOiBcIklOVkFMSURfQVBQTElDQVRJT05fSU5QVVRcIiwgbGFuZ3VhZ2U6IFwiZmx1dHRlclwiLCBtZXNzYWdlfSlcbn1cblxuLyoqXG4gKiBUaHJvd3MgYSBzdGFibGUgaW52YWxpZC1jb25maWd1cmF0aW9uIGRpYWdub3N0aWMuXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIERpYWdub3N0aWMgZGV0YWlsLlxuICogQHJldHVybnMge25ldmVyfSBOZXZlciByZXR1cm5zLlxuICovXG5mdW5jdGlvbiBpbnZhbGlkQ29uZmlndXJhdGlvbihtZXNzYWdlKSB7XG4gIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe2NvZGU6IFwiSU5WQUxJRF9BUFBMSUNBVElPTl9DT05GSUdVUkFUSU9OXCIsIGxhbmd1YWdlOiBcImZsdXR0ZXJcIiwgbWVzc2FnZX0pXG59XG5cbi8qKlxuICogVGhyb3dzIGEgc3RhYmxlIGludmFsaWQtYXNzZXQgZGlhZ25vc3RpYy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRGlhZ25vc3RpYyBkZXRhaWwuXG4gKiBAcmV0dXJucyB7bmV2ZXJ9IE5ldmVyIHJldHVybnMuXG4gKi9cbmZ1bmN0aW9uIGludmFsaWRBc3NldChtZXNzYWdlKSB7XG4gIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe2NvZGU6IFwiSU5WQUxJRF9BUFBMSUNBVElPTl9BU1NFVFwiLCBsYW5ndWFnZTogXCJmbHV0dGVyXCIsIG1lc3NhZ2V9KVxufVxuXG4vKipcbiAqIFRocm93cyBhIHN0YWJsZSBpbnZhbGlkLXBhdGggZGlhZ25vc3RpYy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRGlhZ25vc3RpYyBkZXRhaWwuXG4gKiBAcmV0dXJucyB7bmV2ZXJ9IE5ldmVyIHJldHVybnMuXG4gKi9cbmZ1bmN0aW9uIGludmFsaWRQYXRoKG1lc3NhZ2UpIHtcbiAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7Y29kZTogXCJJTlZBTElEX0FQUExJQ0FUSU9OX1BBVEhcIiwgbGFuZ3VhZ2U6IFwiZmx1dHRlclwiLCBtZXNzYWdlfSlcbn1cbiJdfQ==