semantifold 0.4.0 → 0.6.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 (203) hide show
  1. package/README.md +13 -7
  2. package/build/index.d.ts +12 -8
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +10 -7
  5. package/build/src/backends/android.d.ts +49 -0
  6. package/build/src/backends/android.d.ts.map +1 -0
  7. package/build/src/backends/android.js +1278 -0
  8. package/build/src/backends/identifiers.d.ts +6 -0
  9. package/build/src/backends/identifiers.d.ts.map +1 -1
  10. package/build/src/backends/identifiers.js +30 -1
  11. package/build/src/backends/ios.js +2 -2
  12. package/build/src/backends/kotlin.d.ts +10 -0
  13. package/build/src/backends/kotlin.d.ts.map +1 -1
  14. package/build/src/backends/kotlin.js +11 -9
  15. package/build/src/backends/native-validation.d.ts +2 -2
  16. package/build/src/backends/native-validation.d.ts.map +1 -1
  17. package/build/src/backends/native-validation.js +2 -2
  18. package/build/src/backends/program.d.ts +6 -4
  19. package/build/src/backends/program.d.ts.map +1 -1
  20. package/build/src/backends/program.js +5 -4
  21. package/build/src/backends/scalars.d.ts.map +1 -1
  22. package/build/src/backends/scalars.js +2 -1
  23. package/build/src/backends/shared.d.ts.map +1 -1
  24. package/build/src/backends/shared.js +20 -4
  25. package/build/src/backends/writer.d.ts +21 -1
  26. package/build/src/backends/writer.d.ts.map +1 -1
  27. package/build/src/backends/writer.js +25 -2
  28. package/build/src/backends/zig-runtime.d.ts +5 -0
  29. package/build/src/backends/zig-runtime.d.ts.map +1 -0
  30. package/build/src/backends/zig-runtime.js +92 -0
  31. package/build/src/backends/zig-validation.d.ts +9 -0
  32. package/build/src/backends/zig-validation.d.ts.map +1 -0
  33. package/build/src/backends/zig-validation.js +73 -0
  34. package/build/src/backends/zig.d.ts +42 -0
  35. package/build/src/backends/zig.d.ts.map +1 -0
  36. package/build/src/backends/zig.js +584 -0
  37. package/build/src/frontends/scalars.d.ts.map +1 -1
  38. package/build/src/frontends/scalars.js +2 -1
  39. package/build/src/frontends/zig-parser.d.ts +31 -0
  40. package/build/src/frontends/zig-parser.d.ts.map +1 -0
  41. package/build/src/frontends/zig-parser.js +17 -0
  42. package/build/src/frontends/zig.d.ts +14 -0
  43. package/build/src/frontends/zig.d.ts.map +1 -0
  44. package/build/src/frontends/zig.js +970 -0
  45. package/build/src/language-registry.d.ts.map +1 -1
  46. package/build/src/language-registry.js +40 -1
  47. package/build/src/mapping.js +2 -2
  48. package/build/src/semantic/provenance.js +3 -3
  49. package/build/src/semantic/types.d.ts +184 -4
  50. package/build/src/semantic/types.d.ts.map +1 -1
  51. package/build/src/semantic/types.js +45 -3
  52. package/build/src/semantic/validate.js +2 -2
  53. package/build/src/toolchains.d.ts +6 -0
  54. package/build/src/toolchains.d.ts.map +1 -1
  55. package/build/src/toolchains.js +2 -1
  56. package/build/src/zig-bindings.d.ts +10 -0
  57. package/build/src/zig-bindings.d.ts.map +1 -0
  58. package/build/src/zig-bindings.js +54 -0
  59. package/docs/android.md +79 -0
  60. package/docs/architecture.md +13 -5
  61. package/docs/goals.md +1 -1
  62. package/docs/ios.md +1 -1
  63. package/docs/language-support.md +15 -4
  64. package/docs/parser-qualification.md +31 -1
  65. package/docs/source-maps.md +7 -3
  66. package/docs/specification.md +5 -0
  67. package/docs/testing.md +40 -3
  68. package/docs/zig.md +33 -0
  69. package/index.js +9 -6
  70. package/node_modules/semantifold-tree-sitter-zig-internal/LICENSE +15 -0
  71. package/node_modules/semantifold-tree-sitter-zig-internal/README.md +5 -0
  72. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/LICENSE +21 -0
  73. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/README.md +21 -0
  74. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/binding.gyp +29 -0
  75. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/bindings/node/binding.cc +20 -0
  76. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/bindings/node/binding_test.js +9 -0
  77. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/bindings/node/index.d.ts +28 -0
  78. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/bindings/node/index.js +11 -0
  79. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/grammar.js +900 -0
  80. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/package.json +57 -0
  81. 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
  82. 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
  83. 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
  84. 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
  85. 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
  86. 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
  87. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/queries/folds.scm +23 -0
  88. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/queries/highlights.scm +291 -0
  89. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/queries/indents.scm +22 -0
  90. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/queries/injections.scm +10 -0
  91. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/grammar.json +6570 -0
  92. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/node-types.json +3178 -0
  93. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/parser.c +169829 -0
  94. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/tree_sitter/alloc.h +54 -0
  95. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/tree_sitter/array.h +291 -0
  96. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/src/tree_sitter/parser.h +266 -0
  97. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/tree-sitter-zig.wasm +0 -0
  98. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/@tree-sitter-grammars/tree-sitter-zig/tree-sitter.json +38 -0
  99. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/LICENSE +21 -0
  100. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/README.md +128 -0
  101. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/binding.gyp +80 -0
  102. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/index.js +916 -0
  103. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/package.json +76 -0
  104. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
  105. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
  106. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/linux-arm64/tree-sitter.node +0 -0
  107. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
  108. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/win32-arm64/tree-sitter.node +0 -0
  109. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
  110. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/addon_data.h +47 -0
  111. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/binding.cc +35 -0
  112. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/conversions.cc +140 -0
  113. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/conversions.h +22 -0
  114. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/language.cc +106 -0
  115. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/language.h +17 -0
  116. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/logger.cc +70 -0
  117. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/logger.h +19 -0
  118. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
  119. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
  120. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/node.cc +1088 -0
  121. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/node.h +30 -0
  122. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/parser.cc +306 -0
  123. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/parser.h +35 -0
  124. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/query.cc +397 -0
  125. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/query.h +40 -0
  126. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/tree.cc +316 -0
  127. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/tree.h +45 -0
  128. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
  129. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/src/tree_cursor.h +52 -0
  130. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/tree-sitter.d.ts +1042 -0
  131. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1318 -0
  132. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
  133. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
  134. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +291 -0
  135. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
  136. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
  137. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
  138. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +501 -0
  139. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
  140. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
  141. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +223 -0
  142. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +297 -0
  143. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
  144. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +435 -0
  145. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +49 -0
  146. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +12 -0
  147. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +920 -0
  148. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2165 -0
  149. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +266 -0
  150. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +62 -0
  151. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/portable/endian.h +206 -0
  152. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4187 -0
  153. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
  154. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
  155. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +899 -0
  156. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +130 -0
  157. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1066 -0
  158. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +399 -0
  159. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +170 -0
  160. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
  161. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +712 -0
  162. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
  163. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/ts_assert.h +11 -0
  164. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
  165. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
  166. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
  167. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
  168. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
  169. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
  170. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
  171. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
  172. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
  173. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +83 -0
  174. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +24 -0
  175. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +109 -0
  176. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1302 -0
  177. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1859 -0
  178. package/node_modules/semantifold-tree-sitter-zig-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
  179. package/node_modules/semantifold-tree-sitter-zig-internal/package.json +21 -0
  180. package/node_modules/semantifold-tree-sitter-zig-internal/src/zig.js +134 -0
  181. package/package.json +11 -6
  182. package/src/backends/android.js +1374 -0
  183. package/src/backends/identifiers.js +30 -0
  184. package/src/backends/ios.js +1 -1
  185. package/src/backends/kotlin.js +11 -8
  186. package/src/backends/native-validation.js +1 -1
  187. package/src/backends/program.js +4 -3
  188. package/src/backends/scalars.js +1 -0
  189. package/src/backends/shared.js +22 -3
  190. package/src/backends/writer.js +27 -2
  191. package/src/backends/zig-runtime.js +93 -0
  192. package/src/backends/zig-validation.js +68 -0
  193. package/src/backends/zig.js +579 -0
  194. package/src/frontends/scalars.js +1 -0
  195. package/src/frontends/zig-parser.js +20 -0
  196. package/src/frontends/zig.js +994 -0
  197. package/src/language-registry.js +40 -0
  198. package/src/mapping.js +1 -1
  199. package/src/semantic/provenance.js +2 -2
  200. package/src/semantic/types.js +47 -2
  201. package/src/semantic/validate.js +1 -1
  202. package/src/toolchains.js +1 -0
  203. package/src/zig-bindings.js +46 -0
@@ -0,0 +1,1278 @@
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 { preflightSemanticProgram } from "./program.js";
10
+ import { emitScalarType } from "./scalars.js";
11
+ import { kotlinRuntime } from "./kotlin-runtime.js";
12
+ import { emitKotlinBlock } from "./kotlin.js";
13
+ import { SourceWriter } from "./writer.js";
14
+ const projectRoot = "generated/android-app";
15
+ const generatorVersion = "0.4.0";
16
+ /** @type {Readonly<Set<import("../semantic/types.js").SemanticLanguage>>} */
17
+ const androidSourceLanguages = new Set([
18
+ "php", "ruby", "javascript", "typescript", "java", "kotlin", "python", "csharp", "go", "c", "cpp", "rust", "swift", "dart", "zig"
19
+ ]);
20
+ const requestFields = new Set(["assets", "configuration", "language", "module", "program", "resources", "role"]);
21
+ const configurationFields = new Set([
22
+ "activityClassName", "applicationId", "buildToolsVersion", "compileSdk", "displayName", "minimumSdk", "namespace",
23
+ "orientation", "packageName", "permissions", "productName", "targetSdk", "theme", "versionCode", "versionName"
24
+ ]);
25
+ const resourceFields = new Set(["content", "mediaType", "path", "sha256"]);
26
+ const kotlinKeywords = new Set([
27
+ "as", "break", "class", "continue", "do", "else", "false", "for", "fun", "if", "in", "interface", "is", "null",
28
+ "object", "package", "return", "super", "this", "throw", "true", "try", "typealias", "typeof", "val", "var", "when", "while"
29
+ ]);
30
+ const androidScaffoldSymbols = new Set([
31
+ "Activity", "Base64", "Bundle", "IllegalStateException", "Instrumentation", "Intent", "R", "SemantifoldEntryTest",
32
+ "SemantifoldUiInstrumentation", "StandardCharsets", "String", "SuppressLint", "Test", "TextView", "Throwable", "View"
33
+ ]);
34
+ const mediaTypePattern = /^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+(?:;[\u0020-\u007e]+)?$/u;
35
+ 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;
36
+ const toolchain = Object.freeze({
37
+ androidGradlePlugin: "8.11.1",
38
+ archives: {
39
+ buildTools: {
40
+ revision: "35.0.0",
41
+ sha256: "bd3a4966912eb8b30ed0d00b0cda6b6543b949d5ffe00bea54c04c81e1561d88",
42
+ url: "https://dl.google.com/android/repository/build-tools_r35_linux.zip"
43
+ },
44
+ commandLineTools: {
45
+ revision: "11076708",
46
+ sha256: "2d2d50857e4eb553af5a6dc3ad507a17adf43d115264b1afc116f95c92e5e258",
47
+ url: "https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip"
48
+ },
49
+ emulator: {
50
+ buildId: "13610412",
51
+ revision: "35.6.11",
52
+ sha256: "2fe2b56fe93ce75e1d478a40162131381d911c355efeaedb54dd1e0d0897a5cf",
53
+ url: "https://edgedl.me.gvt1.com/edgedl/android/repository/emulator-linux_x64-13610412.zip"
54
+ },
55
+ platform: {
56
+ revision: "35-r2",
57
+ sha256: "0988cacad01b38a18a47bac14a0695f246bc76c1b06c0eeb8eb0dc825ab0c8e0",
58
+ url: "https://dl.google.com/android/repository/platform-35_r02.zip"
59
+ },
60
+ platformTools: {
61
+ revision: "37.0.1",
62
+ sha256: "d230f13842f60f782a8645f9c813f8f845bf36089ea7289f28c48f17979313f1",
63
+ url: "https://dl.google.com/android/repository/platform-tools_r37.0.1-linux.zip"
64
+ },
65
+ systemImage: {
66
+ revision: "35-google_apis-x86_64-r9",
67
+ sha256: "c67b9ba0ff5bc0eb6d046871bfa228af14d4d47b02f0cdae94f048e511b7566e",
68
+ url: "https://dl.google.com/android/repository/sys-img/google_apis/x86_64-35_r09.zip"
69
+ }
70
+ },
71
+ buildTools: "35.0.0",
72
+ commandLineTools: "11076708",
73
+ compileSdk: 35,
74
+ emulator: "35.6.11",
75
+ gradle: "8.13",
76
+ java: "21.0.8",
77
+ kotlin: "2.2.10",
78
+ kotlinCompilerSha256: "302d1d8e671e5c3207e6ed62ff11fb555462a628e22a1158254dcaaf7e7394bc",
79
+ systemImage: "system-images;android-35;google_apis;x86_64",
80
+ targetSdk: 35
81
+ });
82
+ const excludedPathPatterns = Object.freeze([".gradle/**", "**/build/**", "local.properties"]);
83
+ const androidKotlinRuntime = `@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
84
+
85
+ package __PACKAGE__.semantic
86
+
87
+ ${kotlinRuntime.replaceAll("private ", "internal ")}
88
+ internal class SemantifoldOutputSink {
89
+ private val values: java.util.ArrayList<String> = java.util.ArrayList<String>()
90
+
91
+ fun reset() {
92
+ values.clear()
93
+ }
94
+
95
+ fun write(value: Long) {
96
+ values.add(value.toString())
97
+ }
98
+
99
+ fun write(value: Boolean) {
100
+ values.add(if (value) "true" else "false")
101
+ }
102
+
103
+ fun write(value: String) {
104
+ values.add(value)
105
+ }
106
+
107
+ fun snapshot(): java.util.ArrayList<String> = java.util.ArrayList<String>(values)
108
+ }
109
+ `;
110
+ /** @typedef {{content: string | Uint8Array, contentKind: "binary" | "text", fullPath: string, mediaType: string, path: string, sha256: string}} AndroidInputFile */
111
+ /** @typedef {{end: number, field: string, path: string, start: number}} ConfigurationSpan */
112
+ /**
113
+ * Preflights a complete Android application request before allocating a source writer.
114
+ * @param {Record<string, unknown>} input - Candidate application request.
115
+ * @returns {{assets: AndroidInputFile[], configuration: import("../semantic/types.js").AndroidApplicationConfiguration, modulePaths: Map<string, string>, modules: import("../semantic/types.js").SemanticModule[], packagePath: string, program: import("../semantic/types.js").SemanticProgram, resources: AndroidInputFile[], sources: {content: string, filename: string, language?: import("../semantic/types.js").SemanticLanguage}[]}} Prepared application.
116
+ */
117
+ export function preflightAndroidApplication(input) {
118
+ if (!isPlainObject(input) || Object.keys(input).some(key => !requestFields.has(key)) ||
119
+ Boolean(input.module) == Boolean(input.program)) {
120
+ invalidInput("Android application generation requires a closed request with exactly one semantic module or program.");
121
+ }
122
+ if (input.language !== undefined && input.language != "android" || input.role !== undefined && input.role != "application") {
123
+ invalidInput("Android application generation accepts only the Android application role.");
124
+ }
125
+ const configuration = normalizeConfiguration(input.configuration);
126
+ const program = input.program ?? normalizeSingleModule(
127
+ /** @type {import("../semantic/types.js").SemanticModule | undefined} */ (input.module));
128
+ const prepared = preflightSemanticProgram({
129
+ backendLanguage: "kotlin",
130
+ diagnosticLanguage: "android",
131
+ program: /** @type {import("../semantic/types.js").SemanticProgram} */ (program),
132
+ sourceLanguages: androidSourceLanguages
133
+ });
134
+ validateActivityClassName(configuration.activityClassName, prepared.program.entryModule);
135
+ const packagePath = configuration.packageName.replaceAll(".", "/");
136
+ const semanticRoot = `${projectRoot}/app/src/main/kotlin/${packagePath}/semantic`;
137
+ const modulePaths = new Map(prepared.modules.map(module => [
138
+ /** @type {string} */ (Reflect.get(module, "id")),
139
+ `${semanticRoot}/${moduleName(/** @type {string} */ (Reflect.get(module, "id")))}.kt`
140
+ ]));
141
+ const resources = normalizeInputFiles(input.resources, "resource");
142
+ const assets = normalizeInputFiles(input.assets, "asset");
143
+ const fixedPaths = applicationPaths(configuration, modulePaths);
144
+ const completePaths = [
145
+ ...fixedPaths,
146
+ ...resources.map(({ fullPath }) => fullPath),
147
+ ...assets.map(({ fullPath }) => fullPath)
148
+ ];
149
+ const conflict = findPortableArtifactPathConflict(completePaths);
150
+ if (conflict) {
151
+ invalidPath(`Application artifact path '${conflict.path}' has a ${conflict.kind} conflict${conflict.other ? ` with '${conflict.other}'` : ""}.`);
152
+ }
153
+ return { ...prepared, assets, configuration, modulePaths, packagePath, resources };
154
+ }
155
+ /**
156
+ * Generates one complete deterministic Android/Kotlin project.
157
+ * @param {Record<string, unknown>} input - Application generation request.
158
+ * @returns {{artifacts: import("../semantic/types.js").GeneratedSetArtifact[], metadata: {applicationManifest: string, platformQualification: string}, target: "android"}} Candidate artifact set.
159
+ */
160
+ export function generateAndroidApplication(input) {
161
+ const prepared = preflightAndroidApplication(input);
162
+ const configurationSpans = /** @type {ConfigurationSpan[]} */ ([]);
163
+ const configuration = prepared.configuration;
164
+ const packagePath = prepared.packagePath;
165
+ const semanticArtifacts = renderSemanticArtifacts(prepared);
166
+ const artifacts = /** @type {import("../semantic/types.js").GeneratedSetArtifact[]} */ ([
167
+ configuredText(`${projectRoot}/app/build.gradle.kts`, "manifest", renderAppBuild(configuration, configurationSpans), "Pinned dependency-minimal Android application build."),
168
+ configuredText(`${projectRoot}/app/src/androidTest/AndroidManifest.xml`, "manifest", renderAndroidTestManifest(configuration, configurationSpans), "Platform-only Android instrumentation declaration."),
169
+ configuredText(`${projectRoot}/app/src/androidTest/kotlin/${packagePath}/SemantifoldUiInstrumentation.kt`, "support", renderInstrumentation(configuration, configurationSpans), "Platform-only accessibility and lifecycle assertion."),
170
+ configuredText(`${projectRoot}/app/src/main/AndroidManifest.xml`, "manifest", renderAndroidManifest(configuration, configurationSpans), "Closed allowlisted Android application manifest."),
171
+ configuredText(`${projectRoot}/app/src/main/kotlin/${packagePath}/${configuration.activityClassName}.kt`, "entry", renderActivity(configuration, prepared.program.entryModule, configurationSpans), "Synthetic Android activity lifecycle and native output view binding."),
172
+ ...semanticArtifacts,
173
+ syntheticText(`${projectRoot}/app/src/main/res/layout/activity_main.xml`, "resource", renderLayout(), "Synthetic one-view Android layout and accessibility identity."),
174
+ configuredText(`${projectRoot}/app/src/main/res/values/strings.xml`, "resource", renderStrings(configuration, configurationSpans), "Escaped application labels derived from configuration."),
175
+ syntheticText(`${projectRoot}/app/src/main/res/values/themes.xml`, "resource", renderTheme(), "Closed platform-native application theme."),
176
+ syntheticText(`${projectRoot}/app/src/main/res/xml/backup_rules.xml`, "resource", renderBackupRules(), "Closed API 23-30 full-backup exclusions."),
177
+ syntheticText(`${projectRoot}/app/src/main/res/xml/data_extraction_rules.xml`, "resource", renderDataExtractionRules(), "Closed Android 12+ cloud-backup and device-transfer exclusions."),
178
+ configuredText(`${projectRoot}/app/src/test/kotlin/${packagePath}/SemantifoldEntryTest.kt`, "support", renderUnitTest(configuration, prepared.program.entryModule, configurationSpans), "JUnit test-scope-only semantic determinism assertion."),
179
+ syntheticText(`${projectRoot}/build.gradle.kts`, "manifest", renderRootBuild(), "Pinned Android and Kotlin build plugins."),
180
+ syntheticText(`${projectRoot}/gradle.properties`, "support", renderGradleProperties(), "Pinned hermetic Gradle process properties."),
181
+ configuredText(`${projectRoot}/settings.gradle.kts`, "manifest", renderSettings(configuration, configurationSpans), "Closed official Gradle plugin and dependency repositories."),
182
+ ...prepared.resources.map(inputFileArtifact),
183
+ ...prepared.assets.map(inputFileArtifact)
184
+ ]);
185
+ artifacts.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
186
+ const manifestPath = `${projectRoot}/semantifold-project.json`;
187
+ artifacts.push(syntheticText(manifestPath, "manifest", renderProjectManifest(prepared, artifacts, manifestPath, configurationSpans), "Versioned Android project ownership, toolchain, and provenance manifest."));
188
+ return {
189
+ artifacts,
190
+ metadata: { applicationManifest: manifestPath, platformQualification: "tensorbuzz-kvm" },
191
+ target: "android"
192
+ };
193
+ }
194
+ /**
195
+ * Renders the mapped semantic Kotlin artifacts for every program module.
196
+ * @param {ReturnType<typeof preflightAndroidApplication>} prepared - Prepared application.
197
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact[]} Semantic Kotlin artifacts.
198
+ */
199
+ function renderSemanticArtifacts(prepared) {
200
+ const semanticRoot = `${projectRoot}/app/src/main/kotlin/${prepared.packagePath}/semantic`;
201
+ /** @type {import("../semantic/types.js").GeneratedSetArtifact[]} */
202
+ const artifacts = [syntheticText(`${semanticRoot}/SemantifoldRuntime.kt`, "support", androidKotlinRuntime.replaceAll("__PACKAGE__", prepared.configuration.packageName), "Shared Android application output capture and checked Kotlin scalar support.")];
203
+ const declarations = new Map();
204
+ for (const module of prepared.modules) {
205
+ for (const declaration of module.functions)
206
+ declarations.set(declaration.id, {
207
+ declaration,
208
+ moduleId: /** @type {string} */ (Reflect.get(module, "id"))
209
+ });
210
+ }
211
+ for (const module of prepared.modules) {
212
+ const moduleId = /** @type {string} */ (Reflect.get(module, "id"));
213
+ const filename = /** @type {string} */ (prepared.modulePaths.get(moduleId));
214
+ const sinkName = outputSinkName(module);
215
+ const writer = new SourceWriter({
216
+ callArgumentSuffix: sinkName,
217
+ callNameResolver: expression => {
218
+ const resolved = declarations.get(expression.resolution?.declarationId);
219
+ if (!resolved)
220
+ throw new TypeError(`Unknown validated Android function '${expression.resolution?.declarationId}'.`);
221
+ return `SemantifoldModule${moduleName(resolved.moduleId)}.${resolved.declaration.name}`;
222
+ },
223
+ filename,
224
+ language: "kotlin",
225
+ methodStringEquality: true,
226
+ module,
227
+ program: prepared.program,
228
+ programPaths: prepared.modulePaths,
229
+ sources: prepared.sources
230
+ });
231
+ writer.synthetic(`@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")\n\npackage ${prepared.configuration.packageName}.semantic\n\n`, "Android semantic package namespace", [module], [""]);
232
+ emitSemanticModule(writer, module, moduleId, moduleId == prepared.program.entryModule, sinkName);
233
+ const mapping = finalizeMapping(writer.finish());
234
+ artifacts.push({
235
+ content: mapping.generated.content,
236
+ contentKind: "text",
237
+ mediaType: "text/x-kotlin",
238
+ ownership: "generated",
239
+ path: filename,
240
+ provenance: { kind: "text", mapping, sourceMap: toSourceMapV3(mapping), sourceMapFilename: `${filename}.map` },
241
+ role: "source"
242
+ });
243
+ }
244
+ return artifacts;
245
+ }
246
+ /**
247
+ * Emits one namespaced semantic module and its entry bridge when applicable.
248
+ * @param {SourceWriter} writer - Mapped Kotlin writer.
249
+ * @param {import("../semantic/types.js").SemanticModule} module - Prepared module.
250
+ * @param {string} moduleId - Stable module identity.
251
+ * @param {boolean} entry - Whether this module owns the entry block.
252
+ * @param {string} sinkName - Collision-safe output sink binding.
253
+ */
254
+ function emitSemanticModule(writer, module, moduleId, entry, sinkName) {
255
+ writer.synthetic(`internal object SemantifoldModule${moduleName(moduleId)} {\n`, "Android semantic module namespace", [module], [""]);
256
+ module.functions.forEach((declaration, functionIndex) => {
257
+ const path = `/functions/${functionIndex}`;
258
+ writer.synthetic(" ", "Android namespaced function indentation", [declaration], [path]);
259
+ writer.mapped("fun", { mappingKind: "anchor", node: declaration, path });
260
+ writer.synthetic(" ", "declaration spacing", [declaration], [path]);
261
+ writer.mapped(declaration.name, { mappingKind: "exact", node: declaration, path, role: "name" });
262
+ writer.synthetic("(", "function parameter scaffold", [declaration], [path]);
263
+ declaration.parameters.forEach((parameter, parameterIndex) => {
264
+ const parameterPath = `${path}/parameters/${parameterIndex}`;
265
+ if (parameterIndex)
266
+ writer.synthetic(", ", "parameter separator", [parameter], [parameterPath]);
267
+ writer.mapped(parameter.name, { mappingKind: "exact", node: parameter, path: parameterPath, role: "name" });
268
+ writer.synthetic(": ", "parameter annotation scaffold", [parameter], [parameterPath]);
269
+ writer.mapped(emitScalarType("kotlin", parameter.type), { mappingKind: "exact", node: parameter.type,
270
+ path: `${parameterPath}/type`, role: "type" });
271
+ });
272
+ if (declaration.parameters.length)
273
+ writer.synthetic(", ", "output sink parameter separator", [declaration], [path]);
274
+ writer.synthetic(`${sinkName}: SemantifoldOutputSink): `, "shared Android output sink parameter", [declaration], [path]);
275
+ writer.mapped(emitScalarType("kotlin", declaration.returnType), { mappingKind: "exact", node: declaration.returnType,
276
+ path: `${path}/returnType`, role: "type" });
277
+ writer.synthetic(" {\n", "Kotlin function body scaffold", [declaration], [path]);
278
+ emitKotlinBlock(writer, declaration.body, " ", `${path}/body`, `${sinkName}.write`);
279
+ writer.synthetic(" }\n", "Kotlin function body scaffold", [declaration], [path]);
280
+ });
281
+ if (entry) {
282
+ writer.synthetic(" fun semantifoldEntry(): java.util.ArrayList<String> {\n", "Android semantic entry scaffold", [module.entryPoint], ["/entryPoint"]);
283
+ writer.synthetic(` val ${sinkName} = SemantifoldOutputSink()\n`, "Android output sink allocation", [module.entryPoint], ["/entryPoint"]);
284
+ writer.synthetic(` ${sinkName}.reset()\n`, "Android lifecycle-safe output reset", [module.entryPoint], ["/entryPoint"]);
285
+ emitKotlinBlock(writer, module.entryPoint.body, " ", "/entryPoint/body", `${sinkName}.write`);
286
+ writer.synthetic(` return ${sinkName}.snapshot()\n`, "Android semantic output return", [module.entryPoint], ["/entryPoint"]);
287
+ writer.synthetic(" }\n", "Android semantic entry scaffold", [module.entryPoint], ["/entryPoint"]);
288
+ }
289
+ writer.synthetic("}\n", "Android semantic module namespace", [module], [""]);
290
+ }
291
+ /**
292
+ * Lists every fixed generated path before any writer is allocated.
293
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized application configuration.
294
+ * @param {Map<string, string>} modulePaths - Semantic module output paths.
295
+ * @returns {string[]} Fixed owned artifact paths.
296
+ */
297
+ function applicationPaths(configuration, modulePaths) {
298
+ const packagePath = configuration.packageName.replaceAll(".", "/");
299
+ return [
300
+ `${projectRoot}/app/build.gradle.kts`,
301
+ `${projectRoot}/app/src/androidTest/AndroidManifest.xml`,
302
+ `${projectRoot}/app/src/androidTest/kotlin/${packagePath}/SemantifoldUiInstrumentation.kt`,
303
+ `${projectRoot}/app/src/main/AndroidManifest.xml`,
304
+ `${projectRoot}/app/src/main/kotlin/${packagePath}/${configuration.activityClassName}.kt`,
305
+ ...modulePaths.values(),
306
+ `${projectRoot}/app/src/main/kotlin/${packagePath}/semantic/SemantifoldRuntime.kt`,
307
+ `${projectRoot}/app/src/main/res/layout/activity_main.xml`,
308
+ `${projectRoot}/app/src/main/res/values/strings.xml`,
309
+ `${projectRoot}/app/src/main/res/values/themes.xml`,
310
+ `${projectRoot}/app/src/main/res/xml/backup_rules.xml`,
311
+ `${projectRoot}/app/src/main/res/xml/data_extraction_rules.xml`,
312
+ `${projectRoot}/app/src/test/kotlin/${packagePath}/SemantifoldEntryTest.kt`,
313
+ `${projectRoot}/build.gradle.kts`,
314
+ `${projectRoot}/gradle.properties`,
315
+ `${projectRoot}/settings.gradle.kts`,
316
+ `${projectRoot}/semantifold-project.json`
317
+ ];
318
+ }
319
+ /**
320
+ * Renders the pinned root plugin declarations.
321
+ * @returns {string} Root Gradle Kotlin script.
322
+ */
323
+ function renderRootBuild() {
324
+ return `plugins {
325
+ id("com.android.application") version "${toolchain.androidGradlePlugin}" apply false
326
+ id("org.jetbrains.kotlin.android") version "${toolchain.kotlin}" apply false
327
+ }
328
+ `;
329
+ }
330
+ /**
331
+ * Renders closed project settings and repositories.
332
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized configuration.
333
+ * @param {ConfigurationSpan[]} spans - Collected configuration provenance spans.
334
+ * @returns {string} Settings Gradle Kotlin script.
335
+ */
336
+ function renderSettings(configuration, spans) {
337
+ return configured(`${projectRoot}/settings.gradle.kts`, spans, [`pluginManagement {
338
+ repositories {
339
+ google()
340
+ mavenCentral()
341
+ gradlePluginPortal()
342
+ }
343
+ }
344
+
345
+ dependencyResolutionManagement {
346
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
347
+ repositories {
348
+ google()
349
+ mavenCentral()
350
+ }
351
+ }
352
+
353
+ rootProject.name = "`, field("productName", kotlinEscape(configuration.productName)), `"
354
+ include(":app")
355
+ `]);
356
+ }
357
+ /**
358
+ * Renders deterministic Gradle process properties.
359
+ * @returns {string} Gradle properties file.
360
+ */
361
+ function renderGradleProperties() {
362
+ return `org.gradle.caching=false
363
+ org.gradle.configuration-cache=false
364
+ org.gradle.daemon=false
365
+ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -Duser.language=en -Duser.country=US -Duser.timezone=UTC
366
+ org.gradle.parallel=false
367
+ kotlin.stdlib.default.dependency=false
368
+ kotlin.code.style=official
369
+ `;
370
+ }
371
+ /**
372
+ * Renders the application module build contract.
373
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized configuration.
374
+ * @param {ConfigurationSpan[]} spans - Collected configuration provenance spans.
375
+ * @returns {string} Application Gradle Kotlin script.
376
+ */
377
+ function renderAppBuild(configuration, spans) {
378
+ return configured(`${projectRoot}/app/build.gradle.kts`, spans, [
379
+ `import org.jetbrains.kotlin.gradle.dsl.JvmTarget
380
+ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
381
+
382
+ plugins {
383
+ id("com.android.application")
384
+ id("org.jetbrains.kotlin.android")
385
+ }
386
+
387
+ dependencies {
388
+ testRuntimeOnly("org.hamcrest:hamcrest-core:1.3") {
389
+ isTransitive = false
390
+ }
391
+ }
392
+
393
+ val semantifoldKotlinHome = providers.environmentVariable("SEMANTIFOLD_KOTLIN_HOME").orNull
394
+ ?: throw GradleException("SEMANTIFOLD_ANDROID_INFRASTRUCTURE: SEMANTIFOLD_KOTLIN_HOME is required")
395
+ val semantifoldKotlinStdlib = file("$semantifoldKotlinHome/lib/kotlin-stdlib.jar")
396
+ if (!semantifoldKotlinStdlib.isFile) {
397
+ throw GradleException("SEMANTIFOLD_ANDROID_INFRASTRUCTURE: pinned Kotlin stdlib is missing")
398
+ }
399
+
400
+ dependencies {
401
+ androidTestImplementation(files(semantifoldKotlinStdlib))
402
+ }
403
+ val semantifoldAcceptanceRoot = providers.environmentVariable("SEMANTIFOLD_ANDROID_ACCEPTANCE_ROOT").orNull
404
+ ?: throw GradleException("SEMANTIFOLD_ANDROID_INFRASTRUCTURE: SEMANTIFOLD_ANDROID_ACCEPTANCE_ROOT is required")
405
+ val semantifoldDebugKeystore = file("$semantifoldAcceptanceRoot/debug.keystore")
406
+ if (!semantifoldDebugKeystore.isFile) {
407
+ throw GradleException("SEMANTIFOLD_ANDROID_INFRASTRUCTURE: ephemeral debug keystore is missing")
408
+ }
409
+
410
+ android {
411
+ namespace = "`,
412
+ field("namespace", configuration.namespace), `"\n compileSdk = `, field("compileSdk", String(configuration.compileSdk)),
413
+ `\n buildToolsVersion = "`, field("buildToolsVersion", configuration.buildToolsVersion), `"\n\n defaultConfig {\n applicationId = "`,
414
+ field("applicationId", configuration.applicationId), `"\n minSdk = `, field("minimumSdk", String(configuration.minimumSdk)),
415
+ `\n targetSdk = `, field("targetSdk", String(configuration.targetSdk)), `\n versionCode = `,
416
+ field("versionCode", String(configuration.versionCode)), `\n versionName = "`, field("versionName", kotlinEscape(configuration.versionName)),
417
+ `"\n testApplicationId = "`, field("applicationId", configuration.applicationId),
418
+ `.test"\n testInstrumentationRunner = "`, field("packageName", configuration.packageName),
419
+ `.SemantifoldUiInstrumentation"\n }\n\n signingConfigs {\n getByName("debug") {\n storeFile = semantifoldDebugKeystore\n storePassword = "android"\n keyAlias = "androiddebugkey"\n keyPassword = "android"\n }\n }\n buildTypes {\n getByName("debug") {\n signingConfig = signingConfigs.getByName("debug")\n }\n }\n buildFeatures {\n buildConfig = false\n }\n compileOptions {\n sourceCompatibility = JavaVersion.VERSION_21\n targetCompatibility = JavaVersion.VERSION_21\n }\n lint {\n abortOnError = true\n checkDependencies = true\n disable += "MissingApplicationIcon"\n disable += "OldTargetApi"\n disable += "GradleDependency"\n warningsAsErrors = true\n }\n packaging {\n resources.excludes += setOf("META-INF/LICENSE*", "META-INF/NOTICE*")\n }\n}\n\ntasks.withType<KotlinJvmCompile>().configureEach {\n libraries.from(files(semantifoldKotlinStdlib))\n compilerOptions {\n allWarningsAsErrors.set(true)\n freeCompilerArgs.addAll("-Xno-call-assertions", "-Xno-param-assertions", "-Xno-receiver-assertions")\n jvmTarget.set(JvmTarget.JVM_21)\n }\n}\n\ndependencies {\n testImplementation("junit:junit:4.13.2") {\n isTransitive = false\n }\n}\n`
420
+ ]);
421
+ }
422
+ /**
423
+ * Renders the allowlisted Android application manifest.
424
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized configuration.
425
+ * @param {ConfigurationSpan[]} spans - Collected configuration provenance spans.
426
+ * @returns {string} Android application manifest.
427
+ */
428
+ function renderAndroidManifest(configuration, spans) {
429
+ const orientation = configuration.orientation == "unspecified" ? "" : ` android:screenOrientation="${configuration.orientation}"`;
430
+ return configured(`${projectRoot}/app/src/main/AndroidManifest.xml`, spans, [
431
+ `<?xml version="1.0" encoding="utf-8"?>\n<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n <application\n android:allowBackup="false"\n android:dataExtractionRules="@xml/data_extraction_rules"\n android:fullBackupContent="@xml/backup_rules"\n android:label="@string/app_name"\n android:supportsRtl="true"\n android:theme="@style/Theme.Semantifold">\n <activity\n android:name="`,
432
+ field("packageName", configuration.packageName), `.`, field("activityClassName", configuration.activityClassName),
433
+ `"\n android:exported="true"`,
434
+ orientation ? field("orientation", orientation) : "", `>\n <intent-filter>\n <action android:name="android.intent.action.MAIN" />\n <category android:name="android.intent.category.LAUNCHER" />\n </intent-filter>\n </activity>\n </application>\n</manifest>\n`
435
+ ]);
436
+ }
437
+ /**
438
+ * Renders explicit API 23-30 exclusions for every full-backup storage domain.
439
+ * @returns {string} Android full-backup rules XML.
440
+ */
441
+ function renderBackupRules() {
442
+ return `<?xml version="1.0" encoding="utf-8"?>
443
+ <full-backup-content>
444
+ <exclude domain="root" path="." />
445
+ <exclude domain="file" path="." />
446
+ <exclude domain="database" path="." />
447
+ <exclude domain="sharedpref" path="." />
448
+ <exclude domain="external" path="." />
449
+ <exclude domain="device_root" path="." />
450
+ <exclude domain="device_file" path="." />
451
+ <exclude domain="device_database" path="." />
452
+ <exclude domain="device_sharedpref" path="." />
453
+ </full-backup-content>
454
+ `;
455
+ }
456
+ /**
457
+ * Renders explicit Android 12+ exclusions for every cloud-backup and device-transfer storage domain.
458
+ * @returns {string} Android data extraction rules XML.
459
+ */
460
+ function renderDataExtractionRules() {
461
+ return `<?xml version="1.0" encoding="utf-8"?>
462
+ <data-extraction-rules>
463
+ <cloud-backup>
464
+ <exclude domain="root" path="." />
465
+ <exclude domain="file" path="." />
466
+ <exclude domain="database" path="." />
467
+ <exclude domain="sharedpref" path="." />
468
+ <exclude domain="external" path="." />
469
+ <exclude domain="device_root" path="." />
470
+ <exclude domain="device_file" path="." />
471
+ <exclude domain="device_database" path="." />
472
+ <exclude domain="device_sharedpref" path="." />
473
+ </cloud-backup>
474
+ <device-transfer>
475
+ <exclude domain="root" path="." />
476
+ <exclude domain="file" path="." />
477
+ <exclude domain="database" path="." />
478
+ <exclude domain="sharedpref" path="." />
479
+ <exclude domain="external" path="." />
480
+ <exclude domain="device_root" path="." />
481
+ <exclude domain="device_file" path="." />
482
+ <exclude domain="device_database" path="." />
483
+ <exclude domain="device_sharedpref" path="." />
484
+ </device-transfer>
485
+ </data-extraction-rules>
486
+ `;
487
+ }
488
+ /**
489
+ * Renders the platform-only instrumentation manifest.
490
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized configuration.
491
+ * @param {ConfigurationSpan[]} spans - Collected configuration provenance spans.
492
+ * @returns {string} Android test manifest.
493
+ */
494
+ function renderAndroidTestManifest(configuration, spans) {
495
+ return configured(`${projectRoot}/app/src/androidTest/AndroidManifest.xml`, spans, [
496
+ `<?xml version="1.0" encoding="utf-8"?>\n<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n <instrumentation\n android:name="`,
497
+ field("packageName", configuration.packageName), `.SemantifoldUiInstrumentation"\n android:targetPackage="`,
498
+ field("applicationId", xmlEscape(configuration.applicationId)), `" />\n</manifest>\n`
499
+ ]);
500
+ }
501
+ /**
502
+ * Renders the synthetic launcher activity.
503
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized configuration.
504
+ * @param {string} entryModule - Selected semantic entry module identity.
505
+ * @param {ConfigurationSpan[]} spans - Collected configuration provenance spans.
506
+ * @returns {string} Kotlin launcher activity source.
507
+ */
508
+ function renderActivity(configuration, entryModule, spans) {
509
+ const resourceImport = configuration.namespace == configuration.packageName
510
+ ? []
511
+ : ["import ", field("namespace", configuration.namespace), ".R\n"];
512
+ return configured(`${projectRoot}/app/src/main/kotlin/${configuration.packageName.replaceAll(".", "/")}/${configuration.activityClassName}.kt`, spans, [
513
+ "package ", field("packageName", configuration.packageName), `
514
+
515
+ import android.app.Activity
516
+ import android.annotation.SuppressLint
517
+ import android.os.Bundle
518
+ import android.widget.TextView
519
+ `, ...resourceImport, `import `, field("packageName", configuration.packageName),
520
+ `.semantic.SemantifoldModule${moduleName(entryModule)}
521
+
522
+ class `, field("activityClassName", configuration.activityClassName), ` : Activity() {
523
+ @SuppressLint("SetTextI18n")
524
+ override fun onCreate(savedInstanceState: Bundle?) {
525
+ super.onCreate(savedInstanceState)
526
+ setContentView(R.layout.activity_main)
527
+ val lines = SemantifoldModule${moduleName(entryModule)}.semantifoldEntry()
528
+ val output = java.lang.StringBuilder()
529
+ var index = 0
530
+ while (index < lines.size) {
531
+ if (index > 0) output.append('\\n')
532
+ output.append(lines[index])
533
+ index += 1
534
+ }
535
+ findViewById<TextView>(R.id.semantifold_output).text = output.toString()
536
+ }
537
+ }
538
+ `
539
+ ]);
540
+ }
541
+ /**
542
+ * Renders the single accessibility-important native text view.
543
+ * @returns {string} Android layout XML.
544
+ */
545
+ function renderLayout() {
546
+ return `<?xml version="1.0" encoding="utf-8"?>
547
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
548
+ android:id="@+id/semantifold_output"
549
+ android:layout_width="match_parent"
550
+ android:layout_height="match_parent"
551
+ android:gravity="center"
552
+ android:importantForAccessibility="yes"
553
+ android:textIsSelectable="true" />
554
+ `;
555
+ }
556
+ /**
557
+ * Renders configuration-derived string resources.
558
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized configuration.
559
+ * @param {ConfigurationSpan[]} spans - Collected configuration provenance spans.
560
+ * @returns {string} Android string resource XML.
561
+ */
562
+ function renderStrings(configuration, spans) {
563
+ return configured(`${projectRoot}/app/src/main/res/values/strings.xml`, spans, [
564
+ `<?xml version="1.0" encoding="utf-8"?>\n<resources>\n <string name="app_name">`,
565
+ field("displayName", xmlEscape(configuration.displayName)), `</string>\n</resources>\n`
566
+ ]);
567
+ }
568
+ /**
569
+ * Renders the fixed platform-native baseline theme.
570
+ * @returns {string} Android theme resource XML.
571
+ */
572
+ function renderTheme() {
573
+ return `<?xml version="1.0" encoding="utf-8"?>
574
+ <resources>
575
+ <style name="Theme.Semantifold" parent="android:style/Theme.Material.Light.NoActionBar">
576
+ <item name="android:fontFamily">sans</item>
577
+ <item name="android:windowActionModeOverlay">true</item>
578
+ </style>
579
+ </resources>
580
+ `;
581
+ }
582
+ /**
583
+ * Renders the sole JUnit test-scope semantic assertion.
584
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized configuration.
585
+ * @param {string} entryModule - Selected semantic entry module identity.
586
+ * @param {ConfigurationSpan[]} spans - Collected configuration provenance spans.
587
+ * @returns {string} Kotlin unit test source.
588
+ */
589
+ function renderUnitTest(configuration, entryModule, spans) {
590
+ return configured(`${projectRoot}/app/src/test/kotlin/${configuration.packageName.replaceAll(".", "/")}/SemantifoldEntryTest.kt`, spans, [
591
+ "package ", field("packageName", configuration.packageName), `
592
+
593
+ import `, field("packageName", configuration.packageName), `.semantic.SemantifoldModule${moduleName(entryModule)}
594
+ import org.junit.Test
595
+
596
+ class SemantifoldEntryTest {
597
+ @Test
598
+ fun entryIsDeterministicAcrossFreshRuns() {
599
+ val firstOutput = SemantifoldModule${moduleName(entryModule)}.semantifoldEntry()
600
+ val secondOutput = SemantifoldModule${moduleName(entryModule)}.semantifoldEntry()
601
+ if (!firstOutput.equals(secondOutput)) {
602
+ throw AssertionError("Semantic entry output differs across fresh runs.")
603
+ }
604
+ }
605
+ }
606
+ `
607
+ ]);
608
+ }
609
+ /**
610
+ * Renders the framework-only instrumentation runner.
611
+ * @param {import("../semantic/types.js").AndroidApplicationConfiguration} configuration - Normalized configuration.
612
+ * @param {ConfigurationSpan[]} spans - Collected configuration provenance spans.
613
+ * @returns {string} Kotlin instrumentation source.
614
+ */
615
+ function renderInstrumentation(configuration, spans) {
616
+ const resourceImport = configuration.namespace == configuration.packageName
617
+ ? []
618
+ : ["import ", field("namespace", configuration.namespace), ".R\n"];
619
+ return configured(`${projectRoot}/app/src/androidTest/kotlin/${configuration.packageName.replaceAll(".", "/")}/SemantifoldUiInstrumentation.kt`, spans, [
620
+ "package ", field("packageName", configuration.packageName), `
621
+
622
+ import android.app.Activity
623
+ import android.app.Instrumentation
624
+ import android.content.Intent
625
+ import android.os.Bundle
626
+ import android.util.Base64
627
+ import android.view.View
628
+ import android.widget.TextView
629
+ import java.nio.charset.StandardCharsets
630
+ `, ...resourceImport, `
631
+ class SemantifoldUiInstrumentation : Instrumentation() {
632
+ private var inputArguments: Bundle? = null
633
+
634
+ override fun onCreate(arguments: Bundle?) {
635
+ inputArguments = arguments
636
+ start()
637
+ }
638
+
639
+ override fun onStart() {
640
+ try {
641
+ val providedArguments = inputArguments
642
+ ?: throw IllegalStateException("missing instrumentation arguments")
643
+ val encoded = providedArguments.getString("expected_output_base64")
644
+ ?: throw IllegalStateException("missing expected_output_base64 instrumentation argument")
645
+ val expected = String(Base64.decode(encoded, Base64.NO_WRAP), StandardCharsets.UTF_8)
646
+ val launch = targetContext.packageManager.getLaunchIntentForPackage(targetContext.packageName)
647
+ ?: throw IllegalStateException("generated application has no launcher intent")
648
+ launch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
649
+ val activity = startActivitySync(launch) as `, field("activityClassName", configuration.activityClassName), `
650
+ assertOutput(activity, expected)
651
+ val monitor = addMonitor(`, field("activityClassName", configuration.activityClassName), `::class.java.name, null, false)
652
+ runOnMainSync { activity.recreate() }
653
+ waitForIdleSync()
654
+ val recreated = waitForMonitorWithTimeout(monitor, 10_000)
655
+ ?: throw IllegalStateException("activity was not recreated")
656
+ assertOutput(recreated, expected)
657
+ finish(Activity.RESULT_OK, Bundle())
658
+ } catch (error: Throwable) {
659
+ val result = Bundle()
660
+ result.putString("semantifold_failure", android.util.Log.getStackTraceString(error))
661
+ finish(Activity.RESULT_CANCELED, result)
662
+ }
663
+ }
664
+
665
+ private fun assertOutput(activity: Activity, expected: String) {
666
+ waitForIdleSync()
667
+ val actual = activity.findViewById<TextView>(R.id.semantifold_output)
668
+ ?: throw IllegalStateException("missing semantifold_output view")
669
+ if (actual.visibility != View.VISIBLE) throw IllegalStateException("output view is not visible")
670
+ if (actual.javaClass != TextView::class.java) throw IllegalStateException("output view is not a native TextView")
671
+ if (!actual.text.toString().equals(expected)) throw IllegalStateException("output text mismatch")
672
+ if (actual.contentDescription != null) throw IllegalStateException("output content description must stay absent")
673
+ if (actual.importantForAccessibility != View.IMPORTANT_FOR_ACCESSIBILITY_YES) {
674
+ throw IllegalStateException("output view is not accessibility-important")
675
+ }
676
+ }
677
+ }
678
+ `
679
+ ]);
680
+ }
681
+ /**
682
+ * Renders the ownership, toolchain, and provenance manifest.
683
+ * @param {ReturnType<typeof preflightAndroidApplication>} prepared - Prepared application.
684
+ * @param {import("../semantic/types.js").GeneratedSetArtifact[]} artifacts - Owned project artifacts.
685
+ * @param {string} manifestPath - Ownership manifest path.
686
+ * @param {ConfigurationSpan[]} spans - Configuration provenance spans.
687
+ * @returns {string} Canonical project manifest JSON.
688
+ */
689
+ function renderProjectManifest(prepared, artifacts, manifestPath, spans) {
690
+ const inputPaths = new Set([...prepared.resources, ...prepared.assets].map(({ fullPath }) => fullPath));
691
+ const semanticArtifacts = artifacts.filter(artifact => artifact.provenance.kind == "text");
692
+ const ownedPaths = [...artifacts.map(({ path }) => path), manifestPath];
693
+ return stringifyCanonicalJson({
694
+ configuration: prepared.configuration,
695
+ generator: { name: "semantifold", version: generatorVersion },
696
+ ownership: {
697
+ excludedPathPatterns,
698
+ ownedPaths,
699
+ ownedRoot: projectRoot,
700
+ sha256: artifacts.map(artifact => ({ path: artifact.path, sha256: hashContent(artifact.content) }))
701
+ },
702
+ provenance: {
703
+ configuration: Object.keys(prepared.configuration).sort().map(fieldName => ({
704
+ field: fieldName,
705
+ manifestPointer: `/configuration/${fieldName}`,
706
+ outputs: configurationOutputs(spans, fieldName)
707
+ })),
708
+ inputs: [...prepared.resources, ...prepared.assets].map(item => ({
709
+ contentKind: item.contentKind,
710
+ mediaType: item.mediaType,
711
+ path: item.fullPath,
712
+ sha256: item.sha256
713
+ })),
714
+ semanticSources: prepared.sources.map(source => ({
715
+ artifacts: semanticArtifacts.filter(artifact => artifact.provenance.kind == "text" &&
716
+ artifact.provenance.mapping.spans.some(({ origin }) => originReferencesFilename(origin, source.filename)))
717
+ .map(({ path }) => path),
718
+ filename: source.filename,
719
+ ...(source.language === undefined ? {} : { language: source.language }),
720
+ sha256: createHash("sha256").update(source.content).digest("hex")
721
+ })),
722
+ syntheticScaffolding: [...artifacts.filter(artifact => artifact.provenance.kind == "synthetic" &&
723
+ !inputPaths.has(artifact.path)).map(({ path }) => path), manifestPath]
724
+ },
725
+ schema: "SemantifoldAndroidProject",
726
+ semanticProgram: semanticProgramManifest(prepared),
727
+ target: "android",
728
+ toolchain,
729
+ version: 1
730
+ });
731
+ }
732
+ /**
733
+ * Renders semantic module and source identities for the project manifest.
734
+ * @param {ReturnType<typeof preflightAndroidApplication>} prepared - Prepared application.
735
+ * @returns {Record<string, unknown>} Semantic program manifest.
736
+ */
737
+ function semanticProgramManifest(prepared) {
738
+ const sourceContent = new Map(prepared.sources.map(source => [source.filename, source.content]));
739
+ const order = new Map(prepared.program.modules.map((module, index) => [module.id, index]));
740
+ const modules = prepared.program.modules.map(module => {
741
+ const source = prepared.program.sources.find(candidate => candidate.filename == module.sourceFilename);
742
+ const content = sourceContent.get(module.sourceFilename);
743
+ if (!source || content === undefined)
744
+ throw new TypeError(`Preflighted Android module '${module.id}' lost source ownership.`);
745
+ return {
746
+ dependencies: [...new Set(module.imports.map(({ moduleId }) => moduleId))]
747
+ .sort((left, right) => /** @type {number} */ (order.get(left)) - /** @type {number} */ (order.get(right))),
748
+ generatedArtifacts: [prepared.modulePaths.get(module.id)],
749
+ id: module.id,
750
+ namespace: `SemantifoldModule${moduleName(module.id)}`,
751
+ source: { filename: source.filename, id: source.id, sha256: createHash("sha256").update(content).digest("hex") }
752
+ };
753
+ });
754
+ const entryId = prepared.program.entryModule;
755
+ return {
756
+ entry: {
757
+ activityArtifact: `${projectRoot}/app/src/main/kotlin/${prepared.packagePath}/${prepared.configuration.activityClassName}.kt`,
758
+ generatedArtifact: prepared.modulePaths.get(entryId),
759
+ generatedFunctionIdentity: `SemantifoldModule${moduleName(entryId)}.semantifoldEntry`,
760
+ moduleId: entryId
761
+ },
762
+ modules,
763
+ schema: "SemantifoldAndroidSemanticProgram",
764
+ sources: prepared.program.sources.map(source => ({
765
+ filename: source.filename,
766
+ id: source.id,
767
+ language: source.language,
768
+ moduleIds: modules.filter(module => module.source.filename == source.filename).map(({ id }) => id),
769
+ ownership: source.ownership ?? "application",
770
+ sha256: createHash("sha256").update(/** @type {string} */ (sourceContent.get(source.filename))).digest("hex")
771
+ })),
772
+ version: 1
773
+ };
774
+ }
775
+ /**
776
+ * Validates and normalizes the closed Android configuration.
777
+ * @param {unknown} candidate - Candidate configuration.
778
+ * @returns {import("../semantic/types.js").AndroidApplicationConfiguration} Normalized configuration.
779
+ */
780
+ function normalizeConfiguration(candidate) {
781
+ if (candidate === undefined)
782
+ candidate = {};
783
+ if (!isPlainObject(candidate) || Object.keys(candidate).some(key => !configurationFields.has(key))) {
784
+ invalidConfiguration("Android application configuration must be a closed plain object.");
785
+ }
786
+ const configuration = /** @type {import("../semantic/types.js").AndroidApplicationConfigurationInput} */ (candidate);
787
+ const applicationId = configuration.applicationId ?? "dev.semantifold.generated";
788
+ const namespace = configuration.namespace ?? applicationId;
789
+ const packageName = configuration.packageName ?? namespace;
790
+ const activityClassName = configuration.activityClassName ?? "MainActivity";
791
+ const productName = configuration.productName ?? "Semantifold";
792
+ const displayName = configuration.displayName ?? "Semantifold";
793
+ const minimumSdk = configuration.minimumSdk ?? 23;
794
+ const targetSdk = configuration.targetSdk ?? toolchain.targetSdk;
795
+ const compileSdk = configuration.compileSdk ?? toolchain.compileSdk;
796
+ const buildToolsVersion = configuration.buildToolsVersion ?? toolchain.buildTools;
797
+ const versionCode = configuration.versionCode ?? 1;
798
+ const versionName = configuration.versionName ?? "1.0.0";
799
+ const orientation = configuration.orientation ?? "unspecified";
800
+ const theme = configuration.theme ?? "system";
801
+ for (const [label, value] of [["Application ID", applicationId], ["Namespace", namespace], ["Package name", packageName]]) {
802
+ if (typeof value != "string" || !isPackageName(value))
803
+ invalidConfiguration(`${label} must be a lowercase Java package identity.`);
804
+ }
805
+ if (typeof activityClassName != "string" || !/^[A-Z][A-Za-z0-9]*$/u.test(activityClassName) || kotlinKeywords.has(activityClassName)) {
806
+ invalidConfiguration("Activity class name must be an ASCII upper-camel Kotlin identifier.");
807
+ }
808
+ for (const [label, value] of [["Product name", productName], ["Display name", displayName]]) {
809
+ if (typeof value != "string" || value.length == 0 || value.trim() != value || [...value].length > 64 ||
810
+ !hasOnlyUnicodeScalars(value) || /[\p{Cc}\p{Zl}\p{Zp}\uFFFE\uFFFF]/u.test(value)) {
811
+ invalidConfiguration(`${label} must be a non-empty single-line Unicode scalar string of at most 64 characters.`);
812
+ }
813
+ }
814
+ if (/[\\/:<>"?*|]/u.test(productName)) {
815
+ invalidConfiguration("Product name contains a character forbidden by the Gradle project-name contract.");
816
+ }
817
+ if (minimumSdk !== 23 || targetSdk !== 35 || compileSdk !== 35 || minimumSdk > targetSdk || targetSdk > compileSdk) {
818
+ invalidConfiguration("SDK levels must use the qualified minimum 23, target 35, and compile 35 matrix.");
819
+ }
820
+ if (buildToolsVersion != toolchain.buildTools)
821
+ invalidConfiguration("Build Tools version must be exactly '35.0.0'.");
822
+ if (!Number.isSafeInteger(versionCode) || versionCode < 1 || versionCode > 2_100_000_000) {
823
+ invalidConfiguration("Version code must be a positive Android-safe integer.");
824
+ }
825
+ if (typeof versionName != "string" || !semanticVersionPattern.test(versionName)) {
826
+ invalidConfiguration("Version name must be a canonical non-empty semantic version string.");
827
+ }
828
+ if (orientation != "unspecified")
829
+ invalidConfiguration("The baseline orientation is exactly 'unspecified'.");
830
+ if (theme != "system")
831
+ invalidConfiguration("The baseline theme is exactly 'system'.");
832
+ if (configuration.permissions !== undefined &&
833
+ (!isDenseArray(configuration.permissions) || configuration.permissions.length != 0)) {
834
+ invalidConfiguration("The baseline Android permission set must be empty.");
835
+ }
836
+ return {
837
+ activityClassName,
838
+ applicationId,
839
+ buildToolsVersion,
840
+ compileSdk,
841
+ displayName,
842
+ minimumSdk,
843
+ namespace,
844
+ orientation,
845
+ packageName,
846
+ productName,
847
+ targetSdk,
848
+ theme,
849
+ versionCode,
850
+ versionName
851
+ };
852
+ }
853
+ /**
854
+ * Validates, snapshots, and orders caller-provided inputs.
855
+ * @param {unknown} candidate - Candidate resource or asset list.
856
+ * @param {"asset" | "resource"} kind - Android input kind.
857
+ * @returns {AndroidInputFile[]} Normalized inputs.
858
+ */
859
+ function normalizeInputFiles(candidate, kind) {
860
+ if (candidate === undefined)
861
+ return [];
862
+ if (!isDenseArray(candidate))
863
+ invalidResource(`Application ${kind}s must be a dense array.`);
864
+ /** @type {AndroidInputFile[]} */
865
+ const files = [];
866
+ for (let index = 0; index < candidate.length; index += 1) {
867
+ const item = candidate[index];
868
+ if (!isPlainObject(item) || Object.keys(item).length != resourceFields.size ||
869
+ Object.keys(item).some(key => !resourceFields.has(key)))
870
+ invalidResource(`${capitalize(kind)} ${index} must use the closed input schema.`);
871
+ const path = item.path;
872
+ const content = item.content;
873
+ const mediaType = item.mediaType;
874
+ const sha256 = item.sha256;
875
+ if (!isSafeArtifactPath(path) || kind == "resource" && !isAllowedResourcePath(path)) {
876
+ invalidResource(`${capitalize(kind)} ${index} has an unsafe or unsupported path.`);
877
+ }
878
+ if (typeof content != "string" && !(content instanceof Uint8Array) || typeof content == "string" &&
879
+ (content.length == 0 || !hasOnlyUnicodeScalars(content)) || content instanceof Uint8Array && content.byteLength == 0) {
880
+ invalidResource(`${capitalize(kind)} '${path}' requires non-empty exact content.`);
881
+ }
882
+ if (typeof mediaType != "string" || !mediaTypePattern.test(mediaType) || /[\r\n]/u.test(mediaType)) {
883
+ invalidResource(`${capitalize(kind)} '${path}' requires an explicit valid media type.`);
884
+ }
885
+ if (kind == "resource" && path.startsWith("drawable-") && !["image/png", "image/webp"].includes(mediaType)) {
886
+ invalidResource(`Drawable resource '${path}' must use PNG or WebP media type.`);
887
+ }
888
+ const snapshot = typeof content == "string" ? content : new Uint8Array(content);
889
+ const actualHash = createHash("sha256").update(snapshot).digest("hex");
890
+ if (typeof sha256 != "string" || !/^[0-9a-f]{64}$/u.test(sha256) || sha256 != actualHash) {
891
+ invalidResource(`${capitalize(kind)} '${path}' SHA-256 does not match its exact content.`);
892
+ }
893
+ const fullPath = `${projectRoot}/app/src/main/${kind == "resource" ? "res" : "assets"}/${path}`;
894
+ files.push({ content: snapshot, contentKind: typeof snapshot == "string" ? "text" : "binary", fullPath, mediaType, path, sha256 });
895
+ }
896
+ files.sort((left, right) => left.fullPath < right.fullPath ? -1 : left.fullPath > right.fullPath ? 1 : 0);
897
+ const conflict = findPortableArtifactPathConflict(files.map(({ fullPath }) => fullPath));
898
+ if (conflict)
899
+ invalidResource(`${capitalize(kind)} path '${conflict.path}' has a ${conflict.kind} conflict.`);
900
+ if (kind == "resource")
901
+ validateResourceIdentifiers(files);
902
+ return files;
903
+ }
904
+ /**
905
+ * Rejects two files that Android would compile to the same resource identifier in one configuration.
906
+ * @param {AndroidInputFile[]} files - Validated resource inputs.
907
+ */
908
+ function validateResourceIdentifiers(files) {
909
+ const identifiers = new Map();
910
+ for (const file of files) {
911
+ const separator = file.path.indexOf("/");
912
+ const directory = file.path.slice(0, separator);
913
+ const filename = file.path.slice(separator + 1);
914
+ const extension = filename.indexOf(".");
915
+ const name = extension == -1 ? filename : filename.slice(0, extension);
916
+ const resourceType = directory.split("-", 1)[0];
917
+ const key = `${directory}/${name}`;
918
+ const previous = identifiers.get(key);
919
+ if (previous) {
920
+ invalidResource(`Android resource identifier '${resourceType}/${name}' collides between '${previous}' and '${file.path}' in configuration '${directory}'.`);
921
+ }
922
+ identifiers.set(key, file.path);
923
+ }
924
+ }
925
+ /**
926
+ * Tests whether a caller resource uses the narrow allowlisted resource grammar.
927
+ * @param {string} value - Resource path relative to res.
928
+ * @returns {boolean} Whether the path is supported.
929
+ */
930
+ function isAllowedResourcePath(value) {
931
+ if (/^raw\/[a-z][a-z0-9_]*(?:\.[a-z0-9]+)?$/u.test(value))
932
+ return true;
933
+ return /^drawable-(?:mdpi|hdpi|xhdpi|xxhdpi|xxxhdpi)\/[a-z][a-z0-9_]*\.(?:png|webp)$/u.test(value);
934
+ }
935
+ /**
936
+ * Converts a validated input snapshot into an owned artifact.
937
+ * @param {AndroidInputFile} item - Validated caller input.
938
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Owned input artifact.
939
+ */
940
+ function inputFileArtifact(item) {
941
+ const reason = `Exact caller-provided Android input (sha256:${item.sha256}).`;
942
+ if (typeof item.content == "string") {
943
+ return {
944
+ ...syntheticText(item.fullPath, "resource", item.content, reason),
945
+ mediaType: item.mediaType
946
+ };
947
+ }
948
+ const content = new Uint8Array(item.content);
949
+ return {
950
+ content,
951
+ contentKind: "binary",
952
+ mediaType: item.mediaType,
953
+ ownership: "generated",
954
+ path: item.fullPath,
955
+ provenance: { kind: "bytes", mapping: createByteMapping({
956
+ byteLength: content.byteLength,
957
+ path: item.fullPath,
958
+ ranges: [{ generated: { end: content.byteLength, start: 0 },
959
+ origin: { kind: "synthetic", reason, relatedOrigins: [] }, role: "resource" }]
960
+ }) },
961
+ role: "resource"
962
+ };
963
+ }
964
+ /**
965
+ * Creates a deterministic synthetic text artifact.
966
+ * @param {string} path - Artifact path.
967
+ * @param {import("../semantic/types.js").GeneratedArtifactRole} role - Artifact role.
968
+ * @param {string} content - UTF-8 artifact content.
969
+ * @param {string} reason - Synthetic provenance reason.
970
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Text artifact.
971
+ */
972
+ function syntheticText(path, role, content, reason) {
973
+ return { content, contentKind: "text", mediaType: mediaTypeFor(path), ownership: "generated", path,
974
+ provenance: { kind: "synthetic", reason, relatedOrigins: [] }, role };
975
+ }
976
+ /**
977
+ * Creates a configuration-derived text artifact.
978
+ * @param {string} path - Artifact path.
979
+ * @param {import("../semantic/types.js").GeneratedArtifactRole} role - Artifact role.
980
+ * @param {string} content - UTF-8 artifact content.
981
+ * @param {string} reason - Synthetic provenance reason.
982
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Text artifact.
983
+ */
984
+ function configuredText(path, role, content, reason) {
985
+ return syntheticText(path, role, content, reason);
986
+ }
987
+ /**
988
+ * Derives the media type for a generated text path.
989
+ * @param {string} path - Generated artifact path.
990
+ * @returns {string} Artifact media type.
991
+ */
992
+ function mediaTypeFor(path) {
993
+ if (path.endsWith(".json"))
994
+ return "application/json";
995
+ if (path.endsWith(".xml"))
996
+ return "application/xml";
997
+ if (path.endsWith(".kt") || path.endsWith(".kts"))
998
+ return "text/x-kotlin";
999
+ return "text/plain";
1000
+ }
1001
+ /**
1002
+ * Marks one rendered value as configuration-derived.
1003
+ * @param {string} fieldName - Configuration field name.
1004
+ * @param {string} value - Rendered field value.
1005
+ * @returns {{field: string, value: string}} Marked configuration value.
1006
+ */
1007
+ function field(fieldName, value) {
1008
+ return { field: fieldName, value };
1009
+ }
1010
+ /**
1011
+ * Joins rendered parts while recording configuration causality.
1012
+ * @param {string} path - Output artifact path.
1013
+ * @param {ConfigurationSpan[]} spans - Mutable provenance span collector.
1014
+ * @param {(string | {field: string, value: string})[]} parts - Synthetic and marked parts.
1015
+ * @returns {string} Rendered text.
1016
+ */
1017
+ function configured(path, spans, parts) {
1018
+ let content = "";
1019
+ for (const part of parts) {
1020
+ if (typeof part == "string")
1021
+ content += part;
1022
+ else {
1023
+ const start = content.length;
1024
+ content += part.value;
1025
+ spans.push({ end: content.length, field: part.field, path, start });
1026
+ }
1027
+ }
1028
+ return content;
1029
+ }
1030
+ /**
1031
+ * Groups configuration spans by artifact.
1032
+ * @param {ConfigurationSpan[]} spans - All rendered configuration spans.
1033
+ * @param {string} fieldName - Requested configuration field.
1034
+ * @returns {{path: string, ranges: {end: number, start: number}[]}[]} Output ranges.
1035
+ */
1036
+ function configurationOutputs(spans, fieldName) {
1037
+ const grouped = new Map();
1038
+ for (const span of spans) {
1039
+ if (span.field != fieldName)
1040
+ continue;
1041
+ const ranges = grouped.get(span.path) ?? [];
1042
+ ranges.push({ end: span.end, start: span.start });
1043
+ grouped.set(span.path, ranges);
1044
+ }
1045
+ return [...grouped].map(([path, ranges]) => ({ path, ranges }));
1046
+ }
1047
+ /**
1048
+ * Tests whether a mapping origin refers to one semantic source file.
1049
+ * @param {import("../semantic/types.js").SemanticOrigin} origin - Mapping origin.
1050
+ * @param {string} filename - Semantic source filename.
1051
+ * @returns {boolean} Whether the origin owns the filename.
1052
+ */
1053
+ function originReferencesFilename(origin, filename) {
1054
+ if (origin.kind == "source")
1055
+ return origin.location.filename == filename;
1056
+ if (origin.kind == "derived")
1057
+ return origin.origins.some(({ location }) => location.filename == filename);
1058
+ return origin.relatedOrigins.some(({ location }) => location.filename == filename);
1059
+ }
1060
+ /**
1061
+ * Hashes exact text or bytes for ownership records.
1062
+ * @param {string | Uint8Array} content - Exact artifact content.
1063
+ * @returns {string} Lowercase SHA-256 digest.
1064
+ */
1065
+ function hashContent(content) {
1066
+ return createHash("sha256").update(content).digest("hex");
1067
+ }
1068
+ /**
1069
+ * Serializes JSON with recursively stable object-key ordering.
1070
+ * @param {unknown} value - JSON-compatible value.
1071
+ * @returns {string} Canonical indented JSON with trailing newline.
1072
+ */
1073
+ function stringifyCanonicalJson(value) {
1074
+ return `${JSON.stringify(sortJson(value), null, 2)}\n`;
1075
+ }
1076
+ /**
1077
+ * Recursively sorts object keys without changing array order.
1078
+ * @param {unknown} value - JSON-compatible value.
1079
+ * @returns {unknown} Canonically ordered value.
1080
+ */
1081
+ function sortJson(value) {
1082
+ if (Array.isArray(value))
1083
+ return value.map(sortJson);
1084
+ if (!isPlainObject(value))
1085
+ return value;
1086
+ return Object.fromEntries(Object.keys(value).sort().map(key => [key, sortJson(value[key])]));
1087
+ }
1088
+ /**
1089
+ * Tests a lowercase Kotlin-compatible package identity.
1090
+ * @param {string} value - Candidate package name.
1091
+ * @returns {boolean} Whether the name is accepted.
1092
+ */
1093
+ function isPackageName(value) {
1094
+ const parts = value.split(".");
1095
+ return parts.length >= 2 && parts.every(part => /^[a-z][a-z0-9_]*$/u.test(part) && !kotlinKeywords.has(part));
1096
+ }
1097
+ /**
1098
+ * Rejects launcher names that shadow an unqualified symbol in generated same-package Kotlin.
1099
+ * @param {string} activityClassName - Validated launcher class name.
1100
+ * @param {string} entryModule - Selected semantic entry module.
1101
+ */
1102
+ function validateActivityClassName(activityClassName, entryModule) {
1103
+ const semanticEntrySymbol = `SemantifoldModule${moduleName(entryModule)}`;
1104
+ if (androidScaffoldSymbols.has(activityClassName) || activityClassName == semanticEntrySymbol) {
1105
+ invalidConfiguration(`Activity class name '${activityClassName}' collides with generated Kotlin symbol '${activityClassName}'.`);
1106
+ }
1107
+ }
1108
+ /**
1109
+ * Allocates one module-wide output sink that cannot shadow a source binding.
1110
+ * @param {import("../semantic/types.js").SemanticModule} module - Prepared semantic module.
1111
+ * @returns {string} Collision-safe Kotlin binding.
1112
+ */
1113
+ function outputSinkName(module) {
1114
+ const bindings = new Set(module.functions.flatMap(declaration => declaration.parameters.map(({ name }) => name)));
1115
+ for (const declaration of module.functions)
1116
+ collectBlockBindingNames(declaration.body, bindings);
1117
+ collectBlockBindingNames(module.entryPoint.body, bindings);
1118
+ let candidate = "semantifoldOutput";
1119
+ while (bindings.has(candidate))
1120
+ candidate += "_";
1121
+ return candidate;
1122
+ }
1123
+ /**
1124
+ * Collects local bindings recursively from the supported semantic block subset.
1125
+ * @param {import("../semantic/types.js").Block} block - Semantic block.
1126
+ * @param {Set<string>} bindings - Mutable binding-name set.
1127
+ */
1128
+ function collectBlockBindingNames(block, bindings) {
1129
+ for (const statement of block.statements) {
1130
+ if (statement.kind == "LocalDeclaration")
1131
+ bindings.add(statement.name);
1132
+ else if (statement.kind == "IfStatement") {
1133
+ collectBlockBindingNames(statement.consequent, bindings);
1134
+ if (statement.alternate)
1135
+ collectBlockBindingNames(statement.alternate, bindings);
1136
+ }
1137
+ }
1138
+ }
1139
+ /**
1140
+ * Maps a preflighted module identity to a stable Kotlin suffix.
1141
+ * @param {string} id - Semantic module identity.
1142
+ * @returns {string} Kotlin object-name suffix.
1143
+ */
1144
+ function moduleName(id) {
1145
+ return id.split(/[._-]+/u).map(part => `${part[0].toUpperCase()}${part.slice(1)}`).join("");
1146
+ }
1147
+ /**
1148
+ * Wraps legacy single-module input in the canonical program contract.
1149
+ * @param {import("../semantic/types.js").SemanticModule | undefined} candidate - Candidate semantic module.
1150
+ * @returns {import("../semantic/types.js").SemanticProgram} Canonical single-module program.
1151
+ */
1152
+ function normalizeSingleModule(candidate) {
1153
+ if (!isPlainObject(candidate))
1154
+ unsupportedCapability("android", "missing or invalid module", undefined);
1155
+ const module = structuredClone(candidate);
1156
+ const sources = module.provenance?.sources;
1157
+ if (!Array.isArray(sources) || sources.length != 1 || sources[0].content === null ||
1158
+ sources[0].filename != module.location?.filename || typeof sources[0].language != "string") {
1159
+ unsupportedCapability("android", "single-module source ownership", module.location);
1160
+ }
1161
+ rekeyModuleDeclarations(module, "main");
1162
+ const exports = [
1163
+ ...(module.records ?? []).map(declaration => applicationExport(declaration, "record")),
1164
+ ...(module.classes ?? []).map(declaration => applicationExport(declaration, "class")),
1165
+ ...(module.errors ?? []).map(declaration => applicationExport(declaration, "error")),
1166
+ ...module.functions.map(declaration => applicationExport(declaration, "function"))
1167
+ ];
1168
+ const programModule = { ...module, exports, id: "main", imports: [], sourceFilename: sources[0].filename };
1169
+ return { entryModule: "main", kind: "Program", modules: [programModule], sources: structuredClone(sources) };
1170
+ }
1171
+ /**
1172
+ * Creates an application-local export record for single-module compatibility.
1173
+ * @param {{id?: string, location: import("../semantic/types.js").SourceLocation, name: string}} declaration - Semantic declaration.
1174
+ * @param {import("../semantic/types.js").SemanticDeclarationKind} symbolKind - Declaration kind.
1175
+ * @returns {import("../semantic/types.js").SemanticExport} Semantic export.
1176
+ */
1177
+ function applicationExport(declaration, symbolKind) {
1178
+ return { declarationId: /** @type {string} */ (declaration.id), exportedName: declaration.name,
1179
+ kind: /** @type {const} */ ("Export"), location: declaration.location, symbolKind };
1180
+ }
1181
+ /**
1182
+ * Qualifies single-module declaration identities before program preflight.
1183
+ * @param {import("../semantic/types.js").SemanticModule} module - Cloned semantic module.
1184
+ * @param {string} moduleId - Canonical module identity.
1185
+ */
1186
+ function rekeyModuleDeclarations(module, moduleId) {
1187
+ const declarations = [...module.records ?? [], ...module.classes ?? [], ...module.errors ?? [], ...module.functions];
1188
+ const replacements = new Map(declarations.filter(declaration => typeof declaration.id == "string")
1189
+ .map(declaration => [declaration.id, `${moduleId}#${declaration.id}`]));
1190
+ for (const declaration of declarations)
1191
+ if (typeof declaration.id == "string")
1192
+ declaration.id = replacements.get(declaration.id);
1193
+ const seen = new Set();
1194
+ const identityFields = new Set(["classId", "declarationId", "field", "method", "parameterId"]);
1195
+ /**
1196
+ * Rewrites declaration references throughout one semantic value graph.
1197
+ * @param {unknown} value - Candidate nested semantic value.
1198
+ */
1199
+ const visit = value => {
1200
+ if (!value || typeof value != "object" || seen.has(value))
1201
+ return;
1202
+ seen.add(value);
1203
+ for (const [key, nested] of Object.entries(value)) {
1204
+ if (!Array.isArray(value) && identityFields.has(key) && typeof nested == "string" && replacements.has(nested)) {
1205
+ Reflect.set(value, key, replacements.get(nested));
1206
+ }
1207
+ else
1208
+ visit(nested);
1209
+ }
1210
+ };
1211
+ visit(module);
1212
+ }
1213
+ /**
1214
+ * Escapes a configuration value for XML text or attributes.
1215
+ * @param {string} value - Raw configuration value.
1216
+ * @returns {string} XML-safe value.
1217
+ */
1218
+ function xmlEscape(value) {
1219
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")
1220
+ .replaceAll('"', "&quot;").replaceAll("'", "&apos;");
1221
+ }
1222
+ /**
1223
+ * Escapes a configuration value for a Kotlin string literal body.
1224
+ * @param {string} value - Raw configuration value.
1225
+ * @returns {string} Kotlin-safe value.
1226
+ */
1227
+ function kotlinEscape(value) {
1228
+ return value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("$", "\\$");
1229
+ }
1230
+ /**
1231
+ * Uppercases the initial ASCII character of a known non-empty word.
1232
+ * @param {string} value - Non-empty word.
1233
+ * @returns {string} Capitalized word.
1234
+ */
1235
+ function capitalize(value) {
1236
+ return `${value[0].toUpperCase()}${value.slice(1)}`;
1237
+ }
1238
+ /**
1239
+ * Tests whether a value is a plain data object.
1240
+ * @param {unknown} value - Candidate value.
1241
+ * @returns {value is Record<string, unknown>} Whether the value is a plain object.
1242
+ */
1243
+ function isPlainObject(value) {
1244
+ return Boolean(value) && typeof value == "object" && !Array.isArray(value) && Object.getPrototypeOf(value) == Object.prototype;
1245
+ }
1246
+ /**
1247
+ * Throws a stable invalid-request diagnostic.
1248
+ * @param {string} message - Diagnostic message.
1249
+ * @returns {never} Never returns.
1250
+ */
1251
+ function invalidInput(message) {
1252
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_INPUT", language: "android", message });
1253
+ }
1254
+ /**
1255
+ * Throws a stable invalid-configuration diagnostic.
1256
+ * @param {string} message - Diagnostic message.
1257
+ * @returns {never} Never returns.
1258
+ */
1259
+ function invalidConfiguration(message) {
1260
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_CONFIGURATION", language: "android", message });
1261
+ }
1262
+ /**
1263
+ * Throws a stable invalid-resource diagnostic.
1264
+ * @param {string} message - Diagnostic message.
1265
+ * @returns {never} Never returns.
1266
+ */
1267
+ function invalidResource(message) {
1268
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_RESOURCE", language: "android", message });
1269
+ }
1270
+ /**
1271
+ * Throws a stable invalid-path diagnostic.
1272
+ * @param {string} message - Diagnostic message.
1273
+ * @returns {never} Never returns.
1274
+ */
1275
+ function invalidPath(message) {
1276
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_PATH", language: "android", message });
1277
+ }
1278
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5kcm9pZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZW5kcy9hbmRyb2lkLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sYUFBYSxDQUFBO0FBQ3RDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxhQUFhLENBQUE7QUFDeEMsT0FBTyxFQUFDLGdDQUFnQyxFQUFFLGtCQUFrQixFQUFDLE1BQU0scUJBQXFCLENBQUE7QUFDeEYsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sc0JBQXNCLENBQUE7QUFDdEQsT0FBTyxFQUFDLHFCQUFxQixFQUFFLHFCQUFxQixFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDN0UsT0FBTyxFQUFDLGVBQWUsRUFBRSxhQUFhLEVBQUMsTUFBTSxlQUFlLENBQUE7QUFDNUQsT0FBTyxFQUFDLHFCQUFxQixFQUFDLE1BQU0sd0JBQXdCLENBQUE7QUFDNUQsT0FBTyxFQUFDLHdCQUF3QixFQUFDLE1BQU0sY0FBYyxDQUFBO0FBQ3JELE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFDM0MsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLHFCQUFxQixDQUFBO0FBQ2pELE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxhQUFhLENBQUE7QUFDM0MsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGFBQWEsQ0FBQTtBQUV4QyxNQUFNLFdBQVcsR0FBRyx1QkFBdUIsQ0FBQTtBQUMzQyxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQTtBQUNoQyw2RUFBNkU7QUFDN0UsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUNyQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsS0FB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QUFhLENBQUMsS0FBSztJQUMxQixPQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxPQUFPLEtBQUssSUFBSSxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQTtBQUNoSSxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsWUFBWSxDQUFDLE9BQU87SUFDM0IsTUFBTSxJQUFJLHFCQUFxQixDQUFDLEVBQUMsSUFBSSxFQUFFLDJCQUEyQixFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFDLENBQUMsQ0FBQTtBQUNwRyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsb0JBQW9CLENBQUMsT0FBTztJQUNuQyxNQUFNLElBQUkscUJBQXFCLENBQUMsRUFBQyxJQUFJLEVBQUUsbUNBQW1DLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUMsQ0FBQyxDQUFBO0FBQzVHLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxlQUFlLENBQUMsT0FBTztJQUM5QixNQUFNLElBQUkscUJBQXFCLENBQUMsRUFBQyxJQUFJLEVBQUUsOEJBQThCLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUMsQ0FBQyxDQUFBO0FBQ3ZHLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxXQUFXLENBQUMsT0FBTztJQUMxQixNQUFNLElBQUkscUJBQXFCLENBQUMsRUFBQyxJQUFJLEVBQUUsMEJBQTBCLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUMsQ0FBQyxDQUFBO0FBQ25HLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtjcmVhdGVIYXNofSBmcm9tIFwibm9kZTpjcnlwdG9cIlxuaW1wb3J0IHtpc0RlbnNlQXJyYXl9IGZyb20gXCIuLi9hcnJheS5qc1wiXG5pbXBvcnQge2ZpbmRQb3J0YWJsZUFydGlmYWN0UGF0aENvbmZsaWN0LCBpc1NhZmVBcnRpZmFjdFBhdGh9IGZyb20gXCIuLi9hcnRpZmFjdC1wYXRoLmpzXCJcbmltcG9ydCB7Y3JlYXRlQnl0ZU1hcHBpbmd9IGZyb20gXCIuLi9iaW5hcnktbWFwcGluZy5qc1wiXG5pbXBvcnQge1NlbWFudGlmb2xkRGlhZ25vc3RpYywgdW5zdXBwb3J0ZWRDYXBhYmlsaXR5fSBmcm9tIFwiLi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge2ZpbmFsaXplTWFwcGluZywgdG9Tb3VyY2VNYXBWM30gZnJvbSBcIi4uL21hcHBpbmcuanNcIlxuaW1wb3J0IHtoYXNPbmx5VW5pY29kZVNjYWxhcnN9IGZyb20gXCIuLi9zZW1hbnRpYy9zY2FsYXJzLmpzXCJcbmltcG9ydCB7cHJlZmxpZ2h0U2VtYW50aWNQcm9ncmFtfSBmcm9tIFwiLi9wcm9ncmFtLmpzXCJcbmltcG9ydCB7ZW1pdFNjYWxhclR5cGV9IGZyb20gXCIuL3NjYWxhcnMuanNcIlxuaW1wb3J0IHtrb3RsaW5SdW50aW1lfSBmcm9tIFwiLi9rb3RsaW4tcnVudGltZS5qc1wiXG5pbXBvcnQge2VtaXRLb3RsaW5CbG9ja30gZnJvbSBcIi4va290bGluLmpzXCJcbmltcG9ydCB7U291cmNlV3JpdGVyfSBmcm9tIFwiLi93cml0ZXIuanNcIlxuXG5jb25zdCBwcm9qZWN0Um9vdCA9IFwiZ2VuZXJhdGVkL2FuZHJvaWQtYXBwXCJcbmNvbnN0IGdlbmVyYXRvclZlcnNpb24gPSBcIjAuNC4wXCJcbi8qKiBAdHlwZSB7UmVhZG9ubHk8U2V0PGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTGFuZ3VhZ2U+Pn0gKi9cbmNvbnN0IGFuZHJvaWRTb3VyY2VMYW5ndWFnZXMgPSBuZXcgU2V0KFtcbiAgXCJwaHBcIiwgXCJydWJ5XCIsIFwiamF2YXNjcmlwdFwiLCBcInR5cGVzY3JpcHRcIiwgXCJqYXZhXCIsIFwia290bGluXCIsIFwicHl0aG9uXCIsIFwiY3NoYXJwXCIsIFwiZ29cIiwgXCJjXCIsIFwiY3BwXCIsIFwicnVzdFwiLCBcInN3aWZ0XCIsIFwiZGFydFwiLCBcInppZ1wiXG5dKVxuY29uc3QgcmVxdWVzdEZpZWxkcyA9IG5ldyBTZXQoW1wiYXNzZXRzXCIsIFwiY29uZmlndXJhdGlvblwiLCBcImxhbmd1YWdlXCIsIFwibW9kdWxlXCIsIFwicHJvZ3JhbVwiLCBcInJlc291cmNlc1wiLCBcInJvbGVcIl0pXG5jb25zdCBjb25maWd1cmF0aW9uRmllbGRzID0gbmV3IFNldChbXG4gIFwiYWN0aXZpdHlDbGFzc05hbWVcIiwgXCJhcHBsaWNhdGlvbklkXCIsIFwiYnVpbGRUb29sc1ZlcnNpb25cIiwgXCJjb21waWxlU2RrXCIsIFwiZGlzcGxheU5hbWVcIiwgXCJtaW5pbXVtU2RrXCIsIFwibmFtZXNwYWNlXCIsXG4gIFwib3JpZW50YXRpb25cIiwgXCJwYWNrYWdlTmFtZVwiLCBcInBlcm1pc3Npb25zXCIsIFwicHJvZHVjdE5hbWVcIiwgXCJ0YXJnZXRTZGtcIiwgXCJ0aGVtZVwiLCBcInZlcnNpb25Db2RlXCIsIFwidmVyc2lvbk5hbWVcIlxuXSlcbmNvbnN0IHJlc291cmNlRmllbGRzID0gbmV3IFNldChbXCJjb250ZW50XCIsIFwibWVkaWFUeXBlXCIsIFwicGF0aFwiLCBcInNoYTI1NlwiXSlcbmNvbnN0IGtvdGxpbktleXdvcmRzID0gbmV3IFNldChbXG4gIFwiYXNcIiwgXCJicmVha1wiLCBcImNsYXNzXCIsIFwiY29udGludWVcIiwgXCJkb1wiLCBcImVsc2VcIiwgXCJmYWxzZVwiLCBcImZvclwiLCBcImZ1blwiLCBcImlmXCIsIFwiaW5cIiwgXCJpbnRlcmZhY2VcIiwgXCJpc1wiLCBcIm51bGxcIixcbiAgXCJvYmplY3RcIiwgXCJwYWNrYWdlXCIsIFwicmV0dXJuXCIsIFwic3VwZXJcIiwgXCJ0aGlzXCIsIFwidGhyb3dcIiwgXCJ0cnVlXCIsIFwidHJ5XCIsIFwidHlwZWFsaWFzXCIsIFwidHlwZW9mXCIsIFwidmFsXCIsIFwidmFyXCIsIFwid2hlblwiLCBcIndoaWxlXCJcbl0pXG5jb25zdCBhbmRyb2lkU2NhZmZvbGRTeW1ib2xzID0gbmV3IFNldChbXG4gIFwiQWN0aXZpdHlcIiwgXCJCYXNlNjRcIiwgXCJCdW5kbGVcIiwgXCJJbGxlZ2FsU3RhdGVFeGNlcHRpb25cIiwgXCJJbnN0cnVtZW50YXRpb25cIiwgXCJJbnRlbnRcIiwgXCJSXCIsIFwiU2VtYW50aWZvbGRFbnRyeVRlc3RcIixcbiAgXCJTZW1hbnRpZm9sZFVpSW5zdHJ1bWVudGF0aW9uXCIsIFwiU3RhbmRhcmRDaGFyc2V0c1wiLCBcIlN0cmluZ1wiLCBcIlN1cHByZXNzTGludFwiLCBcIlRlc3RcIiwgXCJUZXh0Vmlld1wiLCBcIlRocm93YWJsZVwiLCBcIlZpZXdcIlxuXSlcbmNvbnN0IG1lZGlhVHlwZVBhdHRlcm4gPSAvXltBLVphLXowLTkhIyQmXl8uKy1dK1xcL1tBLVphLXowLTkhIyQmXl8uKy1dKyg/OjtbXFx1MDAyMC1cXHUwMDdlXSspPyQvdVxuY29uc3Qgc2VtYW50aWNWZXJzaW9uUGF0dGVybiA9IC9eKD86MHxbMS05XVswLTldKilcXC4oPzowfFsxLTldWzAtOV0qKVxcLig/OjB8WzEtOV1bMC05XSopKD86LSg/OjB8WzEtOV1bMC05XSp8W0EtWmEtei1dW0EtWmEtejAtOS1dKikoPzpcXC4oPzowfFsxLTldWzAtOV0qfFtBLVphLXotXVtBLVphLXowLTktXSopKSopPyg/OlxcK1tBLVphLXowLTktXSsoPzpcXC5bQS1aYS16MC05LV0rKSopPyQvdVxuY29uc3QgdG9vbGNoYWluID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGFuZHJvaWRHcmFkbGVQbHVnaW46IFwiOC4xMS4xXCIsXG4gIGFyY2hpdmVzOiB7XG4gICAgYnVpbGRUb29sczoge1xuICAgICAgcmV2aXNpb246IFwiMzUuMC4wXCIsXG4gICAgICBzaGEyNTY6IFwiYmQzYTQ5NjY5MTJlYjhiMzBlZDBkMDBiMGNkYTZiNjU0M2I5NDlkNWZmZTAwYmVhNTRjMDRjODFlMTU2MWQ4OFwiLFxuICAgICAgdXJsOiBcImh0dHBzOi8vZGwuZ29vZ2xlLmNvbS9hbmRyb2lkL3JlcG9zaXRvcnkvYnVpbGQtdG9vbHNfcjM1X2xpbnV4LnppcFwiXG4gICAgfSxcbiAgICBjb21tYW5kTGluZVRvb2xzOiB7XG4gICAgICByZXZpc2lvbjogXCIxMTA3NjcwOFwiLFxuICAgICAgc2hhMjU2OiBcIjJkMmQ1MDg1N2U0ZWI1NTNhZjVhNmRjM2FkNTA3YTE3YWRmNDNkMTE1MjY0YjFhZmMxMTZmOTVjOTJlNWUyNThcIixcbiAgICAgIHVybDogXCJodHRwczovL2RsLmdvb2dsZS5jb20vYW5kcm9pZC9yZXBvc2l0b3J5L2NvbW1hbmRsaW5ldG9vbHMtbGludXgtMTEwNzY3MDhfbGF0ZXN0LnppcFwiXG4gICAgfSxcbiAgICBlbXVsYXRvcjoge1xuICAgICAgYnVpbGRJZDogXCIxMzYxMDQxMlwiLFxuICAgICAgcmV2aXNpb246IFwiMzUuNi4xMVwiLFxuICAgICAgc2hhMjU2OiBcIjJmZTJiNTZmZTkzY2U3NWUxZDQ3OGE0MDE2MjEzMTM4MWQ5MTFjMzU1ZWZlYWVkYjU0ZGQxZTBkMDg5N2E1Y2ZcIixcbiAgICAgIHVybDogXCJodHRwczovL2VkZ2VkbC5tZS5ndnQxLmNvbS9lZGdlZGwvYW5kcm9pZC9yZXBvc2l0b3J5L2VtdWxhdG9yLWxpbnV4X3g2NC0xMzYxMDQxMi56aXBcIlxuICAgIH0sXG4gICAgcGxhdGZvcm06IHtcbiAgICAgIHJldmlzaW9uOiBcIjM1LXIyXCIsXG4gICAgICBzaGEyNTY6IFwiMDk4OGNhY2FkMDFiMzhhMThhNDdiYWMxNGEwNjk1ZjI0NmJjNzZjMWIwNmMwZWViOGViMGRjODI1YWIwYzhlMFwiLFxuICAgICAgdXJsOiBcImh0dHBzOi8vZGwuZ29vZ2xlLmNvbS9hbmRyb2lkL3JlcG9zaXRvcnkvcGxhdGZvcm0tMzVfcjAyLnppcFwiXG4gICAgfSxcbiAgICBwbGF0Zm9ybVRvb2xzOiB7XG4gICAgICByZXZpc2lvbjogXCIzNy4wLjFcIixcbiAgICAgIHNoYTI1NjogXCJkMjMwZjEzODQyZjYwZjc4MmE4NjQ1ZjljODEzZjhmODQ1YmYzNjA4OWVhNzI4OWYyOGM0OGYxNzk3OTMxM2YxXCIsXG4gICAgICB1cmw6IFwiaHR0cHM6Ly9kbC5nb29nbGUuY29tL2FuZHJvaWQvcmVwb3NpdG9yeS9wbGF0Zm9ybS10b29sc19yMzcuMC4xLWxpbnV4LnppcFwiXG4gICAgfSxcbiAgICBzeXN0ZW1JbWFnZToge1xuICAgICAgcmV2aXNpb246IFwiMzUtZ29vZ2xlX2FwaXMteDg2XzY0LXI5XCIsXG4gICAgICBzaGEyNTY6IFwiYzY3YjliYTBmZjViYzBlYjZkMDQ2ODcxYmZhMjI4YWYxNGQ0ZDQ3YjAyZjBjZGFlOTRmMDQ4ZTUxMWI3NTY2ZVwiLFxuICAgICAgdXJsOiBcImh0dHBzOi8vZGwuZ29vZ2xlLmNvbS9hbmRyb2lkL3JlcG9zaXRvcnkvc3lzLWltZy9nb29nbGVfYXBpcy94ODZfNjQtMzVfcjA5LnppcFwiXG4gICAgfVxuICB9LFxuICBidWlsZFRvb2xzOiBcIjM1LjAuMFwiLFxuICBjb21tYW5kTGluZVRvb2xzOiBcIjExMDc2NzA4XCIsXG4gIGNvbXBpbGVTZGs6IDM1LFxuICBlbXVsYXRvcjogXCIzNS42LjExXCIsXG4gIGdyYWRsZTogXCI4LjEzXCIsXG4gIGphdmE6IFwiMjEuMC44XCIsXG4gIGtvdGxpbjogXCIyLjIuMTBcIixcbiAga290bGluQ29tcGlsZXJTaGEyNTY6IFwiMzAyZDFkOGU2NzFlNWMzMjA3ZTZlZDYyZmYxMWZiNTU1NDYyYTYyOGUyMmExMTU4MjU0ZGNhYWY3ZTczOTRiY1wiLFxuICBzeXN0ZW1JbWFnZTogXCJzeXN0ZW0taW1hZ2VzO2FuZHJvaWQtMzU7Z29vZ2xlX2FwaXM7eDg2XzY0XCIsXG4gIHRhcmdldFNkazogMzVcbn0pXG5jb25zdCBleGNsdWRlZFBhdGhQYXR0ZXJucyA9IE9iamVjdC5mcmVlemUoW1wiLmdyYWRsZS8qKlwiLCBcIioqL2J1aWxkLyoqXCIsIFwibG9jYWwucHJvcGVydGllc1wiXSlcbmNvbnN0IGFuZHJvaWRLb3RsaW5SdW50aW1lID0gYEBmaWxlOlN1cHByZXNzKFwiUExBVEZPUk1fQ0xBU1NfTUFQUEVEX1RPX0tPVExJTlwiKVxuXG5wYWNrYWdlIF9fUEFDS0FHRV9fLnNlbWFudGljXG5cbiR7a290bGluUnVudGltZS5yZXBsYWNlQWxsKFwicHJpdmF0ZSBcIiwgXCJpbnRlcm5hbCBcIil9XG5pbnRlcm5hbCBjbGFzcyBTZW1hbnRpZm9sZE91dHB1dFNpbmsge1xuICBwcml2YXRlIHZhbCB2YWx1ZXM6IGphdmEudXRpbC5BcnJheUxpc3Q8U3RyaW5nPiA9IGphdmEudXRpbC5BcnJheUxpc3Q8U3RyaW5nPigpXG5cbiAgZnVuIHJlc2V0KCkge1xuICAgIHZhbHVlcy5jbGVhcigpXG4gIH1cblxuICBmdW4gd3JpdGUodmFsdWU6IExvbmcpIHtcbiAgICB2YWx1ZXMuYWRkKHZhbHVlLnRvU3RyaW5nKCkpXG4gIH1cblxuICBmdW4gd3JpdGUodmFsdWU6IEJvb2xlYW4pIHtcbiAgICB2YWx1ZXMuYWRkKGlmICh2YWx1ZSkgXCJ0cnVlXCIgZWxzZSBcImZhbHNlXCIpXG4gIH1cblxuICBmdW4gd3JpdGUodmFsdWU6IFN0cmluZykge1xuICAgIHZhbHVlcy5hZGQodmFsdWUpXG4gIH1cblxuICBmdW4gc25hcHNob3QoKTogamF2YS51dGlsLkFycmF5TGlzdDxTdHJpbmc+ID0gamF2YS51dGlsLkFycmF5TGlzdDxTdHJpbmc+KHZhbHVlcylcbn1cbmBcblxuLyoqIEB0eXBlZGVmIHt7Y29udGVudDogc3RyaW5nIHwgVWludDhBcnJheSwgY29udGVudEtpbmQ6IFwiYmluYXJ5XCIgfCBcInRleHRcIiwgZnVsbFBhdGg6IHN0cmluZywgbWVkaWFUeXBlOiBzdHJpbmcsIHBhdGg6IHN0cmluZywgc2hhMjU2OiBzdHJpbmd9fSBBbmRyb2lkSW5wdXRGaWxlICovXG4vKiogQHR5cGVkZWYge3tlbmQ6IG51bWJlciwgZmllbGQ6IHN0cmluZywgcGF0aDogc3RyaW5nLCBzdGFydDogbnVtYmVyfX0gQ29uZmlndXJhdGlvblNwYW4gKi9cblxuLyoqXG4gKiBQcmVmbGlnaHRzIGEgY29tcGxldGUgQW5kcm9pZCBhcHBsaWNhdGlvbiByZXF1ZXN0IGJlZm9yZSBhbGxvY2F0aW5nIGEgc291cmNlIHdyaXRlci5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IGlucHV0IC0gQ2FuZGlkYXRlIGFwcGxpY2F0aW9uIHJlcXVlc3QuXG4gKiBAcmV0dXJucyB7e2Fzc2V0czogQW5kcm9pZElucHV0RmlsZVtdLCBjb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5BbmRyb2lkQXBwbGljYXRpb25Db25maWd1cmF0aW9uLCBtb2R1bGVQYXRoczogTWFwPHN0cmluZywgc3RyaW5nPiwgbW9kdWxlczogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGVbXSwgcGFja2FnZVBhdGg6IHN0cmluZywgcHJvZ3JhbTogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNQcm9ncmFtLCByZXNvdXJjZXM6IEFuZHJvaWRJbnB1dEZpbGVbXSwgc291cmNlczoge2NvbnRlbnQ6IHN0cmluZywgZmlsZW5hbWU6IHN0cmluZywgbGFuZ3VhZ2U/OiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY0xhbmd1YWdlfVtdfX0gUHJlcGFyZWQgYXBwbGljYXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmVmbGlnaHRBbmRyb2lkQXBwbGljYXRpb24oaW5wdXQpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KGlucHV0KSB8fCBPYmplY3Qua2V5cyhpbnB1dCkuc29tZShrZXkgPT4gIXJlcXVlc3RGaWVsZHMuaGFzKGtleSkpIHx8XG4gICAgQm9vbGVhbihpbnB1dC5tb2R1bGUpID09IEJvb2xlYW4oaW5wdXQucHJvZ3JhbSkpIHtcbiAgICBpbnZhbGlkSW5wdXQoXCJBbmRyb2lkIGFwcGxpY2F0aW9uIGdlbmVyYXRpb24gcmVxdWlyZXMgYSBjbG9zZWQgcmVxdWVzdCB3aXRoIGV4YWN0bHkgb25lIHNlbWFudGljIG1vZHVsZSBvciBwcm9ncmFtLlwiKVxuICB9XG4gIGlmIChpbnB1dC5sYW5ndWFnZSAhPT0gdW5kZWZpbmVkICYmIGlucHV0Lmxhbmd1YWdlICE9IFwiYW5kcm9pZFwiIHx8IGlucHV0LnJvbGUgIT09IHVuZGVmaW5lZCAmJiBpbnB1dC5yb2xlICE9IFwiYXBwbGljYXRpb25cIikge1xuICAgIGludmFsaWRJbnB1dChcIkFuZHJvaWQgYXBwbGljYXRpb24gZ2VuZXJhdGlvbiBhY2NlcHRzIG9ubHkgdGhlIEFuZHJvaWQgYXBwbGljYXRpb24gcm9sZS5cIilcbiAgfVxuICBjb25zdCBjb25maWd1cmF0aW9uID0gbm9ybWFsaXplQ29uZmlndXJhdGlvbihpbnB1dC5jb25maWd1cmF0aW9uKVxuICBjb25zdCBwcm9ncmFtID0gaW5wdXQucHJvZ3JhbSA/PyBub3JtYWxpemVTaW5nbGVNb2R1bGUoXG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZSB8IHVuZGVmaW5lZH0gKi8gKGlucHV0Lm1vZHVsZSkpXG4gIGNvbnN0IHByZXBhcmVkID0gcHJlZmxpZ2h0U2VtYW50aWNQcm9ncmFtKHtcbiAgICBiYWNrZW5kTGFuZ3VhZ2U6IFwia290bGluXCIsXG4gICAgZGlhZ25vc3RpY0xhbmd1YWdlOiBcImFuZHJvaWRcIixcbiAgICBwcm9ncmFtOiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljUHJvZ3JhbX0gKi8gKHByb2dyYW0pLFxuICAgIHNvdXJjZUxhbmd1YWdlczogYW5kcm9pZFNvdXJjZUxhbmd1YWdlc1xuICB9KVxuICB2YWxpZGF0ZUFjdGl2aXR5Q2xhc3NOYW1lKGNvbmZpZ3VyYXRpb24uYWN0aXZpdHlDbGFzc05hbWUsIHByZXBhcmVkLnByb2dyYW0uZW50cnlNb2R1bGUpXG4gIGNvbnN0IHBhY2thZ2VQYXRoID0gY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZS5yZXBsYWNlQWxsKFwiLlwiLCBcIi9cIilcbiAgY29uc3Qgc2VtYW50aWNSb290ID0gYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9rb3RsaW4vJHtwYWNrYWdlUGF0aH0vc2VtYW50aWNgXG4gIGNvbnN0IG1vZHVsZVBhdGhzID0gbmV3IE1hcChwcmVwYXJlZC5tb2R1bGVzLm1hcChtb2R1bGUgPT4gW1xuICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoUmVmbGVjdC5nZXQobW9kdWxlLCBcImlkXCIpKSxcbiAgICBgJHtzZW1hbnRpY1Jvb3R9LyR7bW9kdWxlTmFtZSgvKiogQHR5cGUge3N0cmluZ30gKi8gKFJlZmxlY3QuZ2V0KG1vZHVsZSwgXCJpZFwiKSkpfS5rdGBcbiAgXSkpXG4gIGNvbnN0IHJlc291cmNlcyA9IG5vcm1hbGl6ZUlucHV0RmlsZXMoaW5wdXQucmVzb3VyY2VzLCBcInJlc291cmNlXCIpXG4gIGNvbnN0IGFzc2V0cyA9IG5vcm1hbGl6ZUlucHV0RmlsZXMoaW5wdXQuYXNzZXRzLCBcImFzc2V0XCIpXG4gIGNvbnN0IGZpeGVkUGF0aHMgPSBhcHBsaWNhdGlvblBhdGhzKGNvbmZpZ3VyYXRpb24sIG1vZHVsZVBhdGhzKVxuICBjb25zdCBjb21wbGV0ZVBhdGhzID0gW1xuICAgIC4uLmZpeGVkUGF0aHMsXG4gICAgLi4ucmVzb3VyY2VzLm1hcCgoe2Z1bGxQYXRofSkgPT4gZnVsbFBhdGgpLFxuICAgIC4uLmFzc2V0cy5tYXAoKHtmdWxsUGF0aH0pID0+IGZ1bGxQYXRoKVxuICBdXG4gIGNvbnN0IGNvbmZsaWN0ID0gZmluZFBvcnRhYmxlQXJ0aWZhY3RQYXRoQ29uZmxpY3QoY29tcGxldGVQYXRocylcblxuICBpZiAoY29uZmxpY3QpIHtcbiAgICBpbnZhbGlkUGF0aChgQXBwbGljYXRpb24gYXJ0aWZhY3QgcGF0aCAnJHtjb25mbGljdC5wYXRofScgaGFzIGEgJHtjb25mbGljdC5raW5kfSBjb25mbGljdCR7Y29uZmxpY3Qub3RoZXIgPyBgIHdpdGggJyR7Y29uZmxpY3Qub3RoZXJ9J2AgOiBcIlwifS5gKVxuICB9XG5cbiAgcmV0dXJuIHsuLi5wcmVwYXJlZCwgYXNzZXRzLCBjb25maWd1cmF0aW9uLCBtb2R1bGVQYXRocywgcGFja2FnZVBhdGgsIHJlc291cmNlc31cbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgb25lIGNvbXBsZXRlIGRldGVybWluaXN0aWMgQW5kcm9pZC9Lb3RsaW4gcHJvamVjdC5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IGlucHV0IC0gQXBwbGljYXRpb24gZ2VuZXJhdGlvbiByZXF1ZXN0LlxuICogQHJldHVybnMge3thcnRpZmFjdHM6IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0W10sIG1ldGFkYXRhOiB7YXBwbGljYXRpb25NYW5pZmVzdDogc3RyaW5nLCBwbGF0Zm9ybVF1YWxpZmljYXRpb246IHN0cmluZ30sIHRhcmdldDogXCJhbmRyb2lkXCJ9fSBDYW5kaWRhdGUgYXJ0aWZhY3Qgc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVBbmRyb2lkQXBwbGljYXRpb24oaW5wdXQpIHtcbiAgY29uc3QgcHJlcGFyZWQgPSBwcmVmbGlnaHRBbmRyb2lkQXBwbGljYXRpb24oaW5wdXQpXG4gIGNvbnN0IGNvbmZpZ3VyYXRpb25TcGFucyA9IC8qKiBAdHlwZSB7Q29uZmlndXJhdGlvblNwYW5bXX0gKi8gKFtdKVxuICBjb25zdCBjb25maWd1cmF0aW9uID0gcHJlcGFyZWQuY29uZmlndXJhdGlvblxuICBjb25zdCBwYWNrYWdlUGF0aCA9IHByZXBhcmVkLnBhY2thZ2VQYXRoXG4gIGNvbnN0IHNlbWFudGljQXJ0aWZhY3RzID0gcmVuZGVyU2VtYW50aWNBcnRpZmFjdHMocHJlcGFyZWQpXG4gIGNvbnN0IGFydGlmYWN0cyA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3RbXX0gKi8gKFtcbiAgICBjb25maWd1cmVkVGV4dChgJHtwcm9qZWN0Um9vdH0vYXBwL2J1aWxkLmdyYWRsZS5rdHNgLCBcIm1hbmlmZXN0XCIsIHJlbmRlckFwcEJ1aWxkKGNvbmZpZ3VyYXRpb24sIGNvbmZpZ3VyYXRpb25TcGFucyksXG4gICAgICBcIlBpbm5lZCBkZXBlbmRlbmN5LW1pbmltYWwgQW5kcm9pZCBhcHBsaWNhdGlvbiBidWlsZC5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvYW5kcm9pZFRlc3QvQW5kcm9pZE1hbmlmZXN0LnhtbGAsIFwibWFuaWZlc3RcIixcbiAgICAgIHJlbmRlckFuZHJvaWRUZXN0TWFuaWZlc3QoY29uZmlndXJhdGlvbiwgY29uZmlndXJhdGlvblNwYW5zKSwgXCJQbGF0Zm9ybS1vbmx5IEFuZHJvaWQgaW5zdHJ1bWVudGF0aW9uIGRlY2xhcmF0aW9uLlwiKSxcbiAgICBjb25maWd1cmVkVGV4dChgJHtwcm9qZWN0Um9vdH0vYXBwL3NyYy9hbmRyb2lkVGVzdC9rb3RsaW4vJHtwYWNrYWdlUGF0aH0vU2VtYW50aWZvbGRVaUluc3RydW1lbnRhdGlvbi5rdGAsIFwic3VwcG9ydFwiLFxuICAgICAgcmVuZGVySW5zdHJ1bWVudGF0aW9uKGNvbmZpZ3VyYXRpb24sIGNvbmZpZ3VyYXRpb25TcGFucyksIFwiUGxhdGZvcm0tb25seSBhY2Nlc3NpYmlsaXR5IGFuZCBsaWZlY3ljbGUgYXNzZXJ0aW9uLlwiKSxcbiAgICBjb25maWd1cmVkVGV4dChgJHtwcm9qZWN0Um9vdH0vYXBwL3NyYy9tYWluL0FuZHJvaWRNYW5pZmVzdC54bWxgLCBcIm1hbmlmZXN0XCIsXG4gICAgICByZW5kZXJBbmRyb2lkTWFuaWZlc3QoY29uZmlndXJhdGlvbiwgY29uZmlndXJhdGlvblNwYW5zKSwgXCJDbG9zZWQgYWxsb3dsaXN0ZWQgQW5kcm9pZCBhcHBsaWNhdGlvbiBtYW5pZmVzdC5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9rb3RsaW4vJHtwYWNrYWdlUGF0aH0vJHtjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lfS5rdGAsIFwiZW50cnlcIixcbiAgICAgIHJlbmRlckFjdGl2aXR5KGNvbmZpZ3VyYXRpb24sIHByZXBhcmVkLnByb2dyYW0uZW50cnlNb2R1bGUsIGNvbmZpZ3VyYXRpb25TcGFucyksXG4gICAgICBcIlN5bnRoZXRpYyBBbmRyb2lkIGFjdGl2aXR5IGxpZmVjeWNsZSBhbmQgbmF0aXZlIG91dHB1dCB2aWV3IGJpbmRpbmcuXCIpLFxuICAgIC4uLnNlbWFudGljQXJ0aWZhY3RzLFxuICAgIHN5bnRoZXRpY1RleHQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9yZXMvbGF5b3V0L2FjdGl2aXR5X21haW4ueG1sYCwgXCJyZXNvdXJjZVwiLCByZW5kZXJMYXlvdXQoKSxcbiAgICAgIFwiU3ludGhldGljIG9uZS12aWV3IEFuZHJvaWQgbGF5b3V0IGFuZCBhY2Nlc3NpYmlsaXR5IGlkZW50aXR5LlwiKSxcbiAgICBjb25maWd1cmVkVGV4dChgJHtwcm9qZWN0Um9vdH0vYXBwL3NyYy9tYWluL3Jlcy92YWx1ZXMvc3RyaW5ncy54bWxgLCBcInJlc291cmNlXCIsXG4gICAgICByZW5kZXJTdHJpbmdzKGNvbmZpZ3VyYXRpb24sIGNvbmZpZ3VyYXRpb25TcGFucyksIFwiRXNjYXBlZCBhcHBsaWNhdGlvbiBsYWJlbHMgZGVyaXZlZCBmcm9tIGNvbmZpZ3VyYXRpb24uXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9yZXMvdmFsdWVzL3RoZW1lcy54bWxgLCBcInJlc291cmNlXCIsIHJlbmRlclRoZW1lKCksXG4gICAgICBcIkNsb3NlZCBwbGF0Zm9ybS1uYXRpdmUgYXBwbGljYXRpb24gdGhlbWUuXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9yZXMveG1sL2JhY2t1cF9ydWxlcy54bWxgLCBcInJlc291cmNlXCIsIHJlbmRlckJhY2t1cFJ1bGVzKCksXG4gICAgICBcIkNsb3NlZCBBUEkgMjMtMzAgZnVsbC1iYWNrdXAgZXhjbHVzaW9ucy5cIiksXG4gICAgc3ludGhldGljVGV4dChgJHtwcm9qZWN0Um9vdH0vYXBwL3NyYy9tYWluL3Jlcy94bWwvZGF0YV9leHRyYWN0aW9uX3J1bGVzLnhtbGAsIFwicmVzb3VyY2VcIiwgcmVuZGVyRGF0YUV4dHJhY3Rpb25SdWxlcygpLFxuICAgICAgXCJDbG9zZWQgQW5kcm9pZCAxMisgY2xvdWQtYmFja3VwIGFuZCBkZXZpY2UtdHJhbnNmZXIgZXhjbHVzaW9ucy5cIiksXG4gICAgY29uZmlndXJlZFRleHQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvdGVzdC9rb3RsaW4vJHtwYWNrYWdlUGF0aH0vU2VtYW50aWZvbGRFbnRyeVRlc3Qua3RgLCBcInN1cHBvcnRcIixcbiAgICAgIHJlbmRlclVuaXRUZXN0KGNvbmZpZ3VyYXRpb24sIHByZXBhcmVkLnByb2dyYW0uZW50cnlNb2R1bGUsIGNvbmZpZ3VyYXRpb25TcGFucyksXG4gICAgICBcIkpVbml0IHRlc3Qtc2NvcGUtb25seSBzZW1hbnRpYyBkZXRlcm1pbmlzbSBhc3NlcnRpb24uXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoYCR7cHJvamVjdFJvb3R9L2J1aWxkLmdyYWRsZS5rdHNgLCBcIm1hbmlmZXN0XCIsIHJlbmRlclJvb3RCdWlsZCgpLFxuICAgICAgXCJQaW5uZWQgQW5kcm9pZCBhbmQgS290bGluIGJ1aWxkIHBsdWdpbnMuXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoYCR7cHJvamVjdFJvb3R9L2dyYWRsZS5wcm9wZXJ0aWVzYCwgXCJzdXBwb3J0XCIsIHJlbmRlckdyYWRsZVByb3BlcnRpZXMoKSxcbiAgICAgIFwiUGlubmVkIGhlcm1ldGljIEdyYWRsZSBwcm9jZXNzIHByb3BlcnRpZXMuXCIpLFxuICAgIGNvbmZpZ3VyZWRUZXh0KGAke3Byb2plY3RSb290fS9zZXR0aW5ncy5ncmFkbGUua3RzYCwgXCJtYW5pZmVzdFwiLCByZW5kZXJTZXR0aW5ncyhjb25maWd1cmF0aW9uLCBjb25maWd1cmF0aW9uU3BhbnMpLFxuICAgICAgXCJDbG9zZWQgb2ZmaWNpYWwgR3JhZGxlIHBsdWdpbiBhbmQgZGVwZW5kZW5jeSByZXBvc2l0b3JpZXMuXCIpLFxuICAgIC4uLnByZXBhcmVkLnJlc291cmNlcy5tYXAoaW5wdXRGaWxlQXJ0aWZhY3QpLFxuICAgIC4uLnByZXBhcmVkLmFzc2V0cy5tYXAoaW5wdXRGaWxlQXJ0aWZhY3QpXG4gIF0pXG5cbiAgYXJ0aWZhY3RzLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0LnBhdGggPCByaWdodC5wYXRoID8gLTEgOiBsZWZ0LnBhdGggPiByaWdodC5wYXRoID8gMSA6IDApXG4gIGNvbnN0IG1hbmlmZXN0UGF0aCA9IGAke3Byb2plY3RSb290fS9zZW1hbnRpZm9sZC1wcm9qZWN0Lmpzb25gXG5cbiAgYXJ0aWZhY3RzLnB1c2goc3ludGhldGljVGV4dChtYW5pZmVzdFBhdGgsIFwibWFuaWZlc3RcIixcbiAgICByZW5kZXJQcm9qZWN0TWFuaWZlc3QocHJlcGFyZWQsIGFydGlmYWN0cywgbWFuaWZlc3RQYXRoLCBjb25maWd1cmF0aW9uU3BhbnMpLFxuICAgIFwiVmVyc2lvbmVkIEFuZHJvaWQgcHJvamVjdCBvd25lcnNoaXAsIHRvb2xjaGFpbiwgYW5kIHByb3ZlbmFuY2UgbWFuaWZlc3QuXCIpKVxuXG4gIHJldHVybiB7XG4gICAgYXJ0aWZhY3RzLFxuICAgIG1ldGFkYXRhOiB7YXBwbGljYXRpb25NYW5pZmVzdDogbWFuaWZlc3RQYXRoLCBwbGF0Zm9ybVF1YWxpZmljYXRpb246IFwidGVuc29yYnV6ei1rdm1cIn0sXG4gICAgdGFyZ2V0OiBcImFuZHJvaWRcIlxuICB9XG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgbWFwcGVkIHNlbWFudGljIEtvdGxpbiBhcnRpZmFjdHMgZm9yIGV2ZXJ5IHByb2dyYW0gbW9kdWxlLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBwcmVmbGlnaHRBbmRyb2lkQXBwbGljYXRpb24+fSBwcmVwYXJlZCAtIFByZXBhcmVkIGFwcGxpY2F0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0W119IFNlbWFudGljIEtvdGxpbiBhcnRpZmFjdHMuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclNlbWFudGljQXJ0aWZhY3RzKHByZXBhcmVkKSB7XG4gIGNvbnN0IHNlbWFudGljUm9vdCA9IGAke3Byb2plY3RSb290fS9hcHAvc3JjL21haW4va290bGluLyR7cHJlcGFyZWQucGFja2FnZVBhdGh9L3NlbWFudGljYFxuICAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0W119ICovXG4gIGNvbnN0IGFydGlmYWN0cyA9IFtzeW50aGV0aWNUZXh0KGAke3NlbWFudGljUm9vdH0vU2VtYW50aWZvbGRSdW50aW1lLmt0YCwgXCJzdXBwb3J0XCIsXG4gICAgYW5kcm9pZEtvdGxpblJ1bnRpbWUucmVwbGFjZUFsbChcIl9fUEFDS0FHRV9fXCIsIHByZXBhcmVkLmNvbmZpZ3VyYXRpb24ucGFja2FnZU5hbWUpLFxuICAgIFwiU2hhcmVkIEFuZHJvaWQgYXBwbGljYXRpb24gb3V0cHV0IGNhcHR1cmUgYW5kIGNoZWNrZWQgS290bGluIHNjYWxhciBzdXBwb3J0LlwiKV1cbiAgY29uc3QgZGVjbGFyYXRpb25zID0gbmV3IE1hcCgpXG5cbiAgZm9yIChjb25zdCBtb2R1bGUgb2YgcHJlcGFyZWQubW9kdWxlcykge1xuICAgIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgbW9kdWxlLmZ1bmN0aW9ucykgZGVjbGFyYXRpb25zLnNldChkZWNsYXJhdGlvbi5pZCwge1xuICAgICAgZGVjbGFyYXRpb24sXG4gICAgICBtb2R1bGVJZDogLyoqIEB0eXBlIHtzdHJpbmd9ICovIChSZWZsZWN0LmdldChtb2R1bGUsIFwiaWRcIikpXG4gICAgfSlcbiAgfVxuICBmb3IgKGNvbnN0IG1vZHVsZSBvZiBwcmVwYXJlZC5tb2R1bGVzKSB7XG4gICAgY29uc3QgbW9kdWxlSWQgPSAvKiogQHR5cGUge3N0cmluZ30gKi8gKFJlZmxlY3QuZ2V0KG1vZHVsZSwgXCJpZFwiKSlcbiAgICBjb25zdCBmaWxlbmFtZSA9IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAocHJlcGFyZWQubW9kdWxlUGF0aHMuZ2V0KG1vZHVsZUlkKSlcbiAgICBjb25zdCBzaW5rTmFtZSA9IG91dHB1dFNpbmtOYW1lKG1vZHVsZSlcbiAgICBjb25zdCB3cml0ZXIgPSBuZXcgU291cmNlV3JpdGVyKHtcbiAgICAgIGNhbGxBcmd1bWVudFN1ZmZpeDogc2lua05hbWUsXG4gICAgICBjYWxsTmFtZVJlc29sdmVyOiBleHByZXNzaW9uID0+IHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSBkZWNsYXJhdGlvbnMuZ2V0KGV4cHJlc3Npb24ucmVzb2x1dGlvbj8uZGVjbGFyYXRpb25JZClcblxuICAgICAgICBpZiAoIXJlc29sdmVkKSB0aHJvdyBuZXcgVHlwZUVycm9yKGBVbmtub3duIHZhbGlkYXRlZCBBbmRyb2lkIGZ1bmN0aW9uICcke2V4cHJlc3Npb24ucmVzb2x1dGlvbj8uZGVjbGFyYXRpb25JZH0nLmApXG5cbiAgICAgICAgcmV0dXJuIGBTZW1hbnRpZm9sZE1vZHVsZSR7bW9kdWxlTmFtZShyZXNvbHZlZC5tb2R1bGVJZCl9LiR7cmVzb2x2ZWQuZGVjbGFyYXRpb24ubmFtZX1gXG4gICAgICB9LFxuICAgICAgZmlsZW5hbWUsXG4gICAgICBsYW5ndWFnZTogXCJrb3RsaW5cIixcbiAgICAgIG1ldGhvZFN0cmluZ0VxdWFsaXR5OiB0cnVlLFxuICAgICAgbW9kdWxlLFxuICAgICAgcHJvZ3JhbTogcHJlcGFyZWQucHJvZ3JhbSxcbiAgICAgIHByb2dyYW1QYXRoczogcHJlcGFyZWQubW9kdWxlUGF0aHMsXG4gICAgICBzb3VyY2VzOiBwcmVwYXJlZC5zb3VyY2VzXG4gICAgfSlcblxuICAgIHdyaXRlci5zeW50aGV0aWMoYEBmaWxlOlN1cHByZXNzKFwiUExBVEZPUk1fQ0xBU1NfTUFQUEVEX1RPX0tPVExJTlwiKVxcblxcbnBhY2thZ2UgJHtwcmVwYXJlZC5jb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lfS5zZW1hbnRpY1xcblxcbmAsXG4gICAgICBcIkFuZHJvaWQgc2VtYW50aWMgcGFja2FnZSBuYW1lc3BhY2VcIiwgW21vZHVsZV0sIFtcIlwiXSlcbiAgICBlbWl0U2VtYW50aWNNb2R1bGUod3JpdGVyLCBtb2R1bGUsIG1vZHVsZUlkLCBtb2R1bGVJZCA9PSBwcmVwYXJlZC5wcm9ncmFtLmVudHJ5TW9kdWxlLCBzaW5rTmFtZSlcbiAgICBjb25zdCBtYXBwaW5nID0gZmluYWxpemVNYXBwaW5nKHdyaXRlci5maW5pc2goKSlcblxuICAgIGFydGlmYWN0cy5wdXNoKHtcbiAgICAgIGNvbnRlbnQ6IG1hcHBpbmcuZ2VuZXJhdGVkLmNvbnRlbnQsXG4gICAgICBjb250ZW50S2luZDogXCJ0ZXh0XCIsXG4gICAgICBtZWRpYVR5cGU6IFwidGV4dC94LWtvdGxpblwiLFxuICAgICAgb3duZXJzaGlwOiBcImdlbmVyYXRlZFwiLFxuICAgICAgcGF0aDogZmlsZW5hbWUsXG4gICAgICBwcm92ZW5hbmNlOiB7a2luZDogXCJ0ZXh0XCIsIG1hcHBpbmcsIHNvdXJjZU1hcDogdG9Tb3VyY2VNYXBWMyhtYXBwaW5nKSwgc291cmNlTWFwRmlsZW5hbWU6IGAke2ZpbGVuYW1lfS5tYXBgfSxcbiAgICAgIHJvbGU6IFwic291cmNlXCJcbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIGFydGlmYWN0c1xufVxuXG4vKipcbiAqIEVtaXRzIG9uZSBuYW1lc3BhY2VkIHNlbWFudGljIG1vZHVsZSBhbmQgaXRzIGVudHJ5IGJyaWRnZSB3aGVuIGFwcGxpY2FibGUuXG4gKiBAcGFyYW0ge1NvdXJjZVdyaXRlcn0gd3JpdGVyIC0gTWFwcGVkIEtvdGxpbiB3cml0ZXIuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBQcmVwYXJlZCBtb2R1bGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbW9kdWxlSWQgLSBTdGFibGUgbW9kdWxlIGlkZW50aXR5LlxuICogQHBhcmFtIHtib29sZWFufSBlbnRyeSAtIFdoZXRoZXIgdGhpcyBtb2R1bGUgb3ducyB0aGUgZW50cnkgYmxvY2suXG4gKiBAcGFyYW0ge3N0cmluZ30gc2lua05hbWUgLSBDb2xsaXNpb24tc2FmZSBvdXRwdXQgc2luayBiaW5kaW5nLlxuICovXG5mdW5jdGlvbiBlbWl0U2VtYW50aWNNb2R1bGUod3JpdGVyLCBtb2R1bGUsIG1vZHVsZUlkLCBlbnRyeSwgc2lua05hbWUpIHtcbiAgd3JpdGVyLnN5bnRoZXRpYyhgaW50ZXJuYWwgb2JqZWN0IFNlbWFudGlmb2xkTW9kdWxlJHttb2R1bGVOYW1lKG1vZHVsZUlkKX0ge1xcbmAsXG4gICAgXCJBbmRyb2lkIHNlbWFudGljIG1vZHVsZSBuYW1lc3BhY2VcIiwgW21vZHVsZV0sIFtcIlwiXSlcbiAgbW9kdWxlLmZ1bmN0aW9ucy5mb3JFYWNoKChkZWNsYXJhdGlvbiwgZnVuY3Rpb25JbmRleCkgPT4ge1xuICAgIGNvbnN0IHBhdGggPSBgL2Z1bmN0aW9ucy8ke2Z1bmN0aW9uSW5kZXh9YFxuXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIiAgXCIsIFwiQW5kcm9pZCBuYW1lc3BhY2VkIGZ1bmN0aW9uIGluZGVudGF0aW9uXCIsIFtkZWNsYXJhdGlvbl0sIFtwYXRoXSlcbiAgICB3cml0ZXIubWFwcGVkKFwiZnVuXCIsIHttYXBwaW5nS2luZDogXCJhbmNob3JcIiwgbm9kZTogZGVjbGFyYXRpb24sIHBhdGh9KVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgXCIsIFwiZGVjbGFyYXRpb24gc3BhY2luZ1wiLCBbZGVjbGFyYXRpb25dLCBbcGF0aF0pXG4gICAgd3JpdGVyLm1hcHBlZChkZWNsYXJhdGlvbi5uYW1lLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogZGVjbGFyYXRpb24sIHBhdGgsIHJvbGU6IFwibmFtZVwifSlcbiAgICB3cml0ZXIuc3ludGhldGljKFwiKFwiLCBcImZ1bmN0aW9uIHBhcmFtZXRlciBzY2FmZm9sZFwiLCBbZGVjbGFyYXRpb25dLCBbcGF0aF0pXG4gICAgZGVjbGFyYXRpb24ucGFyYW1ldGVycy5mb3JFYWNoKChwYXJhbWV0ZXIsIHBhcmFtZXRlckluZGV4KSA9PiB7XG4gICAgICBjb25zdCBwYXJhbWV0ZXJQYXRoID0gYCR7cGF0aH0vcGFyYW1ldGVycy8ke3BhcmFtZXRlckluZGV4fWBcblxuICAgICAgaWYgKHBhcmFtZXRlckluZGV4KSB3cml0ZXIuc3ludGhldGljKFwiLCBcIiwgXCJwYXJhbWV0ZXIgc2VwYXJhdG9yXCIsIFtwYXJhbWV0ZXJdLCBbcGFyYW1ldGVyUGF0aF0pXG4gICAgICB3cml0ZXIubWFwcGVkKHBhcmFtZXRlci5uYW1lLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogcGFyYW1ldGVyLCBwYXRoOiBwYXJhbWV0ZXJQYXRoLCByb2xlOiBcIm5hbWVcIn0pXG4gICAgICB3cml0ZXIuc3ludGhldGljKFwiOiBcIiwgXCJwYXJhbWV0ZXIgYW5ub3RhdGlvbiBzY2FmZm9sZFwiLCBbcGFyYW1ldGVyXSwgW3BhcmFtZXRlclBhdGhdKVxuICAgICAgd3JpdGVyLm1hcHBlZChlbWl0U2NhbGFyVHlwZShcImtvdGxpblwiLCBwYXJhbWV0ZXIudHlwZSksIHttYXBwaW5nS2luZDogXCJleGFjdFwiLCBub2RlOiBwYXJhbWV0ZXIudHlwZSxcbiAgICAgICAgcGF0aDogYCR7cGFyYW1ldGVyUGF0aH0vdHlwZWAsIHJvbGU6IFwidHlwZVwifSlcbiAgICB9KVxuICAgIGlmIChkZWNsYXJhdGlvbi5wYXJhbWV0ZXJzLmxlbmd0aCkgd3JpdGVyLnN5bnRoZXRpYyhcIiwgXCIsIFwib3V0cHV0IHNpbmsgcGFyYW1ldGVyIHNlcGFyYXRvclwiLCBbZGVjbGFyYXRpb25dLCBbcGF0aF0pXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhgJHtzaW5rTmFtZX06IFNlbWFudGlmb2xkT3V0cHV0U2luayk6IGAsIFwic2hhcmVkIEFuZHJvaWQgb3V0cHV0IHNpbmsgcGFyYW1ldGVyXCIsIFtkZWNsYXJhdGlvbl0sIFtwYXRoXSlcbiAgICB3cml0ZXIubWFwcGVkKGVtaXRTY2FsYXJUeXBlKFwia290bGluXCIsIGRlY2xhcmF0aW9uLnJldHVyblR5cGUpLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogZGVjbGFyYXRpb24ucmV0dXJuVHlwZSxcbiAgICAgIHBhdGg6IGAke3BhdGh9L3JldHVyblR5cGVgLCByb2xlOiBcInR5cGVcIn0pXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIiB7XFxuXCIsIFwiS290bGluIGZ1bmN0aW9uIGJvZHkgc2NhZmZvbGRcIiwgW2RlY2xhcmF0aW9uXSwgW3BhdGhdKVxuICAgIGVtaXRLb3RsaW5CbG9jayh3cml0ZXIsIGRlY2xhcmF0aW9uLmJvZHksIFwiICAgIFwiLCBgJHtwYXRofS9ib2R5YCwgYCR7c2lua05hbWV9LndyaXRlYClcbiAgICB3cml0ZXIuc3ludGhldGljKFwiICB9XFxuXCIsIFwiS290bGluIGZ1bmN0aW9uIGJvZHkgc2NhZmZvbGRcIiwgW2RlY2xhcmF0aW9uXSwgW3BhdGhdKVxuICB9KVxuICBpZiAoZW50cnkpIHtcbiAgICB3cml0ZXIuc3ludGhldGljKFwiICBmdW4gc2VtYW50aWZvbGRFbnRyeSgpOiBqYXZhLnV0aWwuQXJyYXlMaXN0PFN0cmluZz4ge1xcblwiLCBcIkFuZHJvaWQgc2VtYW50aWMgZW50cnkgc2NhZmZvbGRcIiwgW21vZHVsZS5lbnRyeVBvaW50XSwgW1wiL2VudHJ5UG9pbnRcIl0pXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhgICAgIHZhbCAke3NpbmtOYW1lfSA9IFNlbWFudGlmb2xkT3V0cHV0U2luaygpXFxuYCwgXCJBbmRyb2lkIG91dHB1dCBzaW5rIGFsbG9jYXRpb25cIixcbiAgICAgIFttb2R1bGUuZW50cnlQb2ludF0sIFtcIi9lbnRyeVBvaW50XCJdKVxuICAgIHdyaXRlci5zeW50aGV0aWMoYCAgICAke3NpbmtOYW1lfS5yZXNldCgpXFxuYCwgXCJBbmRyb2lkIGxpZmVjeWNsZS1zYWZlIG91dHB1dCByZXNldFwiLCBbbW9kdWxlLmVudHJ5UG9pbnRdLCBbXCIvZW50cnlQb2ludFwiXSlcbiAgICBlbWl0S290bGluQmxvY2sod3JpdGVyLCBtb2R1bGUuZW50cnlQb2ludC5ib2R5LCBcIiAgICBcIiwgXCIvZW50cnlQb2ludC9ib2R5XCIsIGAke3NpbmtOYW1lfS53cml0ZWApXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhgICAgIHJldHVybiAke3NpbmtOYW1lfS5zbmFwc2hvdCgpXFxuYCwgXCJBbmRyb2lkIHNlbWFudGljIG91dHB1dCByZXR1cm5cIixcbiAgICAgIFttb2R1bGUuZW50cnlQb2ludF0sIFtcIi9lbnRyeVBvaW50XCJdKVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgIH1cXG5cIiwgXCJBbmRyb2lkIHNlbWFudGljIGVudHJ5IHNjYWZmb2xkXCIsIFttb2R1bGUuZW50cnlQb2ludF0sIFtcIi9lbnRyeVBvaW50XCJdKVxuICB9XG4gIHdyaXRlci5zeW50aGV0aWMoXCJ9XFxuXCIsIFwiQW5kcm9pZCBzZW1hbnRpYyBtb2R1bGUgbmFtZXNwYWNlXCIsIFttb2R1bGVdLCBbXCJcIl0pXG59XG5cbi8qKlxuICogTGlzdHMgZXZlcnkgZml4ZWQgZ2VuZXJhdGVkIHBhdGggYmVmb3JlIGFueSB3cml0ZXIgaXMgYWxsb2NhdGVkLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5BbmRyb2lkQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gTm9ybWFsaXplZCBhcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBzdHJpbmc+fSBtb2R1bGVQYXRocyAtIFNlbWFudGljIG1vZHVsZSBvdXRwdXQgcGF0aHMuXG4gKiBAcmV0dXJucyB7c3RyaW5nW119IEZpeGVkIG93bmVkIGFydGlmYWN0IHBhdGhzLlxuICovXG5mdW5jdGlvbiBhcHBsaWNhdGlvblBhdGhzKGNvbmZpZ3VyYXRpb24sIG1vZHVsZVBhdGhzKSB7XG4gIGNvbnN0IHBhY2thZ2VQYXRoID0gY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZS5yZXBsYWNlQWxsKFwiLlwiLCBcIi9cIilcblxuICByZXR1cm4gW1xuICAgIGAke3Byb2plY3RSb290fS9hcHAvYnVpbGQuZ3JhZGxlLmt0c2AsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvYW5kcm9pZFRlc3QvQW5kcm9pZE1hbmlmZXN0LnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvYW5kcm9pZFRlc3Qva290bGluLyR7cGFja2FnZVBhdGh9L1NlbWFudGlmb2xkVWlJbnN0cnVtZW50YXRpb24ua3RgLFxuICAgIGAke3Byb2plY3RSb290fS9hcHAvc3JjL21haW4vQW5kcm9pZE1hbmlmZXN0LnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9rb3RsaW4vJHtwYWNrYWdlUGF0aH0vJHtjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lfS5rdGAsXG4gICAgLi4ubW9kdWxlUGF0aHMudmFsdWVzKCksXG4gICAgYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9rb3RsaW4vJHtwYWNrYWdlUGF0aH0vc2VtYW50aWMvU2VtYW50aWZvbGRSdW50aW1lLmt0YCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vYXBwL3NyYy9tYWluL3Jlcy9sYXlvdXQvYWN0aXZpdHlfbWFpbi54bWxgLFxuICAgIGAke3Byb2plY3RSb290fS9hcHAvc3JjL21haW4vcmVzL3ZhbHVlcy9zdHJpbmdzLnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9yZXMvdmFsdWVzL3RoZW1lcy54bWxgLFxuICAgIGAke3Byb2plY3RSb290fS9hcHAvc3JjL21haW4vcmVzL3htbC9iYWNrdXBfcnVsZXMueG1sYCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vYXBwL3NyYy9tYWluL3Jlcy94bWwvZGF0YV9leHRyYWN0aW9uX3J1bGVzLnhtbGAsXG4gICAgYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvdGVzdC9rb3RsaW4vJHtwYWNrYWdlUGF0aH0vU2VtYW50aWZvbGRFbnRyeVRlc3Qua3RgLFxuICAgIGAke3Byb2plY3RSb290fS9idWlsZC5ncmFkbGUua3RzYCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vZ3JhZGxlLnByb3BlcnRpZXNgLFxuICAgIGAke3Byb2plY3RSb290fS9zZXR0aW5ncy5ncmFkbGUua3RzYCxcbiAgICBgJHtwcm9qZWN0Um9vdH0vc2VtYW50aWZvbGQtcHJvamVjdC5qc29uYFxuICBdXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgcGlubmVkIHJvb3QgcGx1Z2luIGRlY2xhcmF0aW9ucy5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IFJvb3QgR3JhZGxlIEtvdGxpbiBzY3JpcHQuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclJvb3RCdWlsZCgpIHtcbiAgcmV0dXJuIGBwbHVnaW5zIHtcbiAgaWQoXCJjb20uYW5kcm9pZC5hcHBsaWNhdGlvblwiKSB2ZXJzaW9uIFwiJHt0b29sY2hhaW4uYW5kcm9pZEdyYWRsZVBsdWdpbn1cIiBhcHBseSBmYWxzZVxuICBpZChcIm9yZy5qZXRicmFpbnMua290bGluLmFuZHJvaWRcIikgdmVyc2lvbiBcIiR7dG9vbGNoYWluLmtvdGxpbn1cIiBhcHBseSBmYWxzZVxufVxuYFxufVxuXG4vKipcbiAqIFJlbmRlcnMgY2xvc2VkIHByb2plY3Qgc2V0dGluZ3MgYW5kIHJlcG9zaXRvcmllcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQW5kcm9pZEFwcGxpY2F0aW9uQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIE5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7Q29uZmlndXJhdGlvblNwYW5bXX0gc3BhbnMgLSBDb2xsZWN0ZWQgY29uZmlndXJhdGlvbiBwcm92ZW5hbmNlIHNwYW5zLlxuICogQHJldHVybnMge3N0cmluZ30gU2V0dGluZ3MgR3JhZGxlIEtvdGxpbiBzY3JpcHQuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclNldHRpbmdzKGNvbmZpZ3VyYXRpb24sIHNwYW5zKSB7XG4gIHJldHVybiBjb25maWd1cmVkKGAke3Byb2plY3RSb290fS9zZXR0aW5ncy5ncmFkbGUua3RzYCwgc3BhbnMsIFtgcGx1Z2luTWFuYWdlbWVudCB7XG4gIHJlcG9zaXRvcmllcyB7XG4gICAgZ29vZ2xlKClcbiAgICBtYXZlbkNlbnRyYWwoKVxuICAgIGdyYWRsZVBsdWdpblBvcnRhbCgpXG4gIH1cbn1cblxuZGVwZW5kZW5jeVJlc29sdXRpb25NYW5hZ2VtZW50IHtcbiAgcmVwb3NpdG9yaWVzTW9kZS5zZXQoUmVwb3NpdG9yaWVzTW9kZS5GQUlMX09OX1BST0pFQ1RfUkVQT1MpXG4gIHJlcG9zaXRvcmllcyB7XG4gICAgZ29vZ2xlKClcbiAgICBtYXZlbkNlbnRyYWwoKVxuICB9XG59XG5cbnJvb3RQcm9qZWN0Lm5hbWUgPSBcImAsIGZpZWxkKFwicHJvZHVjdE5hbWVcIiwga290bGluRXNjYXBlKGNvbmZpZ3VyYXRpb24ucHJvZHVjdE5hbWUpKSwgYFwiXG5pbmNsdWRlKFwiOmFwcFwiKVxuYF0pXG59XG5cbi8qKlxuICogUmVuZGVycyBkZXRlcm1pbmlzdGljIEdyYWRsZSBwcm9jZXNzIHByb3BlcnRpZXMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBHcmFkbGUgcHJvcGVydGllcyBmaWxlLlxuICovXG5mdW5jdGlvbiByZW5kZXJHcmFkbGVQcm9wZXJ0aWVzKCkge1xuICByZXR1cm4gYG9yZy5ncmFkbGUuY2FjaGluZz1mYWxzZVxub3JnLmdyYWRsZS5jb25maWd1cmF0aW9uLWNhY2hlPWZhbHNlXG5vcmcuZ3JhZGxlLmRhZW1vbj1mYWxzZVxub3JnLmdyYWRsZS5qdm1hcmdzPS1YbXgyMDQ4bSAtRGZpbGUuZW5jb2Rpbmc9VVRGLTggLUR1c2VyLmxhbmd1YWdlPWVuIC1EdXNlci5jb3VudHJ5PVVTIC1EdXNlci50aW1lem9uZT1VVENcbm9yZy5ncmFkbGUucGFyYWxsZWw9ZmFsc2VcbmtvdGxpbi5zdGRsaWIuZGVmYXVsdC5kZXBlbmRlbmN5PWZhbHNlXG5rb3RsaW4uY29kZS5zdHlsZT1vZmZpY2lhbFxuYFxufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIGFwcGxpY2F0aW9uIG1vZHVsZSBidWlsZCBjb250cmFjdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQW5kcm9pZEFwcGxpY2F0aW9uQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIE5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7Q29uZmlndXJhdGlvblNwYW5bXX0gc3BhbnMgLSBDb2xsZWN0ZWQgY29uZmlndXJhdGlvbiBwcm92ZW5hbmNlIHNwYW5zLlxuICogQHJldHVybnMge3N0cmluZ30gQXBwbGljYXRpb24gR3JhZGxlIEtvdGxpbiBzY3JpcHQuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckFwcEJ1aWxkKGNvbmZpZ3VyYXRpb24sIHNwYW5zKSB7XG4gIHJldHVybiBjb25maWd1cmVkKGAke3Byb2plY3RSb290fS9hcHAvYnVpbGQuZ3JhZGxlLmt0c2AsIHNwYW5zLCBbXG4gICAgYGltcG9ydCBvcmcuamV0YnJhaW5zLmtvdGxpbi5ncmFkbGUuZHNsLkp2bVRhcmdldFxuaW1wb3J0IG9yZy5qZXRicmFpbnMua290bGluLmdyYWRsZS50YXNrcy5Lb3RsaW5Kdm1Db21waWxlXG5cbnBsdWdpbnMge1xuICBpZChcImNvbS5hbmRyb2lkLmFwcGxpY2F0aW9uXCIpXG4gIGlkKFwib3JnLmpldGJyYWlucy5rb3RsaW4uYW5kcm9pZFwiKVxufVxuXG5kZXBlbmRlbmNpZXMge1xuICB0ZXN0UnVudGltZU9ubHkoXCJvcmcuaGFtY3Jlc3Q6aGFtY3Jlc3QtY29yZToxLjNcIikge1xuICAgIGlzVHJhbnNpdGl2ZSA9IGZhbHNlXG4gIH1cbn1cblxudmFsIHNlbWFudGlmb2xkS290bGluSG9tZSA9IHByb3ZpZGVycy5lbnZpcm9ubWVudFZhcmlhYmxlKFwiU0VNQU5USUZPTERfS09UTElOX0hPTUVcIikub3JOdWxsXG4gID86IHRocm93IEdyYWRsZUV4Y2VwdGlvbihcIlNFTUFOVElGT0xEX0FORFJPSURfSU5GUkFTVFJVQ1RVUkU6IFNFTUFOVElGT0xEX0tPVExJTl9IT01FIGlzIHJlcXVpcmVkXCIpXG52YWwgc2VtYW50aWZvbGRLb3RsaW5TdGRsaWIgPSBmaWxlKFwiJHNlbWFudGlmb2xkS290bGluSG9tZS9saWIva290bGluLXN0ZGxpYi5qYXJcIilcbmlmICghc2VtYW50aWZvbGRLb3RsaW5TdGRsaWIuaXNGaWxlKSB7XG4gIHRocm93IEdyYWRsZUV4Y2VwdGlvbihcIlNFTUFOVElGT0xEX0FORFJPSURfSU5GUkFTVFJVQ1RVUkU6IHBpbm5lZCBLb3RsaW4gc3RkbGliIGlzIG1pc3NpbmdcIilcbn1cblxuZGVwZW5kZW5jaWVzIHtcbiAgYW5kcm9pZFRlc3RJbXBsZW1lbnRhdGlvbihmaWxlcyhzZW1hbnRpZm9sZEtvdGxpblN0ZGxpYikpXG59XG52YWwgc2VtYW50aWZvbGRBY2NlcHRhbmNlUm9vdCA9IHByb3ZpZGVycy5lbnZpcm9ubWVudFZhcmlhYmxlKFwiU0VNQU5USUZPTERfQU5EUk9JRF9BQ0NFUFRBTkNFX1JPT1RcIikub3JOdWxsXG4gID86IHRocm93IEdyYWRsZUV4Y2VwdGlvbihcIlNFTUFOVElGT0xEX0FORFJPSURfSU5GUkFTVFJVQ1RVUkU6IFNFTUFOVElGT0xEX0FORFJPSURfQUNDRVBUQU5DRV9ST09UIGlzIHJlcXVpcmVkXCIpXG52YWwgc2VtYW50aWZvbGREZWJ1Z0tleXN0b3JlID0gZmlsZShcIiRzZW1hbnRpZm9sZEFjY2VwdGFuY2VSb290L2RlYnVnLmtleXN0b3JlXCIpXG5pZiAoIXNlbWFudGlmb2xkRGVidWdLZXlzdG9yZS5pc0ZpbGUpIHtcbiAgdGhyb3cgR3JhZGxlRXhjZXB0aW9uKFwiU0VNQU5USUZPTERfQU5EUk9JRF9JTkZSQVNUUlVDVFVSRTogZXBoZW1lcmFsIGRlYnVnIGtleXN0b3JlIGlzIG1pc3NpbmdcIilcbn1cblxuYW5kcm9pZCB7XG4gIG5hbWVzcGFjZSA9IFwiYCxcbiAgICBmaWVsZChcIm5hbWVzcGFjZVwiLCBjb25maWd1cmF0aW9uLm5hbWVzcGFjZSksIGBcIlxcbiAgY29tcGlsZVNkayA9IGAsIGZpZWxkKFwiY29tcGlsZVNka1wiLCBTdHJpbmcoY29uZmlndXJhdGlvbi5jb21waWxlU2RrKSksXG4gICAgYFxcbiAgYnVpbGRUb29sc1ZlcnNpb24gPSBcImAsIGZpZWxkKFwiYnVpbGRUb29sc1ZlcnNpb25cIiwgY29uZmlndXJhdGlvbi5idWlsZFRvb2xzVmVyc2lvbiksIGBcIlxcblxcbiAgZGVmYXVsdENvbmZpZyB7XFxuICAgIGFwcGxpY2F0aW9uSWQgPSBcImAsXG4gICAgZmllbGQoXCJhcHBsaWNhdGlvbklkXCIsIGNvbmZpZ3VyYXRpb24uYXBwbGljYXRpb25JZCksIGBcIlxcbiAgICBtaW5TZGsgPSBgLCBmaWVsZChcIm1pbmltdW1TZGtcIiwgU3RyaW5nKGNvbmZpZ3VyYXRpb24ubWluaW11bVNkaykpLFxuICAgIGBcXG4gICAgdGFyZ2V0U2RrID0gYCwgZmllbGQoXCJ0YXJnZXRTZGtcIiwgU3RyaW5nKGNvbmZpZ3VyYXRpb24udGFyZ2V0U2RrKSksIGBcXG4gICAgdmVyc2lvbkNvZGUgPSBgLFxuICAgIGZpZWxkKFwidmVyc2lvbkNvZGVcIiwgU3RyaW5nKGNvbmZpZ3VyYXRpb24udmVyc2lvbkNvZGUpKSwgYFxcbiAgICB2ZXJzaW9uTmFtZSA9IFwiYCwgZmllbGQoXCJ2ZXJzaW9uTmFtZVwiLCBrb3RsaW5Fc2NhcGUoY29uZmlndXJhdGlvbi52ZXJzaW9uTmFtZSkpLFxuICAgIGBcIlxcbiAgICB0ZXN0QXBwbGljYXRpb25JZCA9IFwiYCwgZmllbGQoXCJhcHBsaWNhdGlvbklkXCIsIGNvbmZpZ3VyYXRpb24uYXBwbGljYXRpb25JZCksXG4gICAgYC50ZXN0XCJcXG4gICAgdGVzdEluc3RydW1lbnRhdGlvblJ1bm5lciA9IFwiYCwgZmllbGQoXCJwYWNrYWdlTmFtZVwiLCBjb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lKSxcbiAgICBgLlNlbWFudGlmb2xkVWlJbnN0cnVtZW50YXRpb25cIlxcbiAgfVxcblxcbiAgc2lnbmluZ0NvbmZpZ3Mge1xcbiAgICBnZXRCeU5hbWUoXCJkZWJ1Z1wiKSB7XFxuICAgICAgc3RvcmVGaWxlID0gc2VtYW50aWZvbGREZWJ1Z0tleXN0b3JlXFxuICAgICAgc3RvcmVQYXNzd29yZCA9IFwiYW5kcm9pZFwiXFxuICAgICAga2V5QWxpYXMgPSBcImFuZHJvaWRkZWJ1Z2tleVwiXFxuICAgICAga2V5UGFzc3dvcmQgPSBcImFuZHJvaWRcIlxcbiAgICB9XFxuICB9XFxuICBidWlsZFR5cGVzIHtcXG4gICAgZ2V0QnlOYW1lKFwiZGVidWdcIikge1xcbiAgICAgIHNpZ25pbmdDb25maWcgPSBzaWduaW5nQ29uZmlncy5nZXRCeU5hbWUoXCJkZWJ1Z1wiKVxcbiAgICB9XFxuICB9XFxuICBidWlsZEZlYXR1cmVzIHtcXG4gICAgYnVpbGRDb25maWcgPSBmYWxzZVxcbiAgfVxcbiAgY29tcGlsZU9wdGlvbnMge1xcbiAgICBzb3VyY2VDb21wYXRpYmlsaXR5ID0gSmF2YVZlcnNpb24uVkVSU0lPTl8yMVxcbiAgICB0YXJnZXRDb21wYXRpYmlsaXR5ID0gSmF2YVZlcnNpb24uVkVSU0lPTl8yMVxcbiAgfVxcbiAgbGludCB7XFxuICAgIGFib3J0T25FcnJvciA9IHRydWVcXG4gICAgY2hlY2tEZXBlbmRlbmNpZXMgPSB0cnVlXFxuICAgIGRpc2FibGUgKz0gXCJNaXNzaW5nQXBwbGljYXRpb25JY29uXCJcXG4gICAgZGlzYWJsZSArPSBcIk9sZFRhcmdldEFwaVwiXFxuICAgIGRpc2FibGUgKz0gXCJHcmFkbGVEZXBlbmRlbmN5XCJcXG4gICAgd2FybmluZ3NBc0Vycm9ycyA9IHRydWVcXG4gIH1cXG4gIHBhY2thZ2luZyB7XFxuICAgIHJlc291cmNlcy5leGNsdWRlcyArPSBzZXRPZihcIk1FVEEtSU5GL0xJQ0VOU0UqXCIsIFwiTUVUQS1JTkYvTk9USUNFKlwiKVxcbiAgfVxcbn1cXG5cXG50YXNrcy53aXRoVHlwZTxLb3RsaW5Kdm1Db21waWxlPigpLmNvbmZpZ3VyZUVhY2gge1xcbiAgbGlicmFyaWVzLmZyb20oZmlsZXMoc2VtYW50aWZvbGRLb3RsaW5TdGRsaWIpKVxcbiAgY29tcGlsZXJPcHRpb25zIHtcXG4gICAgYWxsV2FybmluZ3NBc0Vycm9ycy5zZXQodHJ1ZSlcXG4gICAgZnJlZUNvbXBpbGVyQXJncy5hZGRBbGwoXCItWG5vLWNhbGwtYXNzZXJ0aW9uc1wiLCBcIi1Ybm8tcGFyYW0tYXNzZXJ0aW9uc1wiLCBcIi1Ybm8tcmVjZWl2ZXItYXNzZXJ0aW9uc1wiKVxcbiAgICBqdm1UYXJnZXQuc2V0KEp2bVRhcmdldC5KVk1fMjEpXFxuICB9XFxufVxcblxcbmRlcGVuZGVuY2llcyB7XFxuICB0ZXN0SW1wbGVtZW50YXRpb24oXCJqdW5pdDpqdW5pdDo0LjEzLjJcIikge1xcbiAgICBpc1RyYW5zaXRpdmUgPSBmYWxzZVxcbiAgfVxcbn1cXG5gXG4gIF0pXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgYWxsb3dsaXN0ZWQgQW5kcm9pZCBhcHBsaWNhdGlvbiBtYW5pZmVzdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQW5kcm9pZEFwcGxpY2F0aW9uQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIE5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7Q29uZmlndXJhdGlvblNwYW5bXX0gc3BhbnMgLSBDb2xsZWN0ZWQgY29uZmlndXJhdGlvbiBwcm92ZW5hbmNlIHNwYW5zLlxuICogQHJldHVybnMge3N0cmluZ30gQW5kcm9pZCBhcHBsaWNhdGlvbiBtYW5pZmVzdC5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyQW5kcm9pZE1hbmlmZXN0KGNvbmZpZ3VyYXRpb24sIHNwYW5zKSB7XG4gIGNvbnN0IG9yaWVudGF0aW9uID0gY29uZmlndXJhdGlvbi5vcmllbnRhdGlvbiA9PSBcInVuc3BlY2lmaWVkXCIgPyBcIlwiIDogYCBhbmRyb2lkOnNjcmVlbk9yaWVudGF0aW9uPVwiJHtjb25maWd1cmF0aW9uLm9yaWVudGF0aW9ufVwiYFxuXG4gIHJldHVybiBjb25maWd1cmVkKGAke3Byb2plY3RSb290fS9hcHAvc3JjL21haW4vQW5kcm9pZE1hbmlmZXN0LnhtbGAsIHNwYW5zLCBbXG4gICAgYDw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cInV0Zi04XCI/PlxcbjxtYW5pZmVzdCB4bWxuczphbmRyb2lkPVwiaHR0cDovL3NjaGVtYXMuYW5kcm9pZC5jb20vYXBrL3Jlcy9hbmRyb2lkXCI+XFxuICA8YXBwbGljYXRpb25cXG4gICAgYW5kcm9pZDphbGxvd0JhY2t1cD1cImZhbHNlXCJcXG4gICAgYW5kcm9pZDpkYXRhRXh0cmFjdGlvblJ1bGVzPVwiQHhtbC9kYXRhX2V4dHJhY3Rpb25fcnVsZXNcIlxcbiAgICBhbmRyb2lkOmZ1bGxCYWNrdXBDb250ZW50PVwiQHhtbC9iYWNrdXBfcnVsZXNcIlxcbiAgICBhbmRyb2lkOmxhYmVsPVwiQHN0cmluZy9hcHBfbmFtZVwiXFxuICAgIGFuZHJvaWQ6c3VwcG9ydHNSdGw9XCJ0cnVlXCJcXG4gICAgYW5kcm9pZDp0aGVtZT1cIkBzdHlsZS9UaGVtZS5TZW1hbnRpZm9sZFwiPlxcbiAgICA8YWN0aXZpdHlcXG4gICAgICBhbmRyb2lkOm5hbWU9XCJgLFxuICAgIGZpZWxkKFwicGFja2FnZU5hbWVcIiwgY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZSksIGAuYCwgZmllbGQoXCJhY3Rpdml0eUNsYXNzTmFtZVwiLCBjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lKSxcbiAgICBgXCJcXG4gICAgICBhbmRyb2lkOmV4cG9ydGVkPVwidHJ1ZVwiYCxcbiAgICBvcmllbnRhdGlvbiA/IGZpZWxkKFwib3JpZW50YXRpb25cIiwgb3JpZW50YXRpb24pIDogXCJcIiwgYD5cXG4gICAgICA8aW50ZW50LWZpbHRlcj5cXG4gICAgICAgIDxhY3Rpb24gYW5kcm9pZDpuYW1lPVwiYW5kcm9pZC5pbnRlbnQuYWN0aW9uLk1BSU5cIiAvPlxcbiAgICAgICAgPGNhdGVnb3J5IGFuZHJvaWQ6bmFtZT1cImFuZHJvaWQuaW50ZW50LmNhdGVnb3J5LkxBVU5DSEVSXCIgLz5cXG4gICAgICA8L2ludGVudC1maWx0ZXI+XFxuICAgIDwvYWN0aXZpdHk+XFxuICA8L2FwcGxpY2F0aW9uPlxcbjwvbWFuaWZlc3Q+XFxuYFxuICBdKVxufVxuXG4vKipcbiAqIFJlbmRlcnMgZXhwbGljaXQgQVBJIDIzLTMwIGV4Y2x1c2lvbnMgZm9yIGV2ZXJ5IGZ1bGwtYmFja3VwIHN0b3JhZ2UgZG9tYWluLlxuICogQHJldHVybnMge3N0cmluZ30gQW5kcm9pZCBmdWxsLWJhY2t1cCBydWxlcyBYTUwuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckJhY2t1cFJ1bGVzKCkge1xuICByZXR1cm4gYDw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cInV0Zi04XCI/PlxuPGZ1bGwtYmFja3VwLWNvbnRlbnQ+XG4gIDxleGNsdWRlIGRvbWFpbj1cInJvb3RcIiBwYXRoPVwiLlwiIC8+XG4gIDxleGNsdWRlIGRvbWFpbj1cImZpbGVcIiBwYXRoPVwiLlwiIC8+XG4gIDxleGNsdWRlIGRvbWFpbj1cImRhdGFiYXNlXCIgcGF0aD1cIi5cIiAvPlxuICA8ZXhjbHVkZSBkb21haW49XCJzaGFyZWRwcmVmXCIgcGF0aD1cIi5cIiAvPlxuICA8ZXhjbHVkZSBkb21haW49XCJleHRlcm5hbFwiIHBhdGg9XCIuXCIgLz5cbiAgPGV4Y2x1ZGUgZG9tYWluPVwiZGV2aWNlX3Jvb3RcIiBwYXRoPVwiLlwiIC8+XG4gIDxleGNsdWRlIGRvbWFpbj1cImRldmljZV9maWxlXCIgcGF0aD1cIi5cIiAvPlxuICA8ZXhjbHVkZSBkb21haW49XCJkZXZpY2VfZGF0YWJhc2VcIiBwYXRoPVwiLlwiIC8+XG4gIDxleGNsdWRlIGRvbWFpbj1cImRldmljZV9zaGFyZWRwcmVmXCIgcGF0aD1cIi5cIiAvPlxuPC9mdWxsLWJhY2t1cC1jb250ZW50PlxuYFxufVxuXG4vKipcbiAqIFJlbmRlcnMgZXhwbGljaXQgQW5kcm9pZCAxMisgZXhjbHVzaW9ucyBmb3IgZXZlcnkgY2xvdWQtYmFja3VwIGFuZCBkZXZpY2UtdHJhbnNmZXIgc3RvcmFnZSBkb21haW4uXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBBbmRyb2lkIGRhdGEgZXh0cmFjdGlvbiBydWxlcyBYTUwuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckRhdGFFeHRyYWN0aW9uUnVsZXMoKSB7XG4gIHJldHVybiBgPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwidXRmLThcIj8+XG48ZGF0YS1leHRyYWN0aW9uLXJ1bGVzPlxuICA8Y2xvdWQtYmFja3VwPlxuICAgIDxleGNsdWRlIGRvbWFpbj1cInJvb3RcIiBwYXRoPVwiLlwiIC8+XG4gICAgPGV4Y2x1ZGUgZG9tYWluPVwiZmlsZVwiIHBhdGg9XCIuXCIgLz5cbiAgICA8ZXhjbHVkZSBkb21haW49XCJkYXRhYmFzZVwiIHBhdGg9XCIuXCIgLz5cbiAgICA8ZXhjbHVkZSBkb21haW49XCJzaGFyZWRwcmVmXCIgcGF0aD1cIi5cIiAvPlxuICAgIDxleGNsdWRlIGRvbWFpbj1cImV4dGVybmFsXCIgcGF0aD1cIi5cIiAvPlxuICAgIDxleGNsdWRlIGRvbWFpbj1cImRldmljZV9yb290XCIgcGF0aD1cIi5cIiAvPlxuICAgIDxleGNsdWRlIGRvbWFpbj1cImRldmljZV9maWxlXCIgcGF0aD1cIi5cIiAvPlxuICAgIDxleGNsdWRlIGRvbWFpbj1cImRldmljZV9kYXRhYmFzZVwiIHBhdGg9XCIuXCIgLz5cbiAgICA8ZXhjbHVkZSBkb21haW49XCJkZXZpY2Vfc2hhcmVkcHJlZlwiIHBhdGg9XCIuXCIgLz5cbiAgPC9jbG91ZC1iYWNrdXA+XG4gIDxkZXZpY2UtdHJhbnNmZXI+XG4gICAgPGV4Y2x1ZGUgZG9tYWluPVwicm9vdFwiIHBhdGg9XCIuXCIgLz5cbiAgICA8ZXhjbHVkZSBkb21haW49XCJmaWxlXCIgcGF0aD1cIi5cIiAvPlxuICAgIDxleGNsdWRlIGRvbWFpbj1cImRhdGFiYXNlXCIgcGF0aD1cIi5cIiAvPlxuICAgIDxleGNsdWRlIGRvbWFpbj1cInNoYXJlZHByZWZcIiBwYXRoPVwiLlwiIC8+XG4gICAgPGV4Y2x1ZGUgZG9tYWluPVwiZXh0ZXJuYWxcIiBwYXRoPVwiLlwiIC8+XG4gICAgPGV4Y2x1ZGUgZG9tYWluPVwiZGV2aWNlX3Jvb3RcIiBwYXRoPVwiLlwiIC8+XG4gICAgPGV4Y2x1ZGUgZG9tYWluPVwiZGV2aWNlX2ZpbGVcIiBwYXRoPVwiLlwiIC8+XG4gICAgPGV4Y2x1ZGUgZG9tYWluPVwiZGV2aWNlX2RhdGFiYXNlXCIgcGF0aD1cIi5cIiAvPlxuICAgIDxleGNsdWRlIGRvbWFpbj1cImRldmljZV9zaGFyZWRwcmVmXCIgcGF0aD1cIi5cIiAvPlxuICA8L2RldmljZS10cmFuc2Zlcj5cbjwvZGF0YS1leHRyYWN0aW9uLXJ1bGVzPlxuYFxufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIHBsYXRmb3JtLW9ubHkgaW5zdHJ1bWVudGF0aW9uIG1hbmlmZXN0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5BbmRyb2lkQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gTm9ybWFsaXplZCBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uU3BhbltdfSBzcGFucyAtIENvbGxlY3RlZCBjb25maWd1cmF0aW9uIHByb3ZlbmFuY2Ugc3BhbnMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBBbmRyb2lkIHRlc3QgbWFuaWZlc3QuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckFuZHJvaWRUZXN0TWFuaWZlc3QoY29uZmlndXJhdGlvbiwgc3BhbnMpIHtcbiAgcmV0dXJuIGNvbmZpZ3VyZWQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvYW5kcm9pZFRlc3QvQW5kcm9pZE1hbmlmZXN0LnhtbGAsIHNwYW5zLCBbXG4gICAgYDw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cInV0Zi04XCI/PlxcbjxtYW5pZmVzdCB4bWxuczphbmRyb2lkPVwiaHR0cDovL3NjaGVtYXMuYW5kcm9pZC5jb20vYXBrL3Jlcy9hbmRyb2lkXCI+XFxuICA8aW5zdHJ1bWVudGF0aW9uXFxuICAgIGFuZHJvaWQ6bmFtZT1cImAsXG4gICAgZmllbGQoXCJwYWNrYWdlTmFtZVwiLCBjb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lKSwgYC5TZW1hbnRpZm9sZFVpSW5zdHJ1bWVudGF0aW9uXCJcXG4gICAgYW5kcm9pZDp0YXJnZXRQYWNrYWdlPVwiYCxcbiAgICBmaWVsZChcImFwcGxpY2F0aW9uSWRcIiwgeG1sRXNjYXBlKGNvbmZpZ3VyYXRpb24uYXBwbGljYXRpb25JZCkpLCBgXCIgLz5cXG48L21hbmlmZXN0PlxcbmBcbiAgXSlcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBzeW50aGV0aWMgbGF1bmNoZXIgYWN0aXZpdHkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkFuZHJvaWRBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb259IGNvbmZpZ3VyYXRpb24gLSBOb3JtYWxpemVkIGNvbmZpZ3VyYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZW50cnlNb2R1bGUgLSBTZWxlY3RlZCBzZW1hbnRpYyBlbnRyeSBtb2R1bGUgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb25TcGFuW119IHNwYW5zIC0gQ29sbGVjdGVkIGNvbmZpZ3VyYXRpb24gcHJvdmVuYW5jZSBzcGFucy5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEtvdGxpbiBsYXVuY2hlciBhY3Rpdml0eSBzb3VyY2UuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckFjdGl2aXR5KGNvbmZpZ3VyYXRpb24sIGVudHJ5TW9kdWxlLCBzcGFucykge1xuICBjb25zdCByZXNvdXJjZUltcG9ydCA9IGNvbmZpZ3VyYXRpb24ubmFtZXNwYWNlID09IGNvbmZpZ3VyYXRpb24ucGFja2FnZU5hbWVcbiAgICA/IFtdXG4gICAgOiBbXCJpbXBvcnQgXCIsIGZpZWxkKFwibmFtZXNwYWNlXCIsIGNvbmZpZ3VyYXRpb24ubmFtZXNwYWNlKSwgXCIuUlxcblwiXVxuXG4gIHJldHVybiBjb25maWd1cmVkKGAke3Byb2plY3RSb290fS9hcHAvc3JjL21haW4va290bGluLyR7Y29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZS5yZXBsYWNlQWxsKFwiLlwiLCBcIi9cIil9LyR7Y29uZmlndXJhdGlvbi5hY3Rpdml0eUNsYXNzTmFtZX0ua3RgLCBzcGFucywgW1xuICAgIFwicGFja2FnZSBcIiwgZmllbGQoXCJwYWNrYWdlTmFtZVwiLCBjb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lKSwgYFxuXG5pbXBvcnQgYW5kcm9pZC5hcHAuQWN0aXZpdHlcbmltcG9ydCBhbmRyb2lkLmFubm90YXRpb24uU3VwcHJlc3NMaW50XG5pbXBvcnQgYW5kcm9pZC5vcy5CdW5kbGVcbmltcG9ydCBhbmRyb2lkLndpZGdldC5UZXh0Vmlld1xuYCwgLi4ucmVzb3VyY2VJbXBvcnQsIGBpbXBvcnQgYCwgZmllbGQoXCJwYWNrYWdlTmFtZVwiLCBjb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lKSxcbiAgICBgLnNlbWFudGljLlNlbWFudGlmb2xkTW9kdWxlJHttb2R1bGVOYW1lKGVudHJ5TW9kdWxlKX1cblxuY2xhc3MgYCwgZmllbGQoXCJhY3Rpdml0eUNsYXNzTmFtZVwiLCBjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lKSwgYCA6IEFjdGl2aXR5KCkge1xuICBAU3VwcHJlc3NMaW50KFwiU2V0VGV4dEkxOG5cIilcbiAgb3ZlcnJpZGUgZnVuIG9uQ3JlYXRlKHNhdmVkSW5zdGFuY2VTdGF0ZTogQnVuZGxlPykge1xuICAgIHN1cGVyLm9uQ3JlYXRlKHNhdmVkSW5zdGFuY2VTdGF0ZSlcbiAgICBzZXRDb250ZW50VmlldyhSLmxheW91dC5hY3Rpdml0eV9tYWluKVxuICAgIHZhbCBsaW5lcyA9IFNlbWFudGlmb2xkTW9kdWxlJHttb2R1bGVOYW1lKGVudHJ5TW9kdWxlKX0uc2VtYW50aWZvbGRFbnRyeSgpXG4gICAgdmFsIG91dHB1dCA9IGphdmEubGFuZy5TdHJpbmdCdWlsZGVyKClcbiAgICB2YXIgaW5kZXggPSAwXG4gICAgd2hpbGUgKGluZGV4IDwgbGluZXMuc2l6ZSkge1xuICAgICAgaWYgKGluZGV4ID4gMCkgb3V0cHV0LmFwcGVuZCgnXFxcXG4nKVxuICAgICAgb3V0cHV0LmFwcGVuZChsaW5lc1tpbmRleF0pXG4gICAgICBpbmRleCArPSAxXG4gICAgfVxuICAgIGZpbmRWaWV3QnlJZDxUZXh0Vmlldz4oUi5pZC5zZW1hbnRpZm9sZF9vdXRwdXQpLnRleHQgPSBvdXRwdXQudG9TdHJpbmcoKVxuICB9XG59XG5gXG4gIF0pXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgc2luZ2xlIGFjY2Vzc2liaWxpdHktaW1wb3J0YW50IG5hdGl2ZSB0ZXh0IHZpZXcuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBBbmRyb2lkIGxheW91dCBYTUwuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckxheW91dCgpIHtcbiAgcmV0dXJuIGA8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJ1dGYtOFwiPz5cbjxUZXh0VmlldyB4bWxuczphbmRyb2lkPVwiaHR0cDovL3NjaGVtYXMuYW5kcm9pZC5jb20vYXBrL3Jlcy9hbmRyb2lkXCJcbiAgYW5kcm9pZDppZD1cIkAraWQvc2VtYW50aWZvbGRfb3V0cHV0XCJcbiAgYW5kcm9pZDpsYXlvdXRfd2lkdGg9XCJtYXRjaF9wYXJlbnRcIlxuICBhbmRyb2lkOmxheW91dF9oZWlnaHQ9XCJtYXRjaF9wYXJlbnRcIlxuICBhbmRyb2lkOmdyYXZpdHk9XCJjZW50ZXJcIlxuICBhbmRyb2lkOmltcG9ydGFudEZvckFjY2Vzc2liaWxpdHk9XCJ5ZXNcIlxuICBhbmRyb2lkOnRleHRJc1NlbGVjdGFibGU9XCJ0cnVlXCIgLz5cbmBcbn1cblxuLyoqXG4gKiBSZW5kZXJzIGNvbmZpZ3VyYXRpb24tZGVyaXZlZCBzdHJpbmcgcmVzb3VyY2VzLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5BbmRyb2lkQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gTm9ybWFsaXplZCBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uU3BhbltdfSBzcGFucyAtIENvbGxlY3RlZCBjb25maWd1cmF0aW9uIHByb3ZlbmFuY2Ugc3BhbnMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBBbmRyb2lkIHN0cmluZyByZXNvdXJjZSBYTUwuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclN0cmluZ3MoY29uZmlndXJhdGlvbiwgc3BhbnMpIHtcbiAgcmV0dXJuIGNvbmZpZ3VyZWQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi9yZXMvdmFsdWVzL3N0cmluZ3MueG1sYCwgc3BhbnMsIFtcbiAgICBgPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwidXRmLThcIj8+XFxuPHJlc291cmNlcz5cXG4gIDxzdHJpbmcgbmFtZT1cImFwcF9uYW1lXCI+YCxcbiAgICBmaWVsZChcImRpc3BsYXlOYW1lXCIsIHhtbEVzY2FwZShjb25maWd1cmF0aW9uLmRpc3BsYXlOYW1lKSksIGA8L3N0cmluZz5cXG48L3Jlc291cmNlcz5cXG5gXG4gIF0pXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgZml4ZWQgcGxhdGZvcm0tbmF0aXZlIGJhc2VsaW5lIHRoZW1lLlxuICogQHJldHVybnMge3N0cmluZ30gQW5kcm9pZCB0aGVtZSByZXNvdXJjZSBYTUwuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclRoZW1lKCkge1xuICByZXR1cm4gYDw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cInV0Zi04XCI/PlxuPHJlc291cmNlcz5cbiAgPHN0eWxlIG5hbWU9XCJUaGVtZS5TZW1hbnRpZm9sZFwiIHBhcmVudD1cImFuZHJvaWQ6c3R5bGUvVGhlbWUuTWF0ZXJpYWwuTGlnaHQuTm9BY3Rpb25CYXJcIj5cbiAgICA8aXRlbSBuYW1lPVwiYW5kcm9pZDpmb250RmFtaWx5XCI+c2FuczwvaXRlbT5cbiAgICA8aXRlbSBuYW1lPVwiYW5kcm9pZDp3aW5kb3dBY3Rpb25Nb2RlT3ZlcmxheVwiPnRydWU8L2l0ZW0+XG4gIDwvc3R5bGU+XG48L3Jlc291cmNlcz5cbmBcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBzb2xlIEpVbml0IHRlc3Qtc2NvcGUgc2VtYW50aWMgYXNzZXJ0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5BbmRyb2lkQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gTm9ybWFsaXplZCBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGVudHJ5TW9kdWxlIC0gU2VsZWN0ZWQgc2VtYW50aWMgZW50cnkgbW9kdWxlIGlkZW50aXR5LlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uU3BhbltdfSBzcGFucyAtIENvbGxlY3RlZCBjb25maWd1cmF0aW9uIHByb3ZlbmFuY2Ugc3BhbnMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBLb3RsaW4gdW5pdCB0ZXN0IHNvdXJjZS5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyVW5pdFRlc3QoY29uZmlndXJhdGlvbiwgZW50cnlNb2R1bGUsIHNwYW5zKSB7XG4gIHJldHVybiBjb25maWd1cmVkKGAke3Byb2plY3RSb290fS9hcHAvc3JjL3Rlc3Qva290bGluLyR7Y29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZS5yZXBsYWNlQWxsKFwiLlwiLCBcIi9cIil9L1NlbWFudGlmb2xkRW50cnlUZXN0Lmt0YCwgc3BhbnMsIFtcbiAgICBcInBhY2thZ2UgXCIsIGZpZWxkKFwicGFja2FnZU5hbWVcIiwgY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZSksIGBcblxuaW1wb3J0IGAsIGZpZWxkKFwicGFja2FnZU5hbWVcIiwgY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZSksIGAuc2VtYW50aWMuU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUoZW50cnlNb2R1bGUpfVxuaW1wb3J0IG9yZy5qdW5pdC5UZXN0XG5cbmNsYXNzIFNlbWFudGlmb2xkRW50cnlUZXN0IHtcbiAgQFRlc3RcbiAgZnVuIGVudHJ5SXNEZXRlcm1pbmlzdGljQWNyb3NzRnJlc2hSdW5zKCkge1xuICAgIHZhbCBmaXJzdE91dHB1dCA9IFNlbWFudGlmb2xkTW9kdWxlJHttb2R1bGVOYW1lKGVudHJ5TW9kdWxlKX0uc2VtYW50aWZvbGRFbnRyeSgpXG4gICAgdmFsIHNlY29uZE91dHB1dCA9IFNlbWFudGlmb2xkTW9kdWxlJHttb2R1bGVOYW1lKGVudHJ5TW9kdWxlKX0uc2VtYW50aWZvbGRFbnRyeSgpXG4gICAgaWYgKCFmaXJzdE91dHB1dC5lcXVhbHMoc2Vjb25kT3V0cHV0KSkge1xuICAgICAgdGhyb3cgQXNzZXJ0aW9uRXJyb3IoXCJTZW1hbnRpYyBlbnRyeSBvdXRwdXQgZGlmZmVycyBhY3Jvc3MgZnJlc2ggcnVucy5cIilcbiAgICB9XG4gIH1cbn1cbmBcbiAgXSlcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBmcmFtZXdvcmstb25seSBpbnN0cnVtZW50YXRpb24gcnVubmVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5BbmRyb2lkQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gTm9ybWFsaXplZCBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uU3BhbltdfSBzcGFucyAtIENvbGxlY3RlZCBjb25maWd1cmF0aW9uIHByb3ZlbmFuY2Ugc3BhbnMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBLb3RsaW4gaW5zdHJ1bWVudGF0aW9uIHNvdXJjZS5cbiAqL1xuZnVuY3Rpb24gcmVuZGVySW5zdHJ1bWVudGF0aW9uKGNvbmZpZ3VyYXRpb24sIHNwYW5zKSB7XG4gIGNvbnN0IHJlc291cmNlSW1wb3J0ID0gY29uZmlndXJhdGlvbi5uYW1lc3BhY2UgPT0gY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZVxuICAgID8gW11cbiAgICA6IFtcImltcG9ydCBcIiwgZmllbGQoXCJuYW1lc3BhY2VcIiwgY29uZmlndXJhdGlvbi5uYW1lc3BhY2UpLCBcIi5SXFxuXCJdXG5cbiAgcmV0dXJuIGNvbmZpZ3VyZWQoYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvYW5kcm9pZFRlc3Qva290bGluLyR7Y29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZS5yZXBsYWNlQWxsKFwiLlwiLCBcIi9cIil9L1NlbWFudGlmb2xkVWlJbnN0cnVtZW50YXRpb24ua3RgLCBzcGFucywgW1xuICAgIFwicGFja2FnZSBcIiwgZmllbGQoXCJwYWNrYWdlTmFtZVwiLCBjb25maWd1cmF0aW9uLnBhY2thZ2VOYW1lKSwgYFxuXG5pbXBvcnQgYW5kcm9pZC5hcHAuQWN0aXZpdHlcbmltcG9ydCBhbmRyb2lkLmFwcC5JbnN0cnVtZW50YXRpb25cbmltcG9ydCBhbmRyb2lkLmNvbnRlbnQuSW50ZW50XG5pbXBvcnQgYW5kcm9pZC5vcy5CdW5kbGVcbmltcG9ydCBhbmRyb2lkLnV0aWwuQmFzZTY0XG5pbXBvcnQgYW5kcm9pZC52aWV3LlZpZXdcbmltcG9ydCBhbmRyb2lkLndpZGdldC5UZXh0Vmlld1xuaW1wb3J0IGphdmEubmlvLmNoYXJzZXQuU3RhbmRhcmRDaGFyc2V0c1xuYCwgLi4ucmVzb3VyY2VJbXBvcnQsIGBcbmNsYXNzIFNlbWFudGlmb2xkVWlJbnN0cnVtZW50YXRpb24gOiBJbnN0cnVtZW50YXRpb24oKSB7XG4gIHByaXZhdGUgdmFyIGlucHV0QXJndW1lbnRzOiBCdW5kbGU/ID0gbnVsbFxuXG4gIG92ZXJyaWRlIGZ1biBvbkNyZWF0ZShhcmd1bWVudHM6IEJ1bmRsZT8pIHtcbiAgICBpbnB1dEFyZ3VtZW50cyA9IGFyZ3VtZW50c1xuICAgIHN0YXJ0KClcbiAgfVxuXG4gIG92ZXJyaWRlIGZ1biBvblN0YXJ0KCkge1xuICAgIHRyeSB7XG4gICAgICB2YWwgcHJvdmlkZWRBcmd1bWVudHMgPSBpbnB1dEFyZ3VtZW50c1xuICAgICAgICA/OiB0aHJvdyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oXCJtaXNzaW5nIGluc3RydW1lbnRhdGlvbiBhcmd1bWVudHNcIilcbiAgICAgIHZhbCBlbmNvZGVkID0gcHJvdmlkZWRBcmd1bWVudHMuZ2V0U3RyaW5nKFwiZXhwZWN0ZWRfb3V0cHV0X2Jhc2U2NFwiKVxuICAgICAgICA/OiB0aHJvdyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oXCJtaXNzaW5nIGV4cGVjdGVkX291dHB1dF9iYXNlNjQgaW5zdHJ1bWVudGF0aW9uIGFyZ3VtZW50XCIpXG4gICAgICB2YWwgZXhwZWN0ZWQgPSBTdHJpbmcoQmFzZTY0LmRlY29kZShlbmNvZGVkLCBCYXNlNjQuTk9fV1JBUCksIFN0YW5kYXJkQ2hhcnNldHMuVVRGXzgpXG4gICAgICB2YWwgbGF1bmNoID0gdGFyZ2V0Q29udGV4dC5wYWNrYWdlTWFuYWdlci5nZXRMYXVuY2hJbnRlbnRGb3JQYWNrYWdlKHRhcmdldENvbnRleHQucGFja2FnZU5hbWUpXG4gICAgICAgID86IHRocm93IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbihcImdlbmVyYXRlZCBhcHBsaWNhdGlvbiBoYXMgbm8gbGF1bmNoZXIgaW50ZW50XCIpXG4gICAgICBsYXVuY2guYWRkRmxhZ3MoSW50ZW50LkZMQUdfQUNUSVZJVFlfTkVXX1RBU0sgb3IgSW50ZW50LkZMQUdfQUNUSVZJVFlfQ0xFQVJfVEFTSylcbiAgICAgIHZhbCBhY3Rpdml0eSA9IHN0YXJ0QWN0aXZpdHlTeW5jKGxhdW5jaCkgYXMgYCwgZmllbGQoXCJhY3Rpdml0eUNsYXNzTmFtZVwiLCBjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lKSwgYFxuICAgICAgYXNzZXJ0T3V0cHV0KGFjdGl2aXR5LCBleHBlY3RlZClcbiAgICAgIHZhbCBtb25pdG9yID0gYWRkTW9uaXRvcihgLCBmaWVsZChcImFjdGl2aXR5Q2xhc3NOYW1lXCIsIGNvbmZpZ3VyYXRpb24uYWN0aXZpdHlDbGFzc05hbWUpLCBgOjpjbGFzcy5qYXZhLm5hbWUsIG51bGwsIGZhbHNlKVxuICAgICAgcnVuT25NYWluU3luYyB7IGFjdGl2aXR5LnJlY3JlYXRlKCkgfVxuICAgICAgd2FpdEZvcklkbGVTeW5jKClcbiAgICAgIHZhbCByZWNyZWF0ZWQgPSB3YWl0Rm9yTW9uaXRvcldpdGhUaW1lb3V0KG1vbml0b3IsIDEwXzAwMClcbiAgICAgICAgPzogdGhyb3cgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKFwiYWN0aXZpdHkgd2FzIG5vdCByZWNyZWF0ZWRcIilcbiAgICAgIGFzc2VydE91dHB1dChyZWNyZWF0ZWQsIGV4cGVjdGVkKVxuICAgICAgZmluaXNoKEFjdGl2aXR5LlJFU1VMVF9PSywgQnVuZGxlKCkpXG4gICAgfSBjYXRjaCAoZXJyb3I6IFRocm93YWJsZSkge1xuICAgICAgdmFsIHJlc3VsdCA9IEJ1bmRsZSgpXG4gICAgICByZXN1bHQucHV0U3RyaW5nKFwic2VtYW50aWZvbGRfZmFpbHVyZVwiLCBhbmRyb2lkLnV0aWwuTG9nLmdldFN0YWNrVHJhY2VTdHJpbmcoZXJyb3IpKVxuICAgICAgZmluaXNoKEFjdGl2aXR5LlJFU1VMVF9DQU5DRUxFRCwgcmVzdWx0KVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZnVuIGFzc2VydE91dHB1dChhY3Rpdml0eTogQWN0aXZpdHksIGV4cGVjdGVkOiBTdHJpbmcpIHtcbiAgICB3YWl0Rm9ySWRsZVN5bmMoKVxuICAgIHZhbCBhY3R1YWwgPSBhY3Rpdml0eS5maW5kVmlld0J5SWQ8VGV4dFZpZXc+KFIuaWQuc2VtYW50aWZvbGRfb3V0cHV0KVxuICAgICAgPzogdGhyb3cgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKFwibWlzc2luZyBzZW1hbnRpZm9sZF9vdXRwdXQgdmlld1wiKVxuICAgIGlmIChhY3R1YWwudmlzaWJpbGl0eSAhPSBWaWV3LlZJU0lCTEUpIHRocm93IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbihcIm91dHB1dCB2aWV3IGlzIG5vdCB2aXNpYmxlXCIpXG4gICAgaWYgKGFjdHVhbC5qYXZhQ2xhc3MgIT0gVGV4dFZpZXc6OmNsYXNzLmphdmEpIHRocm93IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbihcIm91dHB1dCB2aWV3IGlzIG5vdCBhIG5hdGl2ZSBUZXh0Vmlld1wiKVxuICAgIGlmICghYWN0dWFsLnRleHQudG9TdHJpbmcoKS5lcXVhbHMoZXhwZWN0ZWQpKSB0aHJvdyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oXCJvdXRwdXQgdGV4dCBtaXNtYXRjaFwiKVxuICAgIGlmIChhY3R1YWwuY29udGVudERlc2NyaXB0aW9uICE9IG51bGwpIHRocm93IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbihcIm91dHB1dCBjb250ZW50IGRlc2NyaXB0aW9uIG11c3Qgc3RheSBhYnNlbnRcIilcbiAgICBpZiAoYWN0dWFsLmltcG9ydGFudEZvckFjY2Vzc2liaWxpdHkgIT0gVmlldy5JTVBPUlRBTlRfRk9SX0FDQ0VTU0lCSUxJVFlfWUVTKSB7XG4gICAgICB0aHJvdyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oXCJvdXRwdXQgdmlldyBpcyBub3QgYWNjZXNzaWJpbGl0eS1pbXBvcnRhbnRcIilcbiAgICB9XG4gIH1cbn1cbmBcbiAgXSlcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBvd25lcnNoaXAsIHRvb2xjaGFpbiwgYW5kIHByb3ZlbmFuY2UgbWFuaWZlc3QuXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIHByZWZsaWdodEFuZHJvaWRBcHBsaWNhdGlvbj59IHByZXBhcmVkIC0gUHJlcGFyZWQgYXBwbGljYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0W119IGFydGlmYWN0cyAtIE93bmVkIHByb2plY3QgYXJ0aWZhY3RzLlxuICogQHBhcmFtIHtzdHJpbmd9IG1hbmlmZXN0UGF0aCAtIE93bmVyc2hpcCBtYW5pZmVzdCBwYXRoLlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uU3BhbltdfSBzcGFucyAtIENvbmZpZ3VyYXRpb24gcHJvdmVuYW5jZSBzcGFucy5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IENhbm9uaWNhbCBwcm9qZWN0IG1hbmlmZXN0IEpTT04uXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclByb2plY3RNYW5pZmVzdChwcmVwYXJlZCwgYXJ0aWZhY3RzLCBtYW5pZmVzdFBhdGgsIHNwYW5zKSB7XG4gIGNvbnN0IGlucHV0UGF0aHMgPSBuZXcgU2V0KFsuLi5wcmVwYXJlZC5yZXNvdXJjZXMsIC4uLnByZXBhcmVkLmFzc2V0c10ubWFwKCh7ZnVsbFBhdGh9KSA9PiBmdWxsUGF0aCkpXG4gIGNvbnN0IHNlbWFudGljQXJ0aWZhY3RzID0gYXJ0aWZhY3RzLmZpbHRlcihhcnRpZmFjdCA9PiBhcnRpZmFjdC5wcm92ZW5hbmNlLmtpbmQgPT0gXCJ0ZXh0XCIpXG4gIGNvbnN0IG93bmVkUGF0aHMgPSBbLi4uYXJ0aWZhY3RzLm1hcCgoe3BhdGh9KSA9PiBwYXRoKSwgbWFuaWZlc3RQYXRoXVxuXG4gIHJldHVybiBzdHJpbmdpZnlDYW5vbmljYWxKc29uKHtcbiAgICBjb25maWd1cmF0aW9uOiBwcmVwYXJlZC5jb25maWd1cmF0aW9uLFxuICAgIGdlbmVyYXRvcjoge25hbWU6IFwic2VtYW50aWZvbGRcIiwgdmVyc2lvbjogZ2VuZXJhdG9yVmVyc2lvbn0sXG4gICAgb3duZXJzaGlwOiB7XG4gICAgICBleGNsdWRlZFBhdGhQYXR0ZXJucyxcbiAgICAgIG93bmVkUGF0aHMsXG4gICAgICBvd25lZFJvb3Q6IHByb2plY3RSb290LFxuICAgICAgc2hhMjU2OiBhcnRpZmFjdHMubWFwKGFydGlmYWN0ID0+ICh7cGF0aDogYXJ0aWZhY3QucGF0aCwgc2hhMjU2OiBoYXNoQ29udGVudChhcnRpZmFjdC5jb250ZW50KX0pKVxuICAgIH0sXG4gICAgcHJvdmVuYW5jZToge1xuICAgICAgY29uZmlndXJhdGlvbjogT2JqZWN0LmtleXMocHJlcGFyZWQuY29uZmlndXJhdGlvbikuc29ydCgpLm1hcChmaWVsZE5hbWUgPT4gKHtcbiAgICAgICAgZmllbGQ6IGZpZWxkTmFtZSxcbiAgICAgICAgbWFuaWZlc3RQb2ludGVyOiBgL2NvbmZpZ3VyYXRpb24vJHtmaWVsZE5hbWV9YCxcbiAgICAgICAgb3V0cHV0czogY29uZmlndXJhdGlvbk91dHB1dHMoc3BhbnMsIGZpZWxkTmFtZSlcbiAgICAgIH0pKSxcbiAgICAgIGlucHV0czogWy4uLnByZXBhcmVkLnJlc291cmNlcywgLi4ucHJlcGFyZWQuYXNzZXRzXS5tYXAoaXRlbSA9PiAoe1xuICAgICAgICBjb250ZW50S2luZDogaXRlbS5jb250ZW50S2luZCxcbiAgICAgICAgbWVkaWFUeXBlOiBpdGVtLm1lZGlhVHlwZSxcbiAgICAgICAgcGF0aDogaXRlbS5mdWxsUGF0aCxcbiAgICAgICAgc2hhMjU2OiBpdGVtLnNoYTI1NlxuICAgICAgfSkpLFxuICAgICAgc2VtYW50aWNTb3VyY2VzOiBwcmVwYXJlZC5zb3VyY2VzLm1hcChzb3VyY2UgPT4gKHtcbiAgICAgICAgYXJ0aWZhY3RzOiBzZW1hbnRpY0FydGlmYWN0cy5maWx0ZXIoYXJ0aWZhY3QgPT4gYXJ0aWZhY3QucHJvdmVuYW5jZS5raW5kID09IFwidGV4dFwiICYmXG4gICAgICAgICAgYXJ0aWZhY3QucHJvdmVuYW5jZS5tYXBwaW5nLnNwYW5zLnNvbWUoKHtvcmlnaW59KSA9PiBvcmlnaW5SZWZlcmVuY2VzRmlsZW5hbWUob3JpZ2luLCBzb3VyY2UuZmlsZW5hbWUpKSlcbiAgICAgICAgICAubWFwKCh7cGF0aH0pID0+IHBhdGgpLFxuICAgICAgICBmaWxlbmFtZTogc291cmNlLmZpbGVuYW1lLFxuICAgICAgICAuLi4oc291cmNlLmxhbmd1YWdlID09PSB1bmRlZmluZWQgPyB7fSA6IHtsYW5ndWFnZTogc291cmNlLmxhbmd1YWdlfSksXG4gICAgICAgIHNoYTI1NjogY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUoc291cmNlLmNvbnRlbnQpLmRpZ2VzdChcImhleFwiKVxuICAgICAgfSkpLFxuICAgICAgc3ludGhldGljU2NhZmZvbGRpbmc6IFsuLi5hcnRpZmFjdHMuZmlsdGVyKGFydGlmYWN0ID0+IGFydGlmYWN0LnByb3ZlbmFuY2Uua2luZCA9PSBcInN5bnRoZXRpY1wiICYmXG4gICAgICAgICFpbnB1dFBhdGhzLmhhcyhhcnRpZmFjdC5wYXRoKSkubWFwKCh7cGF0aH0pID0+IHBhdGgpLCBtYW5pZmVzdFBhdGhdXG4gICAgfSxcbiAgICBzY2hlbWE6IFwiU2VtYW50aWZvbGRBbmRyb2lkUHJvamVjdFwiLFxuICAgIHNlbWFudGljUHJvZ3JhbTogc2VtYW50aWNQcm9ncmFtTWFuaWZlc3QocHJlcGFyZWQpLFxuICAgIHRhcmdldDogXCJhbmRyb2lkXCIsXG4gICAgdG9vbGNoYWluLFxuICAgIHZlcnNpb246IDFcbiAgfSlcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHNlbWFudGljIG1vZHVsZSBhbmQgc291cmNlIGlkZW50aXRpZXMgZm9yIHRoZSBwcm9qZWN0IG1hbmlmZXN0LlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBwcmVmbGlnaHRBbmRyb2lkQXBwbGljYXRpb24+fSBwcmVwYXJlZCAtIFByZXBhcmVkIGFwcGxpY2F0aW9uLlxuICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSBTZW1hbnRpYyBwcm9ncmFtIG1hbmlmZXN0LlxuICovXG5mdW5jdGlvbiBzZW1hbnRpY1Byb2dyYW1NYW5pZmVzdChwcmVwYXJlZCkge1xuICBjb25zdCBzb3VyY2VDb250ZW50ID0gbmV3IE1hcChwcmVwYXJlZC5zb3VyY2VzLm1hcChzb3VyY2UgPT4gW3NvdXJjZS5maWxlbmFtZSwgc291cmNlLmNvbnRlbnRdKSlcbiAgY29uc3Qgb3JkZXIgPSBuZXcgTWFwKHByZXBhcmVkLnByb2dyYW0ubW9kdWxlcy5tYXAoKG1vZHVsZSwgaW5kZXgpID0+IFttb2R1bGUuaWQsIGluZGV4XSkpXG4gIGNvbnN0IG1vZHVsZXMgPSBwcmVwYXJlZC5wcm9ncmFtLm1vZHVsZXMubWFwKG1vZHVsZSA9PiB7XG4gICAgY29uc3Qgc291cmNlID0gcHJlcGFyZWQucHJvZ3JhbS5zb3VyY2VzLmZpbmQoY2FuZGlkYXRlID0+IGNhbmRpZGF0ZS5maWxlbmFtZSA9PSBtb2R1bGUuc291cmNlRmlsZW5hbWUpXG4gICAgY29uc3QgY29udGVudCA9IHNvdXJjZUNvbnRlbnQuZ2V0KG1vZHVsZS5zb3VyY2VGaWxlbmFtZSlcblxuICAgIGlmICghc291cmNlIHx8IGNvbnRlbnQgPT09IHVuZGVmaW5lZCkgdGhyb3cgbmV3IFR5cGVFcnJvcihgUHJlZmxpZ2h0ZWQgQW5kcm9pZCBtb2R1bGUgJyR7bW9kdWxlLmlkfScgbG9zdCBzb3VyY2Ugb3duZXJzaGlwLmApXG5cbiAgICByZXR1cm4ge1xuICAgICAgZGVwZW5kZW5jaWVzOiBbLi4ubmV3IFNldChtb2R1bGUuaW1wb3J0cy5tYXAoKHttb2R1bGVJZH0pID0+IG1vZHVsZUlkKSldXG4gICAgICAgIC5zb3J0KChsZWZ0LCByaWdodCkgPT4gLyoqIEB0eXBlIHtudW1iZXJ9ICovIChvcmRlci5nZXQobGVmdCkpIC0gLyoqIEB0eXBlIHtudW1iZXJ9ICovIChvcmRlci5nZXQocmlnaHQpKSksXG4gICAgICBnZW5lcmF0ZWRBcnRpZmFjdHM6IFtwcmVwYXJlZC5tb2R1bGVQYXRocy5nZXQobW9kdWxlLmlkKV0sXG4gICAgICBpZDogbW9kdWxlLmlkLFxuICAgICAgbmFtZXNwYWNlOiBgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUobW9kdWxlLmlkKX1gLFxuICAgICAgc291cmNlOiB7ZmlsZW5hbWU6IHNvdXJjZS5maWxlbmFtZSwgaWQ6IHNvdXJjZS5pZCwgc2hhMjU2OiBjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShjb250ZW50KS5kaWdlc3QoXCJoZXhcIil9XG4gICAgfVxuICB9KVxuICBjb25zdCBlbnRyeUlkID0gcHJlcGFyZWQucHJvZ3JhbS5lbnRyeU1vZHVsZVxuXG4gIHJldHVybiB7XG4gICAgZW50cnk6IHtcbiAgICAgIGFjdGl2aXR5QXJ0aWZhY3Q6IGAke3Byb2plY3RSb290fS9hcHAvc3JjL21haW4va290bGluLyR7cHJlcGFyZWQucGFja2FnZVBhdGh9LyR7cHJlcGFyZWQuY29uZmlndXJhdGlvbi5hY3Rpdml0eUNsYXNzTmFtZX0ua3RgLFxuICAgICAgZ2VuZXJhdGVkQXJ0aWZhY3Q6IHByZXBhcmVkLm1vZHVsZVBhdGhzLmdldChlbnRyeUlkKSxcbiAgICAgIGdlbmVyYXRlZEZ1bmN0aW9uSWRlbnRpdHk6IGBTZW1hbnRpZm9sZE1vZHVsZSR7bW9kdWxlTmFtZShlbnRyeUlkKX0uc2VtYW50aWZvbGRFbnRyeWAsXG4gICAgICBtb2R1bGVJZDogZW50cnlJZFxuICAgIH0sXG4gICAgbW9kdWxlcyxcbiAgICBzY2hlbWE6IFwiU2VtYW50aWZvbGRBbmRyb2lkU2VtYW50aWNQcm9ncmFtXCIsXG4gICAgc291cmNlczogcHJlcGFyZWQucHJvZ3JhbS5zb3VyY2VzLm1hcChzb3VyY2UgPT4gKHtcbiAgICAgIGZpbGVuYW1lOiBzb3VyY2UuZmlsZW5hbWUsXG4gICAgICBpZDogc291cmNlLmlkLFxuICAgICAgbGFuZ3VhZ2U6IHNvdXJjZS5sYW5ndWFnZSxcbiAgICAgIG1vZHVsZUlkczogbW9kdWxlcy5maWx0ZXIobW9kdWxlID0+IG1vZHVsZS5zb3VyY2UuZmlsZW5hbWUgPT0gc291cmNlLmZpbGVuYW1lKS5tYXAoKHtpZH0pID0+IGlkKSxcbiAgICAgIG93bmVyc2hpcDogc291cmNlLm93bmVyc2hpcCA/PyBcImFwcGxpY2F0aW9uXCIsXG4gICAgICBzaGEyNTY6IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoc291cmNlQ29udGVudC5nZXQoc291cmNlLmZpbGVuYW1lKSkpLmRpZ2VzdChcImhleFwiKVxuICAgIH0pKSxcbiAgICB2ZXJzaW9uOiAxXG4gIH1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYW5kIG5vcm1hbGl6ZXMgdGhlIGNsb3NlZCBBbmRyb2lkIGNvbmZpZ3VyYXRpb24uXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSBjb25maWd1cmF0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkFuZHJvaWRBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb259IE5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbi5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplQ29uZmlndXJhdGlvbihjYW5kaWRhdGUpIHtcbiAgaWYgKGNhbmRpZGF0ZSA9PT0gdW5kZWZpbmVkKSBjYW5kaWRhdGUgPSB7fVxuICBpZiAoIWlzUGxhaW5PYmplY3QoY2FuZGlkYXRlKSB8fCBPYmplY3Qua2V5cyhjYW5kaWRhdGUpLnNvbWUoa2V5ID0+ICFjb25maWd1cmF0aW9uRmllbGRzLmhhcyhrZXkpKSkge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiQW5kcm9pZCBhcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uIG11c3QgYmUgYSBjbG9zZWQgcGxhaW4gb2JqZWN0LlwiKVxuICB9XG4gIGNvbnN0IGNvbmZpZ3VyYXRpb24gPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkFuZHJvaWRBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb25JbnB1dH0gKi8gKGNhbmRpZGF0ZSlcbiAgY29uc3QgYXBwbGljYXRpb25JZCA9IGNvbmZpZ3VyYXRpb24uYXBwbGljYXRpb25JZCA/PyBcImRldi5zZW1hbnRpZm9sZC5nZW5lcmF0ZWRcIlxuICBjb25zdCBuYW1lc3BhY2UgPSBjb25maWd1cmF0aW9uLm5hbWVzcGFjZSA/PyBhcHBsaWNhdGlvbklkXG4gIGNvbnN0IHBhY2thZ2VOYW1lID0gY29uZmlndXJhdGlvbi5wYWNrYWdlTmFtZSA/PyBuYW1lc3BhY2VcbiAgY29uc3QgYWN0aXZpdHlDbGFzc05hbWUgPSBjb25maWd1cmF0aW9uLmFjdGl2aXR5Q2xhc3NOYW1lID8/IFwiTWFpbkFjdGl2aXR5XCJcbiAgY29uc3QgcHJvZHVjdE5hbWUgPSBjb25maWd1cmF0aW9uLnByb2R1Y3ROYW1lID8/IFwiU2VtYW50aWZvbGRcIlxuICBjb25zdCBkaXNwbGF5TmFtZSA9IGNvbmZpZ3VyYXRpb24uZGlzcGxheU5hbWUgPz8gXCJTZW1hbnRpZm9sZFwiXG4gIGNvbnN0IG1pbmltdW1TZGsgPSBjb25maWd1cmF0aW9uLm1pbmltdW1TZGsgPz8gMjNcbiAgY29uc3QgdGFyZ2V0U2RrID0gY29uZmlndXJhdGlvbi50YXJnZXRTZGsgPz8gdG9vbGNoYWluLnRhcmdldFNka1xuICBjb25zdCBjb21waWxlU2RrID0gY29uZmlndXJhdGlvbi5jb21waWxlU2RrID8/IHRvb2xjaGFpbi5jb21waWxlU2RrXG4gIGNvbnN0IGJ1aWxkVG9vbHNWZXJzaW9uID0gY29uZmlndXJhdGlvbi5idWlsZFRvb2xzVmVyc2lvbiA/PyB0b29sY2hhaW4uYnVpbGRUb29sc1xuICBjb25zdCB2ZXJzaW9uQ29kZSA9IGNvbmZpZ3VyYXRpb24udmVyc2lvbkNvZGUgPz8gMVxuICBjb25zdCB2ZXJzaW9uTmFtZSA9IGNvbmZpZ3VyYXRpb24udmVyc2lvbk5hbWUgPz8gXCIxLjAuMFwiXG4gIGNvbnN0IG9yaWVudGF0aW9uID0gY29uZmlndXJhdGlvbi5vcmllbnRhdGlvbiA/PyBcInVuc3BlY2lmaWVkXCJcbiAgY29uc3QgdGhlbWUgPSBjb25maWd1cmF0aW9uLnRoZW1lID8/IFwic3lzdGVtXCJcblxuICBmb3IgKGNvbnN0IFtsYWJlbCwgdmFsdWVdIG9mIFtbXCJBcHBsaWNhdGlvbiBJRFwiLCBhcHBsaWNhdGlvbklkXSwgW1wiTmFtZXNwYWNlXCIsIG5hbWVzcGFjZV0sIFtcIlBhY2thZ2UgbmFtZVwiLCBwYWNrYWdlTmFtZV1dKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPSBcInN0cmluZ1wiIHx8ICFpc1BhY2thZ2VOYW1lKHZhbHVlKSkgaW52YWxpZENvbmZpZ3VyYXRpb24oYCR7bGFiZWx9IG11c3QgYmUgYSBsb3dlcmNhc2UgSmF2YSBwYWNrYWdlIGlkZW50aXR5LmApXG4gIH1cbiAgaWYgKHR5cGVvZiBhY3Rpdml0eUNsYXNzTmFtZSAhPSBcInN0cmluZ1wiIHx8ICEvXltBLVpdW0EtWmEtejAtOV0qJC91LnRlc3QoYWN0aXZpdHlDbGFzc05hbWUpIHx8IGtvdGxpbktleXdvcmRzLmhhcyhhY3Rpdml0eUNsYXNzTmFtZSkpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIkFjdGl2aXR5IGNsYXNzIG5hbWUgbXVzdCBiZSBhbiBBU0NJSSB1cHBlci1jYW1lbCBLb3RsaW4gaWRlbnRpZmllci5cIilcbiAgfVxuICBmb3IgKGNvbnN0IFtsYWJlbCwgdmFsdWVdIG9mIFtbXCJQcm9kdWN0IG5hbWVcIiwgcHJvZHVjdE5hbWVdLCBbXCJEaXNwbGF5IG5hbWVcIiwgZGlzcGxheU5hbWVdXSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT0gXCJzdHJpbmdcIiB8fCB2YWx1ZS5sZW5ndGggPT0gMCB8fCB2YWx1ZS50cmltKCkgIT0gdmFsdWUgfHwgWy4uLnZhbHVlXS5sZW5ndGggPiA2NCB8fFxuICAgICAgIWhhc09ubHlVbmljb2RlU2NhbGFycyh2YWx1ZSkgfHwgL1tcXHB7Q2N9XFxwe1psfVxccHtacH1cXHVGRkZFXFx1RkZGRl0vdS50ZXN0KHZhbHVlKSkge1xuICAgICAgaW52YWxpZENvbmZpZ3VyYXRpb24oYCR7bGFiZWx9IG11c3QgYmUgYSBub24tZW1wdHkgc2luZ2xlLWxpbmUgVW5pY29kZSBzY2FsYXIgc3RyaW5nIG9mIGF0IG1vc3QgNjQgY2hhcmFjdGVycy5gKVxuICAgIH1cbiAgfVxuICBpZiAoL1tcXFxcLzo8PlwiPyp8XS91LnRlc3QocHJvZHVjdE5hbWUpKSB7XG4gICAgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJQcm9kdWN0IG5hbWUgY29udGFpbnMgYSBjaGFyYWN0ZXIgZm9yYmlkZGVuIGJ5IHRoZSBHcmFkbGUgcHJvamVjdC1uYW1lIGNvbnRyYWN0LlwiKVxuICB9XG4gIGlmIChtaW5pbXVtU2RrICE9PSAyMyB8fCB0YXJnZXRTZGsgIT09IDM1IHx8IGNvbXBpbGVTZGsgIT09IDM1IHx8IG1pbmltdW1TZGsgPiB0YXJnZXRTZGsgfHwgdGFyZ2V0U2RrID4gY29tcGlsZVNkaykge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiU0RLIGxldmVscyBtdXN0IHVzZSB0aGUgcXVhbGlmaWVkIG1pbmltdW0gMjMsIHRhcmdldCAzNSwgYW5kIGNvbXBpbGUgMzUgbWF0cml4LlwiKVxuICB9XG4gIGlmIChidWlsZFRvb2xzVmVyc2lvbiAhPSB0b29sY2hhaW4uYnVpbGRUb29scykgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJCdWlsZCBUb29scyB2ZXJzaW9uIG11c3QgYmUgZXhhY3RseSAnMzUuMC4wJy5cIilcbiAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih2ZXJzaW9uQ29kZSkgfHwgdmVyc2lvbkNvZGUgPCAxIHx8IHZlcnNpb25Db2RlID4gMl8xMDBfMDAwXzAwMCkge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiVmVyc2lvbiBjb2RlIG11c3QgYmUgYSBwb3NpdGl2ZSBBbmRyb2lkLXNhZmUgaW50ZWdlci5cIilcbiAgfVxuICBpZiAodHlwZW9mIHZlcnNpb25OYW1lICE9IFwic3RyaW5nXCIgfHwgIXNlbWFudGljVmVyc2lvblBhdHRlcm4udGVzdCh2ZXJzaW9uTmFtZSkpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIlZlcnNpb24gbmFtZSBtdXN0IGJlIGEgY2Fub25pY2FsIG5vbi1lbXB0eSBzZW1hbnRpYyB2ZXJzaW9uIHN0cmluZy5cIilcbiAgfVxuICBpZiAob3JpZW50YXRpb24gIT0gXCJ1bnNwZWNpZmllZFwiKSBpbnZhbGlkQ29uZmlndXJhdGlvbihcIlRoZSBiYXNlbGluZSBvcmllbnRhdGlvbiBpcyBleGFjdGx5ICd1bnNwZWNpZmllZCcuXCIpXG4gIGlmICh0aGVtZSAhPSBcInN5c3RlbVwiKSBpbnZhbGlkQ29uZmlndXJhdGlvbihcIlRoZSBiYXNlbGluZSB0aGVtZSBpcyBleGFjdGx5ICdzeXN0ZW0nLlwiKVxuICBpZiAoY29uZmlndXJhdGlvbi5wZXJtaXNzaW9ucyAhPT0gdW5kZWZpbmVkICYmXG4gICAgKCFpc0RlbnNlQXJyYXkoY29uZmlndXJhdGlvbi5wZXJtaXNzaW9ucykgfHwgY29uZmlndXJhdGlvbi5wZXJtaXNzaW9ucy5sZW5ndGggIT0gMCkpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIlRoZSBiYXNlbGluZSBBbmRyb2lkIHBlcm1pc3Npb24gc2V0IG11c3QgYmUgZW1wdHkuXCIpXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGFjdGl2aXR5Q2xhc3NOYW1lLFxuICAgIGFwcGxpY2F0aW9uSWQsXG4gICAgYnVpbGRUb29sc1ZlcnNpb24sXG4gICAgY29tcGlsZVNkayxcbiAgICBkaXNwbGF5TmFtZSxcbiAgICBtaW5pbXVtU2RrLFxuICAgIG5hbWVzcGFjZSxcbiAgICBvcmllbnRhdGlvbixcbiAgICBwYWNrYWdlTmFtZSxcbiAgICBwcm9kdWN0TmFtZSxcbiAgICB0YXJnZXRTZGssXG4gICAgdGhlbWUsXG4gICAgdmVyc2lvbkNvZGUsXG4gICAgdmVyc2lvbk5hbWVcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcywgc25hcHNob3RzLCBhbmQgb3JkZXJzIGNhbGxlci1wcm92aWRlZCBpbnB1dHMuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSByZXNvdXJjZSBvciBhc3NldCBsaXN0LlxuICogQHBhcmFtIHtcImFzc2V0XCIgfCBcInJlc291cmNlXCJ9IGtpbmQgLSBBbmRyb2lkIGlucHV0IGtpbmQuXG4gKiBAcmV0dXJucyB7QW5kcm9pZElucHV0RmlsZVtdfSBOb3JtYWxpemVkIGlucHV0cy5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplSW5wdXRGaWxlcyhjYW5kaWRhdGUsIGtpbmQpIHtcbiAgaWYgKGNhbmRpZGF0ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gW11cbiAgaWYgKCFpc0RlbnNlQXJyYXkoY2FuZGlkYXRlKSkgaW52YWxpZFJlc291cmNlKGBBcHBsaWNhdGlvbiAke2tpbmR9cyBtdXN0IGJlIGEgZGVuc2UgYXJyYXkuYClcbiAgLyoqIEB0eXBlIHtBbmRyb2lkSW5wdXRGaWxlW119ICovXG4gIGNvbnN0IGZpbGVzID0gW11cblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgY2FuZGlkYXRlLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIGNvbnN0IGl0ZW0gPSBjYW5kaWRhdGVbaW5kZXhdXG5cbiAgICBpZiAoIWlzUGxhaW5PYmplY3QoaXRlbSkgfHwgT2JqZWN0LmtleXMoaXRlbSkubGVuZ3RoICE9IHJlc291cmNlRmllbGRzLnNpemUgfHxcbiAgICAgIE9iamVjdC5rZXlzKGl0ZW0pLnNvbWUoa2V5ID0+ICFyZXNvdXJjZUZpZWxkcy5oYXMoa2V5KSkpIGludmFsaWRSZXNvdXJjZShgJHtjYXBpdGFsaXplKGtpbmQpfSAke2luZGV4fSBtdXN0IHVzZSB0aGUgY2xvc2VkIGlucHV0IHNjaGVtYS5gKVxuICAgIGNvbnN0IHBhdGggPSBpdGVtLnBhdGhcbiAgICBjb25zdCBjb250ZW50ID0gaXRlbS5jb250ZW50XG4gICAgY29uc3QgbWVkaWFUeXBlID0gaXRlbS5tZWRpYVR5cGVcbiAgICBjb25zdCBzaGEyNTYgPSBpdGVtLnNoYTI1NlxuXG4gICAgaWYgKCFpc1NhZmVBcnRpZmFjdFBhdGgocGF0aCkgfHwga2luZCA9PSBcInJlc291cmNlXCIgJiYgIWlzQWxsb3dlZFJlc291cmNlUGF0aChwYXRoKSkge1xuICAgICAgaW52YWxpZFJlc291cmNlKGAke2NhcGl0YWxpemUoa2luZCl9ICR7aW5kZXh9IGhhcyBhbiB1bnNhZmUgb3IgdW5zdXBwb3J0ZWQgcGF0aC5gKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIGNvbnRlbnQgIT0gXCJzdHJpbmdcIiAmJiAhKGNvbnRlbnQgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB8fCB0eXBlb2YgY29udGVudCA9PSBcInN0cmluZ1wiICYmXG4gICAgICAoY29udGVudC5sZW5ndGggPT0gMCB8fCAhaGFzT25seVVuaWNvZGVTY2FsYXJzKGNvbnRlbnQpKSB8fCBjb250ZW50IGluc3RhbmNlb2YgVWludDhBcnJheSAmJiBjb250ZW50LmJ5dGVMZW5ndGggPT0gMCkge1xuICAgICAgaW52YWxpZFJlc291cmNlKGAke2NhcGl0YWxpemUoa2luZCl9ICcke3BhdGh9JyByZXF1aXJlcyBub24tZW1wdHkgZXhhY3QgY29udGVudC5gKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIG1lZGlhVHlwZSAhPSBcInN0cmluZ1wiIHx8ICFtZWRpYVR5cGVQYXR0ZXJuLnRlc3QobWVkaWFUeXBlKSB8fCAvW1xcclxcbl0vdS50ZXN0KG1lZGlhVHlwZSkpIHtcbiAgICAgIGludmFsaWRSZXNvdXJjZShgJHtjYXBpdGFsaXplKGtpbmQpfSAnJHtwYXRofScgcmVxdWlyZXMgYW4gZXhwbGljaXQgdmFsaWQgbWVkaWEgdHlwZS5gKVxuICAgIH1cbiAgICBpZiAoa2luZCA9PSBcInJlc291cmNlXCIgJiYgcGF0aC5zdGFydHNXaXRoKFwiZHJhd2FibGUtXCIpICYmICFbXCJpbWFnZS9wbmdcIiwgXCJpbWFnZS93ZWJwXCJdLmluY2x1ZGVzKG1lZGlhVHlwZSkpIHtcbiAgICAgIGludmFsaWRSZXNvdXJjZShgRHJhd2FibGUgcmVzb3VyY2UgJyR7cGF0aH0nIG11c3QgdXNlIFBORyBvciBXZWJQIG1lZGlhIHR5cGUuYClcbiAgICB9XG4gICAgY29uc3Qgc25hcHNob3QgPSB0eXBlb2YgY29udGVudCA9PSBcInN0cmluZ1wiID8gY29udGVudCA6IG5ldyBVaW50OEFycmF5KGNvbnRlbnQpXG4gICAgY29uc3QgYWN0dWFsSGFzaCA9IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHNuYXBzaG90KS5kaWdlc3QoXCJoZXhcIilcblxuICAgIGlmICh0eXBlb2Ygc2hhMjU2ICE9IFwic3RyaW5nXCIgfHwgIS9eWzAtOWEtZl17NjR9JC91LnRlc3Qoc2hhMjU2KSB8fCBzaGEyNTYgIT0gYWN0dWFsSGFzaCkge1xuICAgICAgaW52YWxpZFJlc291cmNlKGAke2NhcGl0YWxpemUoa2luZCl9ICcke3BhdGh9JyBTSEEtMjU2IGRvZXMgbm90IG1hdGNoIGl0cyBleGFjdCBjb250ZW50LmApXG4gICAgfVxuICAgIGNvbnN0IGZ1bGxQYXRoID0gYCR7cHJvamVjdFJvb3R9L2FwcC9zcmMvbWFpbi8ke2tpbmQgPT0gXCJyZXNvdXJjZVwiID8gXCJyZXNcIiA6IFwiYXNzZXRzXCJ9LyR7cGF0aH1gXG5cbiAgICBmaWxlcy5wdXNoKHtjb250ZW50OiBzbmFwc2hvdCwgY29udGVudEtpbmQ6IHR5cGVvZiBzbmFwc2hvdCA9PSBcInN0cmluZ1wiID8gXCJ0ZXh0XCIgOiBcImJpbmFyeVwiLCBmdWxsUGF0aCwgbWVkaWFUeXBlLCBwYXRoLCBzaGEyNTZ9KVxuICB9XG4gIGZpbGVzLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0LmZ1bGxQYXRoIDwgcmlnaHQuZnVsbFBhdGggPyAtMSA6IGxlZnQuZnVsbFBhdGggPiByaWdodC5mdWxsUGF0aCA/IDEgOiAwKVxuICBjb25zdCBjb25mbGljdCA9IGZpbmRQb3J0YWJsZUFydGlmYWN0UGF0aENvbmZsaWN0KGZpbGVzLm1hcCgoe2Z1bGxQYXRofSkgPT4gZnVsbFBhdGgpKVxuXG4gIGlmIChjb25mbGljdCkgaW52YWxpZFJlc291cmNlKGAke2NhcGl0YWxpemUoa2luZCl9IHBhdGggJyR7Y29uZmxpY3QucGF0aH0nIGhhcyBhICR7Y29uZmxpY3Qua2luZH0gY29uZmxpY3QuYClcbiAgaWYgKGtpbmQgPT0gXCJyZXNvdXJjZVwiKSB2YWxpZGF0ZVJlc291cmNlSWRlbnRpZmllcnMoZmlsZXMpXG5cbiAgcmV0dXJuIGZpbGVzXG59XG5cbi8qKlxuICogUmVqZWN0cyB0d28gZmlsZXMgdGhhdCBBbmRyb2lkIHdvdWxkIGNvbXBpbGUgdG8gdGhlIHNhbWUgcmVzb3VyY2UgaWRlbnRpZmllciBpbiBvbmUgY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7QW5kcm9pZElucHV0RmlsZVtdfSBmaWxlcyAtIFZhbGlkYXRlZCByZXNvdXJjZSBpbnB1dHMuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlUmVzb3VyY2VJZGVudGlmaWVycyhmaWxlcykge1xuICBjb25zdCBpZGVudGlmaWVycyA9IG5ldyBNYXAoKVxuXG4gIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgIGNvbnN0IHNlcGFyYXRvciA9IGZpbGUucGF0aC5pbmRleE9mKFwiL1wiKVxuICAgIGNvbnN0IGRpcmVjdG9yeSA9IGZpbGUucGF0aC5zbGljZSgwLCBzZXBhcmF0b3IpXG4gICAgY29uc3QgZmlsZW5hbWUgPSBmaWxlLnBhdGguc2xpY2Uoc2VwYXJhdG9yICsgMSlcbiAgICBjb25zdCBleHRlbnNpb24gPSBmaWxlbmFtZS5pbmRleE9mKFwiLlwiKVxuICAgIGNvbnN0IG5hbWUgPSBleHRlbnNpb24gPT0gLTEgPyBmaWxlbmFtZSA6IGZpbGVuYW1lLnNsaWNlKDAsIGV4dGVuc2lvbilcbiAgICBjb25zdCByZXNvdXJjZVR5cGUgPSBkaXJlY3Rvcnkuc3BsaXQoXCItXCIsIDEpWzBdXG4gICAgY29uc3Qga2V5ID0gYCR7ZGlyZWN0b3J5fS8ke25hbWV9YFxuICAgIGNvbnN0IHByZXZpb3VzID0gaWRlbnRpZmllcnMuZ2V0KGtleSlcblxuICAgIGlmIChwcmV2aW91cykge1xuICAgICAgaW52YWxpZFJlc291cmNlKGBBbmRyb2lkIHJlc291cmNlIGlkZW50aWZpZXIgJyR7cmVzb3VyY2VUeXBlfS8ke25hbWV9JyBjb2xsaWRlcyBiZXR3ZWVuICcke3ByZXZpb3VzfScgYW5kICcke2ZpbGUucGF0aH0nIGluIGNvbmZpZ3VyYXRpb24gJyR7ZGlyZWN0b3J5fScuYClcbiAgICB9XG4gICAgaWRlbnRpZmllcnMuc2V0KGtleSwgZmlsZS5wYXRoKVxuICB9XG59XG5cbi8qKlxuICogVGVzdHMgd2hldGhlciBhIGNhbGxlciByZXNvdXJjZSB1c2VzIHRoZSBuYXJyb3cgYWxsb3dsaXN0ZWQgcmVzb3VyY2UgZ3JhbW1hci5cbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFJlc291cmNlIHBhdGggcmVsYXRpdmUgdG8gcmVzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIHBhdGggaXMgc3VwcG9ydGVkLlxuICovXG5mdW5jdGlvbiBpc0FsbG93ZWRSZXNvdXJjZVBhdGgodmFsdWUpIHtcbiAgaWYgKC9ecmF3XFwvW2Etel1bYS16MC05X10qKD86XFwuW2EtejAtOV0rKT8kL3UudGVzdCh2YWx1ZSkpIHJldHVybiB0cnVlXG5cbiAgcmV0dXJuIC9eZHJhd2FibGUtKD86bWRwaXxoZHBpfHhoZHBpfHh4aGRwaXx4eHhoZHBpKVxcL1thLXpdW2EtejAtOV9dKlxcLig/OnBuZ3x3ZWJwKSQvdS50ZXN0KHZhbHVlKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgdmFsaWRhdGVkIGlucHV0IHNuYXBzaG90IGludG8gYW4gb3duZWQgYXJ0aWZhY3QuXG4gKiBAcGFyYW0ge0FuZHJvaWRJbnB1dEZpbGV9IGl0ZW0gLSBWYWxpZGF0ZWQgY2FsbGVyIGlucHV0LlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0fSBPd25lZCBpbnB1dCBhcnRpZmFjdC5cbiAqL1xuZnVuY3Rpb24gaW5wdXRGaWxlQXJ0aWZhY3QoaXRlbSkge1xuICBjb25zdCByZWFzb24gPSBgRXhhY3QgY2FsbGVyLXByb3ZpZGVkIEFuZHJvaWQgaW5wdXQgKHNoYTI1Njoke2l0ZW0uc2hhMjU2fSkuYFxuXG4gIGlmICh0eXBlb2YgaXRlbS5jb250ZW50ID09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uc3ludGhldGljVGV4dChpdGVtLmZ1bGxQYXRoLCBcInJlc291cmNlXCIsIGl0ZW0uY29udGVudCwgcmVhc29uKSxcbiAgICAgIG1lZGlhVHlwZTogaXRlbS5tZWRpYVR5cGVcbiAgICB9XG4gIH1cbiAgY29uc3QgY29udGVudCA9IG5ldyBVaW50OEFycmF5KGl0ZW0uY29udGVudClcblxuICByZXR1cm4ge1xuICAgIGNvbnRlbnQsXG4gICAgY29udGVudEtpbmQ6IFwiYmluYXJ5XCIsXG4gICAgbWVkaWFUeXBlOiBpdGVtLm1lZGlhVHlwZSxcbiAgICBvd25lcnNoaXA6IFwiZ2VuZXJhdGVkXCIsXG4gICAgcGF0aDogaXRlbS5mdWxsUGF0aCxcbiAgICBwcm92ZW5hbmNlOiB7a2luZDogXCJieXRlc1wiLCBtYXBwaW5nOiBjcmVhdGVCeXRlTWFwcGluZyh7XG4gICAgICBieXRlTGVuZ3RoOiBjb250ZW50LmJ5dGVMZW5ndGgsXG4gICAgICBwYXRoOiBpdGVtLmZ1bGxQYXRoLFxuICAgICAgcmFuZ2VzOiBbe2dlbmVyYXRlZDoge2VuZDogY29udGVudC5ieXRlTGVuZ3RoLCBzdGFydDogMH0sXG4gICAgICAgIG9yaWdpbjoge2tpbmQ6IFwic3ludGhldGljXCIsIHJlYXNvbiwgcmVsYXRlZE9yaWdpbnM6IFtdfSwgcm9sZTogXCJyZXNvdXJjZVwifV1cbiAgICB9KX0sXG4gICAgcm9sZTogXCJyZXNvdXJjZVwiXG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZGV0ZXJtaW5pc3RpYyBzeW50aGV0aWMgdGV4dCBhcnRpZmFjdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gQXJ0aWZhY3QgcGF0aC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkQXJ0aWZhY3RSb2xlfSByb2xlIC0gQXJ0aWZhY3Qgcm9sZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250ZW50IC0gVVRGLTggYXJ0aWZhY3QgY29udGVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSByZWFzb24gLSBTeW50aGV0aWMgcHJvdmVuYW5jZSByZWFzb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3R9IFRleHQgYXJ0aWZhY3QuXG4gKi9cbmZ1bmN0aW9uIHN5bnRoZXRpY1RleHQocGF0aCwgcm9sZSwgY29udGVudCwgcmVhc29uKSB7XG4gIHJldHVybiB7Y29udGVudCwgY29udGVudEtpbmQ6IFwidGV4dFwiLCBtZWRpYVR5cGU6IG1lZGlhVHlwZUZvcihwYXRoKSwgb3duZXJzaGlwOiBcImdlbmVyYXRlZFwiLCBwYXRoLFxuICAgIHByb3ZlbmFuY2U6IHtraW5kOiBcInN5bnRoZXRpY1wiLCByZWFzb24sIHJlbGF0ZWRPcmlnaW5zOiBbXX0sIHJvbGV9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNvbmZpZ3VyYXRpb24tZGVyaXZlZCB0ZXh0IGFydGlmYWN0LlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBBcnRpZmFjdCBwYXRoLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0ZWRBcnRpZmFjdFJvbGV9IHJvbGUgLSBBcnRpZmFjdCByb2xlLlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbnRlbnQgLSBVVEYtOCBhcnRpZmFjdCBjb250ZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IHJlYXNvbiAtIFN5bnRoZXRpYyBwcm92ZW5hbmNlIHJlYXNvbi5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0ZWRTZXRBcnRpZmFjdH0gVGV4dCBhcnRpZmFjdC5cbiAqL1xuZnVuY3Rpb24gY29uZmlndXJlZFRleHQocGF0aCwgcm9sZSwgY29udGVudCwgcmVhc29uKSB7XG4gIHJldHVybiBzeW50aGV0aWNUZXh0KHBhdGgsIHJvbGUsIGNvbnRlbnQsIHJlYXNvbilcbn1cblxuLyoqXG4gKiBEZXJpdmVzIHRoZSBtZWRpYSB0eXBlIGZvciBhIGdlbmVyYXRlZCB0ZXh0IHBhdGguXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIEdlbmVyYXRlZCBhcnRpZmFjdCBwYXRoLlxuICogQHJldHVybnMge3N0cmluZ30gQXJ0aWZhY3QgbWVkaWEgdHlwZS5cbiAqL1xuZnVuY3Rpb24gbWVkaWFUeXBlRm9yKHBhdGgpIHtcbiAgaWYgKHBhdGguZW5kc1dpdGgoXCIuanNvblwiKSkgcmV0dXJuIFwiYXBwbGljYXRpb24vanNvblwiXG4gIGlmIChwYXRoLmVuZHNXaXRoKFwiLnhtbFwiKSkgcmV0dXJuIFwiYXBwbGljYXRpb24veG1sXCJcbiAgaWYgKHBhdGguZW5kc1dpdGgoXCIua3RcIikgfHwgcGF0aC5lbmRzV2l0aChcIi5rdHNcIikpIHJldHVybiBcInRleHQveC1rb3RsaW5cIlxuXG4gIHJldHVybiBcInRleHQvcGxhaW5cIlxufVxuXG4vKipcbiAqIE1hcmtzIG9uZSByZW5kZXJlZCB2YWx1ZSBhcyBjb25maWd1cmF0aW9uLWRlcml2ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmllbGROYW1lIC0gQ29uZmlndXJhdGlvbiBmaWVsZCBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gUmVuZGVyZWQgZmllbGQgdmFsdWUuXG4gKiBAcmV0dXJucyB7e2ZpZWxkOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmd9fSBNYXJrZWQgY29uZmlndXJhdGlvbiB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gZmllbGQoZmllbGROYW1lLCB2YWx1ZSkge1xuICByZXR1cm4ge2ZpZWxkOiBmaWVsZE5hbWUsIHZhbHVlfVxufVxuXG4vKipcbiAqIEpvaW5zIHJlbmRlcmVkIHBhcnRzIHdoaWxlIHJlY29yZGluZyBjb25maWd1cmF0aW9uIGNhdXNhbGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gT3V0cHV0IGFydGlmYWN0IHBhdGguXG4gKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb25TcGFuW119IHNwYW5zIC0gTXV0YWJsZSBwcm92ZW5hbmNlIHNwYW4gY29sbGVjdG9yLlxuICogQHBhcmFtIHsoc3RyaW5nIHwge2ZpZWxkOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmd9KVtdfSBwYXJ0cyAtIFN5bnRoZXRpYyBhbmQgbWFya2VkIHBhcnRzLlxuICogQHJldHVybnMge3N0cmluZ30gUmVuZGVyZWQgdGV4dC5cbiAqL1xuZnVuY3Rpb24gY29uZmlndXJlZChwYXRoLCBzcGFucywgcGFydHMpIHtcbiAgbGV0IGNvbnRlbnQgPSBcIlwiXG5cbiAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgaWYgKHR5cGVvZiBwYXJ0ID09IFwic3RyaW5nXCIpIGNvbnRlbnQgKz0gcGFydFxuICAgIGVsc2Uge1xuICAgICAgY29uc3Qgc3RhcnQgPSBjb250ZW50Lmxlbmd0aFxuXG4gICAgICBjb250ZW50ICs9IHBhcnQudmFsdWVcbiAgICAgIHNwYW5zLnB1c2goe2VuZDogY29udGVudC5sZW5ndGgsIGZpZWxkOiBwYXJ0LmZpZWxkLCBwYXRoLCBzdGFydH0pXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNvbnRlbnRcbn1cblxuLyoqXG4gKiBHcm91cHMgY29uZmlndXJhdGlvbiBzcGFucyBieSBhcnRpZmFjdC5cbiAqIEBwYXJhbSB7Q29uZmlndXJhdGlvblNwYW5bXX0gc3BhbnMgLSBBbGwgcmVuZGVyZWQgY29uZmlndXJhdGlvbiBzcGFucy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWVsZE5hbWUgLSBSZXF1ZXN0ZWQgY29uZmlndXJhdGlvbiBmaWVsZC5cbiAqIEByZXR1cm5zIHt7cGF0aDogc3RyaW5nLCByYW5nZXM6IHtlbmQ6IG51bWJlciwgc3RhcnQ6IG51bWJlcn1bXX1bXX0gT3V0cHV0IHJhbmdlcy5cbiAqL1xuZnVuY3Rpb24gY29uZmlndXJhdGlvbk91dHB1dHMoc3BhbnMsIGZpZWxkTmFtZSkge1xuICBjb25zdCBncm91cGVkID0gbmV3IE1hcCgpXG5cbiAgZm9yIChjb25zdCBzcGFuIG9mIHNwYW5zKSB7XG4gICAgaWYgKHNwYW4uZmllbGQgIT0gZmllbGROYW1lKSBjb250aW51ZVxuICAgIGNvbnN0IHJhbmdlcyA9IGdyb3VwZWQuZ2V0KHNwYW4ucGF0aCkgPz8gW11cblxuICAgIHJhbmdlcy5wdXNoKHtlbmQ6IHNwYW4uZW5kLCBzdGFydDogc3Bhbi5zdGFydH0pXG4gICAgZ3JvdXBlZC5zZXQoc3Bhbi5wYXRoLCByYW5nZXMpXG4gIH1cblxuICByZXR1cm4gWy4uLmdyb3VwZWRdLm1hcCgoW3BhdGgsIHJhbmdlc10pID0+ICh7cGF0aCwgcmFuZ2VzfSkpXG59XG5cbi8qKlxuICogVGVzdHMgd2hldGhlciBhIG1hcHBpbmcgb3JpZ2luIHJlZmVycyB0byBvbmUgc2VtYW50aWMgc291cmNlIGZpbGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljT3JpZ2lufSBvcmlnaW4gLSBNYXBwaW5nIG9yaWdpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNlbWFudGljIHNvdXJjZSBmaWxlbmFtZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBvcmlnaW4gb3ducyB0aGUgZmlsZW5hbWUuXG4gKi9cbmZ1bmN0aW9uIG9yaWdpblJlZmVyZW5jZXNGaWxlbmFtZShvcmlnaW4sIGZpbGVuYW1lKSB7XG4gIGlmIChvcmlnaW4ua2luZCA9PSBcInNvdXJjZVwiKSByZXR1cm4gb3JpZ2luLmxvY2F0aW9uLmZpbGVuYW1lID09IGZpbGVuYW1lXG4gIGlmIChvcmlnaW4ua2luZCA9PSBcImRlcml2ZWRcIikgcmV0dXJuIG9yaWdpbi5vcmlnaW5zLnNvbWUoKHtsb2NhdGlvbn0pID0+IGxvY2F0aW9uLmZpbGVuYW1lID09IGZpbGVuYW1lKVxuXG4gIHJldHVybiBvcmlnaW4ucmVsYXRlZE9yaWdpbnMuc29tZSgoe2xvY2F0aW9ufSkgPT4gbG9jYXRpb24uZmlsZW5hbWUgPT0gZmlsZW5hbWUpXG59XG5cbi8qKlxuICogSGFzaGVzIGV4YWN0IHRleHQgb3IgYnl0ZXMgZm9yIG93bmVyc2hpcCByZWNvcmRzLlxuICogQHBhcmFtIHtzdHJpbmcgfCBVaW50OEFycmF5fSBjb250ZW50IC0gRXhhY3QgYXJ0aWZhY3QgY29udGVudC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IExvd2VyY2FzZSBTSEEtMjU2IGRpZ2VzdC5cbiAqL1xuZnVuY3Rpb24gaGFzaENvbnRlbnQoY29udGVudCkge1xuICByZXR1cm4gY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUoY29udGVudCkuZGlnZXN0KFwiaGV4XCIpXG59XG5cbi8qKlxuICogU2VyaWFsaXplcyBKU09OIHdpdGggcmVjdXJzaXZlbHkgc3RhYmxlIG9iamVjdC1rZXkgb3JkZXJpbmcuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gSlNPTi1jb21wYXRpYmxlIHZhbHVlLlxuICogQHJldHVybnMge3N0cmluZ30gQ2Fub25pY2FsIGluZGVudGVkIEpTT04gd2l0aCB0cmFpbGluZyBuZXdsaW5lLlxuICovXG5mdW5jdGlvbiBzdHJpbmdpZnlDYW5vbmljYWxKc29uKHZhbHVlKSB7XG4gIHJldHVybiBgJHtKU09OLnN0cmluZ2lmeShzb3J0SnNvbih2YWx1ZSksIG51bGwsIDIpfVxcbmBcbn1cblxuLyoqXG4gKiBSZWN1cnNpdmVseSBzb3J0cyBvYmplY3Qga2V5cyB3aXRob3V0IGNoYW5naW5nIGFycmF5IG9yZGVyLlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIEpTT04tY29tcGF0aWJsZSB2YWx1ZS5cbiAqIEByZXR1cm5zIHt1bmtub3dufSBDYW5vbmljYWxseSBvcmRlcmVkIHZhbHVlLlxuICovXG5mdW5jdGlvbiBzb3J0SnNvbih2YWx1ZSkge1xuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHJldHVybiB2YWx1ZS5tYXAoc29ydEpzb24pXG4gIGlmICghaXNQbGFpbk9iamVjdCh2YWx1ZSkpIHJldHVybiB2YWx1ZVxuXG4gIHJldHVybiBPYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmtleXModmFsdWUpLnNvcnQoKS5tYXAoa2V5ID0+IFtrZXksIHNvcnRKc29uKHZhbHVlW2tleV0pXSkpXG59XG5cbi8qKlxuICogVGVzdHMgYSBsb3dlcmNhc2UgS290bGluLWNvbXBhdGlibGUgcGFja2FnZSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIENhbmRpZGF0ZSBwYWNrYWdlIG5hbWUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgbmFtZSBpcyBhY2NlcHRlZC5cbiAqL1xuZnVuY3Rpb24gaXNQYWNrYWdlTmFtZSh2YWx1ZSkge1xuICBjb25zdCBwYXJ0cyA9IHZhbHVlLnNwbGl0KFwiLlwiKVxuXG4gIHJldHVybiBwYXJ0cy5sZW5ndGggPj0gMiAmJiBwYXJ0cy5ldmVyeShwYXJ0ID0+IC9eW2Etel1bYS16MC05X10qJC91LnRlc3QocGFydCkgJiYgIWtvdGxpbktleXdvcmRzLmhhcyhwYXJ0KSlcbn1cblxuLyoqXG4gKiBSZWplY3RzIGxhdW5jaGVyIG5hbWVzIHRoYXQgc2hhZG93IGFuIHVucXVhbGlmaWVkIHN5bWJvbCBpbiBnZW5lcmF0ZWQgc2FtZS1wYWNrYWdlIEtvdGxpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpdml0eUNsYXNzTmFtZSAtIFZhbGlkYXRlZCBsYXVuY2hlciBjbGFzcyBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IGVudHJ5TW9kdWxlIC0gU2VsZWN0ZWQgc2VtYW50aWMgZW50cnkgbW9kdWxlLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUFjdGl2aXR5Q2xhc3NOYW1lKGFjdGl2aXR5Q2xhc3NOYW1lLCBlbnRyeU1vZHVsZSkge1xuICBjb25zdCBzZW1hbnRpY0VudHJ5U3ltYm9sID0gYFNlbWFudGlmb2xkTW9kdWxlJHttb2R1bGVOYW1lKGVudHJ5TW9kdWxlKX1gXG5cbiAgaWYgKGFuZHJvaWRTY2FmZm9sZFN5bWJvbHMuaGFzKGFjdGl2aXR5Q2xhc3NOYW1lKSB8fCBhY3Rpdml0eUNsYXNzTmFtZSA9PSBzZW1hbnRpY0VudHJ5U3ltYm9sKSB7XG4gICAgaW52YWxpZENvbmZpZ3VyYXRpb24oYEFjdGl2aXR5IGNsYXNzIG5hbWUgJyR7YWN0aXZpdHlDbGFzc05hbWV9JyBjb2xsaWRlcyB3aXRoIGdlbmVyYXRlZCBLb3RsaW4gc3ltYm9sICcke2FjdGl2aXR5Q2xhc3NOYW1lfScuYClcbiAgfVxufVxuXG4vKipcbiAqIEFsbG9jYXRlcyBvbmUgbW9kdWxlLXdpZGUgb3V0cHV0IHNpbmsgdGhhdCBjYW5ub3Qgc2hhZG93IGEgc291cmNlIGJpbmRpbmcuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBQcmVwYXJlZCBzZW1hbnRpYyBtb2R1bGUuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBDb2xsaXNpb24tc2FmZSBLb3RsaW4gYmluZGluZy5cbiAqL1xuZnVuY3Rpb24gb3V0cHV0U2lua05hbWUobW9kdWxlKSB7XG4gIGNvbnN0IGJpbmRpbmdzID0gbmV3IFNldChtb2R1bGUuZnVuY3Rpb25zLmZsYXRNYXAoZGVjbGFyYXRpb24gPT4gZGVjbGFyYXRpb24ucGFyYW1ldGVycy5tYXAoKHtuYW1lfSkgPT4gbmFtZSkpKVxuXG4gIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgbW9kdWxlLmZ1bmN0aW9ucykgY29sbGVjdEJsb2NrQmluZGluZ05hbWVzKGRlY2xhcmF0aW9uLmJvZHksIGJpbmRpbmdzKVxuICBjb2xsZWN0QmxvY2tCaW5kaW5nTmFtZXMobW9kdWxlLmVudHJ5UG9pbnQuYm9keSwgYmluZGluZ3MpXG4gIGxldCBjYW5kaWRhdGUgPSBcInNlbWFudGlmb2xkT3V0cHV0XCJcblxuICB3aGlsZSAoYmluZGluZ3MuaGFzKGNhbmRpZGF0ZSkpIGNhbmRpZGF0ZSArPSBcIl9cIlxuXG4gIHJldHVybiBjYW5kaWRhdGVcbn1cblxuLyoqXG4gKiBDb2xsZWN0cyBsb2NhbCBiaW5kaW5ncyByZWN1cnNpdmVseSBmcm9tIHRoZSBzdXBwb3J0ZWQgc2VtYW50aWMgYmxvY2sgc3Vic2V0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5CbG9ja30gYmxvY2sgLSBTZW1hbnRpYyBibG9jay5cbiAqIEBwYXJhbSB7U2V0PHN0cmluZz59IGJpbmRpbmdzIC0gTXV0YWJsZSBiaW5kaW5nLW5hbWUgc2V0LlxuICovXG5mdW5jdGlvbiBjb2xsZWN0QmxvY2tCaW5kaW5nTmFtZXMoYmxvY2ssIGJpbmRpbmdzKSB7XG4gIGZvciAoY29uc3Qgc3RhdGVtZW50IG9mIGJsb2NrLnN0YXRlbWVudHMpIHtcbiAgICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJMb2NhbERlY2xhcmF0aW9uXCIpIGJpbmRpbmdzLmFkZChzdGF0ZW1lbnQubmFtZSlcbiAgICBlbHNlIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIklmU3RhdGVtZW50XCIpIHtcbiAgICAgIGNvbGxlY3RCbG9ja0JpbmRpbmdOYW1lcyhzdGF0ZW1lbnQuY29uc2VxdWVudCwgYmluZGluZ3MpXG4gICAgICBpZiAoc3RhdGVtZW50LmFsdGVybmF0ZSkgY29sbGVjdEJsb2NrQmluZGluZ05hbWVzKHN0YXRlbWVudC5hbHRlcm5hdGUsIGJpbmRpbmdzKVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIE1hcHMgYSBwcmVmbGlnaHRlZCBtb2R1bGUgaWRlbnRpdHkgdG8gYSBzdGFibGUgS290bGluIHN1ZmZpeC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFNlbWFudGljIG1vZHVsZSBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IEtvdGxpbiBvYmplY3QtbmFtZSBzdWZmaXguXG4gKi9cbmZ1bmN0aW9uIG1vZHVsZU5hbWUoaWQpIHtcbiAgcmV0dXJuIGlkLnNwbGl0KC9bLl8tXSsvdSkubWFwKHBhcnQgPT4gYCR7cGFydFswXS50b1VwcGVyQ2FzZSgpfSR7cGFydC5zbGljZSgxKX1gKS5qb2luKFwiXCIpXG59XG5cbi8qKlxuICogV3JhcHMgbGVnYWN5IHNpbmdsZS1tb2R1bGUgaW5wdXQgaW4gdGhlIGNhbm9uaWNhbCBwcm9ncmFtIGNvbnRyYWN0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZSB8IHVuZGVmaW5lZH0gY2FuZGlkYXRlIC0gQ2FuZGlkYXRlIHNlbWFudGljIG1vZHVsZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY1Byb2dyYW19IENhbm9uaWNhbCBzaW5nbGUtbW9kdWxlIHByb2dyYW0uXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZVNpbmdsZU1vZHVsZShjYW5kaWRhdGUpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KGNhbmRpZGF0ZSkpIHVuc3VwcG9ydGVkQ2FwYWJpbGl0eShcImFuZHJvaWRcIiwgXCJtaXNzaW5nIG9yIGludmFsaWQgbW9kdWxlXCIsIHVuZGVmaW5lZClcbiAgY29uc3QgbW9kdWxlID0gc3RydWN0dXJlZENsb25lKGNhbmRpZGF0ZSlcbiAgY29uc3Qgc291cmNlcyA9IG1vZHVsZS5wcm92ZW5hbmNlPy5zb3VyY2VzXG5cbiAgaWYgKCFBcnJheS5pc0FycmF5KHNvdXJjZXMpIHx8IHNvdXJjZXMubGVuZ3RoICE9IDEgfHwgc291cmNlc1swXS5jb250ZW50ID09PSBudWxsIHx8XG4gICAgc291cmNlc1swXS5maWxlbmFtZSAhPSBtb2R1bGUubG9jYXRpb24/LmZpbGVuYW1lIHx8IHR5cGVvZiBzb3VyY2VzWzBdLmxhbmd1YWdlICE9IFwic3RyaW5nXCIpIHtcbiAgICB1bnN1cHBvcnRlZENhcGFiaWxpdHkoXCJhbmRyb2lkXCIsIFwic2luZ2xlLW1vZHVsZSBzb3VyY2Ugb3duZXJzaGlwXCIsIG1vZHVsZS5sb2NhdGlvbilcbiAgfVxuICByZWtleU1vZHVsZURlY2xhcmF0aW9ucyhtb2R1bGUsIFwibWFpblwiKVxuICBjb25zdCBleHBvcnRzID0gW1xuICAgIC4uLihtb2R1bGUucmVjb3JkcyA/PyBbXSkubWFwKGRlY2xhcmF0aW9uID0+IGFwcGxpY2F0aW9uRXhwb3J0KGRlY2xhcmF0aW9uLCBcInJlY29yZFwiKSksXG4gICAgLi4uKG1vZHVsZS5jbGFzc2VzID8/IFtdKS5tYXAoZGVjbGFyYXRpb24gPT4gYXBwbGljYXRpb25FeHBvcnQoZGVjbGFyYXRpb24sIFwiY2xhc3NcIikpLFxuICAgIC4uLihtb2R1bGUuZXJyb3JzID8/IFtdKS5tYXAoZGVjbGFyYXRpb24gPT4gYXBwbGljYXRpb25FeHBvcnQoZGVjbGFyYXRpb24sIFwiZXJyb3JcIikpLFxuICAgIC4uLm1vZHVsZS5mdW5jdGlvbnMubWFwKGRlY2xhcmF0aW9uID0+IGFwcGxpY2F0aW9uRXhwb3J0KGRlY2xhcmF0aW9uLCBcImZ1bmN0aW9uXCIpKVxuICBdXG4gIGNvbnN0IHByb2dyYW1Nb2R1bGUgPSB7Li4ubW9kdWxlLCBleHBvcnRzLCBpZDogXCJtYWluXCIsIGltcG9ydHM6IFtdLCBzb3VyY2VGaWxlbmFtZTogc291cmNlc1swXS5maWxlbmFtZX1cblxuICByZXR1cm4ge2VudHJ5TW9kdWxlOiBcIm1haW5cIiwga2luZDogXCJQcm9ncmFtXCIsIG1vZHVsZXM6IFtwcm9ncmFtTW9kdWxlXSwgc291cmNlczogc3RydWN0dXJlZENsb25lKHNvdXJjZXMpfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXBwbGljYXRpb24tbG9jYWwgZXhwb3J0IHJlY29yZCBmb3Igc2luZ2xlLW1vZHVsZSBjb21wYXRpYmlsaXR5LlxuICogQHBhcmFtIHt7aWQ/OiBzdHJpbmcsIGxvY2F0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgbmFtZTogc3RyaW5nfX0gZGVjbGFyYXRpb24gLSBTZW1hbnRpYyBkZWNsYXJhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNEZWNsYXJhdGlvbktpbmR9IHN5bWJvbEtpbmQgLSBEZWNsYXJhdGlvbiBraW5kLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljRXhwb3J0fSBTZW1hbnRpYyBleHBvcnQuXG4gKi9cbmZ1bmN0aW9uIGFwcGxpY2F0aW9uRXhwb3J0KGRlY2xhcmF0aW9uLCBzeW1ib2xLaW5kKSB7XG4gIHJldHVybiB7ZGVjbGFyYXRpb25JZDogLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkZWNsYXJhdGlvbi5pZCksIGV4cG9ydGVkTmFtZTogZGVjbGFyYXRpb24ubmFtZSxcbiAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJFeHBvcnRcIiksIGxvY2F0aW9uOiBkZWNsYXJhdGlvbi5sb2NhdGlvbiwgc3ltYm9sS2luZH1cbn1cblxuLyoqXG4gKiBRdWFsaWZpZXMgc2luZ2xlLW1vZHVsZSBkZWNsYXJhdGlvbiBpZGVudGl0aWVzIGJlZm9yZSBwcm9ncmFtIHByZWZsaWdodC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIENsb25lZCBzZW1hbnRpYyBtb2R1bGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbW9kdWxlSWQgLSBDYW5vbmljYWwgbW9kdWxlIGlkZW50aXR5LlxuICovXG5mdW5jdGlvbiByZWtleU1vZHVsZURlY2xhcmF0aW9ucyhtb2R1bGUsIG1vZHVsZUlkKSB7XG4gIGNvbnN0IGRlY2xhcmF0aW9ucyA9IFsuLi5tb2R1bGUucmVjb3JkcyA/PyBbXSwgLi4ubW9kdWxlLmNsYXNzZXMgPz8gW10sIC4uLm1vZHVsZS5lcnJvcnMgPz8gW10sIC4uLm1vZHVsZS5mdW5jdGlvbnNdXG4gIGNvbnN0IHJlcGxhY2VtZW50cyA9IG5ldyBNYXAoZGVjbGFyYXRpb25zLmZpbHRlcihkZWNsYXJhdGlvbiA9PiB0eXBlb2YgZGVjbGFyYXRpb24uaWQgPT0gXCJzdHJpbmdcIilcbiAgICAubWFwKGRlY2xhcmF0aW9uID0+IFtkZWNsYXJhdGlvbi5pZCwgYCR7bW9kdWxlSWR9IyR7ZGVjbGFyYXRpb24uaWR9YF0pKVxuXG4gIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgZGVjbGFyYXRpb25zKSBpZiAodHlwZW9mIGRlY2xhcmF0aW9uLmlkID09IFwic3RyaW5nXCIpIGRlY2xhcmF0aW9uLmlkID0gcmVwbGFjZW1lbnRzLmdldChkZWNsYXJhdGlvbi5pZClcbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQoKVxuICBjb25zdCBpZGVudGl0eUZpZWxkcyA9IG5ldyBTZXQoW1wiY2xhc3NJZFwiLCBcImRlY2xhcmF0aW9uSWRcIiwgXCJmaWVsZFwiLCBcIm1ldGhvZFwiLCBcInBhcmFtZXRlcklkXCJdKVxuICAvKipcbiAgICogUmV3cml0ZXMgZGVjbGFyYXRpb24gcmVmZXJlbmNlcyB0aHJvdWdob3V0IG9uZSBzZW1hbnRpYyB2YWx1ZSBncmFwaC5cbiAgICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIENhbmRpZGF0ZSBuZXN0ZWQgc2VtYW50aWMgdmFsdWUuXG4gICAqL1xuICBjb25zdCB2aXNpdCA9IHZhbHVlID0+IHtcbiAgICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPSBcIm9iamVjdFwiIHx8IHNlZW4uaGFzKHZhbHVlKSkgcmV0dXJuXG4gICAgc2Vlbi5hZGQodmFsdWUpXG4gICAgZm9yIChjb25zdCBba2V5LCBuZXN0ZWRdIG9mIE9iamVjdC5lbnRyaWVzKHZhbHVlKSkge1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBpZGVudGl0eUZpZWxkcy5oYXMoa2V5KSAmJiB0eXBlb2YgbmVzdGVkID09IFwic3RyaW5nXCIgJiYgcmVwbGFjZW1lbnRzLmhhcyhuZXN0ZWQpKSB7XG4gICAgICAgIFJlZmxlY3Quc2V0KHZhbHVlLCBrZXksIHJlcGxhY2VtZW50cy5nZXQobmVzdGVkKSlcbiAgICAgIH0gZWxzZSB2aXNpdChuZXN0ZWQpXG4gICAgfVxuICB9XG5cbiAgdmlzaXQobW9kdWxlKVxufVxuXG4vKipcbiAqIEVzY2FwZXMgYSBjb25maWd1cmF0aW9uIHZhbHVlIGZvciBYTUwgdGV4dCBvciBhdHRyaWJ1dGVzLlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gUmF3IGNvbmZpZ3VyYXRpb24gdmFsdWUuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBYTUwtc2FmZSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24geG1sRXNjYXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZS5yZXBsYWNlQWxsKFwiJlwiLCBcIiZhbXA7XCIpLnJlcGxhY2VBbGwoXCI8XCIsIFwiJmx0O1wiKS5yZXBsYWNlQWxsKFwiPlwiLCBcIiZndDtcIilcbiAgICAucmVwbGFjZUFsbCgnXCInLCBcIiZxdW90O1wiKS5yZXBsYWNlQWxsKFwiJ1wiLCBcIiZhcG9zO1wiKVxufVxuXG4vKipcbiAqIEVzY2FwZXMgYSBjb25maWd1cmF0aW9uIHZhbHVlIGZvciBhIEtvdGxpbiBzdHJpbmcgbGl0ZXJhbCBib2R5LlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gUmF3IGNvbmZpZ3VyYXRpb24gdmFsdWUuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBLb3RsaW4tc2FmZSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24ga290bGluRXNjYXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZS5yZXBsYWNlQWxsKFwiXFxcXFwiLCBcIlxcXFxcXFxcXCIpLnJlcGxhY2VBbGwoJ1wiJywgJ1xcXFxcIicpLnJlcGxhY2VBbGwoXCIkXCIsIFwiXFxcXCRcIilcbn1cblxuLyoqXG4gKiBVcHBlcmNhc2VzIHRoZSBpbml0aWFsIEFTQ0lJIGNoYXJhY3RlciBvZiBhIGtub3duIG5vbi1lbXB0eSB3b3JkLlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gTm9uLWVtcHR5IHdvcmQuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBDYXBpdGFsaXplZCB3b3JkLlxuICovXG5mdW5jdGlvbiBjYXBpdGFsaXplKHZhbHVlKSB7XG4gIHJldHVybiBgJHt2YWx1ZVswXS50b1VwcGVyQ2FzZSgpfSR7dmFsdWUuc2xpY2UoMSl9YFxufVxuXG4vKipcbiAqIFRlc3RzIHdoZXRoZXIgYSB2YWx1ZSBpcyBhIHBsYWluIGRhdGEgb2JqZWN0LlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIENhbmRpZGF0ZSB2YWx1ZS5cbiAqIEByZXR1cm5zIHt2YWx1ZSBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gV2hldGhlciB0aGUgdmFsdWUgaXMgYSBwbGFpbiBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGlzUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIEJvb2xlYW4odmFsdWUpICYmIHR5cGVvZiB2YWx1ZSA9PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpID09IE9iamVjdC5wcm90b3R5cGVcbn1cblxuLyoqXG4gKiBUaHJvd3MgYSBzdGFibGUgaW52YWxpZC1yZXF1ZXN0IGRpYWdub3N0aWMuXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIERpYWdub3N0aWMgbWVzc2FnZS5cbiAqIEByZXR1cm5zIHtuZXZlcn0gTmV2ZXIgcmV0dXJucy5cbiAqL1xuZnVuY3Rpb24gaW52YWxpZElucHV0KG1lc3NhZ2UpIHtcbiAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7Y29kZTogXCJJTlZBTElEX0FQUExJQ0FUSU9OX0lOUFVUXCIsIGxhbmd1YWdlOiBcImFuZHJvaWRcIiwgbWVzc2FnZX0pXG59XG5cbi8qKlxuICogVGhyb3dzIGEgc3RhYmxlIGludmFsaWQtY29uZmlndXJhdGlvbiBkaWFnbm9zdGljLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBEaWFnbm9zdGljIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7bmV2ZXJ9IE5ldmVyIHJldHVybnMuXG4gKi9cbmZ1bmN0aW9uIGludmFsaWRDb25maWd1cmF0aW9uKG1lc3NhZ2UpIHtcbiAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7Y29kZTogXCJJTlZBTElEX0FQUExJQ0FUSU9OX0NPTkZJR1VSQVRJT05cIiwgbGFuZ3VhZ2U6IFwiYW5kcm9pZFwiLCBtZXNzYWdlfSlcbn1cblxuLyoqXG4gKiBUaHJvd3MgYSBzdGFibGUgaW52YWxpZC1yZXNvdXJjZSBkaWFnbm9zdGljLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBEaWFnbm9zdGljIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7bmV2ZXJ9IE5ldmVyIHJldHVybnMuXG4gKi9cbmZ1bmN0aW9uIGludmFsaWRSZXNvdXJjZShtZXNzYWdlKSB7XG4gIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe2NvZGU6IFwiSU5WQUxJRF9BUFBMSUNBVElPTl9SRVNPVVJDRVwiLCBsYW5ndWFnZTogXCJhbmRyb2lkXCIsIG1lc3NhZ2V9KVxufVxuXG4vKipcbiAqIFRocm93cyBhIHN0YWJsZSBpbnZhbGlkLXBhdGggZGlhZ25vc3RpYy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRGlhZ25vc3RpYyBtZXNzYWdlLlxuICogQHJldHVybnMge25ldmVyfSBOZXZlciByZXR1cm5zLlxuICovXG5mdW5jdGlvbiBpbnZhbGlkUGF0aChtZXNzYWdlKSB7XG4gIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe2NvZGU6IFwiSU5WQUxJRF9BUFBMSUNBVElPTl9QQVRIXCIsIGxhbmd1YWdlOiBcImFuZHJvaWRcIiwgbWVzc2FnZX0pXG59XG4iXX0=