breeze-client 2.1.3 → 2.1.4-mjs

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 (395) hide show
  1. package/README.md +18 -5
  2. package/adapter-ajax-angularjs/{breeze-client-adapter-ajax-angularjs.d.ts → index.d.ts} +1 -0
  3. package/adapter-ajax-fetch/{breeze-client-adapter-ajax-fetch.d.ts → index.d.ts} +1 -0
  4. package/adapter-ajax-httpclient/{breeze-client-adapter-ajax-httpclient.d.ts → index.d.ts} +1 -0
  5. package/adapter-ajax-jquery/{breeze-client-adapter-ajax-jquery.d.ts → index.d.ts} +1 -0
  6. package/adapter-ajax-post/{breeze-client-adapter-ajax-post.d.ts → index.d.ts} +1 -0
  7. package/adapter-data-service-odata/{breeze-client-adapter-data-service-odata.d.ts → index.d.ts} +1 -0
  8. package/adapter-data-service-webapi/{breeze-client-adapter-data-service-webapi.d.ts → index.d.ts} +1 -0
  9. package/adapter-model-library-backing-store/{breeze-client-adapter-model-library-backing-store.d.ts → index.d.ts} +1 -0
  10. package/adapter-model-library-ko/{breeze-client-adapter-model-library-ko.d.ts → index.d.ts} +1 -0
  11. package/adapter-uri-builder-json/{breeze-client-adapter-uri-builder-json.d.ts → index.d.ts} +1 -0
  12. package/adapter-uri-builder-odata/{breeze-client-adapter-uri-builder-odata.d.ts → index.d.ts} +1 -0
  13. package/esm2020/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +130 -0
  14. package/esm2020/adapter-ajax-angularjs/adapter-core.mjs +49 -0
  15. package/esm2020/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +5 -0
  16. package/esm2020/adapter-ajax-fetch/adapter-ajax-fetch.mjs +132 -0
  17. package/esm2020/adapter-ajax-fetch/adapter-core.mjs +49 -0
  18. package/esm2020/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +5 -0
  19. package/esm2020/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +137 -0
  20. package/esm2020/adapter-ajax-httpclient/adapter-core.mjs +49 -0
  21. package/esm2020/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +5 -0
  22. package/esm2020/adapter-ajax-jquery/adapter-ajax-jquery.mjs +103 -0
  23. package/esm2020/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +5 -0
  24. package/esm2020/adapter-ajax-post/adapter-ajax-post.mjs +77 -0
  25. package/esm2020/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +5 -0
  26. package/esm2020/adapter-data-service-odata/adapter-core.mjs +49 -0
  27. package/esm2020/adapter-data-service-odata/adapter-data-service-odata.mjs +456 -0
  28. package/esm2020/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +5 -0
  29. package/esm2020/adapter-data-service-webapi/adapter-data-service-webapi.mjs +93 -0
  30. package/esm2020/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +5 -0
  31. package/esm2020/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +268 -0
  32. package/esm2020/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +5 -0
  33. package/esm2020/adapter-model-library-ko/adapter-model-library-ko.mjs +240 -0
  34. package/esm2020/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +5 -0
  35. package/esm2020/adapter-uri-builder-json/adapter-core.mjs +49 -0
  36. package/esm2020/adapter-uri-builder-json/adapter-uri-builder-json.mjs +36 -0
  37. package/esm2020/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +5 -0
  38. package/esm2020/adapter-uri-builder-odata/adapter-core.mjs +49 -0
  39. package/esm2020/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +190 -0
  40. package/esm2020/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +5 -0
  41. package/esm2020/breeze-client.mjs +5 -0
  42. package/esm2020/index.mjs +2 -0
  43. package/esm2020/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +5 -0
  44. package/esm2020/mixin-get-entity-graph/mixin-get-entity-graph.mjs +269 -0
  45. package/esm2020/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +5 -0
  46. package/esm2020/mixin-save-queuing/mixin-save-queuing.mjs +400 -0
  47. package/esm2020/src/abstract-data-service-adapter.mjs +296 -0
  48. package/esm2020/src/array.mjs +4 -0
  49. package/esm2020/src/assert-param.mjs +312 -0
  50. package/esm2020/src/breeze.mjs +85 -0
  51. package/esm2020/src/complex-array.mjs +117 -0
  52. package/esm2020/src/config.mjs +223 -0
  53. package/esm2020/src/core.mjs +707 -0
  54. package/esm2020/src/csdl-metadata-parser.mjs +385 -0
  55. package/esm2020/src/data-service.mjs +203 -0
  56. package/esm2020/src/data-type.mjs +444 -0
  57. package/esm2020/src/default-property-interceptor.mjs +460 -0
  58. package/esm2020/src/entity-action.mjs +45 -0
  59. package/esm2020/src/entity-aspect.mjs +806 -0
  60. package/esm2020/src/entity-group.mjs +187 -0
  61. package/esm2020/src/entity-key.mjs +116 -0
  62. package/esm2020/src/entity-manager.mjs +2094 -0
  63. package/esm2020/src/entity-metadata.mjs +2109 -0
  64. package/esm2020/src/entity-query.mjs +996 -0
  65. package/esm2020/src/entity-state.mjs +99 -0
  66. package/esm2020/src/enum.mjs +141 -0
  67. package/esm2020/src/event.mjs +256 -0
  68. package/esm2020/src/interface-registry.mjs +41 -0
  69. package/esm2020/src/key-generator.mjs +108 -0
  70. package/esm2020/src/local-query-comparison-options.mjs +65 -0
  71. package/esm2020/src/mapping-context.mjs +405 -0
  72. package/esm2020/src/naming-convention.mjs +88 -0
  73. package/esm2020/src/observable-array.mjs +183 -0
  74. package/esm2020/src/predicate.mjs +1232 -0
  75. package/esm2020/src/primitive-array.mjs +85 -0
  76. package/esm2020/src/query-options.mjs +152 -0
  77. package/esm2020/src/relation-array.mjs +173 -0
  78. package/esm2020/src/save-options.mjs +41 -0
  79. package/esm2020/src/unattached-children-map.mjs +58 -0
  80. package/esm2020/src/validate.mjs +988 -0
  81. package/esm2020/src/validation-options.mjs +64 -0
  82. package/fesm2015/{breeze-client-adapter-ajax-angularjs.js → breeze-client-adapter-ajax-angularjs.mjs} +2 -1
  83. package/fesm2015/breeze-client-adapter-ajax-angularjs.mjs.map +1 -0
  84. package/fesm2015/{breeze-client-adapter-ajax-fetch.js → breeze-client-adapter-ajax-fetch.mjs} +6 -3
  85. package/fesm2015/breeze-client-adapter-ajax-fetch.mjs.map +1 -0
  86. package/fesm2015/{breeze-client-adapter-ajax-httpclient.js → breeze-client-adapter-ajax-httpclient.mjs} +2 -1
  87. package/fesm2015/breeze-client-adapter-ajax-httpclient.mjs.map +1 -0
  88. package/fesm2015/{breeze-client-adapter-ajax-jquery.js → breeze-client-adapter-ajax-jquery.mjs} +3 -2
  89. package/fesm2015/breeze-client-adapter-ajax-jquery.mjs.map +1 -0
  90. package/fesm2015/{breeze-client-adapter-ajax-post.js → breeze-client-adapter-ajax-post.mjs} +2 -1
  91. package/fesm2015/breeze-client-adapter-ajax-post.mjs.map +1 -0
  92. package/fesm2015/{breeze-client-adapter-data-service-odata.js → breeze-client-adapter-data-service-odata.mjs} +21 -22
  93. package/fesm2015/breeze-client-adapter-data-service-odata.mjs.map +1 -0
  94. package/fesm2015/{breeze-client-adapter-data-service-webapi.js → breeze-client-adapter-data-service-webapi.mjs} +14 -13
  95. package/fesm2015/breeze-client-adapter-data-service-webapi.mjs.map +1 -0
  96. package/fesm2015/{breeze-client-adapter-model-library-backing-store.js → breeze-client-adapter-model-library-backing-store.mjs} +14 -13
  97. package/fesm2015/breeze-client-adapter-model-library-backing-store.mjs.map +1 -0
  98. package/fesm2015/{breeze-client-adapter-model-library-ko.js → breeze-client-adapter-model-library-ko.mjs} +14 -13
  99. package/fesm2015/breeze-client-adapter-model-library-ko.mjs.map +1 -0
  100. package/fesm2015/{breeze-client-adapter-uri-builder-json.js → breeze-client-adapter-uri-builder-json.mjs} +9 -8
  101. package/fesm2015/breeze-client-adapter-uri-builder-json.mjs.map +1 -0
  102. package/fesm2015/{breeze-client-adapter-uri-builder-odata.js → breeze-client-adapter-uri-builder-odata.mjs} +86 -86
  103. package/fesm2015/breeze-client-adapter-uri-builder-odata.mjs.map +1 -0
  104. package/fesm2015/{breeze-client-mixin-get-entity-graph.js → breeze-client-mixin-get-entity-graph.mjs} +2 -1
  105. package/fesm2015/breeze-client-mixin-get-entity-graph.mjs.map +1 -0
  106. package/fesm2015/{breeze-client-mixin-save-queuing.js → breeze-client-mixin-save-queuing.mjs} +2 -1
  107. package/fesm2015/breeze-client-mixin-save-queuing.mjs.map +1 -0
  108. package/fesm2015/{breeze-client.js → breeze-client.mjs} +409 -418
  109. package/fesm2015/breeze-client.mjs.map +1 -0
  110. package/{fesm5/breeze-client-adapter-ajax-angularjs.js → fesm2020/breeze-client-adapter-ajax-angularjs.mjs} +42 -42
  111. package/fesm2020/breeze-client-adapter-ajax-angularjs.mjs.map +1 -0
  112. package/{fesm5/breeze-client-adapter-ajax-fetch.js → fesm2020/breeze-client-adapter-ajax-fetch.mjs} +45 -43
  113. package/fesm2020/breeze-client-adapter-ajax-fetch.mjs.map +1 -0
  114. package/{fesm5/breeze-client-adapter-ajax-httpclient.js → fesm2020/breeze-client-adapter-ajax-httpclient.mjs} +44 -44
  115. package/fesm2020/breeze-client-adapter-ajax-httpclient.mjs.map +1 -0
  116. package/{fesm5/breeze-client-adapter-ajax-jquery.js → fesm2020/breeze-client-adapter-ajax-jquery.mjs} +19 -19
  117. package/fesm2020/breeze-client-adapter-ajax-jquery.mjs.map +1 -0
  118. package/{fesm5/breeze-client-adapter-ajax-post.js → fesm2020/breeze-client-adapter-ajax-post.mjs} +9 -11
  119. package/fesm2020/breeze-client-adapter-ajax-post.mjs.map +1 -0
  120. package/{fesm5/breeze-client-adapter-data-service-odata.js → fesm2020/breeze-client-adapter-data-service-odata.mjs} +127 -134
  121. package/fesm2020/breeze-client-adapter-data-service-odata.mjs.map +1 -0
  122. package/{fesm5/breeze-client-adapter-data-service-webapi.js → fesm2020/breeze-client-adapter-data-service-webapi.mjs} +39 -42
  123. package/fesm2020/breeze-client-adapter-data-service-webapi.mjs.map +1 -0
  124. package/{fesm5/breeze-client-adapter-model-library-backing-store.js → fesm2020/breeze-client-adapter-model-library-backing-store.mjs} +64 -64
  125. package/fesm2020/breeze-client-adapter-model-library-backing-store.mjs.map +1 -0
  126. package/{fesm5/breeze-client-adapter-model-library-ko.js → fesm2020/breeze-client-adapter-model-library-ko.mjs} +58 -58
  127. package/fesm2020/breeze-client-adapter-model-library-ko.mjs.map +1 -0
  128. package/fesm2020/breeze-client-adapter-uri-builder-json.mjs +92 -0
  129. package/fesm2020/breeze-client-adapter-uri-builder-json.mjs.map +1 -0
  130. package/fesm2020/breeze-client-adapter-uri-builder-odata.mjs +246 -0
  131. package/fesm2020/breeze-client-adapter-uri-builder-odata.mjs.map +1 -0
  132. package/{fesm5/breeze-client-mixin-get-entity-graph.js → fesm2020/breeze-client-mixin-get-entity-graph.mjs} +46 -45
  133. package/fesm2020/breeze-client-mixin-get-entity-graph.mjs.map +1 -0
  134. package/{fesm5/breeze-client-mixin-save-queuing.js → fesm2020/breeze-client-mixin-save-queuing.mjs} +117 -126
  135. package/fesm2020/breeze-client-mixin-save-queuing.mjs.map +1 -0
  136. package/{fesm5/breeze-client.js → fesm2020/breeze-client.mjs} +3396 -3612
  137. package/fesm2020/breeze-client.mjs.map +1 -0
  138. package/mixin-get-entity-graph/{breeze-client-mixin-get-entity-graph.d.ts → index.d.ts} +1 -0
  139. package/mixin-save-queuing/{breeze-client-mixin-save-queuing.d.ts → index.d.ts} +1 -0
  140. package/mjs/README.md +17 -0
  141. package/package.json +125 -11
  142. package/src/entity-metadata.d.ts +6 -4
  143. package/src/entity-query.d.ts +1 -1
  144. package/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.metadata.json +0 -1
  145. package/adapter-ajax-angularjs/package.json +0 -13
  146. package/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.metadata.json +0 -1
  147. package/adapter-ajax-fetch/package.json +0 -13
  148. package/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.metadata.json +0 -1
  149. package/adapter-ajax-httpclient/package.json +0 -13
  150. package/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.metadata.json +0 -1
  151. package/adapter-ajax-jquery/package.json +0 -13
  152. package/adapter-ajax-post/breeze-client-adapter-ajax-post.metadata.json +0 -1
  153. package/adapter-ajax-post/package.json +0 -13
  154. package/adapter-data-service-odata/breeze-client-adapter-data-service-odata.metadata.json +0 -1
  155. package/adapter-data-service-odata/package.json +0 -13
  156. package/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.metadata.json +0 -1
  157. package/adapter-data-service-webapi/package.json +0 -13
  158. package/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.metadata.json +0 -1
  159. package/adapter-model-library-backing-store/package.json +0 -13
  160. package/adapter-model-library-ko/breeze-client-adapter-model-library-ko.metadata.json +0 -1
  161. package/adapter-model-library-ko/package.json +0 -13
  162. package/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.metadata.json +0 -1
  163. package/adapter-uri-builder-json/package.json +0 -13
  164. package/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.metadata.json +0 -1
  165. package/adapter-uri-builder-odata/package.json +0 -13
  166. package/breeze-client.d.ts +0 -8
  167. package/breeze-client.metadata.json +0 -1
  168. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js +0 -190
  169. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js.map +0 -1
  170. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js +0 -2
  171. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js.map +0 -1
  172. package/bundles/breeze-client-adapter-ajax-fetch.umd.js +0 -190
  173. package/bundles/breeze-client-adapter-ajax-fetch.umd.js.map +0 -1
  174. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js +0 -2
  175. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js.map +0 -1
  176. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js +0 -195
  177. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js.map +0 -1
  178. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js +0 -2
  179. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js.map +0 -1
  180. package/bundles/breeze-client-adapter-ajax-jquery.umd.js +0 -115
  181. package/bundles/breeze-client-adapter-ajax-jquery.umd.js.map +0 -1
  182. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js +0 -2
  183. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js.map +0 -1
  184. package/bundles/breeze-client-adapter-ajax-post.umd.js +0 -92
  185. package/bundles/breeze-client-adapter-ajax-post.umd.js.map +0 -1
  186. package/bundles/breeze-client-adapter-ajax-post.umd.min.js +0 -2
  187. package/bundles/breeze-client-adapter-ajax-post.umd.min.js.map +0 -1
  188. package/bundles/breeze-client-adapter-data-service-odata.umd.js +0 -743
  189. package/bundles/breeze-client-adapter-data-service-odata.umd.js.map +0 -1
  190. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js +0 -16
  191. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js.map +0 -1
  192. package/bundles/breeze-client-adapter-data-service-webapi.umd.js +0 -326
  193. package/bundles/breeze-client-adapter-data-service-webapi.umd.js.map +0 -1
  194. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js +0 -16
  195. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js.map +0 -1
  196. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js +0 -280
  197. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js.map +0 -1
  198. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js +0 -2
  199. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js.map +0 -1
  200. package/bundles/breeze-client-adapter-model-library-ko.umd.js +0 -252
  201. package/bundles/breeze-client-adapter-model-library-ko.umd.js.map +0 -1
  202. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js +0 -2
  203. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js.map +0 -1
  204. package/bundles/breeze-client-adapter-uri-builder-json.umd.js +0 -96
  205. package/bundles/breeze-client-adapter-uri-builder-json.umd.js.map +0 -1
  206. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js +0 -2
  207. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js.map +0 -1
  208. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js +0 -262
  209. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js.map +0 -1
  210. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js +0 -2
  211. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js.map +0 -1
  212. package/bundles/breeze-client-mixin-get-entity-graph.umd.js +0 -258
  213. package/bundles/breeze-client-mixin-get-entity-graph.umd.js.map +0 -1
  214. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js +0 -2
  215. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js.map +0 -1
  216. package/bundles/breeze-client-mixin-save-queuing.umd.js +0 -579
  217. package/bundles/breeze-client-mixin-save-queuing.umd.js.map +0 -1
  218. package/bundles/breeze-client-mixin-save-queuing.umd.min.js +0 -16
  219. package/bundles/breeze-client-mixin-save-queuing.umd.min.js.map +0 -1
  220. package/bundles/breeze-client.umd.js +0 -14098
  221. package/bundles/breeze-client.umd.js.map +0 -1
  222. package/bundles/breeze-client.umd.min.js +0 -16
  223. package/bundles/breeze-client.umd.min.js.map +0 -1
  224. package/esm2015/adapter-ajax-angularjs/adapter-ajax-angularjs.js +0 -130
  225. package/esm2015/adapter-ajax-angularjs/adapter-core.js +0 -49
  226. package/esm2015/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +0 -5
  227. package/esm2015/adapter-ajax-fetch/adapter-ajax-fetch.js +0 -130
  228. package/esm2015/adapter-ajax-fetch/adapter-core.js +0 -49
  229. package/esm2015/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +0 -5
  230. package/esm2015/adapter-ajax-httpclient/adapter-ajax-httpclient.js +0 -137
  231. package/esm2015/adapter-ajax-httpclient/adapter-core.js +0 -49
  232. package/esm2015/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +0 -5
  233. package/esm2015/adapter-ajax-jquery/adapter-ajax-jquery.js +0 -103
  234. package/esm2015/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +0 -5
  235. package/esm2015/adapter-ajax-post/adapter-ajax-post.js +0 -77
  236. package/esm2015/adapter-ajax-post/breeze-client-adapter-ajax-post.js +0 -5
  237. package/esm2015/adapter-data-service-odata/adapter-core.js +0 -49
  238. package/esm2015/adapter-data-service-odata/adapter-data-service-odata.js +0 -459
  239. package/esm2015/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +0 -5
  240. package/esm2015/adapter-data-service-webapi/adapter-data-service-webapi.js +0 -93
  241. package/esm2015/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +0 -5
  242. package/esm2015/adapter-model-library-backing-store/adapter-model-library-backing-store.js +0 -268
  243. package/esm2015/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +0 -5
  244. package/esm2015/adapter-model-library-ko/adapter-model-library-ko.js +0 -240
  245. package/esm2015/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +0 -5
  246. package/esm2015/adapter-uri-builder-json/adapter-core.js +0 -49
  247. package/esm2015/adapter-uri-builder-json/adapter-uri-builder-json.js +0 -36
  248. package/esm2015/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +0 -5
  249. package/esm2015/adapter-uri-builder-odata/adapter-core.js +0 -49
  250. package/esm2015/adapter-uri-builder-odata/adapter-uri-builder-odata.js +0 -192
  251. package/esm2015/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +0 -5
  252. package/esm2015/breeze-client.js +0 -9
  253. package/esm2015/index.js +0 -2
  254. package/esm2015/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +0 -5
  255. package/esm2015/mixin-get-entity-graph/mixin-get-entity-graph.js +0 -269
  256. package/esm2015/mixin-save-queuing/breeze-client-mixin-save-queuing.js +0 -5
  257. package/esm2015/mixin-save-queuing/mixin-save-queuing.js +0 -400
  258. package/esm2015/src/abstract-data-service-adapter.js +0 -296
  259. package/esm2015/src/array.js +0 -4
  260. package/esm2015/src/assert-param.js +0 -312
  261. package/esm2015/src/breeze.js +0 -85
  262. package/esm2015/src/complex-array.js +0 -119
  263. package/esm2015/src/config.js +0 -223
  264. package/esm2015/src/core.js +0 -709
  265. package/esm2015/src/csdl-metadata-parser.js +0 -385
  266. package/esm2015/src/data-service.js +0 -203
  267. package/esm2015/src/data-type.js +0 -444
  268. package/esm2015/src/default-property-interceptor.js +0 -460
  269. package/esm2015/src/entity-action.js +0 -45
  270. package/esm2015/src/entity-aspect.js +0 -806
  271. package/esm2015/src/entity-group.js +0 -187
  272. package/esm2015/src/entity-key.js +0 -116
  273. package/esm2015/src/entity-manager.js +0 -2094
  274. package/esm2015/src/entity-metadata.js +0 -2109
  275. package/esm2015/src/entity-query.js +0 -996
  276. package/esm2015/src/entity-state.js +0 -99
  277. package/esm2015/src/enum.js +0 -141
  278. package/esm2015/src/event.js +0 -256
  279. package/esm2015/src/interface-registry.js +0 -41
  280. package/esm2015/src/key-generator.js +0 -108
  281. package/esm2015/src/local-query-comparison-options.js +0 -65
  282. package/esm2015/src/mapping-context.js +0 -405
  283. package/esm2015/src/naming-convention.js +0 -88
  284. package/esm2015/src/observable-array.js +0 -185
  285. package/esm2015/src/predicate.js +0 -1235
  286. package/esm2015/src/primitive-array.js +0 -87
  287. package/esm2015/src/query-options.js +0 -152
  288. package/esm2015/src/relation-array.js +0 -175
  289. package/esm2015/src/save-options.js +0 -41
  290. package/esm2015/src/unattached-children-map.js +0 -58
  291. package/esm2015/src/validate.js +0 -991
  292. package/esm2015/src/validation-options.js +0 -64
  293. package/esm5/adapter-ajax-angularjs/adapter-ajax-angularjs.js +0 -132
  294. package/esm5/adapter-ajax-angularjs/adapter-core.js +0 -49
  295. package/esm5/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +0 -5
  296. package/esm5/adapter-ajax-fetch/adapter-ajax-fetch.js +0 -132
  297. package/esm5/adapter-ajax-fetch/adapter-core.js +0 -49
  298. package/esm5/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +0 -5
  299. package/esm5/adapter-ajax-httpclient/adapter-ajax-httpclient.js +0 -139
  300. package/esm5/adapter-ajax-httpclient/adapter-core.js +0 -49
  301. package/esm5/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +0 -5
  302. package/esm5/adapter-ajax-jquery/adapter-ajax-jquery.js +0 -105
  303. package/esm5/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +0 -5
  304. package/esm5/adapter-ajax-post/adapter-ajax-post.js +0 -81
  305. package/esm5/adapter-ajax-post/breeze-client-adapter-ajax-post.js +0 -5
  306. package/esm5/adapter-data-service-odata/adapter-core.js +0 -49
  307. package/esm5/adapter-data-service-odata/adapter-data-service-odata.js +0 -466
  308. package/esm5/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +0 -5
  309. package/esm5/adapter-data-service-webapi/adapter-data-service-webapi.js +0 -98
  310. package/esm5/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +0 -5
  311. package/esm5/adapter-model-library-backing-store/adapter-model-library-backing-store.js +0 -270
  312. package/esm5/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +0 -5
  313. package/esm5/adapter-model-library-ko/adapter-model-library-ko.js +0 -242
  314. package/esm5/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +0 -5
  315. package/esm5/adapter-uri-builder-json/adapter-core.js +0 -49
  316. package/esm5/adapter-uri-builder-json/adapter-uri-builder-json.js +0 -38
  317. package/esm5/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +0 -5
  318. package/esm5/adapter-uri-builder-odata/adapter-core.js +0 -49
  319. package/esm5/adapter-uri-builder-odata/adapter-uri-builder-odata.js +0 -197
  320. package/esm5/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +0 -5
  321. package/esm5/breeze-client.js +0 -9
  322. package/esm5/index.js +0 -2
  323. package/esm5/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +0 -5
  324. package/esm5/mixin-get-entity-graph/mixin-get-entity-graph.js +0 -269
  325. package/esm5/mixin-save-queuing/breeze-client-mixin-save-queuing.js +0 -5
  326. package/esm5/mixin-save-queuing/mixin-save-queuing.js +0 -412
  327. package/esm5/src/abstract-data-service-adapter.js +0 -302
  328. package/esm5/src/array.js +0 -4
  329. package/esm5/src/assert-param.js +0 -317
  330. package/esm5/src/breeze.js +0 -85
  331. package/esm5/src/complex-array.js +0 -119
  332. package/esm5/src/config.js +0 -228
  333. package/esm5/src/core.js +0 -717
  334. package/esm5/src/csdl-metadata-parser.js +0 -385
  335. package/esm5/src/data-service.js +0 -207
  336. package/esm5/src/data-type.js +0 -451
  337. package/esm5/src/default-property-interceptor.js +0 -460
  338. package/esm5/src/entity-action.js +0 -52
  339. package/esm5/src/entity-aspect.js +0 -812
  340. package/esm5/src/entity-group.js +0 -189
  341. package/esm5/src/entity-key.js +0 -118
  342. package/esm5/src/entity-manager.js +0 -2112
  343. package/esm5/src/entity-metadata.js +0 -2144
  344. package/esm5/src/entity-query.js +0 -1023
  345. package/esm5/src/entity-state.js +0 -106
  346. package/esm5/src/enum.js +0 -144
  347. package/esm5/src/event.js +0 -259
  348. package/esm5/src/interface-registry.js +0 -43
  349. package/esm5/src/key-generator.js +0 -111
  350. package/esm5/src/local-query-comparison-options.js +0 -67
  351. package/esm5/src/mapping-context.js +0 -407
  352. package/esm5/src/naming-convention.js +0 -90
  353. package/esm5/src/observable-array.js +0 -201
  354. package/esm5/src/predicate.js +0 -1300
  355. package/esm5/src/primitive-array.js +0 -87
  356. package/esm5/src/query-options.js +0 -167
  357. package/esm5/src/relation-array.js +0 -175
  358. package/esm5/src/save-options.js +0 -43
  359. package/esm5/src/unattached-children-map.js +0 -60
  360. package/esm5/src/validate.js +0 -996
  361. package/esm5/src/validation-options.js +0 -66
  362. package/fesm2015/breeze-client-adapter-ajax-angularjs.js.map +0 -1
  363. package/fesm2015/breeze-client-adapter-ajax-fetch.js.map +0 -1
  364. package/fesm2015/breeze-client-adapter-ajax-httpclient.js.map +0 -1
  365. package/fesm2015/breeze-client-adapter-ajax-jquery.js.map +0 -1
  366. package/fesm2015/breeze-client-adapter-ajax-post.js.map +0 -1
  367. package/fesm2015/breeze-client-adapter-data-service-odata.js.map +0 -1
  368. package/fesm2015/breeze-client-adapter-data-service-webapi.js.map +0 -1
  369. package/fesm2015/breeze-client-adapter-model-library-backing-store.js.map +0 -1
  370. package/fesm2015/breeze-client-adapter-model-library-ko.js.map +0 -1
  371. package/fesm2015/breeze-client-adapter-uri-builder-json.js.map +0 -1
  372. package/fesm2015/breeze-client-adapter-uri-builder-odata.js.map +0 -1
  373. package/fesm2015/breeze-client-mixin-get-entity-graph.js.map +0 -1
  374. package/fesm2015/breeze-client-mixin-save-queuing.js.map +0 -1
  375. package/fesm2015/breeze-client.js.map +0 -1
  376. package/fesm5/breeze-client-adapter-ajax-angularjs.js.map +0 -1
  377. package/fesm5/breeze-client-adapter-ajax-fetch.js.map +0 -1
  378. package/fesm5/breeze-client-adapter-ajax-httpclient.js.map +0 -1
  379. package/fesm5/breeze-client-adapter-ajax-jquery.js.map +0 -1
  380. package/fesm5/breeze-client-adapter-ajax-post.js.map +0 -1
  381. package/fesm5/breeze-client-adapter-data-service-odata.js.map +0 -1
  382. package/fesm5/breeze-client-adapter-data-service-webapi.js.map +0 -1
  383. package/fesm5/breeze-client-adapter-model-library-backing-store.js.map +0 -1
  384. package/fesm5/breeze-client-adapter-model-library-ko.js.map +0 -1
  385. package/fesm5/breeze-client-adapter-uri-builder-json.js +0 -92
  386. package/fesm5/breeze-client-adapter-uri-builder-json.js.map +0 -1
  387. package/fesm5/breeze-client-adapter-uri-builder-odata.js +0 -250
  388. package/fesm5/breeze-client-adapter-uri-builder-odata.js.map +0 -1
  389. package/fesm5/breeze-client-mixin-get-entity-graph.js.map +0 -1
  390. package/fesm5/breeze-client-mixin-save-queuing.js.map +0 -1
  391. package/fesm5/breeze-client.js.map +0 -1
  392. package/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.metadata.json +0 -1
  393. package/mixin-get-entity-graph/package.json +0 -13
  394. package/mixin-save-queuing/breeze-client-mixin-save-queuing.metadata.json +0 -1
  395. package/mixin-save-queuing/package.json +0 -13
@@ -0,0 +1,2094 @@
1
+ import { core } from './core';
2
+ import { assertParam, assertConfig } from './assert-param';
3
+ import { config } from './config';
4
+ import { BreezeEvent } from './event';
5
+ import { EntityAspect } from './entity-aspect';
6
+ import { MetadataStore, EntityType, DataProperty, AutoGeneratedKeyType } from './entity-metadata';
7
+ import { EntityKey } from './entity-key';
8
+ import { EntityAction } from './entity-action';
9
+ import { EntityState } from './entity-state';
10
+ import { DataService } from './data-service';
11
+ import { DataType } from './data-type';
12
+ import { ValidationError } from './validate';
13
+ import { ValidationOptions } from './validation-options';
14
+ import { QueryOptions, MergeStrategy, FetchStrategy } from './query-options';
15
+ import { SaveOptions } from './save-options';
16
+ import { KeyGenerator } from './key-generator';
17
+ import { EntityGroup } from './entity-group';
18
+ import { MappingContext } from './mapping-context';
19
+ import { EntityQuery } from './entity-query';
20
+ import { UnattachedChildrenMap } from './unattached-children-map';
21
+ /**
22
+ Instances of the EntityManager contain and manage collections of entities, either retrieved from a backend datastore or created on the client.
23
+ **/
24
+ export class EntityManager {
25
+ /**
26
+ EntityManager constructor.
27
+
28
+ At its most basic an EntityManager can be constructed with just a service name
29
+ > let entityManager = new EntityManager( "breeze/NorthwindIBModel");
30
+
31
+ This is the same as calling it with the following configuration object
32
+ > let entityManager = new EntityManager( {serviceName: "breeze/NorthwindIBModel" });
33
+
34
+ Usually however, configuration objects will contain more than just the 'serviceName';
35
+ > let metadataStore = new MetadataStore();
36
+ > let entityManager = new EntityManager( {
37
+ > serviceName: "breeze/NorthwindIBModel",
38
+ > metadataStore: metadataStore
39
+ > });
40
+
41
+ or
42
+ > return new QueryOptions({
43
+ > mergeStrategy: obj,
44
+ > fetchStrategy: this.fetchStrategy
45
+ > });
46
+ > let queryOptions = new QueryOptions({
47
+ > mergeStrategy: MergeStrategy.OverwriteChanges,
48
+ > fetchStrategy: FetchStrategy.FromServer
49
+ > });
50
+ > let validationOptions = new ValidationOptions({
51
+ > validateOnAttach: true,
52
+ > validateOnSave: true,
53
+ > validateOnQuery: false
54
+ > });
55
+ > let entityManager = new EntityManager({
56
+ > serviceName: "breeze/NorthwindIBModel",
57
+ > queryOptions: queryOptions,
58
+ > validationOptions: validationOptions
59
+ > });
60
+ @param emConfig - Configuration settings or a service name.
61
+ **/
62
+ constructor(emConfig) {
63
+ this.helper = {
64
+ unwrapInstance: unwrapInstance,
65
+ unwrapOriginalValues: unwrapOriginalValues,
66
+ unwrapChangedValues: unwrapChangedValues
67
+ };
68
+ if (arguments.length > 1) {
69
+ throw new Error("The EntityManager ctor has a single optional argument that is either a 'serviceName' or a configuration object.");
70
+ }
71
+ let config;
72
+ if (arguments.length === 0) {
73
+ config = { serviceName: "" };
74
+ }
75
+ else if (typeof emConfig === 'string') {
76
+ config = { serviceName: emConfig };
77
+ }
78
+ else {
79
+ config = emConfig || {};
80
+ }
81
+ EntityManager._updateWithConfig(this, config, true);
82
+ this.entityChanged = new BreezeEvent("entityChanged", this);
83
+ this.validationErrorsChanged = new BreezeEvent("validationErrorsChanged", this);
84
+ this.hasChangesChanged = new BreezeEvent("hasChangesChanged", this);
85
+ this.clear();
86
+ }
87
+ /**
88
+ General purpose property set method. Any of the properties in the [[EntityManagerConfig]]
89
+ may be set.
90
+ > // assume em1 is a previously created EntityManager
91
+ > // where we want to change some of its settings.
92
+ > em1.setProperties( {
93
+ > serviceName: "breeze/foo"
94
+ > });
95
+ @param config - An object containing the selected properties and values to set.
96
+ **/
97
+ setProperties(config) {
98
+ EntityManager._updateWithConfig(this, config, false);
99
+ }
100
+ /** @hidden @internal */
101
+ static _updateWithConfig(em, config, isCtor) {
102
+ let defaultQueryOptions = isCtor ? QueryOptions.defaultInstance : em.queryOptions;
103
+ let defaultSaveOptions = isCtor ? SaveOptions.defaultInstance : em.saveOptions;
104
+ let defaultValidationOptions = isCtor ? ValidationOptions.defaultInstance : em.validationOptions;
105
+ let configParam = assertConfig(config)
106
+ .whereParam("serviceName").isOptional().isString()
107
+ .whereParam("dataService").isOptional().isInstanceOf(DataService)
108
+ .whereParam("queryOptions").isInstanceOf(QueryOptions).isOptional().withDefault(defaultQueryOptions)
109
+ .whereParam("saveOptions").isInstanceOf(SaveOptions).isOptional().withDefault(defaultSaveOptions)
110
+ .whereParam("validationOptions").isInstanceOf(ValidationOptions).isOptional().withDefault(defaultValidationOptions)
111
+ .whereParam("keyGeneratorCtor").isFunction().isOptional();
112
+ if (isCtor) {
113
+ configParam = configParam
114
+ .whereParam("metadataStore").isInstanceOf(MetadataStore).isOptional().withDefault(new MetadataStore());
115
+ }
116
+ configParam.applyAll(em);
117
+ // insure that entityManager's options versions are completely populated
118
+ core.updateWithDefaults(em.queryOptions, defaultQueryOptions);
119
+ core.updateWithDefaults(em.saveOptions, defaultSaveOptions);
120
+ core.updateWithDefaults(em.validationOptions, defaultValidationOptions);
121
+ if (config.serviceName) {
122
+ em.dataService = new DataService({
123
+ serviceName: em.serviceName
124
+ });
125
+ }
126
+ em.serviceName = em.dataService && em.dataService.serviceName;
127
+ em.keyGeneratorCtor = em.keyGeneratorCtor || KeyGenerator;
128
+ if (isCtor || config.keyGeneratorCtor) {
129
+ em.keyGenerator = new em.keyGeneratorCtor();
130
+ }
131
+ }
132
+ /**
133
+ Creates a new entity of a specified type and optionally initializes it. By default the new entity is created with an EntityState of Added
134
+ but you can also optionally specify an EntityState. An EntityState of 'Detached' will insure that the entity is created but not yet added
135
+ to the EntityManager.
136
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
137
+ > // create and add an entity;
138
+ > let emp1 = em1.createEntity("Employee");
139
+ > // create and add an initialized entity;
140
+ > let emp2 = em1.createEntity("Employee", { lastName: "Smith", firstName: "John" });
141
+ > // create and attach (not add) an initialized entity
142
+ > let emp3 = em1.createEntity("Employee", { id: 435, lastName: "Smith", firstName: "John" }, EntityState.Unchanged);
143
+ > // create but don't attach an entity;
144
+ > let emp4 = em1.createEntity("Employee", { id: 435, lastName: "Smith", firstName: "John" }, EntityState.Detached);
145
+ @param typeName - The name of the EntityType for which an instance should be created.
146
+ @param entityType - The EntityType of the type for which an instance should be created.
147
+ @param initialValues - (default=null) Configuration object of the properties to set immediately after creation.
148
+ @param entityState - (default = [[EntityState.Added]]) The EntityState of the entity after being created and added to this EntityManager.
149
+ @param mergeStrategy - (default = [[MergeStrategy.Disallowed]]) - How to handle conflicts if an entity with the same key already exists within this EntityManager.
150
+ @return {Entity} A new Entity of the specified type.
151
+ */
152
+ createEntity(entityType, initialValues, entityState, mergeStrategy) {
153
+ assertParam(entityType, "entityType").isString().or().isInstanceOf(EntityType).check();
154
+ assertParam(entityState, "entityState").isEnumOf(EntityState).isOptional().check();
155
+ assertParam(mergeStrategy, "mergeStrategy").isEnumOf(MergeStrategy).isOptional().check();
156
+ let et = (typeof entityType === "string") ? this.metadataStore._getStructuralType(entityType) : entityType;
157
+ entityState = entityState || EntityState.Added;
158
+ let entity = {};
159
+ core.using(this, "isLoading", true, function () {
160
+ entity = et.createEntity(initialValues);
161
+ });
162
+ if (entityState !== EntityState.Detached) {
163
+ entity = this.attachEntity(entity, entityState, mergeStrategy);
164
+ }
165
+ return entity;
166
+ }
167
+ /**
168
+ Creates a new EntityManager and imports a previously exported result into it.
169
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
170
+ > let bundle = em1.exportEntities();
171
+ > // can be stored via the web storage api
172
+ > window.localStorage.setItem("myEntityManager", bundle);
173
+ > // assume the code below occurs in a different session.
174
+ > let bundleFromStorage = window.localStorage.getItem("myEntityManager");
175
+ > // and imported
176
+ > let em2 = EntityManager.importEntities(bundleFromStorage);
177
+ > // em2 will now have a complete copy of what was in em1
178
+ @param exportedString - The result of a previous 'exportEntities' call as a string
179
+ @param exportedData - The result of a previous 'exportEntities' call as an Object.
180
+ @param config - A configuration object.
181
+ @param config.mergeStrategy - A [[MergeStrategy]] to use when
182
+ merging into an existing EntityManager.
183
+ @param config.metadataVersionFn - A function that takes two arguments (the current metadataVersion and the imported store's 'name')
184
+ and may be used to perform version checking.
185
+ @return A new EntityManager. Note that the return value of this method call is different from that
186
+ provided by the same named method on an EntityManager instance. Use that method if you need additional information
187
+ regarding the imported entities.
188
+ **/
189
+ static importEntities(exported, config) {
190
+ let em = new EntityManager();
191
+ em.importEntities(exported, config);
192
+ return em;
193
+ }
194
+ // instance methods
195
+ /**
196
+ Calls [[EntityAspect.acceptChanges]] on every changed entity in this EntityManager.
197
+ **/
198
+ acceptChanges() {
199
+ this.getChanges().map(function (entity) {
200
+ return entity.entityAspect._checkOperation("acceptChanges");
201
+ }).forEach(function (aspect) {
202
+ aspect.acceptChanges();
203
+ });
204
+ }
205
+ /**
206
+ Exports selected entities, all entities of selected types, or an entire EntityManager cache.
207
+
208
+ This method takes a snapshot of an EntityManager that can be stored offline or held in memory.
209
+ Use the [[EntityManager.importEntities]] method to restore or merge the snapshot
210
+ into another EntityManager at some later time.
211
+ > // let em1 be an EntityManager containing a number of existing entities.
212
+ > // export every entity in em1.
213
+ > let bundle = em1.exportEntities();
214
+ > // save to the browser's local storage
215
+ > window.localStorage.setItem("myEntityManager", bundle);
216
+ > // later retrieve the export
217
+ > let bundleFromStorage = window.localStorage.getItem("myEntityManager");
218
+ > // import the retrieved export bundle into another manager
219
+ > let em2 = em1.createEmptyCopy();
220
+ > em2.importEntities(bundleFromStorage);
221
+ > // em2 now has a complete, faithful copy of the entities that were in em1
222
+
223
+ You can also control exactly which entities are exported.
224
+ > // get em1's unsaved changes (an array) and export them.
225
+ > let changes = em1.getChanges();
226
+ > let bundle = em1.exportEntities(changes);
227
+ > // merge these entities into em2 which may contains some of the same entities.
228
+ > // do NOT overwrite the entities in em2 if they themselves have unsaved changes.
229
+ > em2.importEntities(bundle, { mergeStrategy: MergeStrategy.PreserveChanges} );
230
+
231
+ Metadata are included in an export by default. You may want to exclude the metadata
232
+ especially if you're exporting just a few entities for local storage.
233
+ > let bundle = em1.exportEntities(arrayOfSelectedEntities, {includeMetadata: false});
234
+ > window.localStorage.setItem("goodStuff", bundle);
235
+
236
+ You may still express this option as a boolean value although this older syntax is deprecated.
237
+ > // Exclude the metadata (deprecated syntax)
238
+ > let bundle = em1.exportEntities(arrayOfSelectedEntities, false);
239
+
240
+ You can export all entities of one or more specified EntityTypes.
241
+ > // Export all Customer and Employee entities (and also exclude metadata)
242
+ > let bundle = em1.exportEntities(['Customer', 'Employee'], {includeMetadata: false});
243
+
244
+ All of the above examples return an export bundle as a string which is the default format.
245
+ You can export the bundle as JSON if you prefer by setting the `asString` option to false.
246
+ > // Export all Customer and Employee entities as JSON and exclude the metadata
247
+ > let bundle = em1.exportEntities(['Customer', 'Employee'],
248
+ > {asString: false, includeMetadata: false});
249
+ > // store JSON bundle somewhere ... perhaps indexDb ... and later import as we do here.
250
+ > em2.importEntities(bundle);
251
+ @param entities - The entities to export or the EntityType(s) of the entities to export;
252
+ all entities are exported if this parameter is omitted or null.
253
+ @param exportConfig - Export configuration options or a boolean
254
+ - asString - (boolean) - If true (default), return export bundle as a string.
255
+ - includeMetadata - (boolean) - If true (default), include metadata in the export bundle.
256
+ @return The export bundle either serialized as a string (default) or as a JSON object.
257
+ The bundle contains the metadata (unless excluded) and the entity data grouped by type.
258
+ The entity data include property values, change-state, and temporary key mappings (if any).
259
+
260
+ The export bundle internals are deliberately undocumented. This Breeze-internal representation of entity data is
261
+ suitable for export, storage, and import. The schema and contents of the bundle may change in future versions of Breeze.
262
+ Manipulate it at your own risk with appropriate caution.
263
+ **/
264
+ exportEntities(entities, exportConfig) {
265
+ assertParam(entities, "entities").isArray().isEntity()
266
+ .or().isNonEmptyArray().isInstanceOf(EntityType)
267
+ .or().isNonEmptyArray().isString()
268
+ .or().isOptional().check();
269
+ // assertParam(exportConfig, "exportConfig").isObject()
270
+ // .or().isBoolean()
271
+ // .or().isOptional().check();
272
+ if (exportConfig == null) {
273
+ exportConfig = { includeMetadata: true, asString: true };
274
+ }
275
+ else if (typeof exportConfig === 'boolean') { // deprecated
276
+ exportConfig = { includeMetadata: exportConfig, asString: true };
277
+ }
278
+ assertConfig(exportConfig)
279
+ .whereParam("asString").isBoolean().isOptional().withDefault(true)
280
+ .whereParam("includeMetadata").isBoolean().isOptional().withDefault(true)
281
+ .applyAll(exportConfig);
282
+ let exportBundle = exportEntityGroups(this, entities);
283
+ let json = core.extend({}, exportBundle, ["tempKeys", "entityGroupMap"]);
284
+ if (exportConfig.includeMetadata) {
285
+ json = core.extend(json, this, ["dataService", "saveOptions", "queryOptions", "validationOptions"]);
286
+ json.metadataStore = this.metadataStore.exportMetadata();
287
+ }
288
+ else {
289
+ json.metadataVersion = MetadataStore.metadataVersion;
290
+ json.metadataStoreName = this.metadataStore.name;
291
+ }
292
+ let result = exportConfig.asString ? JSON.stringify(json, null, config.stringifyPad) : json;
293
+ return result;
294
+ }
295
+ /**
296
+ Imports a previously exported result into this EntityManager.
297
+
298
+ This method can be used to make a complete copy of any previously created entityManager, even if created
299
+ in a previous session and stored in localStorage. The static version of this method performs a
300
+ very similar process.
301
+ > // assume em1 is an EntityManager containing a number of existing entities.
302
+ > let bundle = em1.exportEntities();
303
+ > // bundle can be stored in window.localStorage or just held in memory.
304
+ > let em2 = new EntityManager({
305
+ > serviceName: em1.serviceName,
306
+ > metadataStore: em1.metadataStore
307
+ > });
308
+ > em2.importEntities(bundle);
309
+ > // em2 will now have a complete copy of what was in em1
310
+
311
+ It can also be used to merge the contents of a previously created EntityManager with an
312
+ existing EntityManager with control over how the two are merged.
313
+ > let bundle = em1.exportEntities();
314
+ > // assume em2 is another entityManager containing some of the same entities possibly with modifications.
315
+ > em2.importEntities(bundle, { mergeStrategy: MergeStrategy.PreserveChanges} );
316
+ > // em2 will now contain all of the entities from both em1 and em2. Any em2 entities with previously
317
+ > // made modifications will not have been touched, but all other entities from em1 will have been imported.
318
+ @param exportedString - The result of a previous 'export' call.
319
+ @param importConfig - A configuration object.
320
+ @param importConfig.mergeStrategy - A [[MergeStrategy]] to use when
321
+ merging into an existing EntityManager.
322
+ @param importConfig.metadataVersionFn - A function that takes two arguments (the current metadataVersion and the imported store's 'name')
323
+ and may be used to perform version checking.
324
+ @return result
325
+ - result.entities {Array of Entities} The entities that were imported.
326
+ - result.tempKeyMap {Object} Mapping from original EntityKey in the import bundle to its corresponding EntityKey in this EntityManager.
327
+ **/
328
+ importEntities(exported, importConfig) {
329
+ importConfig = importConfig || {};
330
+ assertConfig(importConfig)
331
+ .whereParam("mergeStrategy").isEnumOf(MergeStrategy).isOptional().withDefault(this.queryOptions.mergeStrategy)
332
+ .whereParam("metadataVersionFn").isFunction().isOptional()
333
+ .whereParam("mergeAdds").isBoolean().isOptional()
334
+ .applyAll(importConfig);
335
+ let json = (typeof exported === "string") ? JSON.parse(exported) : exported;
336
+ if (json.metadataStore) {
337
+ this.metadataStore.importMetadata(json.metadataStore);
338
+ // the || clause is for backwards compat with an earlier serialization format.
339
+ this.dataService = (json.dataService && DataService.fromJSON(json.dataService)) || new DataService({ serviceName: json.serviceName });
340
+ this.saveOptions = new SaveOptions(json.saveOptions);
341
+ this.queryOptions = QueryOptions.fromJSON(json.queryOptions);
342
+ this.validationOptions = new ValidationOptions(json.validationOptions);
343
+ }
344
+ else {
345
+ importConfig.metadataVersionFn && importConfig.metadataVersionFn({
346
+ metadataVersion: json.metadataVersion,
347
+ metadataStoreName: json.metadataStoreName
348
+ });
349
+ }
350
+ let tempKeyMap = {};
351
+ json.tempKeys.forEach((k) => {
352
+ let oldKey = EntityKey.fromJSON(k, this.metadataStore);
353
+ // try to use oldKey if not already used in this keyGenerator.
354
+ tempKeyMap[oldKey.toString()] = new EntityKey(oldKey.entityType, this.keyGenerator.generateTempKeyValue(oldKey.entityType, oldKey.values[0]));
355
+ });
356
+ let entitiesToLink = [];
357
+ let impConfig = importConfig;
358
+ impConfig.tempKeyMap = tempKeyMap;
359
+ core.wrapExecution(() => {
360
+ this._pendingPubs = [];
361
+ }, (state) => {
362
+ this._pendingPubs.forEach((fn) => fn());
363
+ this._pendingPubs = undefined;
364
+ this._hasChangesAction && this._hasChangesAction();
365
+ }, () => {
366
+ core.objectForEach(json.entityGroupMap, (entityTypeName, jsonGroup) => {
367
+ let entityType = this.metadataStore._getStructuralType(entityTypeName, false);
368
+ let targetEntityGroup = findOrCreateEntityGroup(this, entityType);
369
+ let entities = importEntityGroup(targetEntityGroup, jsonGroup, impConfig);
370
+ if (entities && entities.length) {
371
+ entitiesToLink = entitiesToLink.concat(entities);
372
+ }
373
+ });
374
+ entitiesToLink.forEach((entity) => {
375
+ if (!entity.entityAspect.entityState.isDeleted()) {
376
+ this._linkRelatedEntities(entity);
377
+ }
378
+ });
379
+ });
380
+ return {
381
+ entities: entitiesToLink,
382
+ tempKeyMapping: tempKeyMap
383
+ };
384
+ }
385
+ /**
386
+ Clears this EntityManager's cache but keeps all other settings. Note that this
387
+ method is not as fast as creating a new EntityManager via 'new EntityManager'.
388
+ This is because clear actually detaches all of the entities from the EntityManager.
389
+ > // assume em1 is an EntityManager containing a number of existing entities.
390
+ > em1.clear();
391
+ > // em1 is will now contain no entities, but all other setting will be maintained.
392
+ **/
393
+ clear() {
394
+ core.objectMap(this._entityGroupMap, function (key, entityGroup) {
395
+ return entityGroup._checkOperation('clear');
396
+ }).forEach((entityGroup) => {
397
+ entityGroup._clear();
398
+ });
399
+ this._entityGroupMap = {};
400
+ this._unattachedChildrenMap = new UnattachedChildrenMap();
401
+ this.keyGenerator = new this.keyGeneratorCtor();
402
+ this.entityChanged.publish({ entityAction: EntityAction.Clear });
403
+ this._setHasChanges(false);
404
+ }
405
+ /**
406
+ Creates an empty copy of this EntityManager but with the same DataService, MetadataStore, QueryOptions, SaveOptions, ValidationOptions, etc.
407
+ > // assume em1 is an EntityManager containing a number of existing entities.
408
+ > let em2 = em1.createEmptyCopy();
409
+ > // em2 is a new EntityManager with all of em1's settings
410
+ > // but no entities.
411
+ @return A new EntityManager.
412
+ **/
413
+ createEmptyCopy() {
414
+ let copy = new EntityManager(core.extend({}, this, ["dataService", "metadataStore", "queryOptions", "saveOptions", "validationOptions", "keyGeneratorCtor"]));
415
+ return copy;
416
+ }
417
+ /**
418
+ Attaches an entity to this EntityManager with an [[EntityState]] of 'Added'.
419
+ > // assume em1 is an EntityManager containing a number of existing entities.
420
+ > let custType = em1.metadataStore.getEntityType("Customer");
421
+ > let cust1 = custType.createEntity();
422
+ > em1.addEntity(cust1);
423
+
424
+ Note that this is the same as using 'attachEntity' with an [[EntityState]] of 'Added'.
425
+
426
+ > // assume em1 is an EntityManager containing a number of existing entities.
427
+ > let custType = em1.metadataStore.getEntityType("Customer");
428
+ > let cust1 = custType.createEntity();
429
+ > em1.attachEntity(cust1, EntityState.Added);
430
+ @param entity - The entity to add.
431
+ @return The added entity.
432
+ **/
433
+ addEntity(entity) {
434
+ return this.attachEntity(entity, EntityState.Added);
435
+ }
436
+ /**
437
+ Attaches an entity to this EntityManager with a specified [[EntityState]].
438
+ > // assume em1 is an EntityManager containing a number of existing entities.
439
+ > let custType = em1.metadataStore.getEntityType("Customer");
440
+ > let cust1 = custType.createEntity();
441
+ > em1.attachEntity(cust1, EntityState.Added);
442
+ @param entity - The entity to add.
443
+ @param entityState - (default=EntityState.Unchanged) The EntityState of the newly attached entity. If omitted this defaults to EntityState.Unchanged.
444
+ @param mergeStrategy - (default = MergeStrategy.Disallowed) How the specified entity should be merged into the EntityManager if this EntityManager already contains an entity with the same key.
445
+ @return The attached entity.
446
+ **/
447
+ attachEntity(entity, entityState, mergeStrategy) {
448
+ assertParam(entity, "entity").isRequired().check();
449
+ this.metadataStore._checkEntityType(entity);
450
+ let esSymbol = assertParam(entityState, "entityState").isEnumOf(EntityState).isOptional().check(EntityState.Unchanged);
451
+ let msSymbol = assertParam(mergeStrategy, "mergeStrategy").isEnumOf(MergeStrategy).isOptional().check(MergeStrategy.Disallowed);
452
+ if (entity.entityType.metadataStore !== this.metadataStore) {
453
+ throw new Error("Cannot attach this entity because the EntityType (" + entity.entityType.name +
454
+ ") and MetadataStore associated with this entity does not match this EntityManager's MetadataStore.");
455
+ }
456
+ let aspect = entity.entityAspect;
457
+ if (aspect) {
458
+ // to avoid reattaching an entity in progress
459
+ if (aspect._inProcessEntity)
460
+ return aspect._inProcessEntity;
461
+ }
462
+ else {
463
+ // this occur's when attaching an entity created via new instead of via createEntity.
464
+ aspect = new EntityAspect(entity);
465
+ }
466
+ let manager = aspect.entityManager;
467
+ if (manager) {
468
+ if (manager === this) {
469
+ return entity;
470
+ }
471
+ else {
472
+ throw new Error("This entity already belongs to another EntityManager");
473
+ }
474
+ }
475
+ let attachedEntity = {};
476
+ core.using(this, "isLoading", true, () => {
477
+ if (esSymbol.isAdded()) {
478
+ checkEntityKey(this, entity);
479
+ }
480
+ // attachedEntity === entity EXCEPT in the case of a merge.
481
+ attachedEntity = this._attachEntityCore(entity, esSymbol, msSymbol);
482
+ aspect._inProcessEntity = attachedEntity;
483
+ try {
484
+ // entity ( not attachedEntity) is deliberate here.
485
+ attachRelatedEntities(this, entity, esSymbol, msSymbol);
486
+ }
487
+ finally {
488
+ // insure that _inProcessEntity is cleared.
489
+ aspect._inProcessEntity = undefined;
490
+ }
491
+ });
492
+ if (this.validationOptions.validateOnAttach) {
493
+ attachedEntity.entityAspect.validateEntity();
494
+ }
495
+ if (!esSymbol.isUnchanged()) {
496
+ this._notifyStateChange(attachedEntity, true);
497
+ }
498
+ this.entityChanged.publish({ entityAction: EntityAction.Attach, entity: attachedEntity });
499
+ return attachedEntity;
500
+ }
501
+ /**
502
+ Detaches an entity from this EntityManager.
503
+ > // assume em1 is an EntityManager containing a number of existing entities.
504
+ > // assume cust1 is a customer Entity previously attached to em1
505
+ > em1.detachEntity(cust1);
506
+ > // em1 will now no longer contain cust1 and cust1 will have an
507
+ > // entityAspect.entityState of EntityState.Detached
508
+ @param entity - The entity to detach.
509
+ @return Whether the entity could be detached. This will return false if the entity is already detached or was never attached.
510
+ **/
511
+ detachEntity(entity) {
512
+ assertParam(entity, "entity").isEntity().check();
513
+ let aspect = entity.entityAspect;
514
+ if (!aspect) {
515
+ // no aspect means in couldn't appear in any group
516
+ return false;
517
+ }
518
+ if (aspect.entityManager !== this) {
519
+ throw new Error("This entity does not belong to this EntityManager.");
520
+ }
521
+ return aspect.setDetached();
522
+ }
523
+ /**
524
+ Fetches the metadata associated with the EntityManager's current 'serviceName'. This call
525
+ occurs internally before the first query to any service if the metadata hasn't already been
526
+ loaded. __Async__
527
+
528
+ Usually you will not actually process the results of a fetchMetadata call directly, but will instead
529
+ ask for the metadata from the EntityManager after the fetchMetadata call returns.
530
+ > let em1 = new EntityManager( "breeze/NorthwindIBModel");
531
+ > em1.fetchMetadata()
532
+ > .then(function() {
533
+ > let metadataStore = em1.metadataStore;
534
+ > // do something with the metadata
535
+ > }).catch(function(exception) {
536
+ > // handle exception here
537
+ > });
538
+
539
+ @param callback - Function called on success.
540
+ @param errorCallback - Function called on failure.
541
+ @return {Promise}
542
+ - schema {Object} The raw Schema object from metadata provider - Because this schema will differ depending on the metadata provider
543
+ it is usually better to access metadata via the 'metadataStore' property of the EntityManager instead of using this 'raw' data.
544
+ **/
545
+ fetchMetadata(dataService, callback, errorCallback) {
546
+ if (typeof (dataService) === "function") {
547
+ // legacy support for when dataService was not an arg. i.e. first arg was callback
548
+ errorCallback = callback;
549
+ callback = dataService;
550
+ dataService = undefined;
551
+ }
552
+ else {
553
+ assertParam(dataService, "dataService").isInstanceOf(DataService).isOptional().check();
554
+ assertParam(callback, "callback").isFunction().isOptional().check();
555
+ assertParam(errorCallback, "errorCallback").isFunction().isOptional().check();
556
+ }
557
+ let promise = this.metadataStore.fetchMetadata(dataService || this.dataService);
558
+ return promiseWithCallbacks(promise, callback, errorCallback);
559
+ }
560
+ /**
561
+ Executes the specified query. __Async__
562
+
563
+ > let em = new EntityManager(serviceName);
564
+ > let query = new EntityQuery("Orders");
565
+ > em.executeQuery(query).then( function(data) {
566
+ > let orders = data.results;
567
+ > ... query results processed here
568
+ > }).catch( function(err) {
569
+ > ... query failure processed here
570
+ > });
571
+
572
+ or with callbacks
573
+ > let em = new EntityManager(serviceName);
574
+ > let query = new EntityQuery("Orders");
575
+ > em.executeQuery(query,
576
+ > function(data) {
577
+ > let orders = data.results;
578
+ > ... query results processed here
579
+ > },
580
+ > function(err) {
581
+ > ... query failure processed here
582
+ > });
583
+
584
+ Either way this method is the same as calling the The [[EntityQuery]] 'execute' method.
585
+ > let em = new EntityManager(serviceName);
586
+ > let query = new EntityQuery("Orders").using(em);
587
+ > query.execute().then( function(data) {
588
+ > let orders = data.results;
589
+ > ... query results processed here
590
+ > }).catch( function(err) {
591
+ > ... query failure processed here
592
+ > });
593
+ @param query - The [[EntityQuery]] or OData query string to execute.
594
+ @param callback - Function called on success.
595
+ @param errorCallback - {Function} Function called on failure.
596
+ @return Promise of
597
+ - results - An array of entities
598
+ - retrievedEntities - A array of all of the entities returned by the query. Differs from results (above) when .expand() is used.
599
+ - query - The original [[EntityQuery]] or query string
600
+ - entityManager - The EntityManager.
601
+ - httpResponse - The [[IHttpResponse]] returned from the server.
602
+ - inlineCount - Only available if 'inlineCount(true)' was applied to the query. Returns the count of
603
+ items that would have been returned by the query before applying any skip or take operators, but after any filter/where predicates
604
+ would have been applied.
605
+ **/
606
+ executeQuery(query, callback, errorCallback) {
607
+ assertParam(query, "query").isInstanceOf(EntityQuery).or().isString().check();
608
+ assertParam(callback, "callback").isFunction().isOptional().check();
609
+ assertParam(errorCallback, "errorCallback").isFunction().isOptional().check();
610
+ let promise;
611
+ // 'resolve' methods create a new typed object with all of its properties fully resolved against a list of sources.
612
+ // Thought about creating a 'normalized' query with these 'resolved' objects
613
+ // but decided not to because the 'query' may not be an EntityQuery (it can be a string) and hence might not have a queryOptions or dataServices property on it.
614
+ let queryOptions = QueryOptions.resolve([query.queryOptions, this.queryOptions, QueryOptions.defaultInstance]);
615
+ let dataService = DataService.resolve([query.dataService, this.dataService]);
616
+ if ((!dataService.hasServerMetadata) || this.metadataStore.hasMetadataFor(dataService.serviceName)) {
617
+ promise = executeQueryCore(this, query, queryOptions, dataService);
618
+ }
619
+ else {
620
+ promise = this.fetchMetadata(dataService).then(() => {
621
+ return executeQueryCore(this, query, queryOptions, dataService);
622
+ });
623
+ }
624
+ return promiseWithCallbacks(promise, callback, errorCallback);
625
+ }
626
+ /**
627
+ Executes the specified query against this EntityManager's local cache.
628
+
629
+ Because this method is executed immediately there is no need for a promise or a callback
630
+ > let em = new EntityManager(serviceName);
631
+ > let query = new EntityQuery("Orders");
632
+ > let orders = em.executeQueryLocally(query);
633
+
634
+ Note that this can also be accomplished using the 'executeQuery' method with
635
+ a FetchStrategy of FromLocalCache and making use of the Promise or callback
636
+ > let em = new EntityManager(serviceName);
637
+ > let query = new EntityQuery("Orders").using(FetchStrategy.FromLocalCache);
638
+ > em.executeQuery(query).then( function(data) {
639
+ > let orders = data.results;
640
+ > ... query results processed here
641
+ > }).catch( function(err) {
642
+ > ... query failure processed here
643
+ > });
644
+ @param query - The [[EntityQuery]] to execute.
645
+ @return {Array of Entity} Array of entities from cache that satisfy the query
646
+ **/
647
+ executeQueryLocally(query) {
648
+ return executeQueryLocallyCore(this, query).results;
649
+ }
650
+ /**
651
+ Saves either a list of specified entities or all changed entities within this EntityManager. If there are no changes to any of the entities
652
+ specified then there will be no server side call made but a valid 'empty' saveResult will still be returned. __Async__
653
+
654
+ Often we will be saving all of the entities within an EntityManager that are either added, modified or deleted
655
+ and we will let the 'saveChanges' call determine which entities these are.
656
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
657
+ > // This could include added, modified and deleted entities.
658
+ > em.saveChanges().then(function(saveResult) {
659
+ > let savedEntities = saveResult.entities;
660
+ > let keyMappings = saveResult.keyMappings;
661
+ > }).catch(function (e) {
662
+ > // e is any exception that was thrown.
663
+ > });
664
+
665
+ But we can also control exactly which entities to save and can specify specific SaveOptions
666
+
667
+ > // assume entitiesToSave is an array of entities to save.
668
+ > let saveOptions = new SaveOptions({ allowConcurrentSaves: true });
669
+ > em.saveChanges(entitiesToSave, saveOptions).then(function(saveResult) {
670
+ > let savedEntities = saveResult.entities;
671
+ > let keyMappings = saveResult.keyMappings;
672
+ > }).catch(function (e) {
673
+ > // e is any exception that was thrown.
674
+ > });
675
+
676
+ Callback methods can also be used
677
+ > em.saveChanges(entitiesToSave, null,
678
+ > function(saveResult) {
679
+ > let savedEntities = saveResult.entities;
680
+ > let keyMappings = saveResult.keyMappings;
681
+ > }, function (e) {
682
+ > // e is any exception that was thrown.
683
+ > }
684
+ > );
685
+
686
+ @param entities - The list of entities to save.
687
+ Every entity in that list will be sent to the server, whether changed or unchanged,
688
+ as long as it is attached to this EntityManager.
689
+ If this parameter is omitted, null or empty (the usual case),
690
+ every entity with pending changes in this EntityManager will be saved.
691
+ @param saveOptions - [[SaveOptions]] for the save - will default to
692
+ [[EntityManager.saveOptions]] if null.
693
+ @param callback - Function called on success.
694
+ @param errorCallback - Function called on failure.
695
+ @return {Promise} Promise
696
+ **/
697
+ saveChanges(entities, saveOptions, callback, errorCallback) {
698
+ assertParam(entities, "entities").isOptional().isArray().isEntity().check();
699
+ assertParam(saveOptions, "saveOptions").isInstanceOf(SaveOptions).isOptional().check();
700
+ assertParam(callback, "callback").isFunction().isOptional().check();
701
+ assertParam(errorCallback, "errorCallback").isFunction().isOptional().check();
702
+ saveOptions = saveOptions || this.saveOptions || SaveOptions.defaultInstance;
703
+ let entitiesToSave = getEntitiesToSave(this, entities ? entities : undefined);
704
+ if (entitiesToSave.length === 0) {
705
+ let result = { entities: [], keyMappings: [] };
706
+ if (callback)
707
+ callback(result);
708
+ return Promise.resolve(result);
709
+ }
710
+ if (!saveOptions.allowConcurrentSaves) {
711
+ let anyPendingSaves = entitiesToSave.some(function (entity) {
712
+ return entity.entityAspect.isBeingSaved;
713
+ });
714
+ if (anyPendingSaves) {
715
+ let err = new Error("Concurrent saves not allowed - SaveOptions.allowConcurrentSaves is false");
716
+ if (errorCallback)
717
+ errorCallback(err);
718
+ return Promise.reject(err);
719
+ }
720
+ }
721
+ clearServerErrors(entitiesToSave);
722
+ let valError = this.saveChangesValidateOnClient(entitiesToSave);
723
+ if (valError) {
724
+ if (errorCallback)
725
+ errorCallback(valError);
726
+ return Promise.reject(valError);
727
+ }
728
+ let dataService = DataService.resolve([saveOptions.dataService, this.dataService]);
729
+ let saveContext = {
730
+ entityManager: this,
731
+ dataService: dataService,
732
+ processSavedEntities: processSavedEntities,
733
+ resourceName: saveOptions.resourceName || this.saveOptions.resourceName || "SaveChanges"
734
+ };
735
+ // TODO: need to check that if we are doing a partial save that all entities whose temp keys
736
+ // are referenced are also in the partial save group
737
+ let saveBundle = { entities: entitiesToSave, saveOptions: saveOptions };
738
+ try { // Guard against exception thrown in dataservice adapter before it goes async
739
+ updateConcurrencyProperties(entitiesToSave);
740
+ return dataService.adapterInstance.saveChanges(saveContext, saveBundle)
741
+ .then(saveSuccess).then((r) => r, saveFail);
742
+ }
743
+ catch (err) {
744
+ // undo the marking by updateConcurrencyProperties
745
+ markIsBeingSaved(entitiesToSave, false);
746
+ if (errorCallback)
747
+ errorCallback(err);
748
+ return Promise.reject(err);
749
+ }
750
+ function saveSuccess(saveResult) {
751
+ let em = saveContext.entityManager;
752
+ markIsBeingSaved(entitiesToSave, false);
753
+ let savedEntities = saveContext.processSavedEntities(saveResult);
754
+ saveResult.entities = savedEntities;
755
+ // update _hasChanges after save.
756
+ em._setHasChanges();
757
+ // can't do this anymore because other changes might have been made while saved entities in flight.
758
+ // let hasChanges = (isFullSave && haveSameContents(entitiesToSave, savedEntities)) ? false : null;
759
+ // em._setHasChanges(hasChanges);
760
+ if (callback)
761
+ callback(saveResult);
762
+ return Promise.resolve(saveResult);
763
+ }
764
+ function processSavedEntities(saveResult) {
765
+ let savedEntities = saveResult.entities;
766
+ let deletedKeys = saveResult.deletedKeys || [];
767
+ if (savedEntities.length === 0 && deletedKeys.length === 0) {
768
+ return [];
769
+ }
770
+ let keyMappings = saveResult.keyMappings;
771
+ let em = saveContext.entityManager;
772
+ // must occur outside of isLoading block
773
+ fixupKeys(em, keyMappings);
774
+ core.using(em, "isLoading", true, () => {
775
+ let mappingContext = new MappingContext({
776
+ query: undefined,
777
+ entityManager: em,
778
+ mergeOptions: { mergeStrategy: MergeStrategy.OverwriteChanges },
779
+ dataService: dataService
780
+ });
781
+ // The visitAndMerge operation has been optimized so that we do not actually perform a merge if the
782
+ // the save operation did not actually return the entity - i.e. during OData and Mongo updates and deletes.
783
+ savedEntities = mappingContext.visitAndMerge(savedEntities, { nodeType: "root" });
784
+ });
785
+ // detach any entities found in the em that appear in the deletedKeys list.
786
+ deletedKeys.forEach(key => {
787
+ let entityType = em.metadataStore._getStructuralType(key.entityTypeName);
788
+ let ekey = new EntityKey(entityType, key.keyValues);
789
+ let entity = em.getEntityByKey(ekey);
790
+ if (entity) {
791
+ entity.entityAspect.setDetached();
792
+ }
793
+ });
794
+ return savedEntities;
795
+ }
796
+ function saveFail(serverError) {
797
+ markIsBeingSaved(entitiesToSave, false);
798
+ let clientError = processServerErrors(saveContext, serverError);
799
+ if (errorCallback)
800
+ errorCallback(clientError);
801
+ return Promise.reject(clientError);
802
+ }
803
+ }
804
+ /**
805
+ Run the "saveChanges" pre-save client validation logic.
806
+
807
+ This is NOT a general purpose validation method.
808
+ It is intended for utilities that must know if saveChanges
809
+ would reject the save due to client validation errors.
810
+
811
+ It only validates entities if the EntityManager's
812
+ [[ValidationOptions]].validateOnSave is true.
813
+
814
+ @param entitiesToSave {Array of Entity} The list of entities to save (to validate).
815
+ @return {Error} Validation error or null if no error
816
+ **/
817
+ saveChangesValidateOnClient(entitiesToSave) {
818
+ if (this.validationOptions.validateOnSave) {
819
+ let failedEntities = entitiesToSave.filter(function (entity) {
820
+ let aspect = entity.entityAspect;
821
+ let isValid = aspect.entityState.isDeleted() || aspect.validateEntity();
822
+ return !isValid;
823
+ });
824
+ if (failedEntities.length > 0) {
825
+ let valError = new Error("Client side validation errors encountered - see the entityErrors collection on this object for more detail");
826
+ valError.entityErrors = createEntityErrors(failedEntities);
827
+ return valError; // TODO: type this.
828
+ }
829
+ }
830
+ return null;
831
+ }
832
+ /** @hidden @internal */
833
+ _findEntityGroup(entityType) {
834
+ return this._entityGroupMap[entityType.name];
835
+ }
836
+ /**
837
+ Attempts to locate an entity within this EntityManager by its [EntityKey].
838
+ @param entityKey - The [[EntityKey]] of the Entity to be located.
839
+ @param type - The [[EntityType]] for this key.
840
+ @param typeName - The EntityType name for this key.
841
+ @param keyValues - The values for this key - will usually just be a single value; an array is only needed for multipart keys.
842
+ @return An Entity or null;
843
+ **/
844
+ getEntityByKey(...args) {
845
+ let entityKey = createEntityKey(this, args).entityKey;
846
+ let entityTypes = entityKey._subtypes || [entityKey.entityType];
847
+ let e;
848
+ // hack use of some to simulate mapFirst logic.
849
+ entityTypes.some((et) => {
850
+ let group = this._findEntityGroup(et);
851
+ // group version of findEntityByKey doesn't care about entityType
852
+ e = group && group.findEntityByKey(entityKey);
853
+ return e != null;
854
+ });
855
+ return e || null;
856
+ }
857
+ /**
858
+ Attempts to fetch an entity from the server by its [[EntityKey]] with
859
+ an option to check the local cache first. Note the this EntityManager's queryOptions.mergeStrategy
860
+ will be used to merge any server side entity returned by this method.
861
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
862
+ > let employeeType = em1.metadataStore.getEntityType("Employee");
863
+ > let employeeKey = new EntityKey(employeeType, 1);
864
+ > em1.fetchEntityByKey(employeeKey).then(function(result) {
865
+ > let employee = result.entity;
866
+ > let entityKey = result.entityKey;
867
+ > let fromCache = result.fromCache;
868
+ > });
869
+ @param typeName - The EntityType name for this key.
870
+ @param entityType - The EntityType for this key.
871
+ @param keyValues - The values for this key - will usually just be a single value; an array is only needed for multipart keys.
872
+ @param entityKey - The [[EntityKey]] of the Entity to be located.
873
+ @param checkLocalCacheFirst - (default = false) - Whether to check this EntityManager first before going to the server. By default, the query will NOT do this.
874
+ @return {Promise}
875
+ - Properties on the promise success result
876
+ - entity {Object} The entity returned or null
877
+ - entityKey {EntityKey} The entityKey of the entity to fetch.
878
+ - fromCache {Boolean} Whether this entity was fetched from the server or was found in the local cache.
879
+ **/
880
+ fetchEntityByKey(...args) {
881
+ let dataService = DataService.resolve([this.dataService]);
882
+ if ((!dataService.hasServerMetadata) || this.metadataStore.hasMetadataFor(dataService.serviceName)) {
883
+ return fetchEntityByKeyCore(this, args);
884
+ }
885
+ else {
886
+ return this.fetchMetadata(dataService).then(() => {
887
+ return fetchEntityByKeyCore(this, args);
888
+ });
889
+ }
890
+ }
891
+ /**
892
+ [Deprecated] - Attempts to locate an entity within this EntityManager by its [[EntityKey]].
893
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
894
+ > let employeeType = em1.metadataStore.getEntityType("Employee");
895
+ > let employeeKey = new EntityKey(employeeType, 1);
896
+ > let employee = em1.findEntityByKey(employeeKey);
897
+ > // employee will either be an entity or null.
898
+ @deprecated Use getEntityByKey instead
899
+ @param entityKey - The [[EntityKey]] of the Entity to be located.
900
+ @return An Entity or null;
901
+ **/
902
+ findEntityByKey(entityKey) {
903
+ return this.getEntityByKey(entityKey);
904
+ }
905
+ /**
906
+ Generates a temporary key for the specified entity. This is used to insure that newly
907
+ created entities have unique keys and to register that these keys are temporary and
908
+ need to be automatically replaced with 'real' key values once these entities are saved.
909
+
910
+ The [[EntityManager.keyGeneratorCtor]] property is used internally by this method to actually generate
911
+ the keys - See the KeyGenerator interface interface description to see
912
+ how a custom key generator can be plugged in.
913
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
914
+ > let custType = em1.metadataStore.getEntityType("Customer");
915
+ > let customer = custType.createEntity();
916
+ > let customerId = em.generateTempKeyValue(customer);
917
+ > // The 'customer' entity 'CustomerID' property is now set to a newly generated unique id value
918
+ > // This property will change again after a successful save of the 'customer' entity.
919
+ >
920
+ > em1.saveChanges().then( function( data) {
921
+ > let sameCust1 = data.results[0];
922
+ > // cust1 === sameCust1;
923
+ > // but cust1.getProperty("CustomerId") != customerId
924
+ > // because the server will have generated a new id
925
+ > // and the client will have been updated with this
926
+ > // new id.
927
+ > })
928
+ @param entity - The Entity to generate a key for.
929
+ @return The new key value
930
+ **/
931
+ generateTempKeyValue(entity) {
932
+ // TODO - check if this entity is attached to this EntityManager.
933
+ assertParam(entity, "entity").isEntity().check();
934
+ let entityType = entity.entityType;
935
+ let nextKeyValue = this.keyGenerator.generateTempKeyValue(entityType);
936
+ let keyProp = entityType.keyProperties[0];
937
+ entity.setProperty(keyProp.name, nextKeyValue);
938
+ entity.entityAspect.hasTempKey = true;
939
+ return nextKeyValue;
940
+ }
941
+ /**
942
+ Returns whether there are any changed entities of the specified [[EntityType]]s. A 'changed' Entity has
943
+ has an [[EntityState]] of either Added, Modified or Deleted.
944
+
945
+ This method can be used to determine if an EntityManager has any changes
946
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
947
+ > if ( em1.hasChanges() {
948
+ > // do something interesting
949
+ > }
950
+
951
+ or if it has any changes on to a specific [[EntityType]].
952
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
953
+ > let custType = em1.metadataStore.getEntityType("Customer");
954
+ > if ( em1.hasChanges(custType) {
955
+ > // do something interesting
956
+ > }
957
+
958
+ or to a collection of [[EntityType]]s
959
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
960
+ > let custType = em1.metadataStore.getEntityType("Customer");
961
+ > let orderType = em1.metadataStore.getEntityType("Order");
962
+ > if ( em1.hasChanges( [custType, orderType]) {
963
+ > // do something interesting
964
+ > }
965
+ @param entityTypes - The [[EntityType]] or EntityTypes for which 'changed' entities will be found.
966
+ @param entityTypeNames - The [[EntityType]] name or names for which 'changed' entities will be found.
967
+ @return Whether there are any changed entities that match the types specified..
968
+ **/
969
+ hasChanges(entityTypes) {
970
+ if (!this._hasChanges)
971
+ return false;
972
+ if (entityTypes === undefined)
973
+ return this._hasChanges;
974
+ return this._hasChangesCore(entityTypes);
975
+ }
976
+ /** @hidden @internal */
977
+ // backdoor to "really" check for changes.
978
+ _hasChangesCore(entityTypes) {
979
+ let ets = checkEntityTypes(this, entityTypes);
980
+ let entityGroups = getEntityGroups(this, ets);
981
+ return entityGroups.some(function (eg) {
982
+ return eg && eg.hasChanges();
983
+ });
984
+ }
985
+ /**
986
+ Returns a array of all changed entities of the specified [[EntityType]]s. A 'changed' Entity has
987
+ has an [[EntityState]] of either Added, Modified or Deleted.
988
+
989
+ This method can be used to get all of the changed entities within an EntityManager
990
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
991
+ > let changedEntities = em1.getChanges();
992
+
993
+ or you can specify that you only want the changes on a specific [[EntityType]]
994
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
995
+ > let custType = em1.metadataStore.getEntityType("Customer");
996
+ > let changedCustomers = em1.getChanges(custType);
997
+
998
+ or to a collection of [[EntityType]]s
999
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
1000
+ > let custType = em1.metadataStore.getEntityType("Customer");
1001
+ > let orderType = em1.metadataStore.getEntityType("Order");
1002
+ > let changedCustomersAndOrders = em1.getChanges([custType, orderType]);
1003
+ @param entityTypes - The [[EntityType]] or EntityTypes for which 'changed' entities will be found.
1004
+ @param entityTypeNames - The [[EntityType]] name or names for which 'changed' entities will be found.
1005
+ @return An array of Entities
1006
+ **/
1007
+ getChanges(entityTypes) {
1008
+ let ets = checkEntityTypes(this, entityTypes);
1009
+ return getChangesCore(this, ets);
1010
+ }
1011
+ /**
1012
+ Rejects (reverses the effects) all of the additions, modifications and deletes from this EntityManager.
1013
+ Calls [[EntityAspect.rejectChanges]] on every changed entity in this EntityManager.
1014
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
1015
+ > let entities = em1.rejectChanges();
1016
+ @return The entities whose changes were rejected. These entities will all have EntityStates of
1017
+ either 'Unchanged' or 'Detached'
1018
+ **/
1019
+ rejectChanges() {
1020
+ if (!this._hasChanges)
1021
+ return [];
1022
+ let changes = getChangesCore(this);
1023
+ // next line stops individual reject changes from each calling _hasChangesCore
1024
+ let aspects = changes.map(function (e) {
1025
+ return e.entityAspect._checkOperation("rejectChanges");
1026
+ });
1027
+ this._hasChanges = false;
1028
+ aspects.forEach(function (aspect) {
1029
+ aspect.rejectChanges();
1030
+ });
1031
+ this.hasChangesChanged.publish({ entityManager: this, hasChanges: false });
1032
+ return changes;
1033
+ }
1034
+ /**
1035
+ Returns a array of all entities of the specified [[EntityType]]s with the specified [[EntityState]]s.
1036
+
1037
+ This method can be used to get all of the entities within an EntityManager
1038
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
1039
+ > let entities = em1.getEntities();
1040
+
1041
+ or you can specify that you only want the changes on a specific [[EntityType]]
1042
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
1043
+ > let custType = em1.metadataStore.getEntityType("Customer");
1044
+ > let customers = em1.getEntities(custType);
1045
+
1046
+ or to a collection of [[EntityType]]s
1047
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
1048
+ > let custType = em1.metadataStore.getEntityType("Customer");
1049
+ > let orderType = em1.metadataStore.getEntityType("Order");
1050
+ > let customersAndOrders = em1.getChanges([custType, orderType]);
1051
+
1052
+ You can also ask for entities with a particular [[EntityState]] or EntityStates.
1053
+ > // assume em1 is an EntityManager containing a number of preexisting entities.
1054
+ > let custType = em1.metadataStore.getEntityType("Customer");
1055
+ > let orderType = em1.metadataStore.getEntityType("Order");
1056
+ > let addedCustomersAndOrders = em1.getEntities([custType, orderType], EntityState.Added);
1057
+
1058
+ @param entityTypeName - The [[EntityType]] name or names for which entities will be found.
1059
+ If this parameter is omitted, all EntityTypes are searched.
1060
+ @param entityTypes - The [[EntityType]] or EntityTypes for which entities will be found.
1061
+ If this parameter is omitted, all EntityTypes are searched.
1062
+ @param entityStates - The [[EntityState]]s for which entities will be found.
1063
+ If this parameter is omitted, entities of all EntityStates are returned.
1064
+ @return An array of Entities
1065
+ **/
1066
+ getEntities(entityTypes, entityStates) {
1067
+ let entTypes = checkEntityTypes(this, entityTypes);
1068
+ assertParam(entityStates, "entityStates").isOptional().isEnumOf(EntityState).or().isNonEmptyArray().isEnumOf(EntityState).check();
1069
+ let states = validateEntityStates(this, entityStates);
1070
+ return getEntitiesCore(this, entTypes, states);
1071
+ }
1072
+ // protected methods
1073
+ /** @hidden @internal */
1074
+ _notifyStateChange(entity, needsSave) {
1075
+ let ecArgs = { entityAction: EntityAction.EntityStateChange, entity: entity };
1076
+ if (needsSave) {
1077
+ if (!this._hasChanges)
1078
+ this._setHasChanges(true);
1079
+ }
1080
+ else {
1081
+ // called when rejecting a change or merging an unchanged record.
1082
+ // NOTE: this can be slow with lots of entities in the cache.
1083
+ // so defer it during a query/import or save and call it once when complete ( if needed).
1084
+ if (this._hasChanges) {
1085
+ if (this.isLoading) {
1086
+ this._hasChangesAction = this._hasChangesAction || function () {
1087
+ this._setHasChanges(null);
1088
+ this.entityChanged.publish(ecArgs);
1089
+ }.bind(this);
1090
+ return;
1091
+ }
1092
+ else {
1093
+ this._setHasChanges();
1094
+ }
1095
+ }
1096
+ }
1097
+ this.entityChanged.publish(ecArgs);
1098
+ }
1099
+ /** @hidden @internal */
1100
+ _setHasChanges(hasChanges) {
1101
+ if (hasChanges == null)
1102
+ hasChanges = this._hasChangesCore();
1103
+ let hadChanges = this._hasChanges;
1104
+ this._hasChanges = hasChanges;
1105
+ if (hasChanges !== hadChanges) {
1106
+ this.hasChangesChanged.publish({ entityManager: this, hasChanges: hasChanges });
1107
+ }
1108
+ this._hasChangesAction = undefined;
1109
+ }
1110
+ /** @hidden @internal */
1111
+ _linkRelatedEntities(entity) {
1112
+ let em = this;
1113
+ let entityAspect = entity.entityAspect;
1114
+ // we do not want entityState to change as a result of linkage.
1115
+ core.using(em, "isLoading", true, function () {
1116
+ let unattachedMap = em._unattachedChildrenMap;
1117
+ let entityKey = entityAspect.getKey();
1118
+ let entityType = entityKey.entityType;
1119
+ while (entityType) {
1120
+ let keystring = entityKey.toString(entityType);
1121
+ // attach any unattachedChildren
1122
+ let tuples = unattachedMap.getTuplesByString(keystring);
1123
+ if (tuples) {
1124
+ tuples.slice(0).forEach(function (tpl) {
1125
+ let unattachedChildren = tpl.children.filter(function (e) {
1126
+ return e.entityAspect.entityState !== EntityState.Detached;
1127
+ });
1128
+ let childToParentNp;
1129
+ let parentToChildNp;
1130
+ // np is usually childToParentNp
1131
+ // except with unidirectional 1-n where it is parentToChildNp;
1132
+ let np = tpl.navigationProperty;
1133
+ let inverseNp = np.inverse;
1134
+ if (inverseNp) {
1135
+ // bidirectional
1136
+ childToParentNp = np;
1137
+ parentToChildNp = inverseNp;
1138
+ if (parentToChildNp.isScalar) {
1139
+ let onlyChild = unattachedChildren[0];
1140
+ entity.setProperty(parentToChildNp.name, onlyChild);
1141
+ onlyChild.setProperty(childToParentNp.name, entity);
1142
+ }
1143
+ else {
1144
+ let currentChildren = entity.getProperty(parentToChildNp.name);
1145
+ unattachedChildren.forEach(function (child) {
1146
+ currentChildren.push(child);
1147
+ child.setProperty(childToParentNp.name, entity);
1148
+ });
1149
+ }
1150
+ unattachedMap.removeChildren(keystring, childToParentNp);
1151
+ }
1152
+ else {
1153
+ // unidirectional
1154
+ // if (np.isScalar || np.parentType !== entity.entityType) {
1155
+ if (np.isScalar) {
1156
+ // n -> 1 eg: child: OrderDetail parent: Product
1157
+ // 1 -> 1 eg child: Employee parent: Employee ( only Manager, no DirectReports property)
1158
+ childToParentNp = np;
1159
+ unattachedChildren.forEach(function (child) {
1160
+ child.setProperty(childToParentNp.name, entity);
1161
+ });
1162
+ unattachedMap.removeChildren(keystring, childToParentNp);
1163
+ }
1164
+ else {
1165
+ // 1 -> n eg: parent: Region child: Terr
1166
+ // TODO: need to remove unattached children from the map after this; only a perf issue.
1167
+ parentToChildNp = np;
1168
+ let currentChildren = entity.getProperty(parentToChildNp.name);
1169
+ unattachedChildren.forEach(function (child) {
1170
+ // we know if can't already be there.
1171
+ currentChildren._push(child);
1172
+ });
1173
+ }
1174
+ }
1175
+ });
1176
+ }
1177
+ entityType = entityType.baseEntityType; // look for relationships up the hierarchy
1178
+ }
1179
+ // now add to unattachedMap if needed.
1180
+ entity.entityType.navigationProperties.forEach(function (np) {
1181
+ if (np.isScalar) {
1182
+ let value = entity.getProperty(np.name);
1183
+ // property is already linked up
1184
+ if (value)
1185
+ return;
1186
+ }
1187
+ // first determine if np contains a parent or child
1188
+ // having a parentKey means that this is a child
1189
+ // if a parent then no need for more work because children will attach to it.
1190
+ let parentKey = entityAspect.getParentKey(np);
1191
+ if (parentKey) {
1192
+ // check for empty keys - meaning that parent id's are not yet set.
1193
+ if (parentKey._isEmpty())
1194
+ return;
1195
+ // if a child - look for parent in the em cache
1196
+ if (np.invForeignKeyNames.length) {
1197
+ // np relates to non-PK property of parent entity
1198
+ const query = new EntityQuery(parentKey.entityType.defaultResourceName).where(np.invForeignKeyNames[0], 'eq', parentKey.values[0]);
1199
+ const qresult = em.executeQueryLocally(query);
1200
+ if (qresult.length === 1) {
1201
+ let parent = qresult[0];
1202
+ entity.setProperty(np.name, parent);
1203
+ }
1204
+ }
1205
+ else {
1206
+ // np relates to PK of parent entity
1207
+ let parent = em.getEntityByKey(parentKey);
1208
+ if (parent) {
1209
+ // if found hook it up
1210
+ entity.setProperty(np.name, parent);
1211
+ }
1212
+ else {
1213
+ // else add parent to unresolvedParentMap;
1214
+ unattachedMap.addChild(parentKey, np, entity);
1215
+ }
1216
+ }
1217
+ }
1218
+ else if (np.inverse && np.inverse.invForeignKeyNames.length) {
1219
+ // np relates to non-PK property of parent entity; query entities by FK
1220
+ const akValue = entity.getProperty(np.inverse.invForeignKeyNames[0]);
1221
+ const query = new EntityQuery(np.entityType.defaultResourceName).where(np.invForeignKeyNames[0], 'eq', akValue);
1222
+ const qresult = em.executeQueryLocally(query);
1223
+ qresult.forEach((child) => {
1224
+ child.setProperty(np.inverse.name, entity);
1225
+ });
1226
+ }
1227
+ });
1228
+ // handle unidirectional 1-x where we set x.fk
1229
+ entity.entityType.foreignKeyProperties.forEach(function (fkProp) {
1230
+ let invNp = fkProp.inverseNavigationProperty;
1231
+ if (!invNp)
1232
+ return;
1233
+ // unidirectional fk props only
1234
+ let fkValue = entity.getProperty(fkProp.name);
1235
+ let parentKey = new EntityKey(invNp.parentType, [fkValue]);
1236
+ let parent = em.getEntityByKey(parentKey);
1237
+ if (parent) {
1238
+ if (invNp.isScalar) {
1239
+ parent.setProperty(invNp.name, entity);
1240
+ }
1241
+ else {
1242
+ if (em.isLoading) {
1243
+ parent.getProperty(invNp.name)._push(entity);
1244
+ }
1245
+ else {
1246
+ parent.getProperty(invNp.name).push(entity);
1247
+ }
1248
+ }
1249
+ }
1250
+ else {
1251
+ // else add parent to unresolvedParentMap;
1252
+ unattachedMap.addChild(parentKey, invNp, entity);
1253
+ }
1254
+ });
1255
+ });
1256
+ }
1257
+ /** @hidden @internal */
1258
+ _attachEntityCore(entity, entityState, mergeStrategy) {
1259
+ let group = findOrCreateEntityGroup(this, entity.entityType);
1260
+ let attachedEntity = group.attachEntity(entity, entityState, mergeStrategy);
1261
+ this._linkRelatedEntities(attachedEntity);
1262
+ return attachedEntity;
1263
+ }
1264
+ /** @hidden @internal */
1265
+ _updateFkVal(fkProp, oldValue, newValue) {
1266
+ let group = this._entityGroupMap[fkProp.parentType.name];
1267
+ if (!group)
1268
+ return;
1269
+ group._updateFkVal(fkProp, oldValue, newValue);
1270
+ }
1271
+ }
1272
+ EntityManager.prototype._$typeName = "EntityManager";
1273
+ BreezeEvent.bubbleEvent(EntityManager.prototype);
1274
+ function clearServerErrors(entities) {
1275
+ entities.forEach(function (entity) {
1276
+ let serverKeys = [];
1277
+ let aspect = entity.entityAspect;
1278
+ core.objectForEach(aspect._validationErrors, function (key, ve) {
1279
+ if (ve.isServerError)
1280
+ serverKeys.push(key);
1281
+ });
1282
+ if (serverKeys.length === 0)
1283
+ return;
1284
+ aspect._processValidationOpAndPublish(function () {
1285
+ serverKeys.forEach(function (key) {
1286
+ aspect._removeValidationError(key);
1287
+ });
1288
+ });
1289
+ });
1290
+ }
1291
+ function createEntityErrors(entities) {
1292
+ let entityErrors = [];
1293
+ entities.forEach((entity) => {
1294
+ core.objectForEach(entity.entityAspect._validationErrors, function (key, ve) {
1295
+ let cfg = core.extend({
1296
+ entity: entity,
1297
+ errorName: ve.validator.name
1298
+ }, ve, ["errorMessage", "propertyName", "isServerError", "custom"]);
1299
+ entityErrors.push(cfg);
1300
+ });
1301
+ });
1302
+ return entityErrors;
1303
+ }
1304
+ function processServerErrors(saveContext, saveError) {
1305
+ // converting ISaveErrorFromServer -> ISaveError
1306
+ let serverErrors = saveError.entityErrors;
1307
+ if (!serverErrors)
1308
+ return saveError;
1309
+ let entityManager = saveContext.entityManager;
1310
+ let metadataStore = entityManager.metadataStore;
1311
+ let entityErrors = serverErrors.map((serr) => {
1312
+ let entity = null;
1313
+ let entityType;
1314
+ if (serr.keyValues) {
1315
+ entityType = metadataStore._getStructuralType(serr.entityTypeName);
1316
+ let ekey = new EntityKey(entityType, serr.keyValues);
1317
+ entity = entityManager.getEntityByKey(ekey);
1318
+ }
1319
+ if (entityType && entity) {
1320
+ let context = serr.propertyName ?
1321
+ {
1322
+ propertyName: serr.propertyName,
1323
+ property: entityType.getProperty(serr.propertyName)
1324
+ } : {};
1325
+ let key = ValidationError.getKey(serr.errorName || serr.errorMessage, serr.propertyName);
1326
+ let ve = new ValidationError(null, context, serr.errorMessage, key);
1327
+ ve.isServerError = true;
1328
+ entity.entityAspect.addValidationError(ve);
1329
+ }
1330
+ let entityError = core.extend({
1331
+ entity: entity,
1332
+ isServerError: true
1333
+ }, serr, ["errorName", "errorMessage", "propertyName", "custom"]);
1334
+ return entityError;
1335
+ });
1336
+ // converting ISaveErrorFromServer -> ISaveError
1337
+ saveError.entityErrors = entityErrors;
1338
+ return saveError;
1339
+ }
1340
+ function fetchEntityByKeyCore(em, args) {
1341
+ let tpl = createEntityKey(em, args);
1342
+ let entityKey = tpl.entityKey;
1343
+ let checkLocalCacheFirst = tpl.remainingArgs.length === 0 ? false : !!tpl.remainingArgs[0];
1344
+ let entity = null;
1345
+ let foundIt = false;
1346
+ if (checkLocalCacheFirst) {
1347
+ entity = em.getEntityByKey(entityKey);
1348
+ foundIt = entity != null;
1349
+ if (entity != null &&
1350
+ // null the entity if it is deleted and we should exclude deleted entities
1351
+ !em.queryOptions.includeDeleted && entity.entityAspect.entityState.isDeleted()) {
1352
+ entity = null;
1353
+ // but resume looking if we'd overwrite deleted entity with a remote entity
1354
+ // note: em.queryOptions is always fully resolved by now
1355
+ foundIt = em.queryOptions.mergeStrategy !== MergeStrategy.OverwriteChanges;
1356
+ }
1357
+ }
1358
+ if (foundIt) {
1359
+ return Promise.resolve({ entity: entity || undefined, entityKey: entityKey, fromCache: true });
1360
+ }
1361
+ else {
1362
+ return EntityQuery.fromEntityKey(entityKey).using(em).execute().then(function (data) {
1363
+ entity = (data.results.length === 0) ? null : data.results[0];
1364
+ return Promise.resolve({ entity: entity || undefined, entityKey: entityKey, fromCache: false });
1365
+ });
1366
+ }
1367
+ }
1368
+ // private fns
1369
+ // takes in entityTypes as either strings or entityTypes or arrays of either
1370
+ // and returns either an entityType or an array of entityTypes or throws an error
1371
+ function checkEntityTypes(em, entityTypes) {
1372
+ assertParam(entityTypes, "entityTypes").isString().isOptional().or().isNonEmptyArray().isString()
1373
+ .or().isInstanceOf(EntityType).or().isNonEmptyArray().isInstanceOf(EntityType).check();
1374
+ let resultTypes;
1375
+ if (typeof entityTypes === "string") {
1376
+ resultTypes = em.metadataStore._getStructuralType(entityTypes, false);
1377
+ }
1378
+ else if (Array.isArray(entityTypes) && typeof entityTypes[0] === "string") {
1379
+ resultTypes = entityTypes.map(function (etName) {
1380
+ return em.metadataStore._getStructuralType(etName, false);
1381
+ });
1382
+ }
1383
+ else {
1384
+ resultTypes = entityTypes;
1385
+ }
1386
+ return resultTypes;
1387
+ }
1388
+ function getChangesCore(em, entityTypes) {
1389
+ let entityGroups = getEntityGroups(em, entityTypes);
1390
+ // TODO: think about writing a core.mapMany method if we see more of these.
1391
+ let selected = [];
1392
+ entityGroups.forEach(function (eg) {
1393
+ // eg may be undefined or null
1394
+ if (!eg)
1395
+ return;
1396
+ let entities = eg.getChanges();
1397
+ if (selected && selected.length) {
1398
+ selected = selected.concat(entities);
1399
+ }
1400
+ else {
1401
+ selected = entities;
1402
+ }
1403
+ });
1404
+ return selected;
1405
+ }
1406
+ function getEntitiesCore(em, entityTypes, entityStates) {
1407
+ let entityGroups = getEntityGroups(em, entityTypes);
1408
+ // TODO: think about writing a core.mapMany method if we see more of these.
1409
+ let selected = [];
1410
+ entityGroups.forEach(function (eg) {
1411
+ // eg may be undefined or null
1412
+ if (!eg)
1413
+ return;
1414
+ let entities = eg.getEntities(entityStates);
1415
+ if (selected && selected.length) {
1416
+ selected = selected.concat(entities);
1417
+ }
1418
+ else {
1419
+ selected = entities;
1420
+ }
1421
+ });
1422
+ return selected;
1423
+ }
1424
+ function createEntityKey(em, args) {
1425
+ try {
1426
+ if (args[0] instanceof EntityKey) {
1427
+ return { entityKey: args[0], remainingArgs: core.arraySlice(args, 1) };
1428
+ }
1429
+ else if (args.length >= 2) {
1430
+ let entityType = (typeof args[0] === 'string') ? em.metadataStore._getStructuralType(args[0], false) : args[0];
1431
+ return { entityKey: new EntityKey(entityType, args[1]), remainingArgs: core.arraySlice(args, 2) };
1432
+ }
1433
+ }
1434
+ catch (e) { /* throw below */
1435
+ // throw new Error("Must supply an EntityKey OR an EntityType name or EntityType followed by a key value or an array of key values.");
1436
+ }
1437
+ throw new Error("Must supply an EntityKey OR an EntityType name or EntityType followed by a key value or an array of key values.");
1438
+ }
1439
+ function markIsBeingSaved(entities, flag) {
1440
+ entities.forEach(function (entity) {
1441
+ entity.entityAspect.isBeingSaved = flag;
1442
+ });
1443
+ }
1444
+ function exportEntityGroups(em, entitiesOrEntityTypes) {
1445
+ let entityGroupMap;
1446
+ let first = entitiesOrEntityTypes && entitiesOrEntityTypes[0];
1447
+ // check if array
1448
+ if (first) {
1449
+ // group entities by entityType and
1450
+ // create 'groups' that look like entityGroups.
1451
+ entityGroupMap = {};
1452
+ if (first.entityType) {
1453
+ let entities = entitiesOrEntityTypes;
1454
+ // assume "entities" is an array of entities;
1455
+ entities.forEach(function (e) {
1456
+ if (e.entityAspect.entityState === EntityState.Detached) {
1457
+ throw new Error("Unable to export an entity with an EntityState of 'Detached'");
1458
+ }
1459
+ let group = entityGroupMap[e.entityType.name];
1460
+ if (!group) {
1461
+ group = {};
1462
+ group.entityType = e.entityType;
1463
+ group._entities = [];
1464
+ entityGroupMap[e.entityType.name] = group;
1465
+ }
1466
+ group._entities.push(e);
1467
+ });
1468
+ }
1469
+ else {
1470
+ // assume "entities" is an array of EntityTypes (or names)
1471
+ let entityTypes = checkEntityTypes(em, entitiesOrEntityTypes);
1472
+ if (entityTypes != null) {
1473
+ entityTypes.forEach((et) => {
1474
+ let group = em._entityGroupMap[et.name];
1475
+ if (group && group._entities.length) {
1476
+ entityGroupMap[et.name] = group;
1477
+ }
1478
+ });
1479
+ }
1480
+ }
1481
+ }
1482
+ else if (entitiesOrEntityTypes && entitiesOrEntityTypes.length === 0) {
1483
+ // empty array = export nothing
1484
+ entityGroupMap = {};
1485
+ }
1486
+ else {
1487
+ entityGroupMap = em._entityGroupMap;
1488
+ }
1489
+ let tempKeys = [];
1490
+ let newGroupMap = {};
1491
+ core.objectForEach(entityGroupMap, (entityTypeName, entityGroup) => {
1492
+ newGroupMap[entityTypeName] = exportEntityGroup(entityGroup, tempKeys);
1493
+ });
1494
+ return { entityGroupMap: newGroupMap, tempKeys: tempKeys };
1495
+ }
1496
+ function exportEntityGroup(entityGroup, tempKeys) {
1497
+ let resultGroup = {};
1498
+ let entityType = entityGroup.entityType;
1499
+ let dps = entityType.dataProperties;
1500
+ let serializerFn = getSerializerFn(entityType);
1501
+ let rawEntities = [];
1502
+ entityGroup._entities.forEach((entity) => {
1503
+ if (entity) {
1504
+ let rawEntity = structuralObjectToJson(entity, dps, serializerFn, tempKeys);
1505
+ rawEntities.push(rawEntity);
1506
+ }
1507
+ });
1508
+ resultGroup.entities = rawEntities;
1509
+ return resultGroup;
1510
+ }
1511
+ function structuralObjectToJson(so, dps, serializerFn, tempKeys) {
1512
+ let result = {};
1513
+ dps.forEach(function (dp) {
1514
+ let dpName = dp.name;
1515
+ let value = so.getProperty(dpName);
1516
+ if (value == null && dp.defaultValue == null)
1517
+ return;
1518
+ if (value && dp.isComplexProperty) {
1519
+ let coDps = dp.dataType.dataProperties;
1520
+ value = core.map(value, function (v) {
1521
+ return structuralObjectToJson(v, coDps, serializerFn);
1522
+ });
1523
+ }
1524
+ else {
1525
+ value = serializerFn ? serializerFn(dp, value) : value;
1526
+ if (dp.isUnmapped) {
1527
+ value = core.toJSONSafe(value, core.toJSONSafeReplacer);
1528
+ }
1529
+ }
1530
+ if (value === undefined)
1531
+ return;
1532
+ result[dpName] = value;
1533
+ });
1534
+ // if (so.entityAspect) {
1535
+ if (EntityAspect.isEntity(so)) {
1536
+ let aspect = so.entityAspect;
1537
+ let entityState = aspect.entityState;
1538
+ let newAspect = {
1539
+ tempNavPropNames: exportTempKeyInfo(aspect, tempKeys || []),
1540
+ entityState: entityState.name
1541
+ };
1542
+ if (aspect.extraMetadata) {
1543
+ newAspect.extraMetadata = aspect.extraMetadata;
1544
+ }
1545
+ if (entityState.isModified() || entityState.isDeleted()) {
1546
+ newAspect.originalValuesMap = aspect.originalValues;
1547
+ }
1548
+ result.entityAspect = newAspect;
1549
+ }
1550
+ else {
1551
+ let aspect = so.complexAspect;
1552
+ let newAspect = {};
1553
+ if (aspect.originalValues && !core.isEmpty(aspect.originalValues)) {
1554
+ newAspect.originalValuesMap = aspect.originalValues;
1555
+ }
1556
+ result.complexAspect = newAspect;
1557
+ }
1558
+ return result;
1559
+ }
1560
+ function exportTempKeyInfo(entityAspect, tempKeys) {
1561
+ let entity = entityAspect.entity;
1562
+ if (entityAspect.hasTempKey) {
1563
+ tempKeys.push(entityAspect.getKey().toJSON());
1564
+ }
1565
+ // create map for this entity with foreignKeys that are 'temporary'
1566
+ // map -> key: tempKey, value: fkPropName
1567
+ let tempNavPropNames = [];
1568
+ entity.entityType.navigationProperties.forEach(function (np) {
1569
+ if (np.relatedDataProperties) {
1570
+ let relatedValue = entity.getProperty(np.name);
1571
+ if (relatedValue && relatedValue.entityAspect.hasTempKey) {
1572
+ tempNavPropNames.push(np.name);
1573
+ }
1574
+ }
1575
+ });
1576
+ return tempNavPropNames;
1577
+ }
1578
+ function importEntityGroup(entityGroup, jsonGroup, importConfig) {
1579
+ let tempKeyMap = importConfig.tempKeyMap;
1580
+ let mergeAdds = !!importConfig.mergeAdds;
1581
+ let entityType = entityGroup.entityType;
1582
+ let mergeStrategy = importConfig.mergeStrategy;
1583
+ let targetEntity;
1584
+ let em = entityGroup.entityManager;
1585
+ let entityChanged = em.entityChanged;
1586
+ let entitiesToLink = [];
1587
+ let rawValueFn = DataProperty.getRawValueFromClient;
1588
+ jsonGroup.entities.forEach(function (rawEntity) {
1589
+ let newAspect = rawEntity.entityAspect;
1590
+ let entityKey = entityType.getEntityKeyFromRawEntity(rawEntity, rawValueFn);
1591
+ let entityState = EntityState.fromName(newAspect.entityState);
1592
+ if (!entityState || entityState === EntityState.Detached) {
1593
+ throw new Error("Only entities with a non detached entity state may be imported.");
1594
+ }
1595
+ // Merge if raw entity is in cache UNLESS this is a new entity w/ a temp key
1596
+ // Cannot safely merge such entities even if could match temp key to an entity in cache.
1597
+ // Can enable merge of entities w/temp key using "mergeAdds" - use at your own risk!
1598
+ let newTempKey = !mergeAdds && entityState.isAdded() && getMappedKey(tempKeyMap, entityKey);
1599
+ targetEntity = newTempKey ? undefined : entityGroup.findEntityByKey(entityKey);
1600
+ if (targetEntity) {
1601
+ if (mergeStrategy === MergeStrategy.SkipMerge) {
1602
+ // deliberate fall thru
1603
+ }
1604
+ else if (mergeStrategy === MergeStrategy.Disallowed) {
1605
+ throw new Error("A MergeStrategy of 'Disallowed' prevents " + entityKey.toString() + " from being merged");
1606
+ }
1607
+ else {
1608
+ let targetEntityState = targetEntity.entityAspect.entityState;
1609
+ let wasUnchanged = targetEntityState.isUnchanged();
1610
+ if (mergeStrategy === MergeStrategy.OverwriteChanges || wasUnchanged) {
1611
+ entityType._updateTargetFromRaw(targetEntity, rawEntity, rawValueFn);
1612
+ targetEntity.entityAspect.setEntityState(entityState);
1613
+ entityChanged.publish({ entityAction: EntityAction.MergeOnImport, entity: targetEntity });
1614
+ }
1615
+ }
1616
+ }
1617
+ else {
1618
+ targetEntity = entityType._createInstanceCore();
1619
+ entityType._updateTargetFromRaw(targetEntity, rawEntity, rawValueFn);
1620
+ if (newTempKey) {
1621
+ targetEntity.entityAspect.hasTempKey = true;
1622
+ // fixup pk
1623
+ targetEntity.setProperty(entityType.keyProperties[0].name, newTempKey.values[0]);
1624
+ // fixup foreign keys
1625
+ // This is safe because the entity is detached here and therefore originalValues will not be updated.
1626
+ if (newAspect.tempNavPropNames) {
1627
+ newAspect.tempNavPropNames.forEach(function (npName) {
1628
+ let np = entityType.getNavigationProperty(npName);
1629
+ let fkPropName = np.relatedDataProperties[0].name;
1630
+ let oldFkValue = targetEntity.getProperty(fkPropName);
1631
+ let fk = new EntityKey(np.entityType, [oldFkValue]);
1632
+ let newFk = getMappedKey(tempKeyMap, fk);
1633
+ targetEntity.setProperty(fkPropName, newFk.values[0]);
1634
+ });
1635
+ }
1636
+ }
1637
+ // Now performed in attachEntity
1638
+ targetEntity = entityGroup.attachEntity(targetEntity, entityState);
1639
+ entityChanged.publish({ entityAction: EntityAction.AttachOnImport, entity: targetEntity });
1640
+ if (!entityState.isUnchanged()) {
1641
+ em._notifyStateChange(targetEntity, true);
1642
+ }
1643
+ }
1644
+ entitiesToLink.push(targetEntity);
1645
+ });
1646
+ return entitiesToLink;
1647
+ }
1648
+ function getMappedKey(tempKeyMap, entityKey) {
1649
+ let newKey = tempKeyMap[entityKey.toString()];
1650
+ if (newKey)
1651
+ return newKey;
1652
+ let subtypes = entityKey._subtypes;
1653
+ if (!subtypes)
1654
+ return null;
1655
+ for (let i = 0, j = subtypes.length; i < j; i++) {
1656
+ newKey = tempKeyMap[entityKey.toString(subtypes[i])];
1657
+ if (newKey)
1658
+ return newKey;
1659
+ }
1660
+ return null;
1661
+ }
1662
+ function promiseWithCallbacks(promise, callback, errorCallback) {
1663
+ promise = promise.then(function (data) {
1664
+ if (callback)
1665
+ callback(data);
1666
+ return Promise.resolve(data);
1667
+ }, function (error) {
1668
+ if (errorCallback)
1669
+ errorCallback(error);
1670
+ return Promise.reject(error);
1671
+ });
1672
+ return promise;
1673
+ }
1674
+ function getEntitiesToSave(em, entities) {
1675
+ let entitiesToSave;
1676
+ if (entities) {
1677
+ entitiesToSave = entities.filter(function (e) {
1678
+ if (e.entityAspect.entityManager !== em) {
1679
+ throw new Error("Only entities in this entityManager may be saved");
1680
+ }
1681
+ return !e.entityAspect.entityState.isDetached();
1682
+ });
1683
+ }
1684
+ else {
1685
+ entitiesToSave = em.getChanges();
1686
+ }
1687
+ return entitiesToSave;
1688
+ }
1689
+ function fixupKeys(em, keyMappings) {
1690
+ em._inKeyFixup = true;
1691
+ keyMappings.forEach(function (km) {
1692
+ let group = em._entityGroupMap[km.entityTypeName];
1693
+ if (!group) {
1694
+ throw new Error("Unable to locate the following fully qualified EntityType name: " + km.entityTypeName);
1695
+ }
1696
+ group._fixupKey(km.tempValue, km.realValue);
1697
+ });
1698
+ em._inKeyFixup = false;
1699
+ }
1700
+ function getEntityGroups(em, entityTypes) {
1701
+ let groupMap = em._entityGroupMap;
1702
+ if (entityTypes) {
1703
+ return core.toArray(entityTypes).map(function (et) {
1704
+ if (et instanceof EntityType) {
1705
+ return groupMap[et.name];
1706
+ }
1707
+ else {
1708
+ throw new Error("The EntityManager.getChanges() 'entityTypes' parameter must be either an entityType or an array of entityTypes or null");
1709
+ }
1710
+ });
1711
+ }
1712
+ else {
1713
+ return core.getOwnPropertyValues(groupMap);
1714
+ }
1715
+ }
1716
+ function checkEntityKey(em, entity) {
1717
+ let ek = entity.entityAspect.getKey();
1718
+ // return properties that are = to defaultValues
1719
+ let keyPropsWithDefaultValues = core.arrayZip(entity.entityType.keyProperties, ek.values, function (kp, kv) {
1720
+ return (kp.defaultValue === kv) ? kp : null;
1721
+ }).filter(function (kp) {
1722
+ return kp !== null;
1723
+ });
1724
+ if (keyPropsWithDefaultValues.length) {
1725
+ if (entity.entityType.autoGeneratedKeyType !== AutoGeneratedKeyType.None) {
1726
+ em.generateTempKeyValue(entity);
1727
+ }
1728
+ else {
1729
+ // we will allow attaches of entities where only part of the key is set.
1730
+ if (keyPropsWithDefaultValues.length === ek.values.length) {
1731
+ throw new Error("Cannot attach an object of type (" + entity.entityType.name + ") to an EntityManager without first setting its key or setting its entityType 'AutoGeneratedKeyType' property to something other than 'None'");
1732
+ }
1733
+ }
1734
+ }
1735
+ }
1736
+ function validateEntityStates(em, entityStates) {
1737
+ if (!entityStates)
1738
+ return [];
1739
+ let entStates = core.toArray(entityStates);
1740
+ entStates.forEach((es) => {
1741
+ if (!(es instanceof EntityState)) {
1742
+ throw new Error("The EntityManager.getChanges() 'entityStates' parameter must either be null, an entityState or an array of entityStates");
1743
+ }
1744
+ });
1745
+ return entStates;
1746
+ }
1747
+ function attachRelatedEntities(em, entity, entityState, mergeStrategy) {
1748
+ let navProps = entity.entityType.navigationProperties;
1749
+ navProps.forEach(function (np) {
1750
+ let related = entity.getProperty(np.name);
1751
+ if (np.isScalar) {
1752
+ if (!related)
1753
+ return;
1754
+ em.attachEntity(related, entityState, mergeStrategy);
1755
+ }
1756
+ else {
1757
+ related.forEach(function (e) {
1758
+ em.attachEntity(e, entityState, mergeStrategy);
1759
+ });
1760
+ }
1761
+ });
1762
+ }
1763
+ // returns a promise
1764
+ function executeQueryCore(em, query, queryOptions, dataService) {
1765
+ try {
1766
+ let results;
1767
+ let metadataStore = em.metadataStore;
1768
+ if (metadataStore.isEmpty() && dataService.hasServerMetadata) {
1769
+ throw new Error("cannot execute _executeQueryCore until metadataStore is populated.");
1770
+ }
1771
+ if (queryOptions.fetchStrategy === FetchStrategy.FromLocalCache) {
1772
+ try {
1773
+ if (typeof query === 'string') {
1774
+ throw new Error("cannot execute 'string' EntityQuery locally.");
1775
+ }
1776
+ let qr = executeQueryLocallyCore(em, query);
1777
+ return Promise.resolve({ results: qr.results, entityManager: em, inlineCount: qr.inlineCount, query: query });
1778
+ }
1779
+ catch (e) {
1780
+ return Promise.reject(e);
1781
+ }
1782
+ }
1783
+ let mappingContext = new MappingContext({
1784
+ query: query,
1785
+ entityManager: em,
1786
+ dataService: dataService,
1787
+ mergeOptions: {
1788
+ mergeStrategy: queryOptions.mergeStrategy,
1789
+ noTracking: !!query.noTrackingEnabled,
1790
+ includeDeleted: queryOptions.includeDeleted
1791
+ }
1792
+ });
1793
+ let validateOnQuery = em.validationOptions.validateOnQuery;
1794
+ return dataService.adapterInstance.executeQuery(mappingContext).then(function (data) {
1795
+ let result = core.wrapExecution(function () {
1796
+ let state = { isLoading: em.isLoading };
1797
+ em.isLoading = true;
1798
+ em._pendingPubs = [];
1799
+ return state;
1800
+ }, function (state) {
1801
+ // cleanup
1802
+ em.isLoading = state.isLoading;
1803
+ em._pendingPubs.forEach(function (fn) {
1804
+ fn();
1805
+ });
1806
+ em._pendingPubs = undefined;
1807
+ em._hasChangesAction && em._hasChangesAction();
1808
+ // TODO: removed - not sure why needed in first place...
1809
+ // // HACK for GC
1810
+ // query = undefined;
1811
+ mappingContext = undefined;
1812
+ // HACK: some errors thrown in next function do not propogate properly - this catches them.
1813
+ if (state.error) {
1814
+ return Promise.reject(state.error);
1815
+ }
1816
+ }, function () {
1817
+ let nodes = dataService.jsonResultsAdapter.extractResults(data);
1818
+ nodes = core.toArray(nodes);
1819
+ results = mappingContext.visitAndMerge(nodes, { nodeType: "root" });
1820
+ if (validateOnQuery) {
1821
+ results.forEach(function (r) {
1822
+ // anon types and simple types will not have an entityAspect.
1823
+ r.entityAspect && r.entityAspect.validateEntity();
1824
+ });
1825
+ }
1826
+ mappingContext.processDeferred();
1827
+ // if query has expand clauses walk each of the 'results' and mark the expanded props as loaded.
1828
+ if (query instanceof EntityQuery) {
1829
+ markLoadedNavProps(results, query);
1830
+ }
1831
+ let retrievedEntities = core.objectMap(mappingContext.refMap);
1832
+ return { results: results, query: query, entityManager: em, httpResponse: data.httpResponse, inlineCount: data.inlineCount, retrievedEntities: retrievedEntities };
1833
+ });
1834
+ return Promise.resolve(result);
1835
+ }, function (e) {
1836
+ if (e) {
1837
+ e.query = query;
1838
+ e.entityManager = em;
1839
+ }
1840
+ return Promise.reject(e);
1841
+ });
1842
+ }
1843
+ catch (e) {
1844
+ if (e) {
1845
+ e.query = query;
1846
+ }
1847
+ return Promise.reject(e);
1848
+ }
1849
+ }
1850
+ function markLoadedNavProps(entities, query) {
1851
+ if (query.noTrackingEnabled)
1852
+ return;
1853
+ let expandClause = query.expandClause;
1854
+ if (expandClause == null)
1855
+ return;
1856
+ expandClause.propertyPaths.forEach(function (propertyPath) {
1857
+ let propNames = propertyPath.split('.');
1858
+ markLoadedNavPath(entities, propNames);
1859
+ });
1860
+ }
1861
+ function markLoadedNavPath(entities, propNames) {
1862
+ let propName = propNames[0];
1863
+ entities.forEach((entity) => {
1864
+ let ea = entity.entityAspect;
1865
+ if (!ea)
1866
+ return; // entity may not be a 'real' entity in the case of a projection.
1867
+ ea._markAsLoaded(propName);
1868
+ if (propNames.length === 1)
1869
+ return;
1870
+ let next = entity.getProperty(propName);
1871
+ if (!next)
1872
+ return; // no children to process.
1873
+ // strange logic because nonscalar nav values are NOT really arrays
1874
+ // otherwise we could use Array.isArray
1875
+ if (!next.arrayChanged)
1876
+ next = [next];
1877
+ markLoadedNavPath(next, propNames.slice(1));
1878
+ });
1879
+ }
1880
+ function updateConcurrencyProperties(entities) {
1881
+ let candidates = entities.filter((e) => {
1882
+ e.entityAspect.isBeingSaved = true;
1883
+ return e.entityAspect.entityState.isModified()
1884
+ && e.entityType.concurrencyProperties.length > 0;
1885
+ });
1886
+ if (candidates.length === 0)
1887
+ return;
1888
+ candidates.forEach(function (c) {
1889
+ c.entityType.concurrencyProperties.forEach(function (cp) {
1890
+ updateConcurrencyProperty(c, cp);
1891
+ });
1892
+ });
1893
+ }
1894
+ function updateConcurrencyProperty(entity, property) {
1895
+ // check if property has already been updated
1896
+ if (entity.entityAspect.originalValues[property.name])
1897
+ return;
1898
+ let value = entity.getProperty(property.name);
1899
+ let dataType = property.dataType;
1900
+ if (!value)
1901
+ value = dataType.defaultValue;
1902
+ if (dataType.isNumeric) {
1903
+ entity.setProperty(property.name, value + 1);
1904
+ }
1905
+ else if (dataType.getConcurrencyValue) {
1906
+ // DataType has its own implementation
1907
+ let nextValue = dataType.getConcurrencyValue(value);
1908
+ entity.setProperty(property.name, nextValue);
1909
+ }
1910
+ else if (dataType === DataType.Binary) {
1911
+ // best guess - that this is a timestamp column and is computed on the server during save
1912
+ // - so no need to set it here.
1913
+ return;
1914
+ }
1915
+ else {
1916
+ // this just leaves DataTypes of Boolean, String and Byte - none of which should be the
1917
+ // type for a concurrency column.
1918
+ // NOTE: thought about just returning here but would rather be safe for now.
1919
+ throw new Error("Unable to update the value of concurrency property before saving: " + property.name);
1920
+ }
1921
+ }
1922
+ function findOrCreateEntityGroup(em, entityType) {
1923
+ let group = em._entityGroupMap[entityType.name];
1924
+ if (!group) {
1925
+ group = new EntityGroup(em, entityType);
1926
+ em._entityGroupMap[entityType.name] = group;
1927
+ }
1928
+ return group;
1929
+ }
1930
+ function findOrCreateEntityGroups(em, entityType) {
1931
+ let entityTypes = entityType.getSelfAndSubtypes();
1932
+ return entityTypes.map((et) => {
1933
+ return findOrCreateEntityGroup(em, et);
1934
+ });
1935
+ }
1936
+ function unwrapInstance(structObj, transformFn) {
1937
+ let rawObject = {};
1938
+ let stype = EntityAspect.isEntity(structObj) ? structObj.entityType : structObj.complexType;
1939
+ let serializerFn = getSerializerFn(stype);
1940
+ let unmapped = {};
1941
+ stype.dataProperties.forEach(function (dp) {
1942
+ if (dp.isComplexProperty) {
1943
+ rawObject[dp.nameOnServer] = core.map(structObj.getProperty(dp.name), function (co) {
1944
+ return unwrapInstance(co, transformFn);
1945
+ });
1946
+ }
1947
+ else {
1948
+ let val = structObj.getProperty(dp.name);
1949
+ val = transformFn ? transformFn(dp, val) : val;
1950
+ if (val === undefined)
1951
+ return;
1952
+ val = serializerFn ? serializerFn(dp, val) : val;
1953
+ if (val !== undefined) {
1954
+ if (dp.isUnmapped) {
1955
+ unmapped[dp.nameOnServer] = core.toJSONSafe(val, core.toJSONSafeReplacer);
1956
+ }
1957
+ else {
1958
+ rawObject[dp.nameOnServer] = val;
1959
+ }
1960
+ }
1961
+ }
1962
+ });
1963
+ if (!core.isEmpty(unmapped)) {
1964
+ // TODO: review this.
1965
+ rawObject.__unmapped = unmapped;
1966
+ }
1967
+ return rawObject;
1968
+ }
1969
+ function unwrapOriginalValues(target, metadataStore, transformFn) {
1970
+ let stype = EntityAspect.isEntity(target) ? target.entityType : target.complexType;
1971
+ let aspect = EntityAspect.isEntity(target) ? target.entityAspect : target.complexAspect;
1972
+ let fn = metadataStore.namingConvention.clientPropertyNameToServer;
1973
+ let result = {};
1974
+ core.objectForEach(aspect.originalValues, function (propName, val) {
1975
+ let prop = stype.getProperty(propName);
1976
+ val = transformFn ? transformFn(prop, val) : val;
1977
+ if (val !== undefined) {
1978
+ result[fn(propName, prop)] = val;
1979
+ }
1980
+ });
1981
+ stype.complexProperties.forEach(function (cp) {
1982
+ let nextTarget = target.getProperty(cp.name);
1983
+ if (cp.isScalar) {
1984
+ let unwrappedCo = unwrapOriginalValues(nextTarget, metadataStore, transformFn);
1985
+ if (!core.isEmpty(unwrappedCo)) {
1986
+ result[fn(cp.name, cp)] = unwrappedCo;
1987
+ }
1988
+ }
1989
+ else {
1990
+ let unwrappedCos = nextTarget.map((item) => {
1991
+ return unwrapOriginalValues(item, metadataStore, transformFn);
1992
+ });
1993
+ result[fn(cp.name, cp)] = unwrappedCos;
1994
+ }
1995
+ });
1996
+ return result;
1997
+ }
1998
+ function unwrapChangedValues(entity, metadataStore, transformFn) {
1999
+ let stype = entity.entityType;
2000
+ let serializerFn = getSerializerFn(stype);
2001
+ let fn = metadataStore.namingConvention.clientPropertyNameToServer;
2002
+ let result = {};
2003
+ core.objectForEach(entity.entityAspect.originalValues, function (propName, value) {
2004
+ let prop = stype.getProperty(propName);
2005
+ let val = entity.getProperty(propName);
2006
+ val = transformFn ? transformFn(prop, val) : val;
2007
+ if (val === undefined)
2008
+ return;
2009
+ val = serializerFn ? serializerFn(prop, val) : val;
2010
+ if (val !== undefined) {
2011
+ result[fn(propName, prop)] = val;
2012
+ }
2013
+ });
2014
+ // any change to any complex object or array of complex objects returns the ENTIRE
2015
+ // current complex object or complex object array. This is by design. Complex Objects
2016
+ // are atomic.
2017
+ stype.complexProperties.forEach((cp) => {
2018
+ if (cpHasOriginalValues(entity, cp)) {
2019
+ let coOrCos = entity.getProperty(cp.name);
2020
+ result[fn(cp.name, cp)] = core.map(coOrCos, function (co) {
2021
+ return unwrapInstance(co, transformFn);
2022
+ });
2023
+ }
2024
+ });
2025
+ return result;
2026
+ }
2027
+ function cpHasOriginalValues(structuralObject, cp) {
2028
+ let coOrCos = structuralObject.getProperty(cp.name);
2029
+ if (cp.isScalar) {
2030
+ return coHasOriginalValues(coOrCos);
2031
+ }
2032
+ else {
2033
+ // this occurs when a nonscalar co array has had cos added or removed.
2034
+ if (coOrCos._origValues)
2035
+ return true;
2036
+ return coOrCos.some(function (co) {
2037
+ return coHasOriginalValues(co);
2038
+ });
2039
+ }
2040
+ }
2041
+ function executeQueryLocallyCore(em, query) {
2042
+ assertParam(query, "query").isInstanceOf(EntityQuery).check();
2043
+ let metadataStore = em.metadataStore;
2044
+ let entityType = query._getFromEntityType(metadataStore, true);
2045
+ // there may be multiple groups is this is a base entity type.
2046
+ let groups = findOrCreateEntityGroups(em, entityType);
2047
+ // filter then order then skip then take
2048
+ let filterFunc = query.wherePredicate && query.wherePredicate.toFunction({ entityType: entityType });
2049
+ let queryOptions = QueryOptions.resolve([query.queryOptions, em.queryOptions, QueryOptions.defaultInstance]);
2050
+ let includeDeleted = queryOptions.includeDeleted === true;
2051
+ let newFilterFunc = function (entity) {
2052
+ return entity && (includeDeleted || !entity.entityAspect.entityState.isDeleted()) && (filterFunc ? filterFunc(entity) : true);
2053
+ };
2054
+ let result = [];
2055
+ // TODO: mapMany
2056
+ groups.forEach((group) => {
2057
+ let entities = group._entities.filter(newFilterFunc);
2058
+ if (entities.length) {
2059
+ result = result.length ? result.concat(entities) : entities;
2060
+ }
2061
+ });
2062
+ let orderByComparer = query.orderByClause && query.orderByClause.getComparer(entityType);
2063
+ if (orderByComparer) {
2064
+ result.sort(orderByComparer);
2065
+ }
2066
+ let inlineCount = query.inlineCountEnabled ? result.length : undefined;
2067
+ let skipCount = query.skipCount;
2068
+ if (skipCount) {
2069
+ result = result.slice(skipCount);
2070
+ }
2071
+ let takeCount = query.takeCount;
2072
+ if (takeCount) {
2073
+ result = result.slice(0, takeCount);
2074
+ }
2075
+ let selectClause = query.selectClause;
2076
+ if (selectClause) {
2077
+ let selectFn = selectClause.toFunction();
2078
+ result = result.map(selectFn);
2079
+ }
2080
+ return { results: result, inlineCount: inlineCount };
2081
+ }
2082
+ function coHasOriginalValues(co) {
2083
+ // next line checks all non complex properties of the co.
2084
+ if (!core.isEmpty(co.complexAspect.originalValues))
2085
+ return true;
2086
+ // now need to recursively check each of the cps
2087
+ return co.complexType.complexProperties.some(function (cp) {
2088
+ return cpHasOriginalValues(co, cp);
2089
+ });
2090
+ }
2091
+ function getSerializerFn(stype) {
2092
+ return stype.serializerFn || (stype.metadataStore && stype.metadataStore.serializerFn);
2093
+ }
2094
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZW50aXR5LW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLElBQUksRUFBMkIsTUFBTSxRQUFRLENBQUM7QUFDdkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDdEMsT0FBTyxFQUFFLFlBQVksRUFBcUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNsSCxPQUFPLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBZSxZQUFZLEVBQXNCLG9CQUFvQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkksT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsWUFBWSxFQUFHLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDN0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDN0UsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JB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TSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUN2RCxDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxFQUFpQjtJQUM1Qyx5REFBeUQ7SUFDekQsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNoRSxnREFBZ0Q7SUFDaEQsT0FBTyxFQUFFLENBQUMsV0FBVyxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7UUFDdkQsT0FBTyxtQkFBbUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckMsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsS0FBK0I7SUFDdEQsT0FBTyxLQUFLLENBQUMsWUFBWSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsSUFBSSxLQUFLLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3pGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEYXRhU2VydmljZUFkYXB0ZXIgfSBmcm9tICcuL2ludGVyZmFjZS1yZWdpc3RyeSc7XHJcbmltcG9ydCB7IGNvcmUsIENhbGxiYWNrLCBFcnJvckNhbGxiYWNrIH0gZnJvbSAnLi9jb3JlJztcclxuaW1wb3J0IHsgYXNzZXJ0UGFyYW0sIGFzc2VydENvbmZpZyB9IGZyb20gJy4vYXNzZXJ0LXBhcmFtJztcclxuaW1wb3J0IHsgY29uZmlnIH0gZnJvbSAnLi9jb25maWcnO1xyXG5pbXBvcnQgeyBCcmVlemVFdmVudCB9IGZyb20gJy4vZXZlbnQnO1xyXG5pbXBvcnQgeyBFbnRpdHlBc3BlY3QsIEVudGl0eSwgQ29tcGxleE9iamVjdCwgU3RydWN0dXJhbE9iamVjdCwgUHJvcGVydHlDaGFuZ2VkRXZlbnRBcmdzIH0gZnJvbSAnLi9lbnRpdHktYXNwZWN0JztcclxuaW1wb3J0IHsgTWV0YWRhdGFTdG9yZSwgRW50aXR5VHlwZSwgQ29tcGxleFR5cGUsIERhdGFQcm9wZXJ0eSwgTmF2aWdhdGlvblByb3BlcnR5LCBBdXRvR2VuZXJhdGVkS2V5VHlwZSB9IGZyb20gJy4vZW50aXR5LW1ldGFkYXRhJztcclxuaW1wb3J0IHsgRW50aXR5S2V5IH0gZnJvbSAnLi9lbnRpdHkta2V5JztcclxuaW1wb3J0IHsgRW50aXR5QWN0aW9uICB9IGZyb20gJy4vZW50aXR5LWFjdGlvbic7XHJcbmltcG9ydCB7IEVudGl0eVN0YXRlIH0gZnJvbSAnLi9lbnRpdHktc3RhdGUnO1xyXG5pbXBvcnQgeyBEYXRhU2VydmljZSB9IGZyb20gJy4vZGF0YS1zZXJ2aWNlJztcclxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuL2RhdGEtdHlwZSc7XHJcbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4vdmFsaWRhdGUnO1xyXG5pbXBvcnQgeyBWYWxpZGF0aW9uT3B0aW9ucyB9IGZyb20gJy4vdmFsaWRhdGlvbi1vcHRpb25zJztcclxuaW1wb3J0IHsgUXVlcnlPcHRpb25zLCBNZXJnZVN0cmF0ZWd5LCBGZXRjaFN0cmF0ZWd5IH0gZnJvbSAnLi9xdWVyeS1vcHRpb25zJztcclxuaW1wb3J0IHsgU2F2ZU9wdGlvbnMgfSBmcm9tICcuL3NhdmUtb3B0aW9ucyc7XHJcbmltcG9ydCB7IEtleUdlbmVyYXRvciB9IGZyb20gJy4va2V5LWdlbmVyYXRvcic7XHJcbmltcG9ydCB7IEVudGl0eUdyb3VwIH0gZnJvbSAnLi9lbnRpdHktZ3JvdXAnO1xyXG5pbXBvcnQgeyBNYXBwaW5nQ29udGV4dCB9IGZyb20gJy4vbWFwcGluZy1jb250ZXh0JztcclxuaW1wb3J0IHsgRW50aXR5UXVlcnkgfSBmcm9tICcuL2VudGl0eS1xdWVyeSc7XHJcbmltcG9ydCB7IFVuYXR0YWNoZWRDaGlsZHJlbk1hcCB9IGZyb20gJy4vdW5hdHRhY2hlZC1jaGlsZHJlbi1tYXAnO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBIdHRwUmVzcG9uc2Uge1xyXG4gIGNvbmZpZzogYW55O1xyXG4gIGRhdGE6IGFueTtcclxuICBlcnJvcj86IGFueTtcclxuICBzYXZlQ29udGV4dD86IGFueTtcclxuICBzdGF0dXM6IG51bWJlcjtcclxuICBnZXRIZWFkZXJzKGhlYWRlck5hbWU6IHN0cmluZyk6IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBJbXBvcnRSZXN1bHQge1xyXG4gIGVudGl0aWVzOiBFbnRpdHlbXTtcclxuICB0ZW1wS2V5TWFwcGluZzogSVRlbXBLZXlNYXA7XHJcbn1cclxuXHJcbi8vIHN1YmNsYXNzZXMgb2YgRXJyb3JcclxuXHJcbi8qKiBCYXNlIHNoYXBlIG9mIGFueSBlcnJvcnMgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZlckVycm9yIGV4dGVuZHMgRXJyb3Ige1xyXG4gIGh0dHBSZXNwb25zZTogSHR0cFJlc3BvbnNlO1xyXG4gIHN0YXR1czogbnVtYmVyO1xyXG4gIG1lc3NhZ2U6IHN0cmluZztcclxuICBzdGF0dXNUZXh0Pzogc3RyaW5nO1xyXG4gIGJvZHk/OiBhbnk7XHJcbiAgdXJsPzogc3RyaW5nO1xyXG59XHJcblxyXG4vKiogU2hhcGUgb2YgYSBzYXZlIGVycm9yIHJldHVybmVkIGZyb20gdGhlIHNlcnZlci4gXHJcbkZvciB1c2UgYnkgYnJlZXplIHBsdWdpbiBhdXRob3JzIG9ubHkuIFRoZSBjbGFzcyBpcyBmb3IgdXNlIGluIGJ1aWxkaW5nIGEgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0gaW1wbGVtZW50YXRpb24uIFxyXG5AYWRhcHRlciAoc2VlIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBAaW50ZXJuYWwgXHJcbiovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZUVycm9yRnJvbVNlcnZlciBleHRlbmRzIFNlcnZlckVycm9yIHtcclxuICBlbnRpdHlFcnJvcnM6IEVudGl0eUVycm9yRnJvbVNlcnZlcltdO1xyXG59XHJcblxyXG4vKiogU2hhcGUgb2YgYSBzYXZlIGVycm9yIHdoZW4gcmV0dXJuZWQgdG8gdGhlIGNsaWVudC4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBTYXZlRXJyb3IgZXh0ZW5kcyBTZXJ2ZXJFcnJvciB7XHJcbiAgZW50aXR5RXJyb3JzOiBFbnRpdHlFcnJvcltdO1xyXG59XHJcblxyXG4vLyBub3Qgc3ViY2xhc3NlcyBvZiBFcnJvclxyXG4vKiogXHJcbkZvciB1c2UgYnkgYnJlZXplIHBsdWdpbiBhdXRob3JzIG9ubHkuIFRoZSBjbGFzcyBpcyBmb3IgdXNlIGluIGJ1aWxkaW5nIGEgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0gaW1wbGVtZW50YXRpb24uIFxyXG5AYWRhcHRlciAoc2VlIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBAaW50ZXJuYWwgXHJcbiovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5RXJyb3JGcm9tU2VydmVyIHtcclxuICBlbnRpdHlUeXBlTmFtZTogc3RyaW5nO1xyXG4gIGtleVZhbHVlczogYW55W107XHJcblxyXG4gIGVycm9yTmFtZTogc3RyaW5nO1xyXG4gIGVycm9yTWVzc2FnZTogc3RyaW5nO1xyXG4gIHByb3BlcnR5TmFtZTogc3RyaW5nO1xyXG4gIGN1c3RvbT86IGFueTtcclxufVxyXG5cclxuLyoqIFNoYXBlIG9mIGFuIGVycm9yIG9uIGEgc3BlY2lmaWMgZW50aXR5LiAgUGFydCBvZiBhIFtbSVNhdmVFcnJvcl1dICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5RXJyb3Ige1xyXG4gIGVudGl0eTogRW50aXR5O1xyXG4gIGVycm9yTmFtZTogc3RyaW5nO1xyXG4gIGVycm9yTWVzc2FnZTogc3RyaW5nO1xyXG4gIHByb3BlcnR5TmFtZTogc3RyaW5nO1xyXG4gIGlzU2VydmVyRXJyb3I6IGJvb2xlYW47XHJcbiAgY3VzdG9tPzogYW55O1xyXG59XHJcblxyXG4vKiogVGhlIHNoYXBlIG9mIHRoZSBQcm9taXNlIHJldHVybmVkIGJ5IGFuIFtbRW50aXR5TWFuYWdlci5leGVjdXRlUXVlcnldXSBjYWxsLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXJ5UmVzdWx0IHtcclxuICAvKiogVG9wIGxldmVsIGVudGl0aWVzIHJldHVybmVkICovXHJcbiAgcmVzdWx0czogYW55W107XHJcbiAgLyoqIFF1ZXJ5IHRoYXQgd2FzIGV4ZWN1dGVkICovXHJcbiAgcXVlcnk6IEVudGl0eVF1ZXJ5IHwgc3RyaW5nO1xyXG4gIC8qKiBFbnRpdHlNYW5hZ2VyIHRoYXQgZXhlY3V0ZWQgdGhlIHF1ZXJ5ICovXHJcbiAgZW50aXR5TWFuYWdlcj86IEVudGl0eU1hbmFnZXI7XHJcbiAgLyoqIFRvdGFsIG51bWJlciBvZiByZXN1bHRzIGF2YWlsYWJsZSBvbiB0aGUgc2VydmVyICovXHJcbiAgaW5saW5lQ291bnQ/OiBudW1iZXI7XHJcbiAgLyoqIEFsbCBlbnRpdGllcyByZXR1cm5lZCBieSB0aGUgcXVlcnkuICBEaWZmZXJzIGZyb20gcmVzdWx0cyB3aGVuIGFuIGV4cGFuZCBpcyB1c2VkLiAqL1xyXG4gIHJldHJpZXZlZEVudGl0aWVzPzogRW50aXR5W107XHJcbiAgICAvKiogUmF3IHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlciAqL1xyXG4gIGh0dHBSZXNwb25zZT86IEh0dHBSZXNwb25zZTtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBRdWVyeVN1Y2Nlc3NDYWxsYmFjayB7XHJcbiAgKGRhdGE6IFF1ZXJ5UmVzdWx0KTogdm9pZDtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBRdWVyeUVycm9yQ2FsbGJhY2sge1xyXG4gIChlcnJvcjogeyBxdWVyeTogRW50aXR5UXVlcnk7IGh0dHBSZXNwb25zZTogSHR0cFJlc3BvbnNlOyBlbnRpdHlNYW5hZ2VyOiBFbnRpdHlNYW5hZ2VyOyBtZXNzYWdlPzogc3RyaW5nOyBzdGFjaz86IHN0cmluZyB9KTogdm9pZDtcclxufVxyXG5cclxuLyoqIEtleSBtYXBwaW5nIGluZm9ybWF0aW9uIHJldHVybmVkIGFzIHBhcnQgb2YgYW4gW1tJU2F2ZVJlc3VsdF1dLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEtleU1hcHBpbmcge1xyXG4gIGVudGl0eVR5cGVOYW1lOiBzdHJpbmc7XHJcbiAgdGVtcFZhbHVlOiBhbnk7XHJcbiAgcmVhbFZhbHVlOiBhbnk7XHJcbn1cclxuXHJcbmludGVyZmFjZSBJVGVtcEtleU1hcCB7XHJcbiAgW2luZGV4OiBzdHJpbmddOiBFbnRpdHlLZXk7XHJcbn1cclxuXHJcbi8qKiBDb25maWd1cmF0aW9uIGluZm8gdG8gYmUgcGFzc2VkIHRvIHRoZSBbW0VudGl0eU1hbmFnZXIuaW1wb3J0RW50aXRpZXNdXSBtZXRob2QgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJbXBvcnRDb25maWcge1xyXG4gIC8qKiBJZiB0cnVlLCBtZXJnZSBBZGRlZCBlbnRpdGllcyAod2l0aCB0ZW1wIGtleXMpIGFzIHdlbGwuICBUaGlzIGNhbiBiZSBkYW5nZXJvdXMuICovXHJcbiAgbWVyZ2VBZGRzPzogYm9vbGVhbjtcclxuICBtZXJnZVN0cmF0ZWd5PzogTWVyZ2VTdHJhdGVneTsgIFxyXG4gIG1ldGFkYXRhVmVyc2lvbkZuPzogKGFyZzogeyBtZXRhZGF0YVZlcnNpb246IGFueSwgbWV0YWRhdGFTdG9yZU5hbWU6IGFueSB9KSA9PiB2b2lkO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSW1wb3J0Q29uZmlnRXh0IGV4dGVuZHMgSW1wb3J0Q29uZmlnIHtcclxuICB0ZW1wS2V5TWFwPzogSVRlbXBLZXlNYXA7XHJcbn1cclxuXHJcbi8qKiBUaGUgc2hhcGUgb2YgdGhlIFByb21pc2UgcmV0dXJuZWQgYnkgYW4gW1tFbnRpdHlNYW5hZ2VyLnNhdmVDaGFuZ2VzXV0gY2FsbC4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBTYXZlUmVzdWx0IHtcclxuICBlbnRpdGllczogRW50aXR5W107XHJcbiAga2V5TWFwcGluZ3M6IEtleU1hcHBpbmdbXTtcclxuICBkZWxldGVkS2V5cz86IHsgZW50aXR5VHlwZU5hbWU6IHN0cmluZywga2V5VmFsdWVzOiBhbnlbXX1bXTtcclxuICBodHRwUmVzcG9uc2U/OiBIdHRwUmVzcG9uc2U7XHJcbn1cclxuXHJcbi8qKiBGb3IgdXNlIGJ5IGJyZWV6ZSBwbHVnaW4gYXV0aG9ycyBvbmx5LiBUaGUgY2xhc3MgaXMgZm9yIHVzZSBpbiBidWlsZGluZyBhIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dIGltcGxlbWVudGF0aW9uLiBcclxuQGFkYXB0ZXIgKHNlZSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSkgICAgXHJcbkBoaWRkZW4gXHJcbiovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZUNvbnRleHQge1xyXG4gIGVudGl0eU1hbmFnZXI6IEVudGl0eU1hbmFnZXI7XHJcbiAgZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlO1xyXG4gIHByb2Nlc3NTYXZlZEVudGl0aWVzOiAoc2F2ZVJlc3VsdDogU2F2ZVJlc3VsdCkgPT4gRW50aXR5W107XHJcbiAgcmVzb3VyY2VOYW1lOiBzdHJpbmc7XHJcbiAgYWRhcHRlcj86IERhdGFTZXJ2aWNlQWRhcHRlcjtcclxuICByb3V0ZVByZWZpeD86IHN0cmluZztcclxufVxyXG5cclxuLyoqIEZvciB1c2UgYnkgYnJlZXplIHBsdWdpbiBhdXRob3JzIG9ubHkuIFRoZSBjbGFzcyBpcyBmb3IgdXNlIGluIGJ1aWxkaW5nIGEgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0gaW1wbGVtZW50YXRpb24uIFxyXG5AYWRhcHRlciAoc2VlIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBcclxuKi9cclxuZXhwb3J0IGludGVyZmFjZSBTYXZlQnVuZGxlIHtcclxuICBlbnRpdGllczogRW50aXR5W107XHJcbiAgc2F2ZU9wdGlvbnM6IFNhdmVPcHRpb25zO1xyXG59XHJcblxyXG4vKiogQ29uZmlndXJhdGlvbiBpbmZvIHRvIGJlIHBhc3NlZCB0byB0aGUgW1tFbnRpdHlNYW5hZ2VyXV0gY29uc3RydWN0b3IgKi9cclxuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlNYW5hZ2VyQ29uZmlnIHtcclxuICAvKiogVGhlIHNlcnZpY2UgbmFtZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAgKiovXHJcbiAgc2VydmljZU5hbWU/OiBzdHJpbmc7XHJcbiAgLyoqIFRoZSBEYXRhU2VydmljZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAqKi9cclxuICBkYXRhU2VydmljZT86IERhdGFTZXJ2aWNlO1xyXG4gIC8qKiBUaGUgW1tRdWVyeU9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAgKiovXHJcbiAgcXVlcnlPcHRpb25zPzogUXVlcnlPcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tTYXZlT3B0aW9uc11dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICoqL1xyXG4gIHNhdmVPcHRpb25zPzogU2F2ZU9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW1ZhbGlkYXRpb25PcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gICoqL1xyXG4gIHZhbGlkYXRpb25PcHRpb25zPzogVmFsaWRhdGlvbk9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW0tleUdlbmVyYXRvcl1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICoqL1xyXG4gIGtleUdlbmVyYXRvcj86IEtleUdlbmVyYXRvcjtcclxuICAvKiogVGhlIFtbS2V5R2VuZXJhdG9yXV0gY29uc3RydWN0b3IgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gKiovXHJcbiAga2V5R2VuZXJhdG9yQ3Rvcj86IHsgbmV3ICgpOiBLZXlHZW5lcmF0b3IgfTsgLy8gVE9ETzogcmV2aWV3IHRoaXNcclxuICAvKiogVGhlIFtbTWV0YWRhdGFTdG9yZV1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICoqL1xyXG4gIG1ldGFkYXRhU3RvcmU/OiBNZXRhZGF0YVN0b3JlO1xyXG59XHJcblxyXG4vKiogVGhlIHNoYXBlIHJldHVybmVkIGJ5IGNhbGxiYWNrcyByZWdpc3RlcmVkIHdpdGggW1tFbnRpdHlNYW5hZ2VyLmVudGl0eUNoYW5nZWRdXSBldmVudCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEVudGl0eUNoYW5nZWRFdmVudEFyZ3Mge1xyXG4gIGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uO1xyXG4gIGVudGl0eT86IEVudGl0eTtcclxuICBhcmdzPzogUHJvcGVydHlDaGFuZ2VkRXZlbnRBcmdzO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkRXZlbnRBcmdzIHtcclxuICBlbnRpdHk6IEVudGl0eTsgXHJcbiAgYWRkZWQ6IFZhbGlkYXRpb25FcnJvcltdOyBcclxuICByZW1vdmVkOiBWYWxpZGF0aW9uRXJyb3JbXTtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBIYXNDaGFuZ2VzQ2hhbmdlZEV2ZW50QXJncyB7XHJcbiAgZW50aXR5TWFuYWdlcjogRW50aXR5TWFuYWdlcjsgXHJcbiAgaGFzQ2hhbmdlczogYm9vbGVhbjtcclxufVxyXG5cclxuLyoqXHJcbkluc3RhbmNlcyBvZiB0aGUgRW50aXR5TWFuYWdlciBjb250YWluIGFuZCBtYW5hZ2UgY29sbGVjdGlvbnMgb2YgZW50aXRpZXMsIGVpdGhlciByZXRyaWV2ZWQgZnJvbSBhIGJhY2tlbmQgZGF0YXN0b3JlIG9yIGNyZWF0ZWQgb24gdGhlIGNsaWVudC5cclxuKiovXHJcbmV4cG9ydCBjbGFzcyBFbnRpdHlNYW5hZ2VyIHtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfJHR5cGVOYW1lOiBzdHJpbmc7IC8vIGFjdHVhbGx5IGRlZmluZWQgb24gcHJvdG90eXBlXHJcblxyXG4gIC8qKiBUaGUgc2VydmljZSBuYW1lIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgc2VydmljZU5hbWU6IHN0cmluZztcclxuICAvKiogVGhlIERhdGFTZXJ2aWNlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlO1xyXG4gIC8qKiBUaGUgW1tRdWVyeU9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIHF1ZXJ5T3B0aW9uczogUXVlcnlPcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tTYXZlT3B0aW9uc11dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgc2F2ZU9wdGlvbnM6IFNhdmVPcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tWYWxpZGF0aW9uT3B0aW9uc11dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgdmFsaWRhdGlvbk9wdGlvbnM6IFZhbGlkYXRpb25PcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tLZXlHZW5lcmF0b3JdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGtleUdlbmVyYXRvcjogS2V5R2VuZXJhdG9yO1xyXG4gIC8qKiBUaGUgW1tLZXlHZW5lcmF0b3JdXSBjb25zdHJ1Y3RvciBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGtleUdlbmVyYXRvckN0b3I6IHsgbmV3ICgpOiBLZXlHZW5lcmF0b3IgfTsgLy8gVE9ETzogcmV2aWV3IHRoaXNcclxuICAvKiogVGhlIFtbTWV0YWRhdGFTdG9yZV1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgbWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZTtcclxuICBpc0xvYWRpbmc6IGJvb2xlYW47XHJcbiAgaXNSZWplY3RpbmdDaGFuZ2VzOiBib29sZWFuO1xyXG5cclxuICAvLyBldmVudHNcclxuICAvKipcclxuICBBIFtbQnJlZXplRXZlbnRdXSB0aGF0IGZpcmVzIHdoZW5ldmVyIGEgY2hhbmdlIHRvIGFueSBlbnRpdHkgaW4gdGhpcyBFbnRpdHlNYW5hZ2VyIG9jY3Vycy4gX19SZWFkIE9ubHlfX1xyXG5cclxuICBAZXZlbnRBcmdzIC0gXHJcbiAgLSBlbnRpdHlBY3Rpb24gLSBUaGUgW1tFbnRpdHlBY3Rpb25dXSB0aGF0IG9jY3VyZWQuXHJcbiAgLSBlbnRpdHkgLSBUaGUgZW50aXR5IHRoYXQgY2hhbmdlZC4gIElmIHRoaXMgaXMgbnVsbCwgdGhlbiBhbGwgZW50aXRpZXMgaW4gdGhlIGVudGl0eU1hbmFnZXIgd2VyZSBhZmZlY3RlZC5cclxuICAtIGFyZ3MgLSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IHRoaXMgZXZlbnQuIFRoaXMgd2lsbCBkaWZmZXIgYmFzZWQgb24gdGhlIGVudGl0eUFjdGlvbi5cclxuXHJcbiAgPiAgICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKCB7c2VydmljZU5hbWU6IFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIiB9KTtcclxuICA+ICAgICAgZW0uZW50aXR5Q2hhbmdlZC5zdWJzY3JpYmUoZnVuY3Rpb24oY2hhbmdlQXJncykge1xyXG4gID4gICAgICAgICAgLy8gVGhpcyBjb2RlIHdpbGwgYmUgZXhlY3V0ZWQgYW55IHRpbWUgYW55IGVudGl0eSB3aXRoaW4gdGhlIGVudGl0eU1hbmFnZXIgXHJcbiAgPiAgICAgICAgICAvLyBpcyBhZGRlZCwgbW9kaWZpZWQsIGRlbGV0ZWQgb3IgZGV0YWNoZWQgZm9yIGFueSByZWFzb24uXHJcbiAgPiAgICAgICAgICBsZXQgYWN0aW9uID0gY2hhbmdlQXJncy5lbnRpdHlBY3Rpb247XHJcbiAgPiAgICAgICAgICBsZXQgZW50aXR5ID0gY2hhbmdlQXJncy5lbnRpdHk7XHJcbiAgPiAgICAgICAgICAvLyAuLiBkbyBzb21ldGhpbmcgdG8gdGhpcyBlbnRpdHkgd2hlbiBpdCBpcyBjaGFuZ2VkLlxyXG4gID4gICAgICB9KTtcclxuICA+ICB9KTtcclxuICBAZXZlbnRcclxuICAqKi9cclxuICBlbnRpdHlDaGFuZ2VkOiBCcmVlemVFdmVudDxFbnRpdHlDaGFuZ2VkRXZlbnRBcmdzPjtcclxuXHJcbiAgLyoqXHJcbiAgQW4gW1tCcmVlemVFdmVudF1dIHRoYXQgZmlyZXMgd2hlbmV2ZXIgdmFsaWRhdGlvbkVycm9ycyBjaGFuZ2UgZm9yIGFueSBlbnRpdHkgaW4gdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fXHJcbiAgQGV2ZW50QXJncyAtXHJcbiAgICAtIGVudGl0eSAtIFRoZSBlbnRpdHkgb24gd2hpY2ggdGhlIHZhbGlkYXRpb24gZXJyb3JzIGhhdmUgYmVlbiBhZGRlZCBvciByZW1vdmVkLlxyXG4gICAgLSBhZGRlZCAtIEFuIGFycmF5IGNvbnRhaW5pbmcgYW55IG5ld2x5IGFkZGVkIFtbVmFsaWRhdGlvbkVycm9yXV1zXHJcbiAgICAtIHJlbW92ZWQgLSBBbiBhcnJheSBjb250YWluaW5nIGFueSBuZXdseSByZW1vdmVkIFtbVmFsaWRhdGlvbkVycm9yXV1zLiBUaGlzIGlzIHRob3NlIGVycm9ycyB0aGF0IGhhdmUgYmVlbiAnZml4ZWQnICBcclxuXHJcbiAgPiAgICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKCB7c2VydmljZU5hbWU6IFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIiB9KTtcclxuICA+ICAgICAgZW0udmFsaWRhdGlvbkVycm9yc0NoYW5nZWQuc3Vic2NyaWJlKGZ1bmN0aW9uKGNoYW5nZUFyZ3MpIHtcclxuICA+ICAgICAgICAgICAgICAvLyBUaGlzIGNvZGUgd2lsbCBiZSBleGVjdXRlZCBhbnkgdGltZSBhbnkgZW50aXR5IHdpdGhpbiB0aGUgZW50aXR5TWFuYWdlciBleHBlcmllbmNlcyBhIGNoYW5nZSB0byBpdHMgdmFsaWRhdGlvbkVycm9ycyBjb2xsZWN0aW9uLlxyXG4gID4gICAgICAgICAgICAgIGZ1bmN0aW9uICh2YWxpZGF0aW9uQ2hhbmdlQXJncykge1xyXG4gID4gICAgICAgICAgICAgICAgICBsZXQgZW50aXR5ID09IHZhbGlkYXRpb25DaGFuZ2VBcmdzLmVudGl0eTtcclxuICA+ICAgICAgICAgICAgICAgICAgbGV0IGVycm9yc0FkZGVkID0gdmFsaWRhdGlvbkNoYW5nZUFyZ3MuYWRkZWQ7XHJcbiAgPiAgICAgICAgICAgICAgICAgIGxldCBlcnJvcnNDbGVhcmVkID0gdmFsaWRhdGlvbkNoYW5nZUFyZ3MucmVtb3ZlZDtcclxuICA+ICAgICAgICAgICAgICAgICAgLy8gLi4uIGRvIHNvbWV0aGluZyBpbnRlcmVzdGluZyB3aXRoIHRoZSBvcmRlci5cclxuICA+ICAgICAgICAgICAgICB9KTtcclxuICA+ICAgICAgICAgIH0pO1xyXG4gID4gICAgICB9KTtcclxuICBAZXZlbnRcclxuICAqKi9cclxuICB2YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZDogQnJlZXplRXZlbnQ8VmFsaWRhdGlvbkVycm9yc0NoYW5nZWRFdmVudEFyZ3M+O1xyXG5cclxuICAvKipcclxuICBBIFtbQnJlZXplRXZlbnRdXSB0aGF0IGZpcmVzIHdoZW5ldmVyIGFuIEVudGl0eU1hbmFnZXIgdHJhbnNpdGlvbnMgdG8gb3IgZnJvbSBoYXZpbmcgY2hhbmdlcy4gX19SZWFkIE9ubHlfX1xyXG4gIEBldmVudEFyZ3MgLVxyXG4gICAgLSBlbnRpdHlNYW5hZ2VyIC0gVGhlIEVudGl0eU1hbmFnZXIgd2hvc2UgJ2hhc0NoYW5nZXMnIHN0YXR1cyBoYXMgY2hhbmdlZC5cclxuICAgIC0gaGFzQ2hhbmdlcyAtIFdoZXRoZXIgb3Igbm90IHRoaXMgRW50aXR5TWFuYWdlciBoYXMgY2hhbmdlcy5cclxuXHJcbiAgPiAgICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKCB7c2VydmljZU5hbWU6IFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIiB9KTtcclxuICA+ICAgICAgZW0uaGFzQ2hhbmdlc0NoYW5nZWQuc3Vic2NyaWJlKGZ1bmN0aW9uKGFyZ3MpIHtcclxuICA+ICAgICAgICAgICAgICBsZXQgaGFzQ2hhbmdlc0NoYW5nZWQgPSBhcmdzLmhhc0NoYW5nZXM7XHJcbiAgPiAgICAgICAgICAgICAgbGV0IGVudGl0eU1hbmFnZXIgPSBhcmdzLmVudGl0eU1hbmFnZXI7XHJcbiAgPiAgICAgICAgICB9KTtcclxuICA+ICAgICAgfSk7XHJcbiAgQGV2ZW50IFxyXG4gICoqL1xyXG4gIGhhc0NoYW5nZXNDaGFuZ2VkOiBCcmVlemVFdmVudDxIYXNDaGFuZ2VzQ2hhbmdlZEV2ZW50QXJncz47XHJcblxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfcGVuZGluZ1B1YnM/OiBhbnlbXTsgLy8gVE9ETzogcmVmaW5lIGxhdGVyXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2hhc0NoYW5nZXNBY3Rpb24/OiAoKCkgPT4gYm9vbGVhbik7IC8vIFRPRE8gcmVmaW5lIGxhdGVyXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2hhc0NoYW5nZXM6IGJvb2xlYW47XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2VudGl0eUdyb3VwTWFwOiB7IFtpbmRleDogc3RyaW5nXTogRW50aXR5R3JvdXAgfTtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfdW5hdHRhY2hlZENoaWxkcmVuTWFwOiBVbmF0dGFjaGVkQ2hpbGRyZW5NYXA7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2luS2V5Rml4dXA6IGJvb2xlYW47XHJcblxyXG4gIGhlbHBlciA9IHtcclxuICAgIHVud3JhcEluc3RhbmNlOiB1bndyYXBJbnN0YW5jZSxcclxuICAgIHVud3JhcE9yaWdpbmFsVmFsdWVzOiB1bndyYXBPcmlnaW5hbFZhbHVlcyxcclxuICAgIHVud3JhcENoYW5nZWRWYWx1ZXM6IHVud3JhcENoYW5nZWRWYWx1ZXNcclxuICB9O1xyXG5cclxuICAvKipcclxuICBFbnRpdHlNYW5hZ2VyIGNvbnN0cnVjdG9yLlxyXG5cclxuICBBdCBpdHMgbW9zdCBiYXNpYyBhbiBFbnRpdHlNYW5hZ2VyIGNhbiBiZSBjb25zdHJ1Y3RlZCB3aXRoIGp1c3QgYSBzZXJ2aWNlIG5hbWVcclxuICA+ICAgICBsZXQgZW50aXR5TWFuYWdlciA9IG5ldyBFbnRpdHlNYW5hZ2VyKCBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIpO1xyXG5cclxuICBUaGlzIGlzIHRoZSBzYW1lIGFzIGNhbGxpbmcgaXQgd2l0aCB0aGUgZm9sbG93aW5nIGNvbmZpZ3VyYXRpb24gb2JqZWN0XHJcbiAgPiAgICAgbGV0IGVudGl0eU1hbmFnZXIgPSBuZXcgRW50aXR5TWFuYWdlcigge3NlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIgfSk7XHJcblxyXG4gIFVzdWFsbHkgaG93ZXZlciwgY29uZmlndXJhdGlvbiBvYmplY3RzIHdpbGwgY29udGFpbiBtb3JlIHRoYW4ganVzdCB0aGUgJ3NlcnZpY2VOYW1lJztcclxuICA+ICAgICBsZXQgbWV0YWRhdGFTdG9yZSA9IG5ldyBNZXRhZGF0YVN0b3JlKCk7XHJcbiAgPiAgICAgbGV0IGVudGl0eU1hbmFnZXIgPSBuZXcgRW50aXR5TWFuYWdlcigge1xyXG4gID4gICAgICAgc2VydmljZU5hbWU6IFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIixcclxuICA+ICAgICAgIG1ldGFkYXRhU3RvcmU6IG1ldGFkYXRhU3RvcmVcclxuICA+ICAgICB9KTtcclxuXHJcbiAgb3JcclxuICA+ICAgICByZXR1cm4gbmV3IFF1ZXJ5T3B0aW9ucyh7XHJcbiAgPiAgICAgICAgIG1lcmdlU3RyYXRlZ3k6IG9iaixcclxuICA+ICAgICAgICAgZmV0Y2hTdHJhdGVneTogdGhpcy5mZXRjaFN0cmF0ZWd5XHJcbiAgPiAgICAgfSk7XHJcbiAgPiAgICAgbGV0IHF1ZXJ5T3B0aW9ucyA9IG5ldyBRdWVyeU9wdGlvbnMoe1xyXG4gID4gICAgICAgICBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5Lk92ZXJ3cml0ZUNoYW5nZXMsXHJcbiAgPiAgICAgICAgIGZldGNoU3RyYXRlZ3k6IEZldGNoU3RyYXRlZ3kuRnJvbVNlcnZlclxyXG4gID4gICAgIH0pO1xyXG4gID4gICAgIGxldCB2YWxpZGF0aW9uT3B0aW9ucyA9IG5ldyBWYWxpZGF0aW9uT3B0aW9ucyh7XHJcbiAgPiAgICAgICAgIHZhbGlkYXRlT25BdHRhY2g6IHRydWUsXHJcbiAgPiAgICAgICAgIHZhbGlkYXRlT25TYXZlOiB0cnVlLFxyXG4gID4gICAgICAgICB2YWxpZGF0ZU9uUXVlcnk6IGZhbHNlXHJcbiAgPiAgICAgfSk7XHJcbiAgPiAgICAgbGV0IGVudGl0eU1hbmFnZXIgPSBuZXcgRW50aXR5TWFuYWdlcih7XHJcbiAgPiAgICAgICAgIHNlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIsXHJcbiAgPiAgICAgICAgIHF1ZXJ5T3B0aW9uczogcXVlcnlPcHRpb25zLFxyXG4gID4gICAgICAgICB2YWxpZGF0aW9uT3B0aW9uczogdmFsaWRhdGlvbk9wdGlvbnNcclxuICA+ICAgICB9KTtcclxuICBAcGFyYW0gZW1Db25maWcgLSBDb25maWd1cmF0aW9uIHNldHRpbmdzIG9yIGEgc2VydmljZSBuYW1lLiAgXHJcbiAgKiovXHJcbiAgY29uc3RydWN0b3IoZW1Db25maWc/OiBFbnRpdHlNYW5hZ2VyQ29uZmlnIHwgc3RyaW5nKSB7XHJcblxyXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBFbnRpdHlNYW5hZ2VyIGN0b3IgaGFzIGEgc2luZ2xlIG9wdGlvbmFsIGFyZ3VtZW50IHRoYXQgaXMgZWl0aGVyIGEgJ3NlcnZpY2VOYW1lJyBvciBhIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlwiKTtcclxuICAgIH1cclxuICAgIGxldCBjb25maWc6IEVudGl0eU1hbmFnZXJDb25maWc7XHJcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICBjb25maWcgPSB7IHNlcnZpY2VOYW1lOiBcIlwiIH07XHJcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBlbUNvbmZpZyA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgY29uZmlnID0geyBzZXJ2aWNlTmFtZTogZW1Db25maWcgfTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbmZpZyA9IGVtQ29uZmlnIHx8IHt9O1xyXG4gICAgfVxyXG5cclxuICAgIEVudGl0eU1hbmFnZXIuX3VwZGF0ZVdpdGhDb25maWcodGhpcywgY29uZmlnLCB0cnVlKTtcclxuXHJcbiAgICB0aGlzLmVudGl0eUNoYW5nZWQgPSBuZXcgQnJlZXplRXZlbnQoXCJlbnRpdHlDaGFuZ2VkXCIsIHRoaXMpO1xyXG4gICAgdGhpcy52YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZCA9IG5ldyBCcmVlemVFdmVudChcInZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkXCIsIHRoaXMpO1xyXG4gICAgdGhpcy5oYXNDaGFuZ2VzQ2hhbmdlZCA9IG5ldyBCcmVlemVFdmVudChcImhhc0NoYW5nZXNDaGFuZ2VkXCIsIHRoaXMpO1xyXG5cclxuICAgIHRoaXMuY2xlYXIoKTtcclxuXHJcbiAgfVxyXG5cclxuICAvKipcclxuICBHZW5lcmFsIHB1cnBvc2UgcHJvcGVydHkgc2V0IG1ldGhvZC4gIEFueSBvZiB0aGUgcHJvcGVydGllcyBpbiB0aGUgW1tFbnRpdHlNYW5hZ2VyQ29uZmlnXV1cclxuICBtYXkgYmUgc2V0LlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGEgcHJldmlvdXNseSBjcmVhdGVkIEVudGl0eU1hbmFnZXJcclxuICA+ICAgICAgLy8gd2hlcmUgd2Ugd2FudCB0byBjaGFuZ2Ugc29tZSBvZiBpdHMgc2V0dGluZ3MuXHJcbiAgPiAgICAgIGVtMS5zZXRQcm9wZXJ0aWVzKCB7XHJcbiAgPiAgICAgICAgICBzZXJ2aWNlTmFtZTogXCJicmVlemUvZm9vXCJcclxuICA+ICAgICAgfSk7XHJcbiAgQHBhcmFtIGNvbmZpZyAtIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBzZWxlY3RlZCBwcm9wZXJ0aWVzIGFuZCB2YWx1ZXMgdG8gc2V0LlxyXG4gICoqL1xyXG4gIHNldFByb3BlcnRpZXMoY29uZmlnOiBFbnRpdHlNYW5hZ2VyQ29uZmlnKSB7XHJcbiAgICBFbnRpdHlNYW5hZ2VyLl91cGRhdGVXaXRoQ29uZmlnKHRoaXMsIGNvbmZpZywgZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgc3RhdGljIF91cGRhdGVXaXRoQ29uZmlnKGVtOiBFbnRpdHlNYW5hZ2VyLCBjb25maWc6IEVudGl0eU1hbmFnZXJDb25maWcsIGlzQ3RvcjogYm9vbGVhbikge1xyXG4gICAgbGV0IGRlZmF1bHRRdWVyeU9wdGlvbnMgPSBpc0N0b3IgPyBRdWVyeU9wdGlvbnMuZGVmYXVsdEluc3RhbmNlIDogZW0ucXVlcnlPcHRpb25zO1xyXG4gICAgbGV0IGRlZmF1bHRTYXZlT3B0aW9ucyA9IGlzQ3RvciA/IFNhdmVPcHRpb25zLmRlZmF1bHRJbnN0YW5jZSA6IGVtLnNhdmVPcHRpb25zO1xyXG4gICAgbGV0IGRlZmF1bHRWYWxpZGF0aW9uT3B0aW9ucyA9IGlzQ3RvciA/IFZhbGlkYXRpb25PcHRpb25zLmRlZmF1bHRJbnN0YW5jZSA6IGVtLnZhbGlkYXRpb25PcHRpb25zO1xyXG5cclxuICAgIGxldCBjb25maWdQYXJhbSA9IGFzc2VydENvbmZpZyhjb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwic2VydmljZU5hbWVcIikuaXNPcHRpb25hbCgpLmlzU3RyaW5nKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJkYXRhU2VydmljZVwiKS5pc09wdGlvbmFsKCkuaXNJbnN0YW5jZU9mKERhdGFTZXJ2aWNlKVxyXG4gICAgICAud2hlcmVQYXJhbShcInF1ZXJ5T3B0aW9uc1wiKS5pc0luc3RhbmNlT2YoUXVlcnlPcHRpb25zKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoZGVmYXVsdFF1ZXJ5T3B0aW9ucylcclxuICAgICAgLndoZXJlUGFyYW0oXCJzYXZlT3B0aW9uc1wiKS5pc0luc3RhbmNlT2YoU2F2ZU9wdGlvbnMpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChkZWZhdWx0U2F2ZU9wdGlvbnMpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwidmFsaWRhdGlvbk9wdGlvbnNcIikuaXNJbnN0YW5jZU9mKFZhbGlkYXRpb25PcHRpb25zKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoZGVmYXVsdFZhbGlkYXRpb25PcHRpb25zKVxyXG4gICAgICAud2hlcmVQYXJhbShcImtleUdlbmVyYXRvckN0b3JcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKTtcclxuICAgIGlmIChpc0N0b3IpIHtcclxuICAgICAgY29uZmlnUGFyYW0gPSBjb25maWdQYXJhbVxyXG4gICAgICAgIC53aGVyZVBhcmFtKFwibWV0YWRhdGFTdG9yZVwiKS5pc0luc3RhbmNlT2YoTWV0YWRhdGFTdG9yZSkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KG5ldyBNZXRhZGF0YVN0b3JlKCkpO1xyXG4gICAgfVxyXG4gICAgY29uZmlnUGFyYW0uYXBwbHlBbGwoZW0pO1xyXG5cclxuICAgIC8vIGluc3VyZSB0aGF0IGVudGl0eU1hbmFnZXIncyBvcHRpb25zIHZlcnNpb25zIGFyZSBjb21wbGV0ZWx5IHBvcHVsYXRlZFxyXG4gICAgY29yZS51cGRhdGVXaXRoRGVmYXVsdHMoZW0ucXVlcnlPcHRpb25zLCBkZWZhdWx0UXVlcnlPcHRpb25zKTtcclxuICAgIGNvcmUudXBkYXRlV2l0aERlZmF1bHRzKGVtLnNhdmVPcHRpb25zLCBkZWZhdWx0U2F2ZU9wdGlvbnMpO1xyXG4gICAgY29yZS51cGRhdGVXaXRoRGVmYXVsdHMoZW0udmFsaWRhdGlvbk9wdGlvbnMsIGRlZmF1bHRWYWxpZGF0aW9uT3B0aW9ucyk7XHJcblxyXG4gICAgaWYgKGNvbmZpZy5zZXJ2aWNlTmFtZSkge1xyXG4gICAgICBlbS5kYXRhU2VydmljZSA9IG5ldyBEYXRhU2VydmljZSh7XHJcbiAgICAgICAgc2VydmljZU5hbWU6IGVtLnNlcnZpY2VOYW1lXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgZW0uc2VydmljZU5hbWUgPSBlbS5kYXRhU2VydmljZSAmJiBlbS5kYXRhU2VydmljZS5zZXJ2aWNlTmFtZTtcclxuXHJcbiAgICBlbS5rZXlHZW5lcmF0b3JDdG9yID0gZW0ua2V5R2VuZXJhdG9yQ3RvciB8fCBLZXlHZW5lcmF0b3I7XHJcbiAgICBpZiAoaXNDdG9yIHx8IGNvbmZpZy5rZXlHZW5lcmF0b3JDdG9yKSB7XHJcbiAgICAgIGVtLmtleUdlbmVyYXRvciA9IG5ldyBlbS5rZXlHZW5lcmF0b3JDdG9yKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjcmVhdGVFbnRpdHkodHlwZU5hbWU6IHN0cmluZywgaW5pdGlhbFZhbHVlcz86IE9iamVjdCwgZW50aXR5U3RhdGU/OiBFbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneT86IE1lcmdlU3RyYXRlZ3kpOiBFbnRpdHk7XHJcbiAgY3JlYXRlRW50aXR5KGVudGl0eVR5cGU6IEVudGl0eVR5cGUsIGluaXRpYWxWYWx1ZXM/OiBPYmplY3QsIGVudGl0eVN0YXRlPzogRW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3k/OiBNZXJnZVN0cmF0ZWd5KTogRW50aXR5O1xyXG4gIC8qKlxyXG4gIENyZWF0ZXMgYSBuZXcgZW50aXR5IG9mIGEgc3BlY2lmaWVkIHR5cGUgYW5kIG9wdGlvbmFsbHkgaW5pdGlhbGl6ZXMgaXQuIEJ5IGRlZmF1bHQgdGhlIG5ldyBlbnRpdHkgaXMgY3JlYXRlZCB3aXRoIGFuIEVudGl0eVN0YXRlIG9mIEFkZGVkXHJcbiAgYnV0IHlvdSBjYW4gYWxzbyBvcHRpb25hbGx5IHNwZWNpZnkgYW4gRW50aXR5U3RhdGUuICBBbiBFbnRpdHlTdGF0ZSBvZiAnRGV0YWNoZWQnIHdpbGwgaW5zdXJlIHRoYXQgdGhlIGVudGl0eSBpcyBjcmVhdGVkIGJ1dCBub3QgeWV0IGFkZGVkXHJcbiAgdG8gdGhlIEVudGl0eU1hbmFnZXIuIFxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgLy8gY3JlYXRlIGFuZCBhZGQgYW4gZW50aXR5O1xyXG4gID4gICAgICBsZXQgZW1wMSA9IGVtMS5jcmVhdGVFbnRpdHkoXCJFbXBsb3llZVwiKTtcclxuICA+ICAgICAgLy8gY3JlYXRlIGFuZCBhZGQgYW4gaW5pdGlhbGl6ZWQgZW50aXR5O1xyXG4gID4gICAgICBsZXQgZW1wMiA9IGVtMS5jcmVhdGVFbnRpdHkoXCJFbXBsb3llZVwiLCB7IGxhc3ROYW1lOiBcIlNtaXRoXCIsIGZpcnN0TmFtZTogXCJKb2huXCIgfSk7XHJcbiAgPiAgICAgIC8vIGNyZWF0ZSBhbmQgYXR0YWNoIChub3QgYWRkKSBhbiBpbml0aWFsaXplZCBlbnRpdHlcclxuICA+ICAgICAgbGV0IGVtcDMgPSBlbTEuY3JlYXRlRW50aXR5KFwiRW1wbG95ZWVcIiwgeyBpZDogNDM1LCBsYXN0TmFtZTogXCJTbWl0aFwiLCBmaXJzdE5hbWU6IFwiSm9oblwiIH0sIEVudGl0eVN0YXRlLlVuY2hhbmdlZCk7XHJcbiAgPiAgICAgIC8vIGNyZWF0ZSBidXQgZG9uJ3QgYXR0YWNoIGFuIGVudGl0eTtcclxuICA+ICAgICAgbGV0IGVtcDQgPSBlbTEuY3JlYXRlRW50aXR5KFwiRW1wbG95ZWVcIiwgeyBpZDogNDM1LCBsYXN0TmFtZTogXCJTbWl0aFwiLCBmaXJzdE5hbWU6IFwiSm9oblwiIH0sIEVudGl0eVN0YXRlLkRldGFjaGVkKTtcclxuICBAcGFyYW0gdHlwZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgRW50aXR5VHlwZSBmb3Igd2hpY2ggYW4gaW5zdGFuY2Ugc2hvdWxkIGJlIGNyZWF0ZWQuXHJcbiAgQHBhcmFtIGVudGl0eVR5cGUgLSBUaGUgRW50aXR5VHlwZSBvZiB0aGUgdHlwZSBmb3Igd2hpY2ggYW4gaW5zdGFuY2Ugc2hvdWxkIGJlIGNyZWF0ZWQuXHJcbiAgQHBhcmFtIGluaXRpYWxWYWx1ZXMgLSAoZGVmYXVsdD1udWxsKSBDb25maWd1cmF0aW9uIG9iamVjdCBvZiB0aGUgcHJvcGVydGllcyB0byBzZXQgaW1tZWRpYXRlbHkgYWZ0ZXIgY3JlYXRpb24uXHJcbiAgQHBhcmFtIGVudGl0eVN0YXRlIC0gKGRlZmF1bHQgPSBbW0VudGl0eVN0YXRlLkFkZGVkXV0pIFRoZSBFbnRpdHlTdGF0ZSBvZiB0aGUgZW50aXR5IGFmdGVyIGJlaW5nIGNyZWF0ZWQgYW5kIGFkZGVkIHRvIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICBAcGFyYW0gbWVyZ2VTdHJhdGVneSAtIChkZWZhdWx0ID0gW1tNZXJnZVN0cmF0ZWd5LkRpc2FsbG93ZWRdXSkgLSBIb3cgdG8gaGFuZGxlIGNvbmZsaWN0cyBpZiBhbiBlbnRpdHkgd2l0aCB0aGUgc2FtZSBrZXkgYWxyZWFkeSBleGlzdHMgd2l0aGluIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICBAcmV0dXJuIHtFbnRpdHl9IEEgbmV3IEVudGl0eSBvZiB0aGUgc3BlY2lmaWVkIHR5cGUuIFxyXG4gICovXHJcbiAgY3JlYXRlRW50aXR5KGVudGl0eVR5cGU6IEVudGl0eVR5cGUgfCBzdHJpbmcsIGluaXRpYWxWYWx1ZXM6IE9iamVjdCwgZW50aXR5U3RhdGU6IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5KSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHlUeXBlLCBcImVudGl0eVR5cGVcIikuaXNTdHJpbmcoKS5vcigpLmlzSW5zdGFuY2VPZihFbnRpdHlUeXBlKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5U3RhdGUsIFwiZW50aXR5U3RhdGVcIikuaXNFbnVtT2YoRW50aXR5U3RhdGUpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0obWVyZ2VTdHJhdGVneSwgXCJtZXJnZVN0cmF0ZWd5XCIpLmlzRW51bU9mKE1lcmdlU3RyYXRlZ3kpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG5cclxuICAgIGxldCBldCA9ICh0eXBlb2YgZW50aXR5VHlwZSA9PT0gXCJzdHJpbmdcIikgPyB0aGlzLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGVudGl0eVR5cGUpIGFzIEVudGl0eVR5cGUgOiBlbnRpdHlUeXBlO1xyXG4gICAgZW50aXR5U3RhdGUgPSBlbnRpdHlTdGF0ZSB8fCBFbnRpdHlTdGF0ZS5BZGRlZDtcclxuICAgIGxldCBlbnRpdHkgPSB7fSBhcyBFbnRpdHk7XHJcbiAgICBjb3JlLnVzaW5nKHRoaXMsIFwiaXNMb2FkaW5nXCIsIHRydWUsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgZW50aXR5ID0gZXQuY3JlYXRlRW50aXR5KGluaXRpYWxWYWx1ZXMpO1xyXG4gICAgfSk7XHJcbiAgICBpZiAoZW50aXR5U3RhdGUgIT09IEVudGl0eVN0YXRlLkRldGFjaGVkKSB7XHJcbiAgICAgIGVudGl0eSA9IHRoaXMuYXR0YWNoRW50aXR5KGVudGl0eSwgZW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3kpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGVudGl0eTtcclxuICB9XHJcblxyXG4gIHN0YXRpYyBpbXBvcnRFbnRpdGllcyhleHBvcnRlZFN0cmluZzogc3RyaW5nLCBjb25maWc/OiBJbXBvcnRDb25maWcpOiBFbnRpdHlNYW5hZ2VyO1xyXG4gIHN0YXRpYyBpbXBvcnRFbnRpdGllcyhleHBvcnRlZERhdGE6IE9iamVjdCwgY29uZmlnPzogSW1wb3J0Q29uZmlnKTogRW50aXR5TWFuYWdlcjtcclxuICAvKipcclxuICBDcmVhdGVzIGEgbmV3IEVudGl0eU1hbmFnZXIgYW5kIGltcG9ydHMgYSBwcmV2aW91c2x5IGV4cG9ydGVkIHJlc3VsdCBpbnRvIGl0LlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcygpO1xyXG4gID4gICAgICAvLyBjYW4gYmUgc3RvcmVkIHZpYSB0aGUgd2ViIHN0b3JhZ2UgYXBpXHJcbiAgPiAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm15RW50aXR5TWFuYWdlclwiLCBidW5kbGUpO1xyXG4gID4gICAgICAvLyBhc3N1bWUgdGhlIGNvZGUgYmVsb3cgb2NjdXJzIGluIGEgZGlmZmVyZW50IHNlc3Npb24uXHJcbiAgPiAgICAgIGxldCBidW5kbGVGcm9tU3RvcmFnZSA9IHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbShcIm15RW50aXR5TWFuYWdlclwiKTtcclxuICA+ICAgICAgLy8gYW5kIGltcG9ydGVkXHJcbiAgPiAgICAgIGxldCBlbTIgPSBFbnRpdHlNYW5hZ2VyLmltcG9ydEVudGl0aWVzKGJ1bmRsZUZyb21TdG9yYWdlKTtcclxuICA+ICAgICAgLy8gZW0yIHdpbGwgbm93IGhhdmUgYSBjb21wbGV0ZSBjb3B5IG9mIHdoYXQgd2FzIGluIGVtMVxyXG4gIEBwYXJhbSBleHBvcnRlZFN0cmluZyAtIFRoZSByZXN1bHQgb2YgYSBwcmV2aW91cyAnZXhwb3J0RW50aXRpZXMnIGNhbGwgYXMgYSBzdHJpbmdcclxuICBAcGFyYW0gZXhwb3J0ZWREYXRhIC0gVGhlIHJlc3VsdCBvZiBhIHByZXZpb3VzICdleHBvcnRFbnRpdGllcycgY2FsbCBhcyBhbiBPYmplY3QuXHJcbiAgQHBhcmFtIGNvbmZpZyAtIEEgY29uZmlndXJhdGlvbiBvYmplY3QuXHJcbiAgQHBhcmFtIGNvbmZpZy5tZXJnZVN0cmF0ZWd5IC0gQSAgW1tNZXJnZVN0cmF0ZWd5XV0gdG8gdXNlIHdoZW4gXHJcbiAgbWVyZ2luZyBpbnRvIGFuIGV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgQHBhcmFtIGNvbmZpZy5tZXRhZGF0YVZlcnNpb25GbiAtIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyB0d28gYXJndW1lbnRzICh0aGUgY3VycmVudCBtZXRhZGF0YVZlcnNpb24gYW5kIHRoZSBpbXBvcnRlZCBzdG9yZSdzICduYW1lJylcclxuICBhbmQgbWF5IGJlIHVzZWQgdG8gcGVyZm9ybSB2ZXJzaW9uIGNoZWNraW5nLlxyXG4gIEByZXR1cm4gQSBuZXcgRW50aXR5TWFuYWdlci4gIE5vdGUgdGhhdCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoaXMgbWV0aG9kIGNhbGwgaXMgZGlmZmVyZW50IGZyb20gdGhhdFxyXG4gIHByb3ZpZGVkIGJ5IHRoZSBzYW1lIG5hbWVkIG1ldGhvZCBvbiBhbiBFbnRpdHlNYW5hZ2VyIGluc3RhbmNlLiBVc2UgdGhhdCBtZXRob2QgaWYgeW91IG5lZWQgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxyXG4gIHJlZ2FyZGluZyB0aGUgaW1wb3J0ZWQgZW50aXRpZXMuXHJcbiAgKiovXHJcbiAgc3RhdGljIGltcG9ydEVudGl0aWVzKGV4cG9ydGVkOiBzdHJpbmcgfCBPYmplY3QsIGNvbmZpZz86IEltcG9ydENvbmZpZykge1xyXG4gICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoKTtcclxuICAgIGVtLmltcG9ydEVudGl0aWVzKGV4cG9ydGVkLCBjb25maWcpO1xyXG4gICAgcmV0dXJuIGVtO1xyXG4gIH1cclxuXHJcbiAgLy8gaW5zdGFuY2UgbWV0aG9kc1xyXG5cclxuICAvKipcclxuICBDYWxscyBbW0VudGl0eUFzcGVjdC5hY2NlcHRDaGFuZ2VzXV0gb24gZXZlcnkgY2hhbmdlZCBlbnRpdHkgaW4gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gICoqL1xyXG4gIGFjY2VwdENoYW5nZXMoKSB7XHJcbiAgICB0aGlzLmdldENoYW5nZXMoKS5tYXAoZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgICByZXR1cm4gZW50aXR5LmVudGl0eUFzcGVjdC5fY2hlY2tPcGVyYXRpb24oXCJhY2NlcHRDaGFuZ2VzXCIpO1xyXG4gICAgfSkuZm9yRWFjaChmdW5jdGlvbiAoYXNwZWN0KSB7XHJcbiAgICAgIGFzcGVjdC5hY2NlcHRDaGFuZ2VzKCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEV4cG9ydHMgc2VsZWN0ZWQgZW50aXRpZXMsIGFsbCBlbnRpdGllcyBvZiBzZWxlY3RlZCB0eXBlcywgb3IgYW4gZW50aXJlIEVudGl0eU1hbmFnZXIgY2FjaGUuXHJcblxyXG4gIFRoaXMgbWV0aG9kIHRha2VzIGEgc25hcHNob3Qgb2YgYW4gRW50aXR5TWFuYWdlciB0aGF0IGNhbiBiZSBzdG9yZWQgb2ZmbGluZSBvciBoZWxkIGluIG1lbW9yeS5cclxuICBVc2UgdGhlIFtbRW50aXR5TWFuYWdlci5pbXBvcnRFbnRpdGllc11dIG1ldGhvZCB0byByZXN0b3JlIG9yIG1lcmdlIHRoZSBzbmFwc2hvdFxyXG4gIGludG8gYW5vdGhlciBFbnRpdHlNYW5hZ2VyIGF0IHNvbWUgbGF0ZXIgdGltZS5cclxuICA+ICAgICAgLy8gbGV0IGVtMSBiZSBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgLy8gZXhwb3J0IGV2ZXJ5IGVudGl0eSBpbiBlbTEuXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcygpO1xyXG4gID4gICAgIC8vIHNhdmUgdG8gdGhlIGJyb3dzZXIncyBsb2NhbCBzdG9yYWdlXHJcbiAgPiAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKFwibXlFbnRpdHlNYW5hZ2VyXCIsIGJ1bmRsZSk7XHJcbiAgPiAgICAgLy8gbGF0ZXIgcmV0cmlldmUgdGhlIGV4cG9ydFxyXG4gID4gICAgIGxldCBidW5kbGVGcm9tU3RvcmFnZSA9IHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbShcIm15RW50aXR5TWFuYWdlclwiKTtcclxuICA+ICAgICAvLyBpbXBvcnQgdGhlIHJldHJpZXZlZCBleHBvcnQgYnVuZGxlIGludG8gYW5vdGhlciBtYW5hZ2VyXHJcbiAgPiAgICAgbGV0IGVtMiA9IGVtMS5jcmVhdGVFbXB0eUNvcHkoKTtcclxuICA+ICAgICBlbTIuaW1wb3J0RW50aXRpZXMoYnVuZGxlRnJvbVN0b3JhZ2UpO1xyXG4gID4gICAgIC8vIGVtMiBub3cgaGFzIGEgY29tcGxldGUsIGZhaXRoZnVsIGNvcHkgb2YgdGhlIGVudGl0aWVzIHRoYXQgd2VyZSBpbiBlbTFcclxuXHJcbiAgWW91IGNhbiBhbHNvIGNvbnRyb2wgZXhhY3RseSB3aGljaCBlbnRpdGllcyBhcmUgZXhwb3J0ZWQuXHJcbiAgPiAgICAgLy8gZ2V0IGVtMSdzIHVuc2F2ZWQgY2hhbmdlcyAoYW4gYXJyYXkpIGFuZCBleHBvcnQgdGhlbS5cclxuICA+ICAgICBsZXQgY2hhbmdlcyA9IGVtMS5nZXRDaGFuZ2VzKCk7XHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcyhjaGFuZ2VzKTtcclxuICA+ICAgICAvLyBtZXJnZSB0aGVzZSBlbnRpdGllcyBpbnRvIGVtMiB3aGljaCBtYXkgY29udGFpbnMgc29tZSBvZiB0aGUgc2FtZSBlbnRpdGllcy5cclxuICA+ICAgICAvLyBkbyBOT1Qgb3ZlcndyaXRlIHRoZSBlbnRpdGllcyBpbiBlbTIgaWYgdGhleSB0aGVtc2VsdmVzIGhhdmUgdW5zYXZlZCBjaGFuZ2VzLlxyXG4gID4gICAgIGVtMi5pbXBvcnRFbnRpdGllcyhidW5kbGUsIHsgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneS5QcmVzZXJ2ZUNoYW5nZXN9ICk7XHJcblxyXG4gIE1ldGFkYXRhIGFyZSBpbmNsdWRlZCBpbiBhbiBleHBvcnQgYnkgZGVmYXVsdC4gWW91IG1heSB3YW50IHRvIGV4Y2x1ZGUgdGhlIG1ldGFkYXRhXHJcbiAgZXNwZWNpYWxseSBpZiB5b3UncmUgZXhwb3J0aW5nIGp1c3QgYSBmZXcgZW50aXRpZXMgZm9yIGxvY2FsIHN0b3JhZ2UuXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcyhhcnJheU9mU2VsZWN0ZWRFbnRpdGllcywge2luY2x1ZGVNZXRhZGF0YTogZmFsc2V9KTtcclxuICA+ICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJnb29kU3R1ZmZcIiwgYnVuZGxlKTtcclxuXHJcbiAgWW91IG1heSBzdGlsbCBleHByZXNzIHRoaXMgb3B0aW9uIGFzIGEgYm9vbGVhbiB2YWx1ZSBhbHRob3VnaCB0aGlzIG9sZGVyIHN5bnRheCBpcyBkZXByZWNhdGVkLlxyXG4gID4gICAgIC8vIEV4Y2x1ZGUgdGhlIG1ldGFkYXRhIChkZXByZWNhdGVkIHN5bnRheClcclxuICA+ICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKGFycmF5T2ZTZWxlY3RlZEVudGl0aWVzLCBmYWxzZSk7XHJcblxyXG4gIFlvdSBjYW4gZXhwb3J0IGFsbCBlbnRpdGllcyBvZiBvbmUgb3IgbW9yZSBzcGVjaWZpZWQgRW50aXR5VHlwZXMuXHJcbiAgPiAgICAgLy8gRXhwb3J0IGFsbCBDdXN0b21lciBhbmQgRW1wbG95ZWUgZW50aXRpZXMgKGFuZCBhbHNvIGV4Y2x1ZGUgbWV0YWRhdGEpXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcyhbJ0N1c3RvbWVyJywgJ0VtcGxveWVlJ10sIHtpbmNsdWRlTWV0YWRhdGE6IGZhbHNlfSk7XHJcblxyXG4gIEFsbCBvZiB0aGUgYWJvdmUgZXhhbXBsZXMgcmV0dXJuIGFuIGV4cG9ydCBidW5kbGUgYXMgYSBzdHJpbmcgd2hpY2ggaXMgdGhlIGRlZmF1bHQgZm9ybWF0LlxyXG4gIFlvdSBjYW4gZXhwb3J0IHRoZSBidW5kbGUgYXMgSlNPTiBpZiB5b3UgcHJlZmVyIGJ5IHNldHRpbmcgdGhlIGBhc1N0cmluZ2Agb3B0aW9uIHRvIGZhbHNlLlxyXG4gID4gICAgIC8vIEV4cG9ydCBhbGwgQ3VzdG9tZXIgYW5kIEVtcGxveWVlIGVudGl0aWVzIGFzIEpTT04gYW5kIGV4Y2x1ZGUgdGhlIG1ldGFkYXRhXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcyhbJ0N1c3RvbWVyJywgJ0VtcGxveWVlJ10sXHJcbiAgPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7YXNTdHJpbmc6IGZhbHNlLCBpbmNsdWRlTWV0YWRhdGE6IGZhbHNlfSk7XHJcbiAgPiAgICAgLy8gc3RvcmUgSlNPTiBidW5kbGUgc29tZXdoZXJlIC4uLiBwZXJoYXBzIGluZGV4RGIgLi4uIGFuZCBsYXRlciBpbXBvcnQgYXMgd2UgZG8gaGVyZS5cclxuICA+ICAgICBlbTIuaW1wb3J0RW50aXRpZXMoYnVuZGxlKTtcclxuICBAcGFyYW0gZW50aXRpZXMgLSBUaGUgZW50aXRpZXMgdG8gZXhwb3J0IG9yIHRoZSBFbnRpdHlUeXBlKHMpIG9mIHRoZSBlbnRpdGllcyB0byBleHBvcnQ7XHJcbiAgICBhbGwgZW50aXRpZXMgYXJlIGV4cG9ydGVkIGlmIHRoaXMgcGFyYW1ldGVyIGlzIG9taXR0ZWQgb3IgbnVsbC5cclxuICBAcGFyYW0gZXhwb3J0Q29uZmlnIC0gRXhwb3J0IGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBvciBhIGJvb2xlYW5cclxuICAgIC0gYXNTdHJpbmcgLSAoYm9vbGVhbikgLSBJZiB0cnVlIChkZWZhdWx0KSwgcmV0dXJuIGV4cG9ydCBidW5kbGUgYXMgYSBzdHJpbmcuXHJcbiAgICAtIGluY2x1ZGVNZXRhZGF0YSAtIChib29sZWFuKSAtIElmIHRydWUgKGRlZmF1bHQpLCBpbmNsdWRlIG1ldGFkYXRhIGluIHRoZSBleHBvcnQgYnVuZGxlLlxyXG4gIEByZXR1cm4gVGhlIGV4cG9ydCBidW5kbGUgZWl0aGVyIHNlcmlhbGl6ZWQgYXMgYSBzdHJpbmcgKGRlZmF1bHQpIG9yIGFzIGEgSlNPTiBvYmplY3QuXHJcbiAgVGhlIGJ1bmRsZSBjb250YWlucyB0aGUgbWV0YWRhdGEgKHVubGVzcyBleGNsdWRlZCkgYW5kIHRoZSBlbnRpdHkgZGF0YSBncm91cGVkIGJ5IHR5cGUuXHJcbiAgVGhlIGVudGl0eSBkYXRhIGluY2x1ZGUgcHJvcGVydHkgdmFsdWVzLCBjaGFuZ2Utc3RhdGUsIGFuZCB0ZW1wb3Jhcnkga2V5IG1hcHBpbmdzIChpZiBhbnkpLlxyXG5cclxuICBUaGUgZXhwb3J0IGJ1bmRsZSBpbnRlcm5hbHMgYXJlIGRlbGliZXJhdGVseSB1bmRvY3VtZW50ZWQuICBUaGlzIEJyZWV6ZS1pbnRlcm5hbCByZXByZXNlbnRhdGlvbiBvZiBlbnRpdHkgZGF0YSBpc1xyXG4gIHN1aXRhYmxlIGZvciBleHBvcnQsIHN0b3JhZ2UsIGFuZCBpbXBvcnQuIFRoZSBzY2hlbWEgYW5kIGNvbnRlbnRzIG9mIHRoZSBidW5kbGUgbWF5IGNoYW5nZSBpbiBmdXR1cmUgdmVyc2lvbnMgb2YgQnJlZXplLlxyXG4gIE1hbmlwdWxhdGUgaXQgYXQgeW91ciBvd24gcmlzayB3aXRoIGFwcHJvcHJpYXRlIGNhdXRpb24uXHJcbiAgKiovXHJcbiAgZXhwb3J0RW50aXRpZXMoZW50aXRpZXM/OiBFbnRpdHlbXSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZ1tdLCBleHBvcnRDb25maWc/OiB7IGFzU3RyaW5nPzogYm9vbGVhbiwgaW5jbHVkZU1ldGFkYXRhPzogYm9vbGVhbiB9IHwgYm9vbGVhbik6IHN0cmluZyB8IE9iamVjdCB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdGllcywgXCJlbnRpdGllc1wiKS5pc0FycmF5KCkuaXNFbnRpdHkoKVxyXG4gICAgICAub3IoKS5pc05vbkVtcHR5QXJyYXkoKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSlcclxuICAgICAgLm9yKCkuaXNOb25FbXB0eUFycmF5KCkuaXNTdHJpbmcoKVxyXG4gICAgICAub3IoKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuXHJcbiAgICAvLyBhc3NlcnRQYXJhbShleHBvcnRDb25maWcsIFwiZXhwb3J0Q29uZmlnXCIpLmlzT2JqZWN0KClcclxuICAgIC8vICAgLm9yKCkuaXNCb29sZWFuKClcclxuICAgIC8vICAgLm9yKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcblxyXG4gICAgaWYgKGV4cG9ydENvbmZpZyA9PSBudWxsKSB7XHJcbiAgICAgIGV4cG9ydENvbmZpZyA9IHsgaW5jbHVkZU1ldGFkYXRhOiB0cnVlLCBhc1N0cmluZzogdHJ1ZSB9O1xyXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0Q29uZmlnID09PSAnYm9vbGVhbicpIHsgLy8gZGVwcmVjYXRlZFxyXG4gICAgICBleHBvcnRDb25maWcgPSB7IGluY2x1ZGVNZXRhZGF0YTogZXhwb3J0Q29uZmlnLCBhc1N0cmluZzogdHJ1ZSB9O1xyXG4gICAgfVxyXG5cclxuICAgIGFzc2VydENvbmZpZyhleHBvcnRDb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiYXNTdHJpbmdcIikuaXNCb29sZWFuKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KHRydWUpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaW5jbHVkZU1ldGFkYXRhXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdCh0cnVlKVxyXG4gICAgICAuYXBwbHlBbGwoZXhwb3J0Q29uZmlnKTtcclxuXHJcbiAgICBsZXQgZXhwb3J0QnVuZGxlID0gZXhwb3J0RW50aXR5R3JvdXBzKHRoaXMsIGVudGl0aWVzKTtcclxuICAgIGxldCBqc29uID0gY29yZS5leHRlbmQoe30sIGV4cG9ydEJ1bmRsZSwgW1widGVtcEtleXNcIiwgXCJlbnRpdHlHcm91cE1hcFwiXSk7XHJcblxyXG4gICAgaWYgKGV4cG9ydENvbmZpZy5pbmNsdWRlTWV0YWRhdGEpIHtcclxuICAgICAganNvbiA9IGNvcmUuZXh0ZW5kKGpzb24sIHRoaXMsIFtcImRhdGFTZXJ2aWNlXCIsIFwic2F2ZU9wdGlvbnNcIiwgXCJxdWVyeU9wdGlvbnNcIiwgXCJ2YWxpZGF0aW9uT3B0aW9uc1wiXSk7XHJcbiAgICAgIChqc29uIGFzIGFueSkubWV0YWRhdGFTdG9yZSA9IHRoaXMubWV0YWRhdGFTdG9yZS5leHBvcnRNZXRhZGF0YSgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgKGpzb24gYXMgYW55KS5tZXRhZGF0YVZlcnNpb24gPSBNZXRhZGF0YVN0b3JlLm1ldGFkYXRhVmVyc2lvbjtcclxuICAgICAgKGpzb24gYXMgYW55KS5tZXRhZGF0YVN0b3JlTmFtZSA9IHRoaXMubWV0YWRhdGFTdG9yZS5uYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCByZXN1bHQgPSBleHBvcnRDb25maWcuYXNTdHJpbmcgPyBKU09OLnN0cmluZ2lmeShqc29uLCBudWxsLCBjb25maWcuc3RyaW5naWZ5UGFkKSA6IGpzb247XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgLy8gVE9ETzogdHlwZSB0aGUgcmV0dXJuIHZhbHVlIHsgZW50aXRpZXM6IGVudGl0aWVzVG9MaW5rLCB0ZW1wS2V5TWFwcGluZzogdGVtcEtleU1hcCB9XHJcbiAgaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWRTdHJpbmc6IHN0cmluZywgY29uZmlnPzogSW1wb3J0Q29uZmlnKTogSW1wb3J0UmVzdWx0O1xyXG4gIGltcG9ydEVudGl0aWVzKGV4cG9ydGVkRGF0YTogT2JqZWN0LCBjb25maWc/OiBJbXBvcnRDb25maWcpOiBJbXBvcnRSZXN1bHQ7XHJcbiAgLyoqXHJcbiAgSW1wb3J0cyBhIHByZXZpb3VzbHkgZXhwb3J0ZWQgcmVzdWx0IGludG8gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG5cclxuICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBtYWtlIGEgY29tcGxldGUgY29weSBvZiBhbnkgcHJldmlvdXNseSBjcmVhdGVkIGVudGl0eU1hbmFnZXIsIGV2ZW4gaWYgY3JlYXRlZFxyXG4gIGluIGEgcHJldmlvdXMgc2Vzc2lvbiBhbmQgc3RvcmVkIGluIGxvY2FsU3RvcmFnZS4gVGhlIHN0YXRpYyB2ZXJzaW9uIG9mIHRoaXMgbWV0aG9kIHBlcmZvcm1zIGFcclxuICB2ZXJ5IHNpbWlsYXIgcHJvY2Vzcy5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKCk7XHJcbiAgPiAgICAgLy8gYnVuZGxlIGNhbiBiZSBzdG9yZWQgaW4gd2luZG93LmxvY2FsU3RvcmFnZSBvciBqdXN0IGhlbGQgaW4gbWVtb3J5LlxyXG4gID4gICAgIGxldCBlbTIgPSBuZXcgRW50aXR5TWFuYWdlcih7XHJcbiAgPiAgICAgICAgIHNlcnZpY2VOYW1lOiBlbTEuc2VydmljZU5hbWUsXHJcbiAgPiAgICAgICAgIG1ldGFkYXRhU3RvcmU6IGVtMS5tZXRhZGF0YVN0b3JlXHJcbiAgPiAgICAgfSk7XHJcbiAgPiAgICAgZW0yLmltcG9ydEVudGl0aWVzKGJ1bmRsZSk7XHJcbiAgPiAgICAgLy8gZW0yIHdpbGwgbm93IGhhdmUgYSBjb21wbGV0ZSBjb3B5IG9mIHdoYXQgd2FzIGluIGVtMVxyXG5cclxuICBJdCBjYW4gYWxzbyBiZSB1c2VkIHRvIG1lcmdlIHRoZSBjb250ZW50cyBvZiBhIHByZXZpb3VzbHkgY3JlYXRlZCBFbnRpdHlNYW5hZ2VyIHdpdGggYW5cclxuICBleGlzdGluZyBFbnRpdHlNYW5hZ2VyIHdpdGggY29udHJvbCBvdmVyIGhvdyB0aGUgdHdvIGFyZSBtZXJnZWQuXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcygpO1xyXG4gID4gICAgIC8vIGFzc3VtZSBlbTIgaXMgYW5vdGhlciBlbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgc29tZSBvZiB0aGUgc2FtZSBlbnRpdGllcyBwb3NzaWJseSB3aXRoIG1vZGlmaWNhdGlvbnMuXHJcbiAgPiAgICAgZW0yLmltcG9ydEVudGl0aWVzKGJ1bmRsZSwgeyBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5LlByZXNlcnZlQ2hhbmdlc30gKTtcclxuICA+ICAgICAvLyBlbTIgd2lsbCBub3cgY29udGFpbiBhbGwgb2YgdGhlIGVudGl0aWVzIGZyb20gYm90aCBlbTEgYW5kIGVtMi4gIEFueSBlbTIgZW50aXRpZXMgd2l0aCBwcmV2aW91c2x5XHJcbiAgPiAgICAgLy8gbWFkZSBtb2RpZmljYXRpb25zIHdpbGwgbm90IGhhdmUgYmVlbiB0b3VjaGVkLCBidXQgYWxsIG90aGVyIGVudGl0aWVzIGZyb20gZW0xIHdpbGwgaGF2ZSBiZWVuIGltcG9ydGVkLlxyXG4gIEBwYXJhbSBleHBvcnRlZFN0cmluZyAtIFRoZSByZXN1bHQgb2YgYSBwcmV2aW91cyAnZXhwb3J0JyBjYWxsLlxyXG4gIEBwYXJhbSBpbXBvcnRDb25maWcgLSBBIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxyXG4gIEBwYXJhbSBpbXBvcnRDb25maWcubWVyZ2VTdHJhdGVneSAtICBBIFtbTWVyZ2VTdHJhdGVneV1dIHRvIHVzZSB3aGVuXHJcbiAgbWVyZ2luZyBpbnRvIGFuIGV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgQHBhcmFtIGltcG9ydENvbmZpZy5tZXRhZGF0YVZlcnNpb25GbiAtIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyB0d28gYXJndW1lbnRzICh0aGUgY3VycmVudCBtZXRhZGF0YVZlcnNpb24gYW5kIHRoZSBpbXBvcnRlZCBzdG9yZSdzICduYW1lJylcclxuICBhbmQgbWF5IGJlIHVzZWQgdG8gcGVyZm9ybSB2ZXJzaW9uIGNoZWNraW5nLlxyXG4gIEByZXR1cm4gcmVzdWx0IFxyXG4gICAgLSByZXN1bHQuZW50aXRpZXMge0FycmF5IG9mIEVudGl0aWVzfSBUaGUgZW50aXRpZXMgdGhhdCB3ZXJlIGltcG9ydGVkLlxyXG4gICAgLSByZXN1bHQudGVtcEtleU1hcCB7T2JqZWN0fSBNYXBwaW5nIGZyb20gb3JpZ2luYWwgRW50aXR5S2V5IGluIHRoZSBpbXBvcnQgYnVuZGxlIHRvIGl0cyBjb3JyZXNwb25kaW5nIEVudGl0eUtleSBpbiB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgKiovXHJcbiAgaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWQ6IHN0cmluZyB8IE9iamVjdCwgaW1wb3J0Q29uZmlnPzogSW1wb3J0Q29uZmlnKSB7XHJcbiAgICBpbXBvcnRDb25maWcgPSBpbXBvcnRDb25maWcgfHwge307XHJcbiAgICBhc3NlcnRDb25maWcoaW1wb3J0Q29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm1lcmdlU3RyYXRlZ3lcIikuaXNFbnVtT2YoTWVyZ2VTdHJhdGVneSkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KHRoaXMucXVlcnlPcHRpb25zLm1lcmdlU3RyYXRlZ3kpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwibWV0YWRhdGFWZXJzaW9uRm5cIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm1lcmdlQWRkc1wiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKGltcG9ydENvbmZpZyk7XHJcblxyXG4gICAgbGV0IGpzb24gPSAodHlwZW9mIGV4cG9ydGVkID09PSBcInN0cmluZ1wiKSA/IEpTT04ucGFyc2UoZXhwb3J0ZWQpIDogZXhwb3J0ZWQ7XHJcbiAgICBpZiAoanNvbi5tZXRhZGF0YVN0b3JlKSB7XHJcbiAgICAgIHRoaXMubWV0YWRhdGFTdG9yZS5pbXBvcnRNZXRhZGF0YShqc29uLm1ldGFkYXRhU3RvcmUpO1xyXG4gICAgICAvLyB0aGUgfHwgY2xhdXNlIGlzIGZvciBiYWNrd2FyZHMgY29tcGF0IHdpdGggYW4gZWFybGllciBzZXJpYWxpemF0aW9uIGZvcm1hdC5cclxuICAgICAgdGhpcy5kYXRhU2VydmljZSA9IChqc29uLmRhdGFTZXJ2aWNlICYmIERhdGFTZXJ2aWNlLmZyb21KU09OKGpzb24uZGF0YVNlcnZpY2UpKSB8fCBuZXcgRGF0YVNlcnZpY2UoeyBzZXJ2aWNlTmFtZToganNvbi5zZXJ2aWNlTmFtZSB9KTtcclxuXHJcbiAgICAgIHRoaXMuc2F2ZU9wdGlvbnMgPSBuZXcgU2F2ZU9wdGlvbnMoanNvbi5zYXZlT3B0aW9ucyk7XHJcbiAgICAgIHRoaXMucXVlcnlPcHRpb25zID0gUXVlcnlPcHRpb25zLmZyb21KU09OKGpzb24ucXVlcnlPcHRpb25zKTtcclxuICAgICAgdGhpcy52YWxpZGF0aW9uT3B0aW9ucyA9IG5ldyBWYWxpZGF0aW9uT3B0aW9ucyhqc29uLnZhbGlkYXRpb25PcHRpb25zKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGltcG9ydENvbmZpZy5tZXRhZGF0YVZlcnNpb25GbiAmJiBpbXBvcnRDb25maWcubWV0YWRhdGFWZXJzaW9uRm4oe1xyXG4gICAgICAgIG1ldGFkYXRhVmVyc2lvbjoganNvbi5tZXRhZGF0YVZlcnNpb24sXHJcbiAgICAgICAgbWV0YWRhdGFTdG9yZU5hbWU6IGpzb24ubWV0YWRhdGFTdG9yZU5hbWVcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHRlbXBLZXlNYXA6IElUZW1wS2V5TWFwID0ge307XHJcbiAgICBqc29uLnRlbXBLZXlzLmZvckVhY2goKGs6IGFueSkgPT4ge1xyXG4gICAgICBsZXQgb2xkS2V5ID0gRW50aXR5S2V5LmZyb21KU09OKGssIHRoaXMubWV0YWRhdGFTdG9yZSk7XHJcbiAgICAgIC8vIHRyeSB0byB1c2Ugb2xkS2V5IGlmIG5vdCBhbHJlYWR5IHVzZWQgaW4gdGhpcyBrZXlHZW5lcmF0b3IuXHJcbiAgICAgIHRlbXBLZXlNYXBbb2xkS2V5LnRvU3RyaW5nKCldID0gbmV3IEVudGl0eUtleShvbGRLZXkuZW50aXR5VHlwZSwgdGhpcy5rZXlHZW5lcmF0b3IuZ2VuZXJhdGVUZW1wS2V5VmFsdWUob2xkS2V5LmVudGl0eVR5cGUsIG9sZEtleS52YWx1ZXNbMF0pKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGxldCBlbnRpdGllc1RvTGluazogRW50aXR5W10gPSBbXTtcclxuICAgIGxldCBpbXBDb25maWcgPSBpbXBvcnRDb25maWcgYXMgSW1wb3J0Q29uZmlnRXh0O1xyXG5cclxuICAgIGltcENvbmZpZy50ZW1wS2V5TWFwID0gdGVtcEtleU1hcDtcclxuICAgIGNvcmUud3JhcEV4ZWN1dGlvbigoKSA9PiB7XHJcbiAgICAgIHRoaXMuX3BlbmRpbmdQdWJzID0gW107XHJcbiAgICB9LCAoc3RhdGUpID0+IHtcclxuICAgICAgdGhpcy5fcGVuZGluZ1B1YnMhLmZvckVhY2goKGZuKSA9PiBmbigpKTtcclxuICAgICAgdGhpcy5fcGVuZGluZ1B1YnMgPSB1bmRlZmluZWQ7XHJcbiAgICAgIHRoaXMuX2hhc0NoYW5nZXNBY3Rpb24gJiYgdGhpcy5faGFzQ2hhbmdlc0FjdGlvbigpO1xyXG4gICAgfSwgKCkgPT4ge1xyXG4gICAgICBjb3JlLm9iamVjdEZvckVhY2goanNvbi5lbnRpdHlHcm91cE1hcCwgKGVudGl0eVR5cGVOYW1lLCBqc29uR3JvdXApID0+IHtcclxuICAgICAgICBsZXQgZW50aXR5VHlwZSA9IHRoaXMubWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoZW50aXR5VHlwZU5hbWUsIGZhbHNlKSBhcyBFbnRpdHlUeXBlO1xyXG4gICAgICAgIGxldCB0YXJnZXRFbnRpdHlHcm91cCA9IGZpbmRPckNyZWF0ZUVudGl0eUdyb3VwKHRoaXMsIGVudGl0eVR5cGUpO1xyXG4gICAgICAgIGxldCBlbnRpdGllcyA9IGltcG9ydEVudGl0eUdyb3VwKHRhcmdldEVudGl0eUdyb3VwLCBqc29uR3JvdXAsIGltcENvbmZpZyk7XHJcbiAgICAgICAgaWYgKGVudGl0aWVzICYmIGVudGl0aWVzLmxlbmd0aCkge1xyXG4gICAgICAgICAgZW50aXRpZXNUb0xpbmsgPSBlbnRpdGllc1RvTGluay5jb25jYXQoZW50aXRpZXMpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICAgIGVudGl0aWVzVG9MaW5rLmZvckVhY2goKGVudGl0eSkgPT4ge1xyXG4gICAgICAgIGlmICghZW50aXR5LmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZS5pc0RlbGV0ZWQoKSkge1xyXG4gICAgICAgICAgdGhpcy5fbGlua1JlbGF0ZWRFbnRpdGllcyhlbnRpdHkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIGVudGl0aWVzOiBlbnRpdGllc1RvTGluayxcclxuICAgICAgdGVtcEtleU1hcHBpbmc6IHRlbXBLZXlNYXBcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBDbGVhcnMgdGhpcyBFbnRpdHlNYW5hZ2VyJ3MgY2FjaGUgYnV0IGtlZXBzIGFsbCBvdGhlciBzZXR0aW5ncy4gTm90ZSB0aGF0IHRoaXNcclxuICBtZXRob2QgaXMgbm90IGFzIGZhc3QgYXMgY3JlYXRpbmcgYSBuZXcgRW50aXR5TWFuYWdlciB2aWEgJ25ldyBFbnRpdHlNYW5hZ2VyJy5cclxuICBUaGlzIGlzIGJlY2F1c2UgY2xlYXIgYWN0dWFsbHkgZGV0YWNoZXMgYWxsIG9mIHRoZSBlbnRpdGllcyBmcm9tIHRoZSBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGVtMS5jbGVhcigpO1xyXG4gID4gICAgIC8vIGVtMSBpcyB3aWxsIG5vdyBjb250YWluIG5vIGVudGl0aWVzLCBidXQgYWxsIG90aGVyIHNldHRpbmcgd2lsbCBiZSBtYWludGFpbmVkLlxyXG4gICoqL1xyXG4gIGNsZWFyKCkge1xyXG4gICAgY29yZS5vYmplY3RNYXAodGhpcy5fZW50aXR5R3JvdXBNYXAsIGZ1bmN0aW9uIChrZXk6IHN0cmluZywgZW50aXR5R3JvdXA6IEVudGl0eUdyb3VwKSB7XHJcbiAgICAgIHJldHVybiBlbnRpdHlHcm91cC5fY2hlY2tPcGVyYXRpb24oJ2NsZWFyJyk7XHJcbiAgICB9KS5mb3JFYWNoKChlbnRpdHlHcm91cDogRW50aXR5R3JvdXApID0+IHtcclxuICAgICAgZW50aXR5R3JvdXAuX2NsZWFyKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLl9lbnRpdHlHcm91cE1hcCA9IHt9O1xyXG4gICAgdGhpcy5fdW5hdHRhY2hlZENoaWxkcmVuTWFwID0gbmV3IFVuYXR0YWNoZWRDaGlsZHJlbk1hcCgpO1xyXG4gICAgdGhpcy5rZXlHZW5lcmF0b3IgPSBuZXcgdGhpcy5rZXlHZW5lcmF0b3JDdG9yKCk7XHJcbiAgICB0aGlzLmVudGl0eUNoYW5nZWQucHVibGlzaCh7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLkNsZWFyIH0pO1xyXG4gICAgdGhpcy5fc2V0SGFzQ2hhbmdlcyhmYWxzZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBDcmVhdGVzIGFuIGVtcHR5IGNvcHkgb2YgdGhpcyBFbnRpdHlNYW5hZ2VyIGJ1dCB3aXRoIHRoZSBzYW1lIERhdGFTZXJ2aWNlLCBNZXRhZGF0YVN0b3JlLCBRdWVyeU9wdGlvbnMsIFNhdmVPcHRpb25zLCBWYWxpZGF0aW9uT3B0aW9ucywgZXRjLiBcclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgZW0yID0gZW0xLmNyZWF0ZUVtcHR5Q29weSgpO1xyXG4gID4gICAgIC8vIGVtMiBpcyBhIG5ldyBFbnRpdHlNYW5hZ2VyIHdpdGggYWxsIG9mIGVtMSdzIHNldHRpbmdzXHJcbiAgPiAgICAgLy8gYnV0IG5vIGVudGl0aWVzLlxyXG4gIEByZXR1cm4gQSBuZXcgRW50aXR5TWFuYWdlci5cclxuICAqKi9cclxuICBjcmVhdGVFbXB0eUNvcHkoKSB7XHJcbiAgICBsZXQgY29weSA9IG5ldyBFbnRpdHlNYW5hZ2VyKGNvcmUuZXh0ZW5kKHt9LCB0aGlzLFxyXG4gICAgICBbXCJkYXRhU2VydmljZVwiLCBcIm1ldGFkYXRhU3RvcmVcIiwgXCJxdWVyeU9wdGlvbnNcIiwgXCJzYXZlT3B0aW9uc1wiLCBcInZhbGlkYXRpb25PcHRpb25zXCIsIFwia2V5R2VuZXJhdG9yQ3RvclwiXSkpO1xyXG4gICAgcmV0dXJuIGNvcHk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBBdHRhY2hlcyBhbiBlbnRpdHkgdG8gdGhpcyBFbnRpdHlNYW5hZ2VyIHdpdGggYW4gIFtbRW50aXR5U3RhdGVdXSBvZiAnQWRkZWQnLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICBsZXQgY3VzdDEgPSBjdXN0VHlwZS5jcmVhdGVFbnRpdHkoKTtcclxuICA+ICAgICBlbTEuYWRkRW50aXR5KGN1c3QxKTtcclxuXHJcbiAgTm90ZSB0aGF0IHRoaXMgaXMgdGhlIHNhbWUgYXMgdXNpbmcgJ2F0dGFjaEVudGl0eScgd2l0aCBhbiBbW0VudGl0eVN0YXRlXV0gb2YgJ0FkZGVkJy5cclxuXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgIGxldCBjdXN0MSA9IGN1c3RUeXBlLmNyZWF0ZUVudGl0eSgpO1xyXG4gID4gICAgIGVtMS5hdHRhY2hFbnRpdHkoY3VzdDEsIEVudGl0eVN0YXRlLkFkZGVkKTtcclxuICBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBhZGQuXHJcbiAgQHJldHVybiBUaGUgYWRkZWQgZW50aXR5LlxyXG4gICoqL1xyXG4gIGFkZEVudGl0eShlbnRpdHk6IEVudGl0eSkge1xyXG4gICAgcmV0dXJuIHRoaXMuYXR0YWNoRW50aXR5KGVudGl0eSwgRW50aXR5U3RhdGUuQWRkZWQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQXR0YWNoZXMgYW4gZW50aXR5IHRvIHRoaXMgRW50aXR5TWFuYWdlciB3aXRoIGEgc3BlY2lmaWVkIFtbRW50aXR5U3RhdGVdXS5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgbGV0IGN1c3QxID0gY3VzdFR5cGUuY3JlYXRlRW50aXR5KCk7XHJcbiAgPiAgICAgZW0xLmF0dGFjaEVudGl0eShjdXN0MSwgRW50aXR5U3RhdGUuQWRkZWQpO1xyXG4gIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIGFkZC5cclxuICBAcGFyYW0gZW50aXR5U3RhdGUgLSAoZGVmYXVsdD1FbnRpdHlTdGF0ZS5VbmNoYW5nZWQpIFRoZSBFbnRpdHlTdGF0ZSBvZiB0aGUgbmV3bHkgYXR0YWNoZWQgZW50aXR5LiBJZiBvbWl0dGVkIHRoaXMgZGVmYXVsdHMgdG8gRW50aXR5U3RhdGUuVW5jaGFuZ2VkLlxyXG4gIEBwYXJhbSBtZXJnZVN0cmF0ZWd5IC0gKGRlZmF1bHQgPSBNZXJnZVN0cmF0ZWd5LkRpc2FsbG93ZWQpIEhvdyB0aGUgc3BlY2lmaWVkIGVudGl0eSBzaG91bGQgYmUgbWVyZ2VkIGludG8gdGhlIEVudGl0eU1hbmFnZXIgaWYgdGhpcyBFbnRpdHlNYW5hZ2VyIGFscmVhZHkgY29udGFpbnMgYW4gZW50aXR5IHdpdGggdGhlIHNhbWUga2V5LlxyXG4gIEByZXR1cm4gVGhlIGF0dGFjaGVkIGVudGl0eS5cclxuICAqKi9cclxuICBhdHRhY2hFbnRpdHkoZW50aXR5OiBFbnRpdHksIGVudGl0eVN0YXRlPzogRW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3k/OiBNZXJnZVN0cmF0ZWd5KSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHksIFwiZW50aXR5XCIpLmlzUmVxdWlyZWQoKS5jaGVjaygpO1xyXG4gICAgdGhpcy5tZXRhZGF0YVN0b3JlLl9jaGVja0VudGl0eVR5cGUoZW50aXR5KTtcclxuICAgIGxldCBlc1N5bWJvbCA9IGFzc2VydFBhcmFtKGVudGl0eVN0YXRlLCBcImVudGl0eVN0YXRlXCIpLmlzRW51bU9mKEVudGl0eVN0YXRlKS5pc09wdGlvbmFsKCkuY2hlY2soRW50aXR5U3RhdGUuVW5jaGFuZ2VkKSBhcyBFbnRpdHlTdGF0ZTtcclxuICAgIGxldCBtc1N5bWJvbCA9IGFzc2VydFBhcmFtKG1lcmdlU3RyYXRlZ3ksIFwibWVyZ2VTdHJhdGVneVwiKS5pc0VudW1PZihNZXJnZVN0cmF0ZWd5KS5pc09wdGlvbmFsKCkuY2hlY2soTWVyZ2VTdHJhdGVneS5EaXNhbGxvd2VkKSBhcyBNZXJnZVN0cmF0ZWd5O1xyXG5cclxuICAgIGlmIChlbnRpdHkuZW50aXR5VHlwZS5tZXRhZGF0YVN0b3JlICE9PSB0aGlzLm1ldGFkYXRhU3RvcmUpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGF0dGFjaCB0aGlzIGVudGl0eSBiZWNhdXNlIHRoZSBFbnRpdHlUeXBlIChcIiArIGVudGl0eS5lbnRpdHlUeXBlLm5hbWUgK1xyXG4gICAgICAgIFwiKSBhbmQgTWV0YWRhdGFTdG9yZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBlbnRpdHkgZG9lcyBub3QgbWF0Y2ggdGhpcyBFbnRpdHlNYW5hZ2VyJ3MgTWV0YWRhdGFTdG9yZS5cIik7XHJcbiAgICB9XHJcbiAgICBsZXQgYXNwZWN0ID0gZW50aXR5LmVudGl0eUFzcGVjdDtcclxuICAgIGlmIChhc3BlY3QpIHtcclxuICAgICAgLy8gdG8gYXZvaWQgcmVhdHRhY2hpbmcgYW4gZW50aXR5IGluIHByb2dyZXNzXHJcbiAgICAgIGlmIChhc3BlY3QuX2luUHJvY2Vzc0VudGl0eSkgcmV0dXJuIGFzcGVjdC5faW5Qcm9jZXNzRW50aXR5O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gdGhpcyBvY2N1cidzIHdoZW4gYXR0YWNoaW5nIGFuIGVudGl0eSBjcmVhdGVkIHZpYSBuZXcgaW5zdGVhZCBvZiB2aWEgY3JlYXRlRW50aXR5LlxyXG4gICAgICBhc3BlY3QgPSBuZXcgRW50aXR5QXNwZWN0KGVudGl0eSk7XHJcbiAgICB9XHJcbiAgICBsZXQgbWFuYWdlciA9IGFzcGVjdC5lbnRpdHlNYW5hZ2VyO1xyXG4gICAgaWYgKG1hbmFnZXIpIHtcclxuICAgICAgaWYgKG1hbmFnZXIgPT09IHRoaXMpIHtcclxuICAgICAgICByZXR1cm4gZW50aXR5O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgZW50aXR5IGFscmVhZHkgYmVsb25ncyB0byBhbm90aGVyIEVudGl0eU1hbmFnZXJcIik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBsZXQgYXR0YWNoZWRFbnRpdHkgPSB7fSBhcyBFbnRpdHk7XHJcbiAgICBjb3JlLnVzaW5nKHRoaXMsIFwiaXNMb2FkaW5nXCIsIHRydWUsICgpID0+IHtcclxuICAgICAgaWYgKGVzU3ltYm9sLmlzQWRkZWQoKSkge1xyXG4gICAgICAgIGNoZWNrRW50aXR5S2V5KHRoaXMsIGVudGl0eSk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gYXR0YWNoZWRFbnRpdHkgPT09IGVudGl0eSBFWENFUFQgaW4gdGhlIGNhc2Ugb2YgYSBtZXJnZS5cclxuICAgICAgYXR0YWNoZWRFbnRpdHkgPSB0aGlzLl9hdHRhY2hFbnRpdHlDb3JlKGVudGl0eSwgZXNTeW1ib2wsIG1zU3ltYm9sKTtcclxuICAgICAgYXNwZWN0Ll9pblByb2Nlc3NFbnRpdHkgPSBhdHRhY2hlZEVudGl0eTtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICAvLyBlbnRpdHkgKCBub3QgYXR0YWNoZWRFbnRpdHkpIGlzIGRlbGliZXJhdGUgaGVyZS5cclxuICAgICAgICBhdHRhY2hSZWxhdGVkRW50aXRpZXModGhpcywgZW50aXR5LCBlc1N5bWJvbCwgbXNTeW1ib2wpO1xyXG4gICAgICB9IGZpbmFsbHkge1xyXG4gICAgICAgIC8vIGluc3VyZSB0aGF0IF9pblByb2Nlc3NFbnRpdHkgaXMgY2xlYXJlZC5cclxuICAgICAgICBhc3BlY3QuX2luUHJvY2Vzc0VudGl0eSA9IHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICBpZiAodGhpcy52YWxpZGF0aW9uT3B0aW9ucy52YWxpZGF0ZU9uQXR0YWNoKSB7XHJcbiAgICAgIGF0dGFjaGVkRW50aXR5LmVudGl0eUFzcGVjdC52YWxpZGF0ZUVudGl0eSgpO1xyXG4gICAgfVxyXG4gICAgaWYgKCFlc1N5bWJvbC5pc1VuY2hhbmdlZCgpKSB7XHJcbiAgICAgIHRoaXMuX25vdGlmeVN0YXRlQ2hhbmdlKGF0dGFjaGVkRW50aXR5LCB0cnVlKTtcclxuICAgIH1cclxuICAgIHRoaXMuZW50aXR5Q2hhbmdlZC5wdWJsaXNoKHsgZW50aXR5QWN0aW9uOiBFbnRpdHlBY3Rpb24uQXR0YWNoLCBlbnRpdHk6IGF0dGFjaGVkRW50aXR5IH0pO1xyXG5cclxuICAgIHJldHVybiBhdHRhY2hlZEVudGl0eTtcclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICBEZXRhY2hlcyBhbiBlbnRpdHkgZnJvbSB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgLy8gYXNzdW1lIGN1c3QxIGlzIGEgY3VzdG9tZXIgRW50aXR5IHByZXZpb3VzbHkgYXR0YWNoZWQgdG8gZW0xXHJcbiAgPiAgICAgZW0xLmRldGFjaEVudGl0eShjdXN0MSk7XHJcbiAgPiAgICAgLy8gZW0xIHdpbGwgbm93IG5vIGxvbmdlciBjb250YWluIGN1c3QxIGFuZCBjdXN0MSB3aWxsIGhhdmUgYW5cclxuICA+ICAgICAvLyBlbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUgb2YgRW50aXR5U3RhdGUuRGV0YWNoZWRcclxuICBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBkZXRhY2guXHJcbiAgQHJldHVybiBXaGV0aGVyIHRoZSBlbnRpdHkgY291bGQgYmUgZGV0YWNoZWQuIFRoaXMgd2lsbCByZXR1cm4gZmFsc2UgaWYgdGhlIGVudGl0eSBpcyBhbHJlYWR5IGRldGFjaGVkIG9yIHdhcyBuZXZlciBhdHRhY2hlZC5cclxuICAqKi9cclxuICBkZXRhY2hFbnRpdHkoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eSwgXCJlbnRpdHlcIikuaXNFbnRpdHkoKS5jaGVjaygpO1xyXG4gICAgbGV0IGFzcGVjdCA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICBpZiAoIWFzcGVjdCkge1xyXG4gICAgICAvLyBubyBhc3BlY3QgbWVhbnMgaW4gY291bGRuJ3QgYXBwZWFyIGluIGFueSBncm91cFxyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGFzcGVjdC5lbnRpdHlNYW5hZ2VyICE9PSB0aGlzKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgZW50aXR5IGRvZXMgbm90IGJlbG9uZyB0byB0aGlzIEVudGl0eU1hbmFnZXIuXCIpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFzcGVjdC5zZXREZXRhY2hlZCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgRmV0Y2hlcyB0aGUgbWV0YWRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBFbnRpdHlNYW5hZ2VyJ3MgY3VycmVudCAnc2VydmljZU5hbWUnLiAgVGhpcyBjYWxsXHJcbiAgb2NjdXJzIGludGVybmFsbHkgYmVmb3JlIHRoZSBmaXJzdCBxdWVyeSB0byBhbnkgc2VydmljZSBpZiB0aGUgbWV0YWRhdGEgaGFzbid0IGFscmVhZHkgYmVlblxyXG4gIGxvYWRlZC4gX19Bc3luY19fXHJcblxyXG4gIFVzdWFsbHkgeW91IHdpbGwgbm90IGFjdHVhbGx5IHByb2Nlc3MgdGhlIHJlc3VsdHMgb2YgYSBmZXRjaE1ldGFkYXRhIGNhbGwgZGlyZWN0bHksIGJ1dCB3aWxsIGluc3RlYWRcclxuICBhc2sgZm9yIHRoZSBtZXRhZGF0YSBmcm9tIHRoZSBFbnRpdHlNYW5hZ2VyIGFmdGVyIHRoZSBmZXRjaE1ldGFkYXRhIGNhbGwgcmV0dXJucy5cclxuICA+ICAgICBsZXQgZW0xID0gbmV3IEVudGl0eU1hbmFnZXIoIFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIik7XHJcbiAgPiAgICAgZW0xLmZldGNoTWV0YWRhdGEoKVxyXG4gID4gICAgICAgLnRoZW4oZnVuY3Rpb24oKSB7XHJcbiAgPiAgICAgICAgICAgbGV0IG1ldGFkYXRhU3RvcmUgPSBlbTEubWV0YWRhdGFTdG9yZTtcclxuICA+ICAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgd2l0aCB0aGUgbWV0YWRhdGFcclxuICA+ICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uKGV4Y2VwdGlvbikge1xyXG4gID4gICAgICAgICAgIC8vIGhhbmRsZSBleGNlcHRpb24gaGVyZVxyXG4gID4gICAgICAgfSk7XHJcbiAgXHJcbiAgQHBhcmFtIGNhbGxiYWNrIC0gRnVuY3Rpb24gY2FsbGVkIG9uIHN1Y2Nlc3MuXHJcbiAgQHBhcmFtIGVycm9yQ2FsbGJhY2sgLSBGdW5jdGlvbiBjYWxsZWQgb24gZmFpbHVyZS5cclxuICBAcmV0dXJuIHtQcm9taXNlfVxyXG4gICAgLSBzY2hlbWEge09iamVjdH0gVGhlIHJhdyBTY2hlbWEgb2JqZWN0IGZyb20gbWV0YWRhdGEgcHJvdmlkZXIgLSBCZWNhdXNlIHRoaXMgc2NoZW1hIHdpbGwgZGlmZmVyIGRlcGVuZGluZyBvbiB0aGUgbWV0YWRhdGEgcHJvdmlkZXJcclxuICAgICAgICBpdCBpcyB1c3VhbGx5IGJldHRlciB0byBhY2Nlc3MgbWV0YWRhdGEgdmlhIHRoZSAnbWV0YWRhdGFTdG9yZScgcHJvcGVydHkgb2YgdGhlIEVudGl0eU1hbmFnZXIgaW5zdGVhZCBvZiB1c2luZyB0aGlzICdyYXcnIGRhdGEuXHJcbiAgKiovXHJcbiAgZmV0Y2hNZXRhZGF0YShkYXRhU2VydmljZT86IERhdGFTZXJ2aWNlLCBjYWxsYmFjaz86IENhbGxiYWNrLCBlcnJvckNhbGxiYWNrPzogRXJyb3JDYWxsYmFjaykge1xyXG4gICAgaWYgKHR5cGVvZiAoZGF0YVNlcnZpY2UpID09PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgICAgLy8gbGVnYWN5IHN1cHBvcnQgZm9yIHdoZW4gZGF0YVNlcnZpY2Ugd2FzIG5vdCBhbiBhcmcuIGkuZS4gZmlyc3QgYXJnIHdhcyBjYWxsYmFja1xyXG4gICAgICBlcnJvckNhbGxiYWNrID0gY2FsbGJhY2s7XHJcbiAgICAgIGNhbGxiYWNrID0gZGF0YVNlcnZpY2U7XHJcbiAgICAgIGRhdGFTZXJ2aWNlID0gdW5kZWZpbmVkO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgYXNzZXJ0UGFyYW0oZGF0YVNlcnZpY2UsIFwiZGF0YVNlcnZpY2VcIikuaXNJbnN0YW5jZU9mKERhdGFTZXJ2aWNlKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgICAgYXNzZXJ0UGFyYW0oY2FsbGJhY2ssIFwiY2FsbGJhY2tcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgICBhc3NlcnRQYXJhbShlcnJvckNhbGxiYWNrLCBcImVycm9yQ2FsbGJhY2tcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBwcm9taXNlID0gdGhpcy5tZXRhZGF0YVN0b3JlLmZldGNoTWV0YWRhdGEoZGF0YVNlcnZpY2UgfHwgdGhpcy5kYXRhU2VydmljZSk7XHJcbiAgICByZXR1cm4gcHJvbWlzZVdpdGhDYWxsYmFja3MocHJvbWlzZSwgY2FsbGJhY2ssIGVycm9yQ2FsbGJhY2spO1xyXG4gIH1cclxuXHJcblxyXG4gIGV4ZWN1dGVRdWVyeShxdWVyeTogc3RyaW5nLCBjYWxsYmFjaz86IFF1ZXJ5U3VjY2Vzc0NhbGxiYWNrLCBlcnJvckNhbGxiYWNrPzogUXVlcnlFcnJvckNhbGxiYWNrKTogUHJvbWlzZTxRdWVyeVJlc3VsdD47XHJcbiAgZXhlY3V0ZVF1ZXJ5KHF1ZXJ5OiBFbnRpdHlRdWVyeSwgY2FsbGJhY2s/OiBRdWVyeVN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IFF1ZXJ5RXJyb3JDYWxsYmFjayk6IFByb21pc2U8UXVlcnlSZXN1bHQ+O1xyXG4gIC8qKlxyXG4gIEV4ZWN1dGVzIHRoZSBzcGVjaWZpZWQgcXVlcnkuIF9fQXN5bmNfXyBcclxuICBcclxuICA+ICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcihzZXJ2aWNlTmFtZSk7XHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiT3JkZXJzXCIpO1xyXG4gID4gICAgIGVtLmV4ZWN1dGVRdWVyeShxdWVyeSkudGhlbiggZnVuY3Rpb24oZGF0YSkge1xyXG4gID4gICAgICAgICBsZXQgb3JkZXJzID0gZGF0YS5yZXN1bHRzO1xyXG4gID4gICAgICAgICAuLi4gcXVlcnkgcmVzdWx0cyBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgIH0pLmNhdGNoKCBmdW5jdGlvbihlcnIpIHtcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IGZhaWx1cmUgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KTtcclxuXHJcbiAgb3Igd2l0aCBjYWxsYmFja3NcclxuICA+ICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcihzZXJ2aWNlTmFtZSk7XHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiT3JkZXJzXCIpO1xyXG4gID4gICAgIGVtLmV4ZWN1dGVRdWVyeShxdWVyeSxcclxuICA+ICAgICAgICAgZnVuY3Rpb24oZGF0YSkge1xyXG4gID4gICAgICAgICAgICAgbGV0IG9yZGVycyA9IGRhdGEucmVzdWx0cztcclxuICA+ICAgICAgICAgICAgIC4uLiBxdWVyeSByZXN1bHRzIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgICAgIH0sXHJcbiAgPiAgICAgICAgIGZ1bmN0aW9uKGVycikge1xyXG4gID4gICAgICAgICAgICAgLi4uIHF1ZXJ5IGZhaWx1cmUgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICAgICAgfSk7XHJcblxyXG4gIEVpdGhlciB3YXkgdGhpcyBtZXRob2QgaXMgdGhlIHNhbWUgYXMgY2FsbGluZyB0aGUgVGhlIFtbRW50aXR5UXVlcnldXSAnZXhlY3V0ZScgbWV0aG9kLlxyXG4gID4gICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKHNlcnZpY2VOYW1lKTtcclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJPcmRlcnNcIikudXNpbmcoZW0pO1xyXG4gID4gICAgIHF1ZXJ5LmV4ZWN1dGUoKS50aGVuKCBmdW5jdGlvbihkYXRhKSB7XHJcbiAgPiAgICAgICAgIGxldCBvcmRlcnMgPSBkYXRhLnJlc3VsdHM7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSByZXN1bHRzIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgfSkuY2F0Y2goIGZ1bmN0aW9uKGVycikge1xyXG4gID4gICAgICAgICAuLi4gcXVlcnkgZmFpbHVyZSBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgIH0pO1xyXG4gIEBwYXJhbSBxdWVyeSAtIFRoZSBbW0VudGl0eVF1ZXJ5XV0gb3IgT0RhdGEgcXVlcnkgc3RyaW5nIHRvIGV4ZWN1dGUuXHJcbiAgQHBhcmFtIGNhbGxiYWNrIC0gRnVuY3Rpb24gY2FsbGVkIG9uIHN1Y2Nlc3MuXHJcbiAgQHBhcmFtIGVycm9yQ2FsbGJhY2sgLSB7RnVuY3Rpb259IEZ1bmN0aW9uIGNhbGxlZCBvbiBmYWlsdXJlLlxyXG4gIEByZXR1cm4gUHJvbWlzZSBvZiBcclxuICAgIC0gcmVzdWx0cyAtIEFuIGFycmF5IG9mIGVudGl0aWVzXHJcbiAgICAtIHJldHJpZXZlZEVudGl0aWVzIC0gQSBhcnJheSBvZiBhbGwgb2YgdGhlIGVudGl0aWVzIHJldHVybmVkIGJ5IHRoZSBxdWVyeS4gIERpZmZlcnMgZnJvbSByZXN1bHRzIChhYm92ZSkgd2hlbiAuZXhwYW5kKCkgaXMgdXNlZC5cclxuICAgIC0gcXVlcnkgLSBUaGUgb3JpZ2luYWwgW1tFbnRpdHlRdWVyeV1dIG9yIHF1ZXJ5IHN0cmluZ1xyXG4gICAgLSBlbnRpdHlNYW5hZ2VyIC0gIFRoZSBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgLSBodHRwUmVzcG9uc2UgLSBUaGUgW1tJSHR0cFJlc3BvbnNlXV0gcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyLlxyXG4gICAgLSBpbmxpbmVDb3VudCAtICBPbmx5IGF2YWlsYWJsZSBpZiAnaW5saW5lQ291bnQodHJ1ZSknIHdhcyBhcHBsaWVkIHRvIHRoZSBxdWVyeS4gIFJldHVybnMgdGhlIGNvdW50IG9mXHJcbiAgICBpdGVtcyB0aGF0IHdvdWxkIGhhdmUgYmVlbiByZXR1cm5lZCBieSB0aGUgcXVlcnkgYmVmb3JlIGFwcGx5aW5nIGFueSBza2lwIG9yIHRha2Ugb3BlcmF0b3JzLCBidXQgYWZ0ZXIgYW55IGZpbHRlci93aGVyZSBwcmVkaWNhdGVzXHJcbiAgICB3b3VsZCBoYXZlIGJlZW4gYXBwbGllZC5cclxuICAqKi9cclxuICBleGVjdXRlUXVlcnkocXVlcnk6IEVudGl0eVF1ZXJ5IHwgc3RyaW5nLCBjYWxsYmFjaz86IFF1ZXJ5U3VjY2Vzc0NhbGxiYWNrLCBlcnJvckNhbGxiYWNrPzogUXVlcnlFcnJvckNhbGxiYWNrKSB7XHJcbiAgICBhc3NlcnRQYXJhbShxdWVyeSwgXCJxdWVyeVwiKS5pc0luc3RhbmNlT2YoRW50aXR5UXVlcnkpLm9yKCkuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oY2FsbGJhY2ssIFwiY2FsbGJhY2tcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oZXJyb3JDYWxsYmFjaywgXCJlcnJvckNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGxldCBwcm9taXNlOiBQcm9taXNlPGFueT47XHJcbiAgICAvLyAncmVzb2x2ZScgbWV0aG9kcyBjcmVhdGUgYSBuZXcgdHlwZWQgb2JqZWN0IHdpdGggYWxsIG9mIGl0cyBwcm9wZXJ0aWVzIGZ1bGx5IHJlc29sdmVkIGFnYWluc3QgYSBsaXN0IG9mIHNvdXJjZXMuXHJcbiAgICAvLyBUaG91Z2h0IGFib3V0IGNyZWF0aW5nIGEgJ25vcm1hbGl6ZWQnIHF1ZXJ5IHdpdGggdGhlc2UgJ3Jlc29sdmVkJyBvYmplY3RzXHJcbiAgICAvLyBidXQgZGVjaWRlZCBub3QgdG8gYmVjYXVzZSB0aGUgJ3F1ZXJ5JyBtYXkgbm90IGJlIGFuIEVudGl0eVF1ZXJ5IChpdCBjYW4gYmUgYSBzdHJpbmcpIGFuZCBoZW5jZSBtaWdodCBub3QgaGF2ZSBhIHF1ZXJ5T3B0aW9ucyBvciBkYXRhU2VydmljZXMgcHJvcGVydHkgb24gaXQuXHJcbiAgICBsZXQgcXVlcnlPcHRpb25zID0gUXVlcnlPcHRpb25zLnJlc29sdmUoWyhxdWVyeSBhcyBhbnkpLnF1ZXJ5T3B0aW9ucywgdGhpcy5xdWVyeU9wdGlvbnMsIFF1ZXJ5T3B0aW9ucy5kZWZhdWx0SW5zdGFuY2VdKTtcclxuICAgIGxldCBkYXRhU2VydmljZSA9IERhdGFTZXJ2aWNlLnJlc29sdmUoWyhxdWVyeSBhcyBhbnkpLmRhdGFTZXJ2aWNlISwgdGhpcy5kYXRhU2VydmljZV0pO1xyXG5cclxuICAgIGlmICgoIWRhdGFTZXJ2aWNlLmhhc1NlcnZlck1ldGFkYXRhKSB8fCB0aGlzLm1ldGFkYXRhU3RvcmUuaGFzTWV0YWRhdGFGb3IoZGF0YVNlcnZpY2Uuc2VydmljZU5hbWUpKSB7XHJcbiAgICAgIHByb21pc2UgPSBleGVjdXRlUXVlcnlDb3JlKHRoaXMsIHF1ZXJ5LCBxdWVyeU9wdGlvbnMsIGRhdGFTZXJ2aWNlKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHByb21pc2UgPSB0aGlzLmZldGNoTWV0YWRhdGEoZGF0YVNlcnZpY2UpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgIHJldHVybiBleGVjdXRlUXVlcnlDb3JlKHRoaXMsIHF1ZXJ5LCBxdWVyeU9wdGlvbnMsIGRhdGFTZXJ2aWNlKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHByb21pc2VXaXRoQ2FsbGJhY2tzKHByb21pc2UsIGNhbGxiYWNrLCBlcnJvckNhbGxiYWNrIGFzIEVycm9yQ2FsbGJhY2spO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgRXhlY3V0ZXMgdGhlIHNwZWNpZmllZCBxdWVyeSBhZ2FpbnN0IHRoaXMgRW50aXR5TWFuYWdlcidzIGxvY2FsIGNhY2hlLlxyXG5cclxuICBCZWNhdXNlIHRoaXMgbWV0aG9kIGlzIGV4ZWN1dGVkIGltbWVkaWF0ZWx5IHRoZXJlIGlzIG5vIG5lZWQgZm9yIGEgcHJvbWlzZSBvciBhIGNhbGxiYWNrXHJcbiAgPiAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKTtcclxuICA+ICAgICBsZXQgb3JkZXJzID0gZW0uZXhlY3V0ZVF1ZXJ5TG9jYWxseShxdWVyeSk7XHJcblxyXG4gIE5vdGUgdGhhdCB0aGlzIGNhbiBhbHNvIGJlIGFjY29tcGxpc2hlZCB1c2luZyB0aGUgJ2V4ZWN1dGVRdWVyeScgbWV0aG9kIHdpdGhcclxuICBhIEZldGNoU3RyYXRlZ3kgb2YgRnJvbUxvY2FsQ2FjaGUgYW5kIG1ha2luZyB1c2Ugb2YgdGhlIFByb21pc2Ugb3IgY2FsbGJhY2tcclxuICA+ICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcihzZXJ2aWNlTmFtZSk7XHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiT3JkZXJzXCIpLnVzaW5nKEZldGNoU3RyYXRlZ3kuRnJvbUxvY2FsQ2FjaGUpO1xyXG4gID4gICAgIGVtLmV4ZWN1dGVRdWVyeShxdWVyeSkudGhlbiggZnVuY3Rpb24oZGF0YSkge1xyXG4gID4gICAgICAgICBsZXQgb3JkZXJzID0gZGF0YS5yZXN1bHRzO1xyXG4gID4gICAgICAgICAuLi4gcXVlcnkgcmVzdWx0cyBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgIH0pLmNhdGNoKCBmdW5jdGlvbihlcnIpIHtcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IGZhaWx1cmUgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KTtcclxuICBAcGFyYW0gcXVlcnkgLSBUaGUgW1tFbnRpdHlRdWVyeV1dIHRvIGV4ZWN1dGUuXHJcbiAgQHJldHVybiAge0FycmF5IG9mIEVudGl0eX0gIEFycmF5IG9mIGVudGl0aWVzIGZyb20gY2FjaGUgdGhhdCBzYXRpc2Z5IHRoZSBxdWVyeVxyXG4gICoqL1xyXG4gIGV4ZWN1dGVRdWVyeUxvY2FsbHkocXVlcnk6IEVudGl0eVF1ZXJ5KSB7XHJcbiAgICByZXR1cm4gZXhlY3V0ZVF1ZXJ5TG9jYWxseUNvcmUodGhpcywgcXVlcnkpLnJlc3VsdHM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBTYXZlcyBlaXRoZXIgYSBsaXN0IG9mIHNwZWNpZmllZCBlbnRpdGllcyBvciBhbGwgY2hhbmdlZCBlbnRpdGllcyB3aXRoaW4gdGhpcyBFbnRpdHlNYW5hZ2VyLiBJZiB0aGVyZSBhcmUgbm8gY2hhbmdlcyB0byBhbnkgb2YgdGhlIGVudGl0aWVzXHJcbiAgc3BlY2lmaWVkIHRoZW4gdGhlcmUgd2lsbCBiZSBubyBzZXJ2ZXIgc2lkZSBjYWxsIG1hZGUgYnV0IGEgdmFsaWQgJ2VtcHR5JyBzYXZlUmVzdWx0IHdpbGwgc3RpbGwgYmUgcmV0dXJuZWQuIF9fQXN5bmNfX1xyXG5cclxuICBPZnRlbiB3ZSB3aWxsIGJlIHNhdmluZyBhbGwgb2YgdGhlIGVudGl0aWVzIHdpdGhpbiBhbiBFbnRpdHlNYW5hZ2VyIHRoYXQgYXJlIGVpdGhlciBhZGRlZCwgbW9kaWZpZWQgb3IgZGVsZXRlZFxyXG4gIGFuZCB3ZSB3aWxsIGxldCB0aGUgJ3NhdmVDaGFuZ2VzJyBjYWxsIGRldGVybWluZSB3aGljaCBlbnRpdGllcyB0aGVzZSBhcmUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICAvLyBUaGlzIGNvdWxkIGluY2x1ZGUgYWRkZWQsIG1vZGlmaWVkIGFuZCBkZWxldGVkIGVudGl0aWVzLlxyXG4gID4gICAgICBlbS5zYXZlQ2hhbmdlcygpLnRoZW4oZnVuY3Rpb24oc2F2ZVJlc3VsdCkge1xyXG4gID4gICAgICAgICAgbGV0IHNhdmVkRW50aXRpZXMgPSBzYXZlUmVzdWx0LmVudGl0aWVzO1xyXG4gID4gICAgICAgICAgbGV0IGtleU1hcHBpbmdzID0gc2F2ZVJlc3VsdC5rZXlNYXBwaW5ncztcclxuICA+ICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGUpIHtcclxuICA+ICAgICAgICAgIC8vIGUgaXMgYW55IGV4Y2VwdGlvbiB0aGF0IHdhcyB0aHJvd24uXHJcbiAgPiAgICAgIH0pO1xyXG5cclxuICBCdXQgd2UgY2FuIGFsc28gY29udHJvbCBleGFjdGx5IHdoaWNoIGVudGl0aWVzIHRvIHNhdmUgYW5kIGNhbiBzcGVjaWZ5IHNwZWNpZmljIFNhdmVPcHRpb25zXHJcblxyXG4gID4gICAgICAvLyBhc3N1bWUgZW50aXRpZXNUb1NhdmUgaXMgYW4gYXJyYXkgb2YgZW50aXRpZXMgdG8gc2F2ZS5cclxuICA+ICAgICAgbGV0IHNhdmVPcHRpb25zID0gbmV3IFNhdmVPcHRpb25zKHsgYWxsb3dDb25jdXJyZW50U2F2ZXM6IHRydWUgfSk7XHJcbiAgPiAgICAgIGVtLnNhdmVDaGFuZ2VzKGVudGl0aWVzVG9TYXZlLCBzYXZlT3B0aW9ucykudGhlbihmdW5jdGlvbihzYXZlUmVzdWx0KSB7XHJcbiAgPiAgICAgICAgICBsZXQgc2F2ZWRFbnRpdGllcyA9IHNhdmVSZXN1bHQuZW50aXRpZXM7XHJcbiAgPiAgICAgICAgICBsZXQga2V5TWFwcGluZ3MgPSBzYXZlUmVzdWx0LmtleU1hcHBpbmdzO1xyXG4gID4gICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZSkge1xyXG4gID4gICAgICAgICAgLy8gZSBpcyBhbnkgZXhjZXB0aW9uIHRoYXQgd2FzIHRocm93bi5cclxuICA+ICAgICAgfSk7XHJcblxyXG4gIENhbGxiYWNrIG1ldGhvZHMgY2FuIGFsc28gYmUgdXNlZFxyXG4gID4gICAgICBlbS5zYXZlQ2hhbmdlcyhlbnRpdGllc1RvU2F2ZSwgbnVsbCxcclxuICA+ICAgICAgICAgIGZ1bmN0aW9uKHNhdmVSZXN1bHQpIHtcclxuICA+ICAgICAgICAgICAgICBsZXQgc2F2ZWRFbnRpdGllcyA9IHNhdmVSZXN1bHQuZW50aXRpZXM7XHJcbiAgPiAgICAgICAgICAgICAgbGV0IGtleU1hcHBpbmdzID0gc2F2ZVJlc3VsdC5rZXlNYXBwaW5ncztcclxuICA+ICAgICAgICAgIH0sIGZ1bmN0aW9uIChlKSB7XHJcbiAgPiAgICAgICAgICAgICAgLy8gZSBpcyBhbnkgZXhjZXB0aW9uIHRoYXQgd2FzIHRocm93bi5cclxuICA+ICAgICAgICAgIH1cclxuICA+ICAgICAgKTtcclxuXHJcbiAgQHBhcmFtIGVudGl0aWVzIC0gVGhlIGxpc3Qgb2YgZW50aXRpZXMgdG8gc2F2ZS5cclxuICBFdmVyeSBlbnRpdHkgaW4gdGhhdCBsaXN0IHdpbGwgYmUgc2VudCB0byB0aGUgc2VydmVyLCB3aGV0aGVyIGNoYW5nZWQgb3IgdW5jaGFuZ2VkLFxyXG4gIGFzIGxvbmcgYXMgaXQgaXMgYXR0YWNoZWQgdG8gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gIElmIHRoaXMgcGFyYW1ldGVyIGlzIG9taXR0ZWQsIG51bGwgb3IgZW1wdHkgKHRoZSB1c3VhbCBjYXNlKSxcclxuICBldmVyeSBlbnRpdHkgd2l0aCBwZW5kaW5nIGNoYW5nZXMgaW4gdGhpcyBFbnRpdHlNYW5hZ2VyIHdpbGwgYmUgc2F2ZWQuXHJcbiAgQHBhcmFtIHNhdmVPcHRpb25zIC0gW1tTYXZlT3B0aW9uc11dIGZvciB0aGUgc2F2ZSAtIHdpbGwgZGVmYXVsdCB0b1xyXG4gIFtbRW50aXR5TWFuYWdlci5zYXZlT3B0aW9uc11dIGlmIG51bGwuXHJcbiAgQHBhcmFtIGNhbGxiYWNrIC0gIEZ1bmN0aW9uIGNhbGxlZCBvbiBzdWNjZXNzLlxyXG4gIEBwYXJhbSBlcnJvckNhbGxiYWNrIC0gRnVuY3Rpb24gY2FsbGVkIG9uIGZhaWx1cmUuXHJcbiAgQHJldHVybiB7UHJvbWlzZX0gUHJvbWlzZVxyXG4gICoqL1xyXG4gIHNhdmVDaGFuZ2VzKGVudGl0aWVzPzogRW50aXR5W10gfCBudWxsLCBzYXZlT3B0aW9ucz86IFNhdmVPcHRpb25zLCBjYWxsYmFjaz86IEZ1bmN0aW9uLCBlcnJvckNhbGxiYWNrPzogRnVuY3Rpb24pIHtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0aWVzLCBcImVudGl0aWVzXCIpLmlzT3B0aW9uYWwoKS5pc0FycmF5KCkuaXNFbnRpdHkoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oc2F2ZU9wdGlvbnMsIFwic2F2ZU9wdGlvbnNcIikuaXNJbnN0YW5jZU9mKFNhdmVPcHRpb25zKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGNhbGxiYWNrLCBcImNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGVycm9yQ2FsbGJhY2ssIFwiZXJyb3JDYWxsYmFja1wiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcblxyXG4gICAgc2F2ZU9wdGlvbnMgPSBzYXZlT3B0aW9ucyB8fCB0aGlzLnNhdmVPcHRpb25zIHx8IFNhdmVPcHRpb25zLmRlZmF1bHRJbnN0YW5jZTtcclxuXHJcbiAgICBsZXQgZW50aXRpZXNUb1NhdmUgPSBnZXRFbnRpdGllc1RvU2F2ZSh0aGlzLCBlbnRpdGllcyA/IGVudGl0aWVzIDogdW5kZWZpbmVkKTtcclxuXHJcbiAgICBpZiAoZW50aXRpZXNUb1NhdmUubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIGxldCByZXN1bHQgPSB7IGVudGl0aWVzOiBbXSwga2V5TWFwcGluZ3M6IFtdIH0gYXMgU2F2ZVJlc3VsdDtcclxuICAgICAgaWYgKGNhbGxiYWNrKSBjYWxsYmFjayhyZXN1bHQpO1xyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFzYXZlT3B0aW9ucy5hbGxvd0NvbmN1cnJlbnRTYXZlcykge1xyXG4gICAgICBsZXQgYW55UGVuZGluZ1NhdmVzID0gZW50aXRpZXNUb1NhdmUuc29tZShmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICAgICAgcmV0dXJuIGVudGl0eS5lbnRpdHlBc3BlY3QuaXNCZWluZ1NhdmVkO1xyXG4gICAgICB9KTtcclxuICAgICAgaWYgKGFueVBlbmRpbmdTYXZlcykge1xyXG4gICAgICAgIGxldCBlcnIgPSBuZXcgRXJyb3IoXCJDb25jdXJyZW50IHNhdmVzIG5vdCBhbGxvd2VkIC0gU2F2ZU9wdGlvbnMuYWxsb3dDb25jdXJyZW50U2F2ZXMgaXMgZmFsc2VcIik7XHJcbiAgICAgICAgaWYgKGVycm9yQ2FsbGJhY2spIGVycm9yQ2FsbGJhY2soZXJyKTtcclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNsZWFyU2VydmVyRXJyb3JzKGVudGl0aWVzVG9TYXZlKTtcclxuXHJcbiAgICBsZXQgdmFsRXJyb3IgPSB0aGlzLnNhdmVDaGFuZ2VzVmFsaWRhdGVPbkNsaWVudChlbnRpdGllc1RvU2F2ZSk7XHJcbiAgICBpZiAodmFsRXJyb3IpIHtcclxuICAgICAgaWYgKGVycm9yQ2FsbGJhY2spIGVycm9yQ2FsbGJhY2sodmFsRXJyb3IpO1xyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QodmFsRXJyb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBkYXRhU2VydmljZSA9IERhdGFTZXJ2aWNlLnJlc29sdmUoW3NhdmVPcHRpb25zLmRhdGFTZXJ2aWNlLCB0aGlzLmRhdGFTZXJ2aWNlXSk7XHJcbiAgICBsZXQgc2F2ZUNvbnRleHQ6IFNhdmVDb250ZXh0ID0ge1xyXG4gICAgICBlbnRpdHlNYW5hZ2VyOiB0aGlzLFxyXG4gICAgICBkYXRhU2VydmljZTogZGF0YVNlcnZpY2UsXHJcbiAgICAgIHByb2Nlc3NTYXZlZEVudGl0aWVzOiBwcm9jZXNzU2F2ZWRFbnRpdGllcyxcclxuICAgICAgcmVzb3VyY2VOYW1lOiBzYXZlT3B0aW9ucy5yZXNvdXJjZU5hbWUgfHwgdGhpcy5zYXZlT3B0aW9ucy5yZXNvdXJjZU5hbWUgfHwgXCJTYXZlQ2hhbmdlc1wiXHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFRPRE86IG5lZWQgdG8gY2hlY2sgdGhhdCBpZiB3ZSBhcmUgZG9pbmcgYSBwYXJ0aWFsIHNhdmUgdGhhdCBhbGwgZW50aXRpZXMgd2hvc2UgdGVtcCBrZXlzXHJcbiAgICAvLyBhcmUgcmVmZXJlbmNlZCBhcmUgYWxzbyBpbiB0aGUgcGFydGlhbCBzYXZlIGdyb3VwXHJcblxyXG4gICAgbGV0IHNhdmVCdW5kbGUgPSB7IGVudGl0aWVzOiBlbnRpdGllc1RvU2F2ZSwgc2F2ZU9wdGlvbnM6IHNhdmVPcHRpb25zIH07XHJcblxyXG5cclxuICAgIHRyeSB7IC8vIEd1YXJkIGFnYWluc3QgZXhjZXB0aW9uIHRocm93biBpbiBkYXRhc2VydmljZSBhZGFwdGVyIGJlZm9yZSBpdCBnb2VzIGFzeW5jXHJcbiAgICAgIHVwZGF0ZUNvbmN1cnJlbmN5UHJvcGVydGllcyhlbnRpdGllc1RvU2F2ZSk7XHJcbiAgICAgIHJldHVybiBkYXRhU2VydmljZS5hZGFwdGVySW5zdGFuY2UhLnNhdmVDaGFuZ2VzKHNhdmVDb250ZXh0LCBzYXZlQnVuZGxlKVxyXG4gICAgICAgIC50aGVuKHNhdmVTdWNjZXNzKS50aGVuKChyKSA9PiByLCBzYXZlRmFpbCk7XHJcbiAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgLy8gdW5kbyB0aGUgbWFya2luZyBieSB1cGRhdGVDb25jdXJyZW5jeVByb3BlcnRpZXNcclxuICAgICAgbWFya0lzQmVpbmdTYXZlZChlbnRpdGllc1RvU2F2ZSwgZmFsc2UpO1xyXG4gICAgICBpZiAoZXJyb3JDYWxsYmFjaykgZXJyb3JDYWxsYmFjayhlcnIpO1xyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBzYXZlU3VjY2VzcyhzYXZlUmVzdWx0OiBTYXZlUmVzdWx0KSB7XHJcbiAgICAgIGxldCBlbSA9IHNhdmVDb250ZXh0LmVudGl0eU1hbmFnZXI7XHJcbiAgICAgIG1hcmtJc0JlaW5nU2F2ZWQoZW50aXRpZXNUb1NhdmUsIGZhbHNlKTtcclxuICAgICAgbGV0IHNhdmVkRW50aXRpZXMgPSBzYXZlQ29udGV4dC5wcm9jZXNzU2F2ZWRFbnRpdGllcyhzYXZlUmVzdWx0KTtcclxuICAgICAgc2F2ZVJlc3VsdC5lbnRpdGllcyA9IHNhdmVkRW50aXRpZXM7XHJcblxyXG4gICAgICAvLyB1cGRhdGUgX2hhc0NoYW5nZXMgYWZ0ZXIgc2F2ZS5cclxuICAgICAgZW0uX3NldEhhc0NoYW5nZXMoKTtcclxuXHJcbiAgICAgIC8vIGNhbid0IGRvIHRoaXMgYW55bW9yZSBiZWNhdXNlIG90aGVyIGNoYW5nZXMgbWlnaHQgaGF2ZSBiZWVuIG1hZGUgd2hpbGUgc2F2ZWQgZW50aXRpZXMgaW4gZmxpZ2h0LlxyXG4gICAgICAvLyAgICAgIGxldCBoYXNDaGFuZ2VzID0gKGlzRnVsbFNhdmUgJiYgaGF2ZVNhbWVDb250ZW50cyhlbnRpdGllc1RvU2F2ZSwgc2F2ZWRFbnRpdGllcykpID8gZmFsc2UgOiBudWxsO1xyXG4gICAgICAvLyAgICAgIGVtLl9zZXRIYXNDaGFuZ2VzKGhhc0NoYW5nZXMpO1xyXG5cclxuICAgICAgaWYgKGNhbGxiYWNrKSBjYWxsYmFjayhzYXZlUmVzdWx0KTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShzYXZlUmVzdWx0KTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBwcm9jZXNzU2F2ZWRFbnRpdGllcyhzYXZlUmVzdWx0OiBTYXZlUmVzdWx0KSB7XHJcbiAgICAgIGxldCBzYXZlZEVudGl0aWVzID0gc2F2ZVJlc3VsdC5lbnRpdGllcztcclxuICAgICAgbGV0IGRlbGV0ZWRLZXlzID0gc2F2ZVJlc3VsdC5kZWxldGVkS2V5cyB8fCBbXTtcclxuICAgICAgaWYgKHNhdmVkRW50aXRpZXMubGVuZ3RoID09PSAwICYmIGRlbGV0ZWRLZXlzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgIHJldHVybiBbXTtcclxuICAgICAgfVxyXG4gICAgICBsZXQga2V5TWFwcGluZ3MgPSBzYXZlUmVzdWx0LmtleU1hcHBpbmdzO1xyXG4gICAgICBsZXQgZW0gPSBzYXZlQ29udGV4dC5lbnRpdHlNYW5hZ2VyO1xyXG5cclxuICAgICAgLy8gbXVzdCBvY2N1ciBvdXRzaWRlIG9mIGlzTG9hZGluZyBibG9ja1xyXG4gICAgICBmaXh1cEtleXMoZW0sIGtleU1hcHBpbmdzKTtcclxuXHJcbiAgICAgIGNvcmUudXNpbmcoZW0sIFwiaXNMb2FkaW5nXCIsIHRydWUsICgpID0+IHtcclxuXHJcbiAgICAgICAgbGV0IG1hcHBpbmdDb250ZXh0ID0gbmV3IE1hcHBpbmdDb250ZXh0KHtcclxuICAgICAgICAgIHF1ZXJ5OiB1bmRlZmluZWQsIC8vIHRlbGxzIHZpc2l0QW5kTWVyZ2UgdGhpcyBpcyBhIHNhdmUgaW5zdGVhZCBvZiBhIHF1ZXJ5XHJcbiAgICAgICAgICBlbnRpdHlNYW5hZ2VyOiBlbSxcclxuICAgICAgICAgIG1lcmdlT3B0aW9uczogeyBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5Lk92ZXJ3cml0ZUNoYW5nZXMgfSxcclxuICAgICAgICAgIGRhdGFTZXJ2aWNlOiBkYXRhU2VydmljZVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBUaGUgdmlzaXRBbmRNZXJnZSBvcGVyYXRpb24gaGFzIGJlZW4gb3B0aW1pemVkIHNvIHRoYXQgd2UgZG8gbm90IGFjdHVhbGx5IHBlcmZvcm0gYSBtZXJnZSBpZiB0aGVcclxuICAgICAgICAvLyB0aGUgc2F2ZSBvcGVyYXRpb24gZGlkIG5vdCBhY3R1YWxseSByZXR1cm4gdGhlIGVudGl0eSAtIGkuZS4gZHVyaW5nIE9EYXRhIGFuZCBNb25nbyB1cGRhdGVzIGFuZCBkZWxldGVzLlxyXG4gICAgICAgIHNhdmVkRW50aXRpZXMgPSBtYXBwaW5nQ29udGV4dC52aXNpdEFuZE1lcmdlKHNhdmVkRW50aXRpZXMsIHsgbm9kZVR5cGU6IFwicm9vdFwiIH0pO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIGRldGFjaCBhbnkgZW50aXRpZXMgZm91bmQgaW4gdGhlIGVtIHRoYXQgYXBwZWFyIGluIHRoZSBkZWxldGVkS2V5cyBsaXN0LiBcclxuICAgICAgZGVsZXRlZEtleXMuZm9yRWFjaChrZXkgPT4ge1xyXG4gICAgICAgIGxldCBlbnRpdHlUeXBlID0gZW0ubWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoa2V5LmVudGl0eVR5cGVOYW1lKSBhcyBFbnRpdHlUeXBlO1xyXG4gICAgICAgIGxldCBla2V5ID0gbmV3IEVudGl0eUtleShlbnRpdHlUeXBlLCBrZXkua2V5VmFsdWVzKTtcclxuICAgICAgICBsZXQgZW50aXR5ID0gZW0uZ2V0RW50aXR5QnlLZXkoZWtleSk7XHJcbiAgICAgICAgaWYgKGVudGl0eSkge1xyXG4gICAgICAgICAgZW50aXR5LmVudGl0eUFzcGVjdC5zZXREZXRhY2hlZCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICByZXR1cm4gc2F2ZWRFbnRpdGllcztcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBzYXZlRmFpbChzZXJ2ZXJFcnJvcjogU2F2ZUVycm9yRnJvbVNlcnZlcikge1xyXG4gICAgICBtYXJrSXNCZWluZ1NhdmVkKGVudGl0aWVzVG9TYXZlLCBmYWxzZSk7XHJcbiAgICAgIGxldCBjbGllbnRFcnJvciA9IHByb2Nlc3NTZXJ2ZXJFcnJvcnMoc2F2ZUNvbnRleHQsIHNlcnZlckVycm9yKTtcclxuICAgICAgaWYgKGVycm9yQ2FsbGJhY2spIGVycm9yQ2FsbGJhY2soY2xpZW50RXJyb3IpO1xyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoY2xpZW50RXJyb3IpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUnVuIHRoZSBcInNhdmVDaGFuZ2VzXCIgcHJlLXNhdmUgY2xpZW50IHZhbGlkYXRpb24gbG9naWMuXHJcbiAgXHJcbiAgVGhpcyBpcyBOT1QgYSBnZW5lcmFsIHB1cnBvc2UgdmFsaWRhdGlvbiBtZXRob2QuXHJcbiAgSXQgaXMgaW50ZW5kZWQgZm9yIHV0aWxpdGllcyB0aGF0IG11c3Qga25vdyBpZiBzYXZlQ2hhbmdlc1xyXG4gIHdvdWxkIHJlamVjdCB0aGUgc2F2ZSBkdWUgdG8gY2xpZW50IHZhbGlkYXRpb24gZXJyb3JzLlxyXG4gIFxyXG4gIEl0IG9ubHkgdmFsaWRhdGVzIGVudGl0aWVzIGlmIHRoZSBFbnRpdHlNYW5hZ2VyJ3NcclxuICBbW1ZhbGlkYXRpb25PcHRpb25zXV0udmFsaWRhdGVPblNhdmUgaXMgdHJ1ZS5cclxuICBcclxuICBAcGFyYW0gZW50aXRpZXNUb1NhdmUge0FycmF5IG9mIEVudGl0eX0gVGhlIGxpc3Qgb2YgZW50aXRpZXMgdG8gc2F2ZSAodG8gdmFsaWRhdGUpLlxyXG4gIEByZXR1cm4ge0Vycm9yfSBWYWxpZGF0aW9uIGVycm9yIG9yIG51bGwgaWYgbm8gZXJyb3JcclxuICAqKi9cclxuICBzYXZlQ2hhbmdlc1ZhbGlkYXRlT25DbGllbnQoZW50aXRpZXNUb1NhdmU6IEVudGl0eVtdKSB7XHJcblxyXG4gICAgaWYgKHRoaXMudmFsaWRhdGlvbk9wdGlvbnMudmFsaWRhdGVPblNhdmUpIHtcclxuICAgICAgbGV0IGZhaWxlZEVudGl0aWVzID0gZW50aXRpZXNUb1NhdmUuZmlsdGVyKGZ1bmN0aW9uIChlbnRpdHkpIHtcclxuICAgICAgICBsZXQgYXNwZWN0ID0gZW50aXR5LmVudGl0eUFzcGVjdDtcclxuICAgICAgICBsZXQgaXNWYWxpZCA9IGFzcGVjdC5lbnRpdHlTdGF0ZS5pc0RlbGV0ZWQoKSB8fCBhc3BlY3QudmFsaWRhdGVFbnRpdHkoKTtcclxuICAgICAgICByZXR1cm4gIWlzVmFsaWQ7XHJcbiAgICAgIH0pO1xyXG4gICAgICBpZiAoZmFpbGVkRW50aXRpZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIGxldCB2YWxFcnJvciA9IG5ldyBFcnJvcihcIkNsaWVudCBzaWRlIHZhbGlkYXRpb24gZXJyb3JzIGVuY291bnRlcmVkIC0gc2VlIHRoZSBlbnRpdHlFcnJvcnMgY29sbGVjdGlvbiBvbiB0aGlzIG9iamVjdCBmb3IgbW9yZSBkZXRhaWxcIik7XHJcbiAgICAgICAgKHZhbEVycm9yIGFzIGFueSkuZW50aXR5RXJyb3JzID0gY3JlYXRlRW50aXR5RXJyb3JzKGZhaWxlZEVudGl0aWVzKTtcclxuICAgICAgICByZXR1cm4gdmFsRXJyb3I7IC8vIFRPRE86IHR5cGUgdGhpcy5cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZmluZEVudGl0eUdyb3VwKGVudGl0eVR5cGU6IEVudGl0eVR5cGUpIHtcclxuICAgIHJldHVybiB0aGlzLl9lbnRpdHlHcm91cE1hcFtlbnRpdHlUeXBlLm5hbWVdO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgZW1wbG95ZWVUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkVtcGxveWVlXCIpO1xyXG4gID4gICAgICBsZXQgZW1wbG95ZWVLZXkgPSBuZXcgRW50aXR5S2V5KGVtcGxveWVlVHlwZSwgMSk7XHJcbiAgPiAgICAgIGxldCBlbXBsb3llZSA9IGVtMS5nZXRFbnRpdHlCeUtleShlbXBsb3llZUtleSk7XHJcbiAgPiAgICAgIC8vIGVtcGxveWVlIHdpbGwgZWl0aGVyIGJlIGFuIGVudGl0eSBvciBudWxsLlxyXG4gICoqL1xyXG4gIGdldEVudGl0eUJ5S2V5KGVudGl0eUtleTogRW50aXR5S2V5KTogRW50aXR5IHwgbnVsbDtcclxuXHJcbiAgLyoqICBcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBlbXBsb3llZSA9IGVtMS5nZXRFbnRpdHlCeUtleShcIkVtcGxveWVlXCIsIDEpO1xyXG4gID4gICAgICAvLyBlbXBsb3llZSB3aWxsIGVpdGhlciBiZSBhbiBlbnRpdHkgb3IgbnVsbC5cclxuICAqKi9cclxuICBnZXRFbnRpdHlCeUtleSh0eXBlTmFtZTogc3RyaW5nLCBrZXlWYWx1ZXM6IGFueSB8IGFueVtdKTogRW50aXR5IHwgbnVsbDtcclxuXHJcbiAgLyoqICBcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBlbXBsb3llZVR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiRW1wbG95ZWVcIik7XHJcbiAgPiAgICAgIGxldCBlbXBsb3llZSA9IGVtMS5nZXRFbnRpdHlCeUtleShlbXBsb3llZVR5cGUsIDEpO1xyXG4gID4gICAgICAvLyBlbXBsb3llZSB3aWxsIGVpdGhlciBiZSBhbiBlbnRpdHkgb3IgbnVsbC5cclxuICAqKi9cclxuICBnZXRFbnRpdHlCeUtleSh0eXBlOiBFbnRpdHlUeXBlLCBrZXlWYWx1ZXM6IGFueSB8IGFueVtdKTogRW50aXR5IHwgbnVsbDtcclxuXHJcbiAgLyoqICBcclxuICBBdHRlbXB0cyB0byBsb2NhdGUgYW4gZW50aXR5IHdpdGhpbiB0aGlzIEVudGl0eU1hbmFnZXIgYnkgaXRzIFtFbnRpdHlLZXldLlxyXG4gIEBwYXJhbSBlbnRpdHlLZXkgLSBUaGUgW1tFbnRpdHlLZXldXSBvZiB0aGUgRW50aXR5IHRvIGJlIGxvY2F0ZWQuXHJcbiAgQHBhcmFtIHR5cGUgLSBUaGUgW1tFbnRpdHlUeXBlXV0gZm9yIHRoaXMga2V5LlxyXG4gIEBwYXJhbSB0eXBlTmFtZSAtIFRoZSBFbnRpdHlUeXBlIG5hbWUgZm9yIHRoaXMga2V5LlxyXG4gIEBwYXJhbSBrZXlWYWx1ZXMgLSBUaGUgdmFsdWVzIGZvciB0aGlzIGtleSAtIHdpbGwgdXN1YWxseSBqdXN0IGJlIGEgc2luZ2xlIHZhbHVlOyBhbiBhcnJheSBpcyBvbmx5IG5lZWRlZCBmb3IgbXVsdGlwYXJ0IGtleXMuICBcclxuICBAcmV0dXJuIEFuIEVudGl0eSBvciBudWxsO1xyXG4gICoqL1xyXG4gIGdldEVudGl0eUJ5S2V5KC4uLmFyZ3M6IGFueVtdKSB7XHJcbiAgICBsZXQgZW50aXR5S2V5ID0gY3JlYXRlRW50aXR5S2V5KHRoaXMsIGFyZ3MpLmVudGl0eUtleTtcclxuICAgIGxldCBlbnRpdHlUeXBlcyA9IGVudGl0eUtleS5fc3VidHlwZXMgfHwgW2VudGl0eUtleS5lbnRpdHlUeXBlXTtcclxuICAgIGxldCBlOiBFbnRpdHkgfCB1bmRlZmluZWQ7XHJcbiAgICAvLyBoYWNrIHVzZSBvZiBzb21lIHRvIHNpbXVsYXRlIG1hcEZpcnN0IGxvZ2ljLlxyXG4gICAgZW50aXR5VHlwZXMuc29tZSgoZXQpID0+IHtcclxuICAgICAgbGV0IGdyb3VwID0gdGhpcy5fZmluZEVudGl0eUdyb3VwKGV0KTtcclxuICAgICAgLy8gZ3JvdXAgdmVyc2lvbiBvZiBmaW5kRW50aXR5QnlLZXkgZG9lc24ndCBjYXJlIGFib3V0IGVudGl0eVR5cGVcclxuICAgICAgZSA9IGdyb3VwICYmIGdyb3VwLmZpbmRFbnRpdHlCeUtleShlbnRpdHlLZXkpO1xyXG4gICAgICByZXR1cm4gZSAhPSBudWxsO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gZSB8fCBudWxsO1xyXG4gIH1cclxuXHJcbiAgZmV0Y2hFbnRpdHlCeUtleSh0eXBlTmFtZTogc3RyaW5nLCBrZXlWYWx1ZXM6IGFueSB8IGFueVtdLCBjaGVja0xvY2FsQ2FjaGVGaXJzdD86IGJvb2xlYW4pOiBQcm9taXNlPElFbnRpdHlCeUtleVJlc3VsdD47XHJcbiAgZmV0Y2hFbnRpdHlCeUtleShlbnRpdHlUeXBlOiBFbnRpdHlUeXBlLCBrZXlWYWx1ZXM6IGFueSB8IGFueVtdLCBjaGVja0xvY2FsQ2FjaGVGaXJzdD86IGJvb2xlYW4pOiBQcm9taXNlPElFbnRpdHlCeUtleVJlc3VsdD47XHJcbiAgZmV0Y2hFbnRpdHlCeUtleShlbnRpdHlLZXk6IEVudGl0eUtleSwgY2hlY2tMb2NhbENhY2hlRmlyc3Q/OiBib29sZWFuKTogUHJvbWlzZTxJRW50aXR5QnlLZXlSZXN1bHQ+O1xyXG4gIC8qKlxyXG4gIEF0dGVtcHRzIHRvIGZldGNoIGFuIGVudGl0eSBmcm9tIHRoZSBzZXJ2ZXIgYnkgaXRzIFtbRW50aXR5S2V5XV0gd2l0aFxyXG4gIGFuIG9wdGlvbiB0byBjaGVjayB0aGUgbG9jYWwgY2FjaGUgZmlyc3QuIE5vdGUgdGhlIHRoaXMgRW50aXR5TWFuYWdlcidzIHF1ZXJ5T3B0aW9ucy5tZXJnZVN0cmF0ZWd5XHJcbiAgd2lsbCBiZSB1c2VkIHRvIG1lcmdlIGFueSBzZXJ2ZXIgc2lkZSBlbnRpdHkgcmV0dXJuZWQgYnkgdGhpcyBtZXRob2QuXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGVtcGxveWVlVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJFbXBsb3llZVwiKTtcclxuICA+ICAgICBsZXQgZW1wbG95ZWVLZXkgPSBuZXcgRW50aXR5S2V5KGVtcGxveWVlVHlwZSwgMSk7XHJcbiAgPiAgICAgZW0xLmZldGNoRW50aXR5QnlLZXkoZW1wbG95ZWVLZXkpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7XHJcbiAgPiAgICAgICBsZXQgZW1wbG95ZWUgPSByZXN1bHQuZW50aXR5O1xyXG4gID4gICAgICAgbGV0IGVudGl0eUtleSA9IHJlc3VsdC5lbnRpdHlLZXk7XHJcbiAgPiAgICAgICBsZXQgZnJvbUNhY2hlID0gcmVzdWx0LmZyb21DYWNoZTtcclxuICA+ICAgICB9KTtcclxuICBAcGFyYW0gdHlwZU5hbWUgIC0gVGhlIEVudGl0eVR5cGUgbmFtZSBmb3IgdGhpcyBrZXkuXHJcbiAgQHBhcmFtIGVudGl0eVR5cGUgIC0gVGhlIEVudGl0eVR5cGUgZm9yIHRoaXMga2V5LlxyXG4gIEBwYXJhbSBrZXlWYWx1ZXMgLSBUaGUgdmFsdWVzIGZvciB0aGlzIGtleSAtIHdpbGwgdXN1YWxseSBqdXN0IGJlIGEgc2luZ2xlIHZhbHVlOyBhbiBhcnJheSBpcyBvbmx5IG5lZWRlZCBmb3IgbXVsdGlwYXJ0IGtleXMuXHJcbiAgQHBhcmFtIGVudGl0eUtleSAtIFRoZSBbW0VudGl0eUtleV1dIG9mIHRoZSBFbnRpdHkgdG8gYmUgbG9jYXRlZC5cclxuICBAcGFyYW0gY2hlY2tMb2NhbENhY2hlRmlyc3QgLSAoZGVmYXVsdCA9IGZhbHNlKSAtIFdoZXRoZXIgdG8gY2hlY2sgdGhpcyBFbnRpdHlNYW5hZ2VyIGZpcnN0IGJlZm9yZSBnb2luZyB0byB0aGUgc2VydmVyLiBCeSBkZWZhdWx0LCB0aGUgcXVlcnkgd2lsbCBOT1QgZG8gdGhpcy5cclxuICBAcmV0dXJuIHtQcm9taXNlfVxyXG4gICAgLSBQcm9wZXJ0aWVzIG9uIHRoZSBwcm9taXNlIHN1Y2Nlc3MgcmVzdWx0XHJcbiAgICAgIC0gZW50aXR5IHtPYmplY3R9IFRoZSBlbnRpdHkgcmV0dXJuZWQgb3IgbnVsbFxyXG4gICAgICAtIGVudGl0eUtleSB7RW50aXR5S2V5fSBUaGUgZW50aXR5S2V5IG9mIHRoZSBlbnRpdHkgdG8gZmV0Y2guXHJcbiAgICAgIC0gZnJvbUNhY2hlIHtCb29sZWFufSBXaGV0aGVyIHRoaXMgZW50aXR5IHdhcyBmZXRjaGVkIGZyb20gdGhlIHNlcnZlciBvciB3YXMgZm91bmQgaW4gdGhlIGxvY2FsIGNhY2hlLlxyXG4gICoqL1xyXG4gIGZldGNoRW50aXR5QnlLZXkoLi4uYXJnczogYW55W10pIHtcclxuICAgIGxldCBkYXRhU2VydmljZSA9IERhdGFTZXJ2aWNlLnJlc29sdmUoW3RoaXMuZGF0YVNlcnZpY2VdKTtcclxuICAgIGlmICgoIWRhdGFTZXJ2aWNlLmhhc1NlcnZlck1ldGFkYXRhKSB8fCB0aGlzLm1ldGFkYXRhU3RvcmUuaGFzTWV0YWRhdGFGb3IoZGF0YVNlcnZpY2Uuc2VydmljZU5hbWUpKSB7XHJcbiAgICAgIHJldHVybiBmZXRjaEVudGl0eUJ5S2V5Q29yZSh0aGlzLCBhcmdzKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmZldGNoTWV0YWRhdGEoZGF0YVNlcnZpY2UpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgIHJldHVybiBmZXRjaEVudGl0eUJ5S2V5Q29yZSh0aGlzLCBhcmdzKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBbRGVwcmVjYXRlZF0gLSBBdHRlbXB0cyB0byBsb2NhdGUgYW4gZW50aXR5IHdpdGhpbiB0aGlzIEVudGl0eU1hbmFnZXIgYnkgaXRzICBbW0VudGl0eUtleV1dLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBlbXBsb3llZVR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiRW1wbG95ZWVcIik7XHJcbiAgPiAgICAgbGV0IGVtcGxveWVlS2V5ID0gbmV3IEVudGl0eUtleShlbXBsb3llZVR5cGUsIDEpO1xyXG4gID4gICAgIGxldCBlbXBsb3llZSA9IGVtMS5maW5kRW50aXR5QnlLZXkoZW1wbG95ZWVLZXkpO1xyXG4gID4gICAgIC8vIGVtcGxveWVlIHdpbGwgZWl0aGVyIGJlIGFuIGVudGl0eSBvciBudWxsLlxyXG4gIEBkZXByZWNhdGVkICAgIFVzZSBnZXRFbnRpdHlCeUtleSBpbnN0ZWFkXHJcbiAgQHBhcmFtIGVudGl0eUtleSAtIFRoZSAgW1tFbnRpdHlLZXldXSBvZiB0aGUgRW50aXR5IHRvIGJlIGxvY2F0ZWQuXHJcbiAgQHJldHVybiBBbiBFbnRpdHkgb3IgbnVsbDtcclxuICAqKi9cclxuICBmaW5kRW50aXR5QnlLZXkoZW50aXR5S2V5OiBFbnRpdHlLZXkpIHtcclxuICAgIHJldHVybiB0aGlzLmdldEVudGl0eUJ5S2V5KGVudGl0eUtleSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBHZW5lcmF0ZXMgYSB0ZW1wb3Jhcnkga2V5IGZvciB0aGUgc3BlY2lmaWVkIGVudGl0eS4gIFRoaXMgaXMgdXNlZCB0byBpbnN1cmUgdGhhdCBuZXdseVxyXG4gIGNyZWF0ZWQgZW50aXRpZXMgaGF2ZSB1bmlxdWUga2V5cyBhbmQgdG8gcmVnaXN0ZXIgdGhhdCB0aGVzZSBrZXlzIGFyZSB0ZW1wb3JhcnkgYW5kXHJcbiAgbmVlZCB0byBiZSBhdXRvbWF0aWNhbGx5IHJlcGxhY2VkIHdpdGggJ3JlYWwnIGtleSB2YWx1ZXMgb25jZSB0aGVzZSBlbnRpdGllcyBhcmUgc2F2ZWQuXHJcbiAgXHJcbiAgVGhlIFtbRW50aXR5TWFuYWdlci5rZXlHZW5lcmF0b3JDdG9yXV0gcHJvcGVydHkgaXMgdXNlZCBpbnRlcm5hbGx5IGJ5IHRoaXMgbWV0aG9kIHRvIGFjdHVhbGx5IGdlbmVyYXRlXHJcbiAgdGhlIGtleXMgLSBTZWUgdGhlICBLZXlHZW5lcmF0b3IgaW50ZXJmYWNlIGludGVyZmFjZSBkZXNjcmlwdGlvbiB0byBzZWVcclxuICBob3cgYSBjdXN0b20ga2V5IGdlbmVyYXRvciBjYW4gYmUgcGx1Z2dlZCBpbi5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IGN1c3RvbWVyID0gY3VzdFR5cGUuY3JlYXRlRW50aXR5KCk7XHJcbiAgPiAgICAgIGxldCBjdXN0b21lcklkID0gZW0uZ2VuZXJhdGVUZW1wS2V5VmFsdWUoY3VzdG9tZXIpO1xyXG4gID4gICAgICAvLyBUaGUgJ2N1c3RvbWVyJyBlbnRpdHkgJ0N1c3RvbWVySUQnIHByb3BlcnR5IGlzIG5vdyBzZXQgdG8gYSBuZXdseSBnZW5lcmF0ZWQgdW5pcXVlIGlkIHZhbHVlXHJcbiAgPiAgICAgIC8vIFRoaXMgcHJvcGVydHkgd2lsbCBjaGFuZ2UgYWdhaW4gYWZ0ZXIgYSBzdWNjZXNzZnVsIHNhdmUgb2YgdGhlICdjdXN0b21lcicgZW50aXR5LlxyXG4gID4gIFxyXG4gID4gICAgICBlbTEuc2F2ZUNoYW5nZXMoKS50aGVuKCBmdW5jdGlvbiggZGF0YSkge1xyXG4gID4gICAgICAgICAgbGV0IHNhbWVDdXN0MSA9IGRhdGEucmVzdWx0c1swXTtcclxuICA+ICAgICAgICAgIC8vIGN1c3QxID09PSBzYW1lQ3VzdDE7XHJcbiAgPiAgICAgICAgICAvLyBidXQgY3VzdDEuZ2V0UHJvcGVydHkoXCJDdXN0b21lcklkXCIpICE9IGN1c3RvbWVySWRcclxuICA+ICAgICAgICAgIC8vIGJlY2F1c2UgdGhlIHNlcnZlciB3aWxsIGhhdmUgZ2VuZXJhdGVkIGEgbmV3IGlkXHJcbiAgPiAgICAgICAgICAvLyBhbmQgdGhlIGNsaWVudCB3aWxsIGhhdmUgYmVlbiB1cGRhdGVkIHdpdGggdGhpc1xyXG4gID4gICAgICAgICAgLy8gbmV3IGlkLlxyXG4gID4gICAgICB9KVxyXG4gIEBwYXJhbSBlbnRpdHkgLSBUaGUgRW50aXR5IHRvIGdlbmVyYXRlIGEga2V5IGZvci5cclxuICBAcmV0dXJuIFRoZSBuZXcga2V5IHZhbHVlXHJcbiAgKiovXHJcbiAgZ2VuZXJhdGVUZW1wS2V5VmFsdWUoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIC8vIFRPRE8gLSBjaGVjayBpZiB0aGlzIGVudGl0eSBpcyBhdHRhY2hlZCB0byB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHksIFwiZW50aXR5XCIpLmlzRW50aXR5KCkuY2hlY2soKTtcclxuICAgIGxldCBlbnRpdHlUeXBlID0gZW50aXR5LmVudGl0eVR5cGU7XHJcbiAgICBsZXQgbmV4dEtleVZhbHVlID0gdGhpcy5rZXlHZW5lcmF0b3IuZ2VuZXJhdGVUZW1wS2V5VmFsdWUoZW50aXR5VHlwZSk7XHJcbiAgICBsZXQga2V5UHJvcCA9IGVudGl0eVR5cGUua2V5UHJvcGVydGllc1swXTtcclxuICAgIGVudGl0eS5zZXRQcm9wZXJ0eShrZXlQcm9wLm5hbWUsIG5leHRLZXlWYWx1ZSk7XHJcbiAgICBlbnRpdHkuZW50aXR5QXNwZWN0Lmhhc1RlbXBLZXkgPSB0cnVlO1xyXG4gICAgcmV0dXJuIG5leHRLZXlWYWx1ZTtcclxuICB9XHJcblxyXG4gIGhhc0NoYW5nZXMoKTogYm9vbGVhbjtcclxuICBoYXNDaGFuZ2VzKGVudGl0eVR5cGVOYW1lczogc3RyaW5nIHwgc3RyaW5nW10pOiBib29sZWFuO1xyXG4gIGhhc0NoYW5nZXMoZW50aXR5VHlwZXM6IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10pOiBib29sZWFuO1xyXG4gIC8qKlxyXG4gIFJldHVybnMgd2hldGhlciB0aGVyZSBhcmUgYW55IGNoYW5nZWQgZW50aXRpZXMgb2YgdGhlIHNwZWNpZmllZCBbW0VudGl0eVR5cGVdXXMuIEEgJ2NoYW5nZWQnIEVudGl0eSBoYXNcclxuICBoYXMgYW4gW1tFbnRpdHlTdGF0ZV1dIG9mIGVpdGhlciBBZGRlZCwgTW9kaWZpZWQgb3IgRGVsZXRlZC5cclxuXHJcbiAgVGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gZGV0ZXJtaW5lIGlmIGFuIEVudGl0eU1hbmFnZXIgaGFzIGFueSBjaGFuZ2VzXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBpZiAoIGVtMS5oYXNDaGFuZ2VzKCkge1xyXG4gID4gICAgICAgICAgLy8gZG8gc29tZXRoaW5nIGludGVyZXN0aW5nXHJcbiAgPiAgICAgIH1cclxuXHJcbiAgb3IgaWYgaXQgaGFzIGFueSBjaGFuZ2VzIG9uIHRvIGEgc3BlY2lmaWMgW1tFbnRpdHlUeXBlXV0uXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGlmICggZW0xLmhhc0NoYW5nZXMoY3VzdFR5cGUpIHtcclxuICA+ICAgICAgICAgIC8vIGRvIHNvbWV0aGluZyBpbnRlcmVzdGluZ1xyXG4gID4gICAgICB9XHJcblxyXG4gIG9yIHRvIGEgY29sbGVjdGlvbiBvZiBbW0VudGl0eVR5cGVdXXNcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IG9yZGVyVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJPcmRlclwiKTtcclxuICA+ICAgICAgaWYgKCBlbTEuaGFzQ2hhbmdlcyggW2N1c3RUeXBlLCBvcmRlclR5cGVdKSB7XHJcbiAgPiAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgaW50ZXJlc3RpbmdcclxuICA+ICAgICAgfVxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlcyAtIFRoZSBbW0VudGl0eVR5cGVdXSBvciBFbnRpdHlUeXBlcyBmb3Igd2hpY2ggJ2NoYW5nZWQnIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgQHBhcmFtIGVudGl0eVR5cGVOYW1lcyAtIFRoZSBbW0VudGl0eVR5cGVdXSBuYW1lIG9yIG5hbWVzIGZvciB3aGljaCAnY2hhbmdlZCcgZW50aXRpZXMgd2lsbCBiZSBmb3VuZC5cclxuICBAcmV0dXJuIFdoZXRoZXIgdGhlcmUgYXJlIGFueSBjaGFuZ2VkIGVudGl0aWVzIHRoYXQgbWF0Y2ggdGhlIHR5cGVzIHNwZWNpZmllZC4uXHJcbiAgKiovXHJcbiAgaGFzQ2hhbmdlcyhlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCBzdHJpbmcgfCBzdHJpbmdbXSkge1xyXG4gICAgaWYgKCF0aGlzLl9oYXNDaGFuZ2VzKSByZXR1cm4gZmFsc2U7XHJcbiAgICBpZiAoZW50aXR5VHlwZXMgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXMuX2hhc0NoYW5nZXM7XHJcbiAgICByZXR1cm4gdGhpcy5faGFzQ2hhbmdlc0NvcmUoZW50aXR5VHlwZXMpO1xyXG4gIH1cclxuXHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIC8vIGJhY2tkb29yIHRvIFwicmVhbGx5XCIgY2hlY2sgZm9yIGNoYW5nZXMuXHJcbiAgX2hhc0NoYW5nZXNDb3JlKGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZyB8IHN0cmluZ1tdKSB7XHJcbiAgICBsZXQgZXRzID0gY2hlY2tFbnRpdHlUeXBlcyh0aGlzLCBlbnRpdHlUeXBlcyk7XHJcbiAgICBsZXQgZW50aXR5R3JvdXBzID0gZ2V0RW50aXR5R3JvdXBzKHRoaXMsIGV0cyk7XHJcbiAgICByZXR1cm4gZW50aXR5R3JvdXBzLnNvbWUoZnVuY3Rpb24gKGVnKSB7XHJcbiAgICAgIHJldHVybiBlZyAmJiBlZy5oYXNDaGFuZ2VzKCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGdldENoYW5nZXMoKTogRW50aXR5W107XHJcbiAgZ2V0Q2hhbmdlcyhlbnRpdHlUeXBlTmFtZXM6IHN0cmluZyB8IHN0cmluZ1tdKTogRW50aXR5W107XHJcbiAgZ2V0Q2hhbmdlcyhlbnRpdHlUeXBlczogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSk6IEVudGl0eVtdO1xyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBhcnJheSBvZiBhbGwgY2hhbmdlZCBlbnRpdGllcyBvZiB0aGUgc3BlY2lmaWVkIFtbRW50aXR5VHlwZV1dcy4gQSAnY2hhbmdlZCcgRW50aXR5IGhhc1xyXG4gIGhhcyBhbiBbW0VudGl0eVN0YXRlXV0gb2YgZWl0aGVyIEFkZGVkLCBNb2RpZmllZCBvciBEZWxldGVkLlxyXG4gIFxyXG4gIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGdldCBhbGwgb2YgdGhlIGNoYW5nZWQgZW50aXRpZXMgd2l0aGluIGFuIEVudGl0eU1hbmFnZXJcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjaGFuZ2VkRW50aXRpZXMgPSBlbTEuZ2V0Q2hhbmdlcygpO1xyXG5cclxuICBvciB5b3UgY2FuIHNwZWNpZnkgdGhhdCB5b3Ugb25seSB3YW50IHRoZSBjaGFuZ2VzIG9uIGEgc3BlY2lmaWMgW1tFbnRpdHlUeXBlXV1cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IGNoYW5nZWRDdXN0b21lcnMgPSBlbTEuZ2V0Q2hhbmdlcyhjdXN0VHlwZSk7XHJcblxyXG4gIG9yIHRvIGEgY29sbGVjdGlvbiBvZiBbW0VudGl0eVR5cGVdXXNcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IG9yZGVyVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJPcmRlclwiKTtcclxuICA+ICAgICAgbGV0IGNoYW5nZWRDdXN0b21lcnNBbmRPcmRlcnMgPSBlbTEuZ2V0Q2hhbmdlcyhbY3VzdFR5cGUsIG9yZGVyVHlwZV0pO1xyXG4gIEBwYXJhbSBlbnRpdHlUeXBlcyAtIFRoZSBbW0VudGl0eVR5cGVdXSBvciBFbnRpdHlUeXBlcyBmb3Igd2hpY2ggJ2NoYW5nZWQnIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgQHBhcmFtIGVudGl0eVR5cGVOYW1lcyAtIFRoZSBbW0VudGl0eVR5cGVdXSBuYW1lIG9yIG5hbWVzIGZvciB3aGljaCAnY2hhbmdlZCcgZW50aXRpZXMgd2lsbCBiZSBmb3VuZC5cclxuICBAcmV0dXJuIEFuIGFycmF5IG9mIEVudGl0aWVzXHJcbiAgKiovXHJcbiAgZ2V0Q2hhbmdlcyhlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCBzdHJpbmcgfCBzdHJpbmdbXSkge1xyXG4gICAgbGV0IGV0cyA9IGNoZWNrRW50aXR5VHlwZXModGhpcywgZW50aXR5VHlwZXMpO1xyXG4gICAgcmV0dXJuIGdldENoYW5nZXNDb3JlKHRoaXMsIGV0cyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZWplY3RzIChyZXZlcnNlcyB0aGUgZWZmZWN0cykgYWxsIG9mIHRoZSBhZGRpdGlvbnMsIG1vZGlmaWNhdGlvbnMgYW5kIGRlbGV0ZXMgZnJvbSB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgQ2FsbHMgW1tFbnRpdHlBc3BlY3QucmVqZWN0Q2hhbmdlc11dIG9uIGV2ZXJ5IGNoYW5nZWQgZW50aXR5IGluIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBlbnRpdGllcyA9IGVtMS5yZWplY3RDaGFuZ2VzKCk7XHJcbiAgQHJldHVybiBUaGUgZW50aXRpZXMgd2hvc2UgY2hhbmdlcyB3ZXJlIHJlamVjdGVkLiBUaGVzZSBlbnRpdGllcyB3aWxsIGFsbCBoYXZlIEVudGl0eVN0YXRlcyBvZlxyXG4gIGVpdGhlciAnVW5jaGFuZ2VkJyBvciAnRGV0YWNoZWQnXHJcbiAgKiovXHJcbiAgcmVqZWN0Q2hhbmdlcygpIHtcclxuICAgIGlmICghdGhpcy5faGFzQ2hhbmdlcykgcmV0dXJuIFtdO1xyXG4gICAgbGV0IGNoYW5nZXMgPSBnZXRDaGFuZ2VzQ29yZSh0aGlzKTtcclxuICAgIC8vIG5leHQgbGluZSBzdG9wcyBpbmRpdmlkdWFsIHJlamVjdCBjaGFuZ2VzIGZyb20gZWFjaCBjYWxsaW5nIF9oYXNDaGFuZ2VzQ29yZVxyXG4gICAgbGV0IGFzcGVjdHMgPSBjaGFuZ2VzLm1hcChmdW5jdGlvbiAoZSkge1xyXG4gICAgICByZXR1cm4gZS5lbnRpdHlBc3BlY3QuX2NoZWNrT3BlcmF0aW9uKFwicmVqZWN0Q2hhbmdlc1wiKTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5faGFzQ2hhbmdlcyA9IGZhbHNlO1xyXG4gICAgYXNwZWN0cy5mb3JFYWNoKGZ1bmN0aW9uIChhc3BlY3QpIHtcclxuICAgICAgYXNwZWN0LnJlamVjdENoYW5nZXMoKTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5oYXNDaGFuZ2VzQ2hhbmdlZC5wdWJsaXNoKHsgZW50aXR5TWFuYWdlcjogdGhpcywgaGFzQ2hhbmdlczogZmFsc2UgfSk7XHJcbiAgICByZXR1cm4gY2hhbmdlcztcclxuICB9XHJcblxyXG4gIGdldEVudGl0aWVzKGVudGl0eVR5cGVOYW1lcz86IHN0cmluZyB8IHN0cmluZ1tdLCBlbnRpdHlTdGF0ZXM/OiBFbnRpdHlTdGF0ZSB8IEVudGl0eVN0YXRlW10pOiBFbnRpdHlbXTtcclxuICBnZXRFbnRpdGllcyhlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10sIGVudGl0eVN0YXRlcz86IEVudGl0eVN0YXRlIHwgRW50aXR5U3RhdGVbXSk6IEVudGl0eVtdO1xyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBhcnJheSBvZiBhbGwgZW50aXRpZXMgb2YgdGhlIHNwZWNpZmllZCBbW0VudGl0eVR5cGVdXXMgd2l0aCB0aGUgc3BlY2lmaWVkIFtbRW50aXR5U3RhdGVdXXMuXHJcblxyXG4gIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGdldCBhbGwgb2YgdGhlIGVudGl0aWVzIHdpdGhpbiBhbiBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgZW50aXRpZXMgPSBlbTEuZ2V0RW50aXRpZXMoKTtcclxuXHJcbiAgb3IgeW91IGNhbiBzcGVjaWZ5IHRoYXQgeW91IG9ubHkgd2FudCB0aGUgY2hhbmdlcyBvbiBhIHNwZWNpZmljIFtbRW50aXR5VHlwZV1dXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBjdXN0b21lcnMgPSBlbTEuZ2V0RW50aXRpZXMoY3VzdFR5cGUpO1xyXG5cclxuICBvciB0byBhIGNvbGxlY3Rpb24gb2YgW1tFbnRpdHlUeXBlXV1zXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBvcmRlclR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiT3JkZXJcIik7XHJcbiAgPiAgICAgIGxldCBjdXN0b21lcnNBbmRPcmRlcnMgPSBlbTEuZ2V0Q2hhbmdlcyhbY3VzdFR5cGUsIG9yZGVyVHlwZV0pO1xyXG5cclxuICBZb3UgY2FuIGFsc28gYXNrIGZvciBlbnRpdGllcyB3aXRoIGEgcGFydGljdWxhciBbW0VudGl0eVN0YXRlXV0gb3IgRW50aXR5U3RhdGVzLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gID4gICAgICBsZXQgYWRkZWRDdXN0b21lcnNBbmRPcmRlcnMgPSBlbTEuZ2V0RW50aXRpZXMoW2N1c3RUeXBlLCBvcmRlclR5cGVdLCBFbnRpdHlTdGF0ZS5BZGRlZCk7XHJcbiBcclxuICBAcGFyYW0gZW50aXR5VHlwZU5hbWUgLSBUaGUgW1tFbnRpdHlUeXBlXV0gbmFtZSBvciBuYW1lcyBmb3Igd2hpY2ggZW50aXRpZXMgd2lsbCBiZSBmb3VuZC5cclxuICBJZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkLCBhbGwgRW50aXR5VHlwZXMgYXJlIHNlYXJjaGVkLiAgXHJcbiAgQHBhcmFtIGVudGl0eVR5cGVzIC0gVGhlIFtbRW50aXR5VHlwZV1dIG9yIEVudGl0eVR5cGVzIGZvciB3aGljaCBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIElmIHRoaXMgcGFyYW1ldGVyIGlzIG9taXR0ZWQsIGFsbCBFbnRpdHlUeXBlcyBhcmUgc2VhcmNoZWQuIFxyXG4gIEBwYXJhbSBlbnRpdHlTdGF0ZXMgLSBUaGUgW1tFbnRpdHlTdGF0ZV1dcyBmb3Igd2hpY2ggZW50aXRpZXMgd2lsbCBiZSBmb3VuZC5cclxuICBJZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkLCBlbnRpdGllcyBvZiBhbGwgRW50aXR5U3RhdGVzIGFyZSByZXR1cm5lZC5cclxuICBAcmV0dXJuIEFuIGFycmF5IG9mIEVudGl0aWVzXHJcbiAgKiovXHJcbiAgZ2V0RW50aXRpZXMoZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nIHwgc3RyaW5nW10sIGVudGl0eVN0YXRlcz86IEVudGl0eVN0YXRlIHwgRW50aXR5U3RhdGVbXSkge1xyXG4gICAgbGV0IGVudFR5cGVzID0gY2hlY2tFbnRpdHlUeXBlcyh0aGlzLCBlbnRpdHlUeXBlcyk7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHlTdGF0ZXMsIFwiZW50aXR5U3RhdGVzXCIpLmlzT3B0aW9uYWwoKS5pc0VudW1PZihFbnRpdHlTdGF0ZSkub3IoKS5pc05vbkVtcHR5QXJyYXkoKS5pc0VudW1PZihFbnRpdHlTdGF0ZSkuY2hlY2soKTtcclxuXHJcbiAgICBsZXQgc3RhdGVzID0gdmFsaWRhdGVFbnRpdHlTdGF0ZXModGhpcywgZW50aXR5U3RhdGVzKTtcclxuICAgIHJldHVybiBnZXRFbnRpdGllc0NvcmUodGhpcywgZW50VHlwZXMsIHN0YXRlcyk7XHJcbiAgfVxyXG5cclxuXHJcbiAgLy8gcHJvdGVjdGVkIG1ldGhvZHNcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfbm90aWZ5U3RhdGVDaGFuZ2UoZW50aXR5OiBFbnRpdHksIG5lZWRzU2F2ZTogYm9vbGVhbikge1xyXG4gICAgbGV0IGVjQXJncyA9IHsgZW50aXR5QWN0aW9uOiBFbnRpdHlBY3Rpb24uRW50aXR5U3RhdGVDaGFuZ2UsIGVudGl0eTogZW50aXR5IH07XHJcblxyXG4gICAgaWYgKG5lZWRzU2F2ZSkge1xyXG4gICAgICBpZiAoIXRoaXMuX2hhc0NoYW5nZXMpIHRoaXMuX3NldEhhc0NoYW5nZXModHJ1ZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBjYWxsZWQgd2hlbiByZWplY3RpbmcgYSBjaGFuZ2Ugb3IgbWVyZ2luZyBhbiB1bmNoYW5nZWQgcmVjb3JkLlxyXG4gICAgICAvLyBOT1RFOiB0aGlzIGNhbiBiZSBzbG93IHdpdGggbG90cyBvZiBlbnRpdGllcyBpbiB0aGUgY2FjaGUuXHJcbiAgICAgIC8vIHNvIGRlZmVyIGl0IGR1cmluZyBhIHF1ZXJ5L2ltcG9ydCBvciBzYXZlIGFuZCBjYWxsIGl0IG9uY2Ugd2hlbiBjb21wbGV0ZSAoIGlmIG5lZWRlZCkuXHJcbiAgICAgIGlmICh0aGlzLl9oYXNDaGFuZ2VzKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNMb2FkaW5nKSB7XHJcbiAgICAgICAgICB0aGlzLl9oYXNDaGFuZ2VzQWN0aW9uID0gdGhpcy5faGFzQ2hhbmdlc0FjdGlvbiB8fCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3NldEhhc0NoYW5nZXMobnVsbCk7XHJcbiAgICAgICAgICAgIHRoaXMuZW50aXR5Q2hhbmdlZC5wdWJsaXNoKGVjQXJncyk7XHJcbiAgICAgICAgICB9LmJpbmQodGhpcyk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMuX3NldEhhc0NoYW5nZXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHRoaXMuZW50aXR5Q2hhbmdlZC5wdWJsaXNoKGVjQXJncyk7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfc2V0SGFzQ2hhbmdlcyhoYXNDaGFuZ2VzPzogYm9vbGVhbikge1xyXG4gICAgaWYgKGhhc0NoYW5nZXMgPT0gbnVsbCkgaGFzQ2hhbmdlcyA9IHRoaXMuX2hhc0NoYW5nZXNDb3JlKCk7XHJcbiAgICBsZXQgaGFkQ2hhbmdlcyA9IHRoaXMuX2hhc0NoYW5nZXM7XHJcbiAgICB0aGlzLl9oYXNDaGFuZ2VzID0gaGFzQ2hhbmdlcztcclxuICAgIGlmIChoYXNDaGFuZ2VzICE9PSBoYWRDaGFuZ2VzKSB7XHJcbiAgICAgIHRoaXMuaGFzQ2hhbmdlc0NoYW5nZWQucHVibGlzaCh7IGVudGl0eU1hbmFnZXI6IHRoaXMsIGhhc0NoYW5nZXM6IGhhc0NoYW5nZXMgfSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLl9oYXNDaGFuZ2VzQWN0aW9uID0gdW5kZWZpbmVkO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2xpbmtSZWxhdGVkRW50aXRpZXMoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIGxldCBlbSA9IHRoaXM7XHJcbiAgICBsZXQgZW50aXR5QXNwZWN0ID0gZW50aXR5LmVudGl0eUFzcGVjdDtcclxuICAgIC8vIHdlIGRvIG5vdCB3YW50IGVudGl0eVN0YXRlIHRvIGNoYW5nZSBhcyBhIHJlc3VsdCBvZiBsaW5rYWdlLlxyXG4gICAgY29yZS51c2luZyhlbSwgXCJpc0xvYWRpbmdcIiwgdHJ1ZSwgZnVuY3Rpb24gKCkge1xyXG5cclxuICAgICAgbGV0IHVuYXR0YWNoZWRNYXAgPSBlbS5fdW5hdHRhY2hlZENoaWxkcmVuTWFwO1xyXG4gICAgICBsZXQgZW50aXR5S2V5ID0gZW50aXR5QXNwZWN0LmdldEtleSgpO1xyXG4gICAgICBsZXQgZW50aXR5VHlwZSA9IGVudGl0eUtleS5lbnRpdHlUeXBlO1xyXG5cclxuICAgICAgd2hpbGUgKGVudGl0eVR5cGUpIHtcclxuICAgICAgICBsZXQga2V5c3RyaW5nID0gZW50aXR5S2V5LnRvU3RyaW5nKGVudGl0eVR5cGUpO1xyXG5cclxuICAgICAgICAvLyBhdHRhY2ggYW55IHVuYXR0YWNoZWRDaGlsZHJlblxyXG4gICAgICAgIGxldCB0dXBsZXMgPSB1bmF0dGFjaGVkTWFwLmdldFR1cGxlc0J5U3RyaW5nKGtleXN0cmluZyk7XHJcbiAgICAgICAgaWYgKHR1cGxlcykge1xyXG4gICAgICAgICAgdHVwbGVzLnNsaWNlKDApLmZvckVhY2goZnVuY3Rpb24gKHRwbCkge1xyXG5cclxuICAgICAgICAgICAgbGV0IHVuYXR0YWNoZWRDaGlsZHJlbiA9IHRwbC5jaGlsZHJlbi5maWx0ZXIoZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICByZXR1cm4gZS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUgIT09IEVudGl0eVN0YXRlLkRldGFjaGVkO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIGxldCBjaGlsZFRvUGFyZW50TnA6IE5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuICAgICAgICAgICAgbGV0IHBhcmVudFRvQ2hpbGROcDogTmF2aWdhdGlvblByb3BlcnR5O1xyXG5cclxuICAgICAgICAgICAgLy8gbnAgaXMgdXN1YWxseSBjaGlsZFRvUGFyZW50TnBcclxuICAgICAgICAgICAgLy8gZXhjZXB0IHdpdGggdW5pZGlyZWN0aW9uYWwgMS1uIHdoZXJlIGl0IGlzIHBhcmVudFRvQ2hpbGROcDtcclxuICAgICAgICAgICAgbGV0IG5wID0gdHBsLm5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuXHJcbiAgICAgICAgICAgIGxldCBpbnZlcnNlTnAgPSBucC5pbnZlcnNlO1xyXG4gICAgICAgICAgICBpZiAoaW52ZXJzZU5wKSB7XHJcbiAgICAgICAgICAgICAgLy8gYmlkaXJlY3Rpb25hbFxyXG4gICAgICAgICAgICAgIGNoaWxkVG9QYXJlbnROcCA9IG5wO1xyXG4gICAgICAgICAgICAgIHBhcmVudFRvQ2hpbGROcCA9IGludmVyc2VOcDtcclxuXHJcbiAgICAgICAgICAgICAgaWYgKHBhcmVudFRvQ2hpbGROcC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgICAgICAgbGV0IG9ubHlDaGlsZCA9IHVuYXR0YWNoZWRDaGlsZHJlblswXTtcclxuICAgICAgICAgICAgICAgIGVudGl0eS5zZXRQcm9wZXJ0eShwYXJlbnRUb0NoaWxkTnAubmFtZSwgb25seUNoaWxkKTtcclxuICAgICAgICAgICAgICAgIG9ubHlDaGlsZC5zZXRQcm9wZXJ0eShjaGlsZFRvUGFyZW50TnAubmFtZSwgZW50aXR5KTtcclxuICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRDaGlsZHJlbiA9IGVudGl0eS5nZXRQcm9wZXJ0eShwYXJlbnRUb0NoaWxkTnAubmFtZSk7XHJcbiAgICAgICAgICAgICAgICB1bmF0dGFjaGVkQ2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgICAgY3VycmVudENoaWxkcmVuLnB1c2goY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgICBjaGlsZC5zZXRQcm9wZXJ0eShjaGlsZFRvUGFyZW50TnAubmFtZSwgZW50aXR5KTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB1bmF0dGFjaGVkTWFwLnJlbW92ZUNoaWxkcmVuKGtleXN0cmluZywgY2hpbGRUb1BhcmVudE5wKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAvLyB1bmlkaXJlY3Rpb25hbFxyXG4gICAgICAgICAgICAgIC8vIGlmIChucC5pc1NjYWxhciB8fCBucC5wYXJlbnRUeXBlICE9PSBlbnRpdHkuZW50aXR5VHlwZSkge1xyXG4gICAgICAgICAgICAgIGlmIChucC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgICAgICAgLy8gbiAtPiAxICBlZzogY2hpbGQ6IE9yZGVyRGV0YWlsIHBhcmVudDogUHJvZHVjdFxyXG4gICAgICAgICAgICAgICAgLy8gMSAtPiAxIGVnIGNoaWxkOiBFbXBsb3llZSBwYXJlbnQ6IEVtcGxveWVlICggb25seSBNYW5hZ2VyLCBubyBEaXJlY3RSZXBvcnRzIHByb3BlcnR5KVxyXG4gICAgICAgICAgICAgICAgY2hpbGRUb1BhcmVudE5wID0gbnA7XHJcbiAgICAgICAgICAgICAgICB1bmF0dGFjaGVkQ2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgICAgY2hpbGQuc2V0UHJvcGVydHkoY2hpbGRUb1BhcmVudE5wLm5hbWUsIGVudGl0eSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHVuYXR0YWNoZWRNYXAucmVtb3ZlQ2hpbGRyZW4oa2V5c3RyaW5nLCBjaGlsZFRvUGFyZW50TnApO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyAxIC0+IG4gIGVnOiBwYXJlbnQ6IFJlZ2lvbiBjaGlsZDogVGVyclxyXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogbmVlZCB0byByZW1vdmUgdW5hdHRhY2hlZCBjaGlsZHJlbiBmcm9tIHRoZSBtYXAgYWZ0ZXIgdGhpczsgb25seSBhIHBlcmYgaXNzdWUuXHJcbiAgICAgICAgICAgICAgICBwYXJlbnRUb0NoaWxkTnAgPSBucDtcclxuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50Q2hpbGRyZW4gPSBlbnRpdHkuZ2V0UHJvcGVydHkocGFyZW50VG9DaGlsZE5wLm5hbWUpO1xyXG4gICAgICAgICAgICAgICAgdW5hdHRhY2hlZENoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICAgIC8vIHdlIGtub3cgaWYgY2FuJ3QgYWxyZWFkeSBiZSB0aGVyZS5cclxuICAgICAgICAgICAgICAgICAgY3VycmVudENoaWxkcmVuLl9wdXNoKGNoaWxkKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVudGl0eVR5cGUgPSBlbnRpdHlUeXBlLmJhc2VFbnRpdHlUeXBlOyAvLyBsb29rIGZvciByZWxhdGlvbnNoaXBzIHVwIHRoZSBoaWVyYXJjaHlcclxuICAgICAgfVxyXG5cclxuXHJcbiAgICAgIC8vIG5vdyBhZGQgdG8gdW5hdHRhY2hlZE1hcCBpZiBuZWVkZWQuXHJcbiAgICAgIGVudGl0eS5lbnRpdHlUeXBlLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKG5wKSB7XHJcbiAgICAgICAgaWYgKG5wLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICBsZXQgdmFsdWUgPSBlbnRpdHkuZ2V0UHJvcGVydHkobnAubmFtZSk7XHJcbiAgICAgICAgICAvLyBwcm9wZXJ0eSBpcyBhbHJlYWR5IGxpbmtlZCB1cFxyXG4gICAgICAgICAgaWYgKHZhbHVlKSByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBmaXJzdCBkZXRlcm1pbmUgaWYgbnAgY29udGFpbnMgYSBwYXJlbnQgb3IgY2hpbGRcclxuICAgICAgICAvLyBoYXZpbmcgYSBwYXJlbnRLZXkgbWVhbnMgdGhhdCB0aGlzIGlzIGEgY2hpbGRcclxuICAgICAgICAvLyBpZiBhIHBhcmVudCB0aGVuIG5vIG5lZWQgZm9yIG1vcmUgd29yayBiZWNhdXNlIGNoaWxkcmVuIHdpbGwgYXR0YWNoIHRvIGl0LlxyXG4gICAgICAgIGxldCBwYXJlbnRLZXkgPSBlbnRpdHlBc3BlY3QuZ2V0UGFyZW50S2V5KG5wKTtcclxuICAgICAgICBpZiAocGFyZW50S2V5KSB7XHJcbiAgICAgICAgICAvLyBjaGVjayBmb3IgZW1wdHkga2V5cyAtIG1lYW5pbmcgdGhhdCBwYXJlbnQgaWQncyBhcmUgbm90IHlldCBzZXQuXHJcbiAgICAgICAgICBpZiAocGFyZW50S2V5Ll9pc0VtcHR5KCkpIHJldHVybjtcclxuICAgICAgICAgIC8vIGlmIGEgY2hpbGQgLSBsb29rIGZvciBwYXJlbnQgaW4gdGhlIGVtIGNhY2hlXHJcbiAgICAgICAgICBpZiAobnAuaW52Rm9yZWlnbktleU5hbWVzLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAvLyBucCByZWxhdGVzIHRvIG5vbi1QSyBwcm9wZXJ0eSBvZiBwYXJlbnQgZW50aXR5XHJcbiAgICAgICAgICAgIGNvbnN0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KHBhcmVudEtleS5lbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUpLndoZXJlKG5wLmludkZvcmVpZ25LZXlOYW1lc1swXSwgJ2VxJywgcGFyZW50S2V5LnZhbHVlc1swXSk7XHJcbiAgICAgICAgICAgIGNvbnN0IHFyZXN1bHQgPSBlbS5leGVjdXRlUXVlcnlMb2NhbGx5KHF1ZXJ5KTtcclxuICAgICAgICAgICAgaWYgKHFyZXN1bHQubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgICAgICAgbGV0IHBhcmVudCA9IHFyZXN1bHRbMF07XHJcbiAgICAgICAgICAgICAgZW50aXR5LnNldFByb3BlcnR5KG5wLm5hbWUsIHBhcmVudCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIG5wIHJlbGF0ZXMgdG8gUEsgb2YgcGFyZW50IGVudGl0eVxyXG4gICAgICAgICAgICBsZXQgcGFyZW50ID0gZW0uZ2V0RW50aXR5QnlLZXkocGFyZW50S2V5KTtcclxuICAgICAgICAgICAgaWYgKHBhcmVudCkge1xyXG4gICAgICAgICAgICAgIC8vIGlmIGZvdW5kIGhvb2sgaXQgdXBcclxuICAgICAgICAgICAgICBlbnRpdHkuc2V0UHJvcGVydHkobnAubmFtZSwgcGFyZW50KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAvLyBlbHNlIGFkZCBwYXJlbnQgdG8gdW5yZXNvbHZlZFBhcmVudE1hcDtcclxuICAgICAgICAgICAgICB1bmF0dGFjaGVkTWFwLmFkZENoaWxkKHBhcmVudEtleSwgbnAsIGVudGl0eSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2UgaWYgKG5wLmludmVyc2UgJiYgbnAuaW52ZXJzZS5pbnZGb3JlaWduS2V5TmFtZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAvLyBucCByZWxhdGVzIHRvIG5vbi1QSyBwcm9wZXJ0eSBvZiBwYXJlbnQgZW50aXR5OyBxdWVyeSBlbnRpdGllcyBieSBGS1xyXG4gICAgICAgICAgY29uc3QgYWtWYWx1ZSA9IGVudGl0eS5nZXRQcm9wZXJ0eShucC5pbnZlcnNlLmludkZvcmVpZ25LZXlOYW1lc1swXSk7XHJcbiAgICAgICAgICBjb25zdCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShucC5lbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUpLndoZXJlKG5wLmludkZvcmVpZ25LZXlOYW1lc1swXSwgJ2VxJywgYWtWYWx1ZSk7XHJcbiAgICAgICAgICBjb25zdCBxcmVzdWx0ID0gZW0uZXhlY3V0ZVF1ZXJ5TG9jYWxseShxdWVyeSk7XHJcbiAgICAgICAgICBxcmVzdWx0LmZvckVhY2goKGNoaWxkOiBFbnRpdHkpID0+IHtcclxuICAgICAgICAgICAgY2hpbGQuc2V0UHJvcGVydHkobnAuaW52ZXJzZS5uYW1lLCBlbnRpdHkpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIGhhbmRsZSB1bmlkaXJlY3Rpb25hbCAxLXggd2hlcmUgd2Ugc2V0IHguZmtcclxuICAgICAgZW50aXR5LmVudGl0eVR5cGUuZm9yZWlnbktleVByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZmtQcm9wKSB7XHJcbiAgICAgICAgbGV0IGludk5wID0gZmtQcm9wLmludmVyc2VOYXZpZ2F0aW9uUHJvcGVydHk7XHJcbiAgICAgICAgaWYgKCFpbnZOcCkgcmV0dXJuO1xyXG4gICAgICAgIC8vIHVuaWRpcmVjdGlvbmFsIGZrIHByb3BzIG9ubHlcclxuICAgICAgICBsZXQgZmtWYWx1ZSA9IGVudGl0eS5nZXRQcm9wZXJ0eShma1Byb3AubmFtZSk7XHJcbiAgICAgICAgbGV0IHBhcmVudEtleSA9IG5ldyBFbnRpdHlLZXkoaW52TnAucGFyZW50VHlwZSwgW2ZrVmFsdWVdKTtcclxuICAgICAgICBsZXQgcGFyZW50ID0gZW0uZ2V0RW50aXR5QnlLZXkocGFyZW50S2V5KTtcclxuXHJcbiAgICAgICAgaWYgKHBhcmVudCkge1xyXG4gICAgICAgICAgaWYgKGludk5wLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICAgIHBhcmVudC5zZXRQcm9wZXJ0eShpbnZOcC5uYW1lLCBlbnRpdHkpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKGVtLmlzTG9hZGluZykge1xyXG4gICAgICAgICAgICAgIHBhcmVudC5nZXRQcm9wZXJ0eShpbnZOcC5uYW1lKS5fcHVzaChlbnRpdHkpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIHBhcmVudC5nZXRQcm9wZXJ0eShpbnZOcC5uYW1lKS5wdXNoKGVudGl0eSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy8gZWxzZSBhZGQgcGFyZW50IHRvIHVucmVzb2x2ZWRQYXJlbnRNYXA7XHJcbiAgICAgICAgICB1bmF0dGFjaGVkTWFwLmFkZENoaWxkKHBhcmVudEtleSwgaW52TnAsIGVudGl0eSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG5cclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9hdHRhY2hFbnRpdHlDb3JlKGVudGl0eTogRW50aXR5LCBlbnRpdHlTdGF0ZTogRW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3k6IE1lcmdlU3RyYXRlZ3kpIHtcclxuICAgIGxldCBncm91cCA9IGZpbmRPckNyZWF0ZUVudGl0eUdyb3VwKHRoaXMsIGVudGl0eS5lbnRpdHlUeXBlKTtcclxuICAgIGxldCBhdHRhY2hlZEVudGl0eSA9IGdyb3VwLmF0dGFjaEVudGl0eShlbnRpdHksIGVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5KTtcclxuICAgIHRoaXMuX2xpbmtSZWxhdGVkRW50aXRpZXMoYXR0YWNoZWRFbnRpdHkpO1xyXG4gICAgcmV0dXJuIGF0dGFjaGVkRW50aXR5O1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VwZGF0ZUZrVmFsKGZrUHJvcDogRGF0YVByb3BlcnR5LCBvbGRWYWx1ZTogYW55LCBuZXdWYWx1ZTogYW55KSB7XHJcbiAgICBsZXQgZ3JvdXAgPSB0aGlzLl9lbnRpdHlHcm91cE1hcFtma1Byb3AucGFyZW50VHlwZS5uYW1lXTtcclxuICAgIGlmICghZ3JvdXApIHJldHVybjtcclxuICAgIGdyb3VwLl91cGRhdGVGa1ZhbChma1Byb3AsIG9sZFZhbHVlLCBuZXdWYWx1ZSk7XHJcbiAgfVxyXG59XHJcblxyXG5FbnRpdHlNYW5hZ2VyLnByb3RvdHlwZS5fJHR5cGVOYW1lID0gXCJFbnRpdHlNYW5hZ2VyXCI7XHJcblxyXG5CcmVlemVFdmVudC5idWJibGVFdmVudChFbnRpdHlNYW5hZ2VyLnByb3RvdHlwZSk7XHJcblxyXG5mdW5jdGlvbiBjbGVhclNlcnZlckVycm9ycyhlbnRpdGllczogRW50aXR5W10pIHtcclxuICBlbnRpdGllcy5mb3JFYWNoKGZ1bmN0aW9uIChlbnRpdHkpIHtcclxuICAgIGxldCBzZXJ2ZXJLZXlzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgbGV0IGFzcGVjdCA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICBjb3JlLm9iamVjdEZvckVhY2goYXNwZWN0Ll92YWxpZGF0aW9uRXJyb3JzLCBmdW5jdGlvbiAoa2V5LCB2ZSkge1xyXG4gICAgICBpZiAodmUuaXNTZXJ2ZXJFcnJvcikgc2VydmVyS2V5cy5wdXNoKGtleSk7XHJcbiAgICB9KTtcclxuICAgIGlmIChzZXJ2ZXJLZXlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xyXG4gICAgYXNwZWN0Ll9wcm9jZXNzVmFsaWRhdGlvbk9wQW5kUHVibGlzaChmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHNlcnZlcktleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XHJcbiAgICAgICAgYXNwZWN0Ll9yZW1vdmVWYWxpZGF0aW9uRXJyb3Ioa2V5KTtcclxuICAgICAgfSk7XHJcbiAgICB9KTtcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlRW50aXR5RXJyb3JzKGVudGl0aWVzOiBFbnRpdHlbXSkge1xyXG4gIGxldCBlbnRpdHlFcnJvcnM6IEVudGl0eUVycm9yW10gPSBbXTtcclxuICBlbnRpdGllcy5mb3JFYWNoKChlbnRpdHkpID0+IHtcclxuICAgIGNvcmUub2JqZWN0Rm9yRWFjaChlbnRpdHkuZW50aXR5QXNwZWN0Ll92YWxpZGF0aW9uRXJyb3JzLCBmdW5jdGlvbiAoa2V5LCB2ZSkge1xyXG4gICAgICBsZXQgY2ZnID0gY29yZS5leHRlbmQoe1xyXG4gICAgICAgIGVudGl0eTogZW50aXR5LFxyXG4gICAgICAgIGVycm9yTmFtZTogdmUudmFsaWRhdG9yLm5hbWVcclxuICAgICAgfSwgdmUsIFtcImVycm9yTWVzc2FnZVwiLCBcInByb3BlcnR5TmFtZVwiLCBcImlzU2VydmVyRXJyb3JcIiwgXCJjdXN0b21cIl0pIGFzIEVudGl0eUVycm9yO1xyXG4gICAgICBlbnRpdHlFcnJvcnMucHVzaChjZmcpO1xyXG4gICAgfSk7XHJcbiAgfSk7XHJcbiAgcmV0dXJuIGVudGl0eUVycm9ycztcclxufVxyXG5cclxuXHJcbmZ1bmN0aW9uIHByb2Nlc3NTZXJ2ZXJFcnJvcnMoc2F2ZUNvbnRleHQ6IFNhdmVDb250ZXh0LCBzYXZlRXJyb3I6IFNhdmVFcnJvckZyb21TZXJ2ZXIpIHtcclxuICAvLyBjb252ZXJ0aW5nIElTYXZlRXJyb3JGcm9tU2VydmVyIC0+IElTYXZlRXJyb3JcclxuICBsZXQgc2VydmVyRXJyb3JzID0gc2F2ZUVycm9yLmVudGl0eUVycm9ycztcclxuICBpZiAoIXNlcnZlckVycm9ycykgcmV0dXJuIDxTYXZlRXJyb3I+IDxhbnk+IHNhdmVFcnJvcjtcclxuICBsZXQgZW50aXR5TWFuYWdlciA9IHNhdmVDb250ZXh0LmVudGl0eU1hbmFnZXI7XHJcbiAgbGV0IG1ldGFkYXRhU3RvcmUgPSBlbnRpdHlNYW5hZ2VyLm1ldGFkYXRhU3RvcmU7XHJcbiAgbGV0IGVudGl0eUVycm9ycyA9IHNlcnZlckVycm9ycy5tYXAoKHNlcnIpID0+IHtcclxuICAgIGxldCBlbnRpdHk6IEVudGl0eSB8IG51bGwgPSBudWxsO1xyXG4gICAgbGV0IGVudGl0eVR5cGU6IEVudGl0eVR5cGUgfCB1bmRlZmluZWQ7XHJcbiAgICBpZiAoc2Vyci5rZXlWYWx1ZXMpIHtcclxuICAgICAgZW50aXR5VHlwZSA9IG1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKHNlcnIuZW50aXR5VHlwZU5hbWUpIGFzIEVudGl0eVR5cGU7XHJcbiAgICAgIGxldCBla2V5ID0gbmV3IEVudGl0eUtleShlbnRpdHlUeXBlLCBzZXJyLmtleVZhbHVlcyk7XHJcbiAgICAgIGVudGl0eSA9IGVudGl0eU1hbmFnZXIuZ2V0RW50aXR5QnlLZXkoZWtleSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGVudGl0eVR5cGUgJiYgZW50aXR5KSB7XHJcbiAgICAgIGxldCBjb250ZXh0ID0gc2Vyci5wcm9wZXJ0eU5hbWUgP1xyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3BlcnR5TmFtZTogc2Vyci5wcm9wZXJ0eU5hbWUsXHJcbiAgICAgICAgICBwcm9wZXJ0eTogZW50aXR5VHlwZS5nZXRQcm9wZXJ0eShzZXJyLnByb3BlcnR5TmFtZSlcclxuICAgICAgICB9IDoge1xyXG4gICAgICAgIH07XHJcbiAgICAgIGxldCBrZXkgPSBWYWxpZGF0aW9uRXJyb3IuZ2V0S2V5KHNlcnIuZXJyb3JOYW1lIHx8IHNlcnIuZXJyb3JNZXNzYWdlLCBzZXJyLnByb3BlcnR5TmFtZSk7XHJcblxyXG4gICAgICBsZXQgdmUgPSBuZXcgVmFsaWRhdGlvbkVycm9yKG51bGwsIGNvbnRleHQsIHNlcnIuZXJyb3JNZXNzYWdlLCBrZXkpO1xyXG4gICAgICB2ZS5pc1NlcnZlckVycm9yID0gdHJ1ZTtcclxuICAgICAgZW50aXR5LmVudGl0eUFzcGVjdC5hZGRWYWxpZGF0aW9uRXJyb3IodmUpO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBlbnRpdHlFcnJvciA9IGNvcmUuZXh0ZW5kKHtcclxuICAgICAgZW50aXR5OiBlbnRpdHksXHJcbiAgICAgIGlzU2VydmVyRXJyb3I6IHRydWVcclxuICAgIH0sIHNlcnIsIFtcImVycm9yTmFtZVwiLCBcImVycm9yTWVzc2FnZVwiLCBcInByb3BlcnR5TmFtZVwiLCBcImN1c3RvbVwiXSkgYXMgRW50aXR5RXJyb3I7XHJcbiAgICByZXR1cm4gZW50aXR5RXJyb3I7XHJcbiAgfSk7XHJcbiAgLy8gY29udmVydGluZyBJU2F2ZUVycm9yRnJvbVNlcnZlciAtPiBJU2F2ZUVycm9yIFxyXG4gIHNhdmVFcnJvci5lbnRpdHlFcnJvcnMgPSBlbnRpdHlFcnJvcnMgYXMgYW55O1xyXG4gIHJldHVybiA8U2F2ZUVycm9yPiA8YW55PiBzYXZlRXJyb3I7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUVudGl0eUJ5S2V5UmVzdWx0IHtcclxuICBlbnRpdHk/OiBFbnRpdHk7XHJcbiAgZW50aXR5S2V5OiBFbnRpdHlLZXk7XHJcbiAgZnJvbUNhY2hlOiBib29sZWFuO1xyXG59XHJcblxyXG5mdW5jdGlvbiBmZXRjaEVudGl0eUJ5S2V5Q29yZShlbTogRW50aXR5TWFuYWdlciwgYXJnczogYW55W10pOiBQcm9taXNlPElFbnRpdHlCeUtleVJlc3VsdD4ge1xyXG4gIGxldCB0cGwgPSBjcmVhdGVFbnRpdHlLZXkoZW0sIGFyZ3MpO1xyXG4gIGxldCBlbnRpdHlLZXkgPSB0cGwuZW50aXR5S2V5O1xyXG5cclxuICBsZXQgY2hlY2tMb2NhbENhY2hlRmlyc3QgPSB0cGwucmVtYWluaW5nQXJncy5sZW5ndGggPT09IDAgPyBmYWxzZSA6ICEhdHBsLnJlbWFpbmluZ0FyZ3NbMF07XHJcbiAgbGV0IGVudGl0eTogRW50aXR5IHwgbnVsbCA9IG51bGw7XHJcbiAgbGV0IGZvdW5kSXQgPSBmYWxzZTtcclxuICBpZiAoY2hlY2tMb2NhbENhY2hlRmlyc3QpIHtcclxuICAgIGVudGl0eSA9IGVtLmdldEVudGl0eUJ5S2V5KGVudGl0eUtleSk7XHJcbiAgICBmb3VuZEl0ID0gZW50aXR5ICE9IG51bGw7XHJcbiAgICBpZiAoZW50aXR5ICE9IG51bGwgJiZcclxuICAgICAgLy8gbnVsbCB0aGUgZW50aXR5IGlmIGl0IGlzIGRlbGV0ZWQgYW5kIHdlIHNob3VsZCBleGNsdWRlIGRlbGV0ZWQgZW50aXRpZXNcclxuICAgICAgIWVtLnF1ZXJ5T3B0aW9ucy5pbmNsdWRlRGVsZXRlZCAmJiBlbnRpdHkuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlLmlzRGVsZXRlZCgpKSB7XHJcbiAgICAgIGVudGl0eSA9IG51bGw7XHJcbiAgICAgIC8vIGJ1dCByZXN1bWUgbG9va2luZyBpZiB3ZSdkIG92ZXJ3cml0ZSBkZWxldGVkIGVudGl0eSB3aXRoIGEgcmVtb3RlIGVudGl0eVxyXG4gICAgICAvLyBub3RlOiBlbS5xdWVyeU9wdGlvbnMgaXMgYWx3YXlzIGZ1bGx5IHJlc29sdmVkIGJ5IG5vd1xyXG4gICAgICBmb3VuZEl0ID0gZW0ucXVlcnlPcHRpb25zLm1lcmdlU3RyYXRlZ3kgIT09IE1lcmdlU3RyYXRlZ3kuT3ZlcndyaXRlQ2hhbmdlcztcclxuICAgIH1cclxuICB9XHJcbiAgaWYgKGZvdW5kSXQpIHtcclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBlbnRpdHk6IGVudGl0eSB8fCB1bmRlZmluZWQsIGVudGl0eUtleTogZW50aXR5S2V5LCBmcm9tQ2FjaGU6IHRydWUgfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIHJldHVybiBFbnRpdHlRdWVyeS5mcm9tRW50aXR5S2V5KGVudGl0eUtleSkudXNpbmcoZW0pLmV4ZWN1dGUoKS50aGVuKGZ1bmN0aW9uIChkYXRhOiBhbnkpIHtcclxuICAgICAgZW50aXR5ID0gKGRhdGEucmVzdWx0cy5sZW5ndGggPT09IDApID8gbnVsbCA6IGRhdGEucmVzdWx0c1swXTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGVudGl0eTogZW50aXR5IHx8IHVuZGVmaW5lZCwgZW50aXR5S2V5OiBlbnRpdHlLZXksIGZyb21DYWNoZTogZmFsc2UgfSk7XHJcbiAgICB9KTtcclxuICB9XHJcbn1cclxuXHJcblxyXG4vLyBwcml2YXRlIGZuc1xyXG5cclxuLy8gdGFrZXMgaW4gZW50aXR5VHlwZXMgYXMgZWl0aGVyIHN0cmluZ3Mgb3IgZW50aXR5VHlwZXMgb3IgYXJyYXlzIG9mIGVpdGhlclxyXG4vLyBhbmQgcmV0dXJucyBlaXRoZXIgYW4gZW50aXR5VHlwZSBvciBhbiBhcnJheSBvZiBlbnRpdHlUeXBlcyBvciB0aHJvd3MgYW4gZXJyb3JcclxuZnVuY3Rpb24gY2hlY2tFbnRpdHlUeXBlcyhlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICBhc3NlcnRQYXJhbShlbnRpdHlUeXBlcywgXCJlbnRpdHlUeXBlc1wiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKS5vcigpLmlzTm9uRW1wdHlBcnJheSgpLmlzU3RyaW5nKClcclxuICAgIC5vcigpLmlzSW5zdGFuY2VPZihFbnRpdHlUeXBlKS5vcigpLmlzTm9uRW1wdHlBcnJheSgpLmlzSW5zdGFuY2VPZihFbnRpdHlUeXBlKS5jaGVjaygpO1xyXG4gIGxldCByZXN1bHRUeXBlczogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHVuZGVmaW5lZDtcclxuICBpZiAodHlwZW9mIGVudGl0eVR5cGVzID09PSBcInN0cmluZ1wiKSB7XHJcbiAgICByZXN1bHRUeXBlcyA9IGVtLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGVudGl0eVR5cGVzLCBmYWxzZSkgYXMgKEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10pO1xyXG4gIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShlbnRpdHlUeXBlcykgJiYgdHlwZW9mIGVudGl0eVR5cGVzWzBdID09PSBcInN0cmluZ1wiKSB7XHJcbiAgICByZXN1bHRUeXBlcyA9IChlbnRpdHlUeXBlcyBhcyBzdHJpbmdbXSkubWFwKGZ1bmN0aW9uIChldE5hbWUpIHtcclxuICAgICAgcmV0dXJuIGVtLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGV0TmFtZSwgZmFsc2UpIGFzIEVudGl0eVR5cGU7XHJcbiAgICB9KTtcclxuICB9IGVsc2Uge1xyXG4gICAgcmVzdWx0VHlwZXMgPSBlbnRpdHlUeXBlcyBhcyAoRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHVuZGVmaW5lZCk7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmVzdWx0VHlwZXM7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldENoYW5nZXNDb3JlKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10pIHtcclxuICBsZXQgZW50aXR5R3JvdXBzID0gZ2V0RW50aXR5R3JvdXBzKGVtLCBlbnRpdHlUeXBlcyk7XHJcblxyXG4gIC8vIFRPRE86IHRoaW5rIGFib3V0IHdyaXRpbmcgYSBjb3JlLm1hcE1hbnkgbWV0aG9kIGlmIHdlIHNlZSBtb3JlIG9mIHRoZXNlLlxyXG4gIGxldCBzZWxlY3RlZDogRW50aXR5W10gPSBbXTtcclxuICBlbnRpdHlHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZWcpIHtcclxuICAgIC8vIGVnIG1heSBiZSB1bmRlZmluZWQgb3IgbnVsbFxyXG4gICAgaWYgKCFlZykgcmV0dXJuO1xyXG4gICAgbGV0IGVudGl0aWVzID0gZWcuZ2V0Q2hhbmdlcygpO1xyXG4gICAgaWYgKHNlbGVjdGVkICYmIHNlbGVjdGVkLmxlbmd0aCkge1xyXG4gICAgICBzZWxlY3RlZCA9IHNlbGVjdGVkLmNvbmNhdChlbnRpdGllcyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBzZWxlY3RlZCA9IGVudGl0aWVzO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiBzZWxlY3RlZDtcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0RW50aXRpZXNDb3JlKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHlUeXBlczogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHVuZGVmaW5lZCwgZW50aXR5U3RhdGVzOiBFbnRpdHlTdGF0ZVtdKSB7XHJcbiAgbGV0IGVudGl0eUdyb3VwcyA9IGdldEVudGl0eUdyb3VwcyhlbSwgZW50aXR5VHlwZXMpO1xyXG5cclxuICAvLyBUT0RPOiB0aGluayBhYm91dCB3cml0aW5nIGEgY29yZS5tYXBNYW55IG1ldGhvZCBpZiB3ZSBzZWUgbW9yZSBvZiB0aGVzZS5cclxuICBsZXQgc2VsZWN0ZWQ6IEVudGl0eVtdID0gW107XHJcbiAgZW50aXR5R3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGVnKSB7XHJcbiAgICAvLyBlZyBtYXkgYmUgdW5kZWZpbmVkIG9yIG51bGxcclxuICAgIGlmICghZWcpIHJldHVybjtcclxuICAgIGxldCBlbnRpdGllcyA9IGVnLmdldEVudGl0aWVzKGVudGl0eVN0YXRlcyk7XHJcbiAgICBpZiAoc2VsZWN0ZWQgJiYgc2VsZWN0ZWQubGVuZ3RoKSB7XHJcbiAgICAgIHNlbGVjdGVkID0gc2VsZWN0ZWQuY29uY2F0KGVudGl0aWVzKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHNlbGVjdGVkID0gZW50aXRpZXM7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIHNlbGVjdGVkO1xyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gY3JlYXRlRW50aXR5S2V5KGVtOiBFbnRpdHlNYW5hZ2VyLCBhcmdzOiBhbnlbXSkge1xyXG4gIHRyeSB7XHJcbiAgICBpZiAoYXJnc1swXSBpbnN0YW5jZW9mIEVudGl0eUtleSkge1xyXG4gICAgICByZXR1cm4geyBlbnRpdHlLZXk6IGFyZ3NbMF0gYXMgRW50aXR5S2V5LCByZW1haW5pbmdBcmdzOiBjb3JlLmFycmF5U2xpY2UoYXJncywgMSkgfTtcclxuICAgIH0gZWxzZSBpZiAoYXJncy5sZW5ndGggPj0gMikge1xyXG4gICAgICBsZXQgZW50aXR5VHlwZSA9ICh0eXBlb2YgYXJnc1swXSA9PT0gJ3N0cmluZycpID8gZW0ubWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoYXJnc1swXSwgZmFsc2UpIDogYXJnc1swXTtcclxuICAgICAgcmV0dXJuIHsgZW50aXR5S2V5OiBuZXcgRW50aXR5S2V5KGVudGl0eVR5cGUsIGFyZ3NbMV0pLCByZW1haW5pbmdBcmdzOiBjb3JlLmFycmF5U2xpY2UoYXJncywgMikgfTtcclxuICAgIH1cclxuICB9IGNhdGNoIChlKSB7LyogdGhyb3cgYmVsb3cgKi9cclxuICAgIC8vIHRocm93IG5ldyBFcnJvcihcIk11c3Qgc3VwcGx5IGFuIEVudGl0eUtleSBPUiBhbiBFbnRpdHlUeXBlIG5hbWUgb3IgRW50aXR5VHlwZSBmb2xsb3dlZCBieSBhIGtleSB2YWx1ZSBvciBhbiBhcnJheSBvZiBrZXkgdmFsdWVzLlwiKTtcclxuICB9XHJcbiAgdGhyb3cgbmV3IEVycm9yKFwiTXVzdCBzdXBwbHkgYW4gRW50aXR5S2V5IE9SIGFuIEVudGl0eVR5cGUgbmFtZSBvciBFbnRpdHlUeXBlIGZvbGxvd2VkIGJ5IGEga2V5IHZhbHVlIG9yIGFuIGFycmF5IG9mIGtleSB2YWx1ZXMuXCIpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBtYXJrSXNCZWluZ1NhdmVkKGVudGl0aWVzOiBFbnRpdHlbXSwgZmxhZzogYm9vbGVhbikge1xyXG4gIGVudGl0aWVzLmZvckVhY2goZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgZW50aXR5LmVudGl0eUFzcGVjdC5pc0JlaW5nU2F2ZWQgPSBmbGFnO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBleHBvcnRFbnRpdHlHcm91cHMoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0aWVzT3JFbnRpdHlUeXBlczogRW50aXR5W10gfCBFbnRpdHlUeXBlW10gfCBzdHJpbmdbXSkge1xyXG4gIGxldCBlbnRpdHlHcm91cE1hcDogeyBbaW5kZXg6IHN0cmluZ106IEVudGl0eUdyb3VwIH07XHJcbiAgbGV0IGZpcnN0ID0gZW50aXRpZXNPckVudGl0eVR5cGVzICYmIGVudGl0aWVzT3JFbnRpdHlUeXBlc1swXTtcclxuICAvLyBjaGVjayBpZiBhcnJheVxyXG4gIGlmIChmaXJzdCkge1xyXG4gICAgLy8gZ3JvdXAgZW50aXRpZXMgYnkgZW50aXR5VHlwZSBhbmRcclxuICAgIC8vIGNyZWF0ZSAnZ3JvdXBzJyB0aGF0IGxvb2sgbGlrZSBlbnRpdHlHcm91cHMuXHJcbiAgICBlbnRpdHlHcm91cE1hcCA9IHt9O1xyXG4gICAgaWYgKChmaXJzdCBhcyBhbnkpLmVudGl0eVR5cGUpIHtcclxuICAgICAgbGV0IGVudGl0aWVzID0gZW50aXRpZXNPckVudGl0eVR5cGVzIGFzIEVudGl0eVtdO1xyXG4gICAgICAvLyBhc3N1bWUgXCJlbnRpdGllc1wiIGlzIGFuIGFycmF5IG9mIGVudGl0aWVzO1xyXG4gICAgICBlbnRpdGllcy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgaWYgKGUuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlID09PSBFbnRpdHlTdGF0ZS5EZXRhY2hlZCkge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIGV4cG9ydCBhbiBlbnRpdHkgd2l0aCBhbiBFbnRpdHlTdGF0ZSBvZiAnRGV0YWNoZWQnXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBsZXQgZ3JvdXAgPSBlbnRpdHlHcm91cE1hcFtlLmVudGl0eVR5cGUubmFtZV07XHJcbiAgICAgICAgaWYgKCFncm91cCkge1xyXG4gICAgICAgICAgZ3JvdXAgPSB7fSBhcyBFbnRpdHlHcm91cDtcclxuICAgICAgICAgIGdyb3VwLmVudGl0eVR5cGUgPSBlLmVudGl0eVR5cGU7XHJcbiAgICAgICAgICBncm91cC5fZW50aXRpZXMgPSBbXTtcclxuICAgICAgICAgIGVudGl0eUdyb3VwTWFwW2UuZW50aXR5VHlwZS5uYW1lXSA9IGdyb3VwO1xyXG4gICAgICAgIH1cclxuICAgICAgICBncm91cC5fZW50aXRpZXMucHVzaChlKTtcclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBhc3N1bWUgXCJlbnRpdGllc1wiIGlzIGFuIGFycmF5IG9mIEVudGl0eVR5cGVzIChvciBuYW1lcylcclxuICAgICAgbGV0IGVudGl0eVR5cGVzID0gY2hlY2tFbnRpdHlUeXBlcyhlbSwgZW50aXRpZXNPckVudGl0eVR5cGVzIGFzIEVudGl0eVR5cGVbXSB8IHN0cmluZ1tdKSBhcyBFbnRpdHlUeXBlW107XHJcbiAgICAgIGlmIChlbnRpdHlUeXBlcyAhPSBudWxsKSB7XHJcbiAgICAgICAgZW50aXR5VHlwZXMuZm9yRWFjaCgoZXQpID0+IHtcclxuICAgICAgICAgIGxldCBncm91cCA9IGVtLl9lbnRpdHlHcm91cE1hcFtldC5uYW1lXTtcclxuICAgICAgICAgIGlmIChncm91cCAmJiBncm91cC5fZW50aXRpZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIGVudGl0eUdyb3VwTWFwW2V0Lm5hbWVdID0gZ3JvdXA7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9IGVsc2UgaWYgKGVudGl0aWVzT3JFbnRpdHlUeXBlcyAmJiBlbnRpdGllc09yRW50aXR5VHlwZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAvLyBlbXB0eSBhcnJheSA9IGV4cG9ydCBub3RoaW5nXHJcbiAgICBlbnRpdHlHcm91cE1hcCA9IHt9O1xyXG4gIH0gZWxzZSB7XHJcbiAgICBlbnRpdHlHcm91cE1hcCA9IGVtLl9lbnRpdHlHcm91cE1hcDtcclxuICB9XHJcblxyXG4gIGxldCB0ZW1wS2V5czogSVRlbXBLZXlbXSA9IFtdO1xyXG4gIGxldCBuZXdHcm91cE1hcCA9IHt9O1xyXG4gIGNvcmUub2JqZWN0Rm9yRWFjaChlbnRpdHlHcm91cE1hcCwgKGVudGl0eVR5cGVOYW1lLCBlbnRpdHlHcm91cCkgPT4ge1xyXG4gICAgbmV3R3JvdXBNYXBbZW50aXR5VHlwZU5hbWVdID0gZXhwb3J0RW50aXR5R3JvdXAoZW50aXR5R3JvdXAsIHRlbXBLZXlzKTtcclxuICB9KTtcclxuXHJcbiAgcmV0dXJuIHsgZW50aXR5R3JvdXBNYXA6IG5ld0dyb3VwTWFwLCB0ZW1wS2V5czogdGVtcEtleXMgfTtcclxufVxyXG5cclxuZnVuY3Rpb24gZXhwb3J0RW50aXR5R3JvdXAoZW50aXR5R3JvdXA6IEVudGl0eUdyb3VwLCB0ZW1wS2V5czogSVRlbXBLZXlbXSkge1xyXG4gIGxldCByZXN1bHRHcm91cCA9IHt9IGFzIHsgZW50aXRpZXM6IGFueVtdIH07XHJcbiAgbGV0IGVudGl0eVR5cGUgPSBlbnRpdHlHcm91cC5lbnRpdHlUeXBlO1xyXG4gIGxldCBkcHMgPSBlbnRpdHlUeXBlLmRhdGFQcm9wZXJ0aWVzO1xyXG4gIGxldCBzZXJpYWxpemVyRm4gPSBnZXRTZXJpYWxpemVyRm4oZW50aXR5VHlwZSk7XHJcbiAgbGV0IHJhd0VudGl0aWVzOiBhbnlbXSA9IFtdO1xyXG4gIGVudGl0eUdyb3VwLl9lbnRpdGllcy5mb3JFYWNoKChlbnRpdHkpID0+IHtcclxuICAgIGlmIChlbnRpdHkpIHtcclxuICAgICAgbGV0IHJhd0VudGl0eSA9IHN0cnVjdHVyYWxPYmplY3RUb0pzb24oZW50aXR5LCBkcHMsIHNlcmlhbGl6ZXJGbiwgdGVtcEtleXMpO1xyXG4gICAgICByYXdFbnRpdGllcy5wdXNoKHJhd0VudGl0eSk7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmVzdWx0R3JvdXAuZW50aXRpZXMgPSByYXdFbnRpdGllcztcclxuICByZXR1cm4gcmVzdWx0R3JvdXA7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHN0cnVjdHVyYWxPYmplY3RUb0pzb24oc286IFN0cnVjdHVyYWxPYmplY3QsIGRwczogRGF0YVByb3BlcnR5W10sIHNlcmlhbGl6ZXJGbj86IChkcDogRGF0YVByb3BlcnR5LCB2YWx1ZTogYW55KSA9PiBhbnksIHRlbXBLZXlzPzogSVRlbXBLZXlbXSkge1xyXG5cclxuICBsZXQgcmVzdWx0ID0ge307XHJcbiAgZHBzLmZvckVhY2goZnVuY3Rpb24gKGRwKSB7XHJcbiAgICBsZXQgZHBOYW1lID0gZHAubmFtZTtcclxuICAgIGxldCB2YWx1ZSA9IHNvLmdldFByb3BlcnR5KGRwTmFtZSk7XHJcbiAgICBpZiAodmFsdWUgPT0gbnVsbCAmJiBkcC5kZWZhdWx0VmFsdWUgPT0gbnVsbCkgcmV0dXJuO1xyXG5cclxuICAgIGlmICh2YWx1ZSAmJiBkcC5pc0NvbXBsZXhQcm9wZXJ0eSkge1xyXG4gICAgICBsZXQgY29EcHMgPSAoZHAuZGF0YVR5cGUgYXMgQ29tcGxleFR5cGUpLmRhdGFQcm9wZXJ0aWVzO1xyXG4gICAgICB2YWx1ZSA9IGNvcmUubWFwKHZhbHVlLCBmdW5jdGlvbiAodjogQ29tcGxleE9iamVjdCkge1xyXG4gICAgICAgIHJldHVybiBzdHJ1Y3R1cmFsT2JqZWN0VG9Kc29uKHYsIGNvRHBzLCBzZXJpYWxpemVyRm4pO1xyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHZhbHVlID0gc2VyaWFsaXplckZuID8gc2VyaWFsaXplckZuKGRwLCB2YWx1ZSkgOiB2YWx1ZTtcclxuICAgICAgaWYgKGRwLmlzVW5tYXBwZWQpIHtcclxuICAgICAgICB2YWx1ZSA9IGNvcmUudG9KU09OU2FmZSh2YWx1ZSwgY29yZS50b0pTT05TYWZlUmVwbGFjZXIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xyXG4gICAgcmVzdWx0W2RwTmFtZV0gPSB2YWx1ZTtcclxuICB9KTtcclxuXHJcbiAgLy8gaWYgKHNvLmVudGl0eUFzcGVjdCkge1xyXG4gIGlmIChFbnRpdHlBc3BlY3QuaXNFbnRpdHkoc28pKSB7XHJcbiAgICBsZXQgYXNwZWN0ID0gc28uZW50aXR5QXNwZWN0O1xyXG4gICAgbGV0IGVudGl0eVN0YXRlID0gYXNwZWN0LmVudGl0eVN0YXRlO1xyXG4gICAgbGV0IG5ld0FzcGVjdCA9IHtcclxuICAgICAgdGVtcE5hdlByb3BOYW1lczogZXhwb3J0VGVtcEtleUluZm8oYXNwZWN0LCB0ZW1wS2V5cyB8fCBbXSksXHJcbiAgICAgIGVudGl0eVN0YXRlOiBlbnRpdHlTdGF0ZS5uYW1lXHJcbiAgICB9IGFzIGFueTtcclxuICAgIGlmIChhc3BlY3QuZXh0cmFNZXRhZGF0YSkge1xyXG4gICAgICBuZXdBc3BlY3QuZXh0cmFNZXRhZGF0YSA9IGFzcGVjdC5leHRyYU1ldGFkYXRhO1xyXG4gICAgfVxyXG4gICAgaWYgKGVudGl0eVN0YXRlLmlzTW9kaWZpZWQoKSB8fCBlbnRpdHlTdGF0ZS5pc0RlbGV0ZWQoKSkge1xyXG4gICAgICBuZXdBc3BlY3Qub3JpZ2luYWxWYWx1ZXNNYXAgPSBhc3BlY3Qub3JpZ2luYWxWYWx1ZXM7XHJcbiAgICB9XHJcbiAgICAocmVzdWx0IGFzIGFueSkuZW50aXR5QXNwZWN0ID0gbmV3QXNwZWN0O1xyXG4gIH0gZWxzZSB7XHJcbiAgICBsZXQgYXNwZWN0ID0gc28uY29tcGxleEFzcGVjdDtcclxuICAgIGxldCBuZXdBc3BlY3QgPSB7fSBhcyBhbnk7XHJcbiAgICBpZiAoYXNwZWN0Lm9yaWdpbmFsVmFsdWVzICYmICFjb3JlLmlzRW1wdHkoYXNwZWN0Lm9yaWdpbmFsVmFsdWVzKSkge1xyXG4gICAgICBuZXdBc3BlY3Qub3JpZ2luYWxWYWx1ZXNNYXAgPSBhc3BlY3Qub3JpZ2luYWxWYWx1ZXM7XHJcbiAgICB9XHJcblxyXG4gICAgKHJlc3VsdCBhcyBhbnkpLmNvbXBsZXhBc3BlY3QgPSBuZXdBc3BlY3Q7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSVRlbXBLZXkge1xyXG4gIGVudGl0eVR5cGU6IHN0cmluZztcclxuICB2YWx1ZXM6IGFueVtdO1xyXG59XHJcblxyXG5mdW5jdGlvbiBleHBvcnRUZW1wS2V5SW5mbyhlbnRpdHlBc3BlY3Q6IEVudGl0eUFzcGVjdCwgdGVtcEtleXM6IElUZW1wS2V5W10pIHtcclxuICBsZXQgZW50aXR5ID0gZW50aXR5QXNwZWN0LmVudGl0eSBhcyBFbnRpdHk7XHJcbiAgaWYgKGVudGl0eUFzcGVjdC5oYXNUZW1wS2V5KSB7XHJcbiAgICB0ZW1wS2V5cy5wdXNoKGVudGl0eUFzcGVjdC5nZXRLZXkoKS50b0pTT04oKSk7XHJcbiAgfVxyXG4gIC8vIGNyZWF0ZSBtYXAgZm9yIHRoaXMgZW50aXR5IHdpdGggZm9yZWlnbktleXMgdGhhdCBhcmUgJ3RlbXBvcmFyeSdcclxuICAvLyBtYXAgLT4ga2V5OiB0ZW1wS2V5LCB2YWx1ZTogZmtQcm9wTmFtZVxyXG4gIGxldCB0ZW1wTmF2UHJvcE5hbWVzOiBzdHJpbmdbXSA9IFtdO1xyXG4gIGVudGl0eS5lbnRpdHlUeXBlLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKG5wKSB7XHJcbiAgICBpZiAobnAucmVsYXRlZERhdGFQcm9wZXJ0aWVzKSB7XHJcbiAgICAgIGxldCByZWxhdGVkVmFsdWUgPSBlbnRpdHkuZ2V0UHJvcGVydHkobnAubmFtZSk7XHJcbiAgICAgIGlmIChyZWxhdGVkVmFsdWUgJiYgcmVsYXRlZFZhbHVlLmVudGl0eUFzcGVjdC5oYXNUZW1wS2V5KSB7XHJcbiAgICAgICAgdGVtcE5hdlByb3BOYW1lcy5wdXNoKG5wLm5hbWUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIHRlbXBOYXZQcm9wTmFtZXM7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGltcG9ydEVudGl0eUdyb3VwKGVudGl0eUdyb3VwOiBFbnRpdHlHcm91cCwganNvbkdyb3VwOiB7IGVudGl0aWVzOiBhbnlbXSB9LCBpbXBvcnRDb25maWc6IEltcG9ydENvbmZpZ0V4dCkge1xyXG5cclxuICBsZXQgdGVtcEtleU1hcCA9IGltcG9ydENvbmZpZy50ZW1wS2V5TWFwO1xyXG4gIGxldCBtZXJnZUFkZHMgPSAhIWltcG9ydENvbmZpZy5tZXJnZUFkZHM7XHJcblxyXG4gIGxldCBlbnRpdHlUeXBlID0gZW50aXR5R3JvdXAuZW50aXR5VHlwZTtcclxuICBsZXQgbWVyZ2VTdHJhdGVneSA9IGltcG9ydENvbmZpZy5tZXJnZVN0cmF0ZWd5O1xyXG5cclxuICBsZXQgdGFyZ2V0RW50aXR5OiBFbnRpdHkgfCB1bmRlZmluZWQ7XHJcblxyXG4gIGxldCBlbSA9IGVudGl0eUdyb3VwLmVudGl0eU1hbmFnZXI7XHJcbiAgbGV0IGVudGl0eUNoYW5nZWQgPSBlbS5lbnRpdHlDaGFuZ2VkO1xyXG4gIGxldCBlbnRpdGllc1RvTGluazogRW50aXR5W10gPSBbXTtcclxuICBsZXQgcmF3VmFsdWVGbiA9IERhdGFQcm9wZXJ0eS5nZXRSYXdWYWx1ZUZyb21DbGllbnQ7XHJcbiAganNvbkdyb3VwLmVudGl0aWVzLmZvckVhY2goZnVuY3Rpb24gKHJhd0VudGl0eTogYW55KSB7XHJcbiAgICBsZXQgbmV3QXNwZWN0ID0gcmF3RW50aXR5LmVudGl0eUFzcGVjdDtcclxuXHJcbiAgICBsZXQgZW50aXR5S2V5ID0gZW50aXR5VHlwZS5nZXRFbnRpdHlLZXlGcm9tUmF3RW50aXR5KHJhd0VudGl0eSwgcmF3VmFsdWVGbik7XHJcbiAgICBsZXQgZW50aXR5U3RhdGUgPSBFbnRpdHlTdGF0ZS5mcm9tTmFtZShuZXdBc3BlY3QuZW50aXR5U3RhdGUpIGFzIEVudGl0eVN0YXRlO1xyXG4gICAgaWYgKCFlbnRpdHlTdGF0ZSB8fCBlbnRpdHlTdGF0ZSA9PT0gRW50aXR5U3RhdGUuRGV0YWNoZWQpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiT25seSBlbnRpdGllcyB3aXRoIGEgbm9uIGRldGFjaGVkIGVudGl0eSBzdGF0ZSBtYXkgYmUgaW1wb3J0ZWQuXCIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIE1lcmdlIGlmIHJhdyBlbnRpdHkgaXMgaW4gY2FjaGUgVU5MRVNTIHRoaXMgaXMgYSBuZXcgZW50aXR5IHcvIGEgdGVtcCBrZXlcclxuICAgIC8vIENhbm5vdCBzYWZlbHkgbWVyZ2Ugc3VjaCBlbnRpdGllcyBldmVuIGlmIGNvdWxkIG1hdGNoIHRlbXAga2V5IHRvIGFuIGVudGl0eSBpbiBjYWNoZS5cclxuICAgIC8vIENhbiBlbmFibGUgbWVyZ2Ugb2YgZW50aXRpZXMgdy90ZW1wIGtleSB1c2luZyBcIm1lcmdlQWRkc1wiIC0gdXNlIGF0IHlvdXIgb3duIHJpc2shXHJcbiAgICBsZXQgbmV3VGVtcEtleSA9ICFtZXJnZUFkZHMgJiYgZW50aXR5U3RhdGUuaXNBZGRlZCgpICYmIGdldE1hcHBlZEtleSh0ZW1wS2V5TWFwISwgZW50aXR5S2V5KTtcclxuICAgIHRhcmdldEVudGl0eSA9IG5ld1RlbXBLZXkgPyB1bmRlZmluZWQgOiBlbnRpdHlHcm91cC5maW5kRW50aXR5QnlLZXkoZW50aXR5S2V5KTtcclxuXHJcbiAgICBpZiAodGFyZ2V0RW50aXR5KSB7XHJcbiAgICAgIGlmIChtZXJnZVN0cmF0ZWd5ID09PSBNZXJnZVN0cmF0ZWd5LlNraXBNZXJnZSkge1xyXG4gICAgICAgIC8vIGRlbGliZXJhdGUgZmFsbCB0aHJ1XHJcbiAgICAgIH0gZWxzZSBpZiAobWVyZ2VTdHJhdGVneSA9PT0gTWVyZ2VTdHJhdGVneS5EaXNhbGxvd2VkKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQSBNZXJnZVN0cmF0ZWd5IG9mICdEaXNhbGxvd2VkJyBwcmV2ZW50cyBcIiArIGVudGl0eUtleS50b1N0cmluZygpICsgXCIgZnJvbSBiZWluZyBtZXJnZWRcIik7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgbGV0IHRhcmdldEVudGl0eVN0YXRlID0gdGFyZ2V0RW50aXR5LmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZTtcclxuICAgICAgICBsZXQgd2FzVW5jaGFuZ2VkID0gdGFyZ2V0RW50aXR5U3RhdGUuaXNVbmNoYW5nZWQoKTtcclxuICAgICAgICBpZiAobWVyZ2VTdHJhdGVneSA9PT0gTWVyZ2VTdHJhdGVneS5PdmVyd3JpdGVDaGFuZ2VzIHx8IHdhc1VuY2hhbmdlZCkge1xyXG4gICAgICAgICAgZW50aXR5VHlwZS5fdXBkYXRlVGFyZ2V0RnJvbVJhdyh0YXJnZXRFbnRpdHksIHJhd0VudGl0eSwgcmF3VmFsdWVGbik7XHJcbiAgICAgICAgICB0YXJnZXRFbnRpdHkuZW50aXR5QXNwZWN0LnNldEVudGl0eVN0YXRlKGVudGl0eVN0YXRlKTtcclxuICAgICAgICAgIGVudGl0eUNoYW5nZWQucHVibGlzaCh7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLk1lcmdlT25JbXBvcnQsIGVudGl0eTogdGFyZ2V0RW50aXR5IH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGFyZ2V0RW50aXR5ID0gZW50aXR5VHlwZS5fY3JlYXRlSW5zdGFuY2VDb3JlKCkgYXMgRW50aXR5O1xyXG4gICAgICBlbnRpdHlUeXBlLl91cGRhdGVUYXJnZXRGcm9tUmF3KHRhcmdldEVudGl0eSwgcmF3RW50aXR5LCByYXdWYWx1ZUZuKTtcclxuICAgICAgaWYgKG5ld1RlbXBLZXkpIHtcclxuICAgICAgICB0YXJnZXRFbnRpdHkuZW50aXR5QXNwZWN0Lmhhc1RlbXBLZXkgPSB0cnVlO1xyXG4gICAgICAgIC8vIGZpeHVwIHBrXHJcbiAgICAgICAgdGFyZ2V0RW50aXR5LnNldFByb3BlcnR5KGVudGl0eVR5cGUua2V5UHJvcGVydGllc1swXS5uYW1lLCBuZXdUZW1wS2V5LnZhbHVlc1swXSk7XHJcblxyXG4gICAgICAgIC8vIGZpeHVwIGZvcmVpZ24ga2V5c1xyXG4gICAgICAgIC8vIFRoaXMgaXMgc2FmZSBiZWNhdXNlIHRoZSBlbnRpdHkgaXMgZGV0YWNoZWQgaGVyZSBhbmQgdGhlcmVmb3JlIG9yaWdpbmFsVmFsdWVzIHdpbGwgbm90IGJlIHVwZGF0ZWQuXHJcbiAgICAgICAgaWYgKG5ld0FzcGVjdC50ZW1wTmF2UHJvcE5hbWVzKSB7XHJcbiAgICAgICAgICBuZXdBc3BlY3QudGVtcE5hdlByb3BOYW1lcy5mb3JFYWNoKGZ1bmN0aW9uIChucE5hbWU6IHN0cmluZykge1xyXG4gICAgICAgICAgICBsZXQgbnAgPSBlbnRpdHlUeXBlLmdldE5hdmlnYXRpb25Qcm9wZXJ0eShucE5hbWUpO1xyXG4gICAgICAgICAgICBsZXQgZmtQcm9wTmFtZSA9IG5wIS5yZWxhdGVkRGF0YVByb3BlcnRpZXNbMF0ubmFtZTtcclxuICAgICAgICAgICAgbGV0IG9sZEZrVmFsdWUgPSB0YXJnZXRFbnRpdHkhLmdldFByb3BlcnR5KGZrUHJvcE5hbWUpO1xyXG4gICAgICAgICAgICBsZXQgZmsgPSBuZXcgRW50aXR5S2V5KG5wIS5lbnRpdHlUeXBlLCBbb2xkRmtWYWx1ZV0pO1xyXG4gICAgICAgICAgICBsZXQgbmV3RmsgPSBnZXRNYXBwZWRLZXkodGVtcEtleU1hcCEsIGZrKTtcclxuICAgICAgICAgICAgdGFyZ2V0RW50aXR5IS5zZXRQcm9wZXJ0eShma1Byb3BOYW1lLCBuZXdGayEudmFsdWVzWzBdKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICAvLyBOb3cgcGVyZm9ybWVkIGluIGF0dGFjaEVudGl0eVxyXG4gICAgICB0YXJnZXRFbnRpdHkgPSBlbnRpdHlHcm91cC5hdHRhY2hFbnRpdHkodGFyZ2V0RW50aXR5LCBlbnRpdHlTdGF0ZSk7XHJcbiAgICAgIGVudGl0eUNoYW5nZWQucHVibGlzaCh7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLkF0dGFjaE9uSW1wb3J0LCBlbnRpdHk6IHRhcmdldEVudGl0eSB9KTtcclxuICAgICAgaWYgKCFlbnRpdHlTdGF0ZS5pc1VuY2hhbmdlZCgpKSB7XHJcbiAgICAgICAgZW0uX25vdGlmeVN0YXRlQ2hhbmdlKHRhcmdldEVudGl0eSwgdHJ1ZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBlbnRpdGllc1RvTGluay5wdXNoKHRhcmdldEVudGl0eSk7XHJcbiAgfSk7XHJcbiAgcmV0dXJuIGVudGl0aWVzVG9MaW5rO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRNYXBwZWRLZXkodGVtcEtleU1hcDogSVRlbXBLZXlNYXAsIGVudGl0eUtleTogRW50aXR5S2V5KSB7XHJcbiAgbGV0IG5ld0tleSA9IHRlbXBLZXlNYXBbZW50aXR5S2V5LnRvU3RyaW5nKCldO1xyXG4gIGlmIChuZXdLZXkpIHJldHVybiBuZXdLZXk7XHJcbiAgbGV0IHN1YnR5cGVzID0gZW50aXR5S2V5Ll9zdWJ0eXBlcztcclxuICBpZiAoIXN1YnR5cGVzKSByZXR1cm4gbnVsbDtcclxuICBmb3IgKGxldCBpID0gMCwgaiA9IHN1YnR5cGVzLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG4gICAgbmV3S2V5ID0gdGVtcEtleU1hcFtlbnRpdHlLZXkudG9TdHJpbmcoc3VidHlwZXNbaV0pXTtcclxuICAgIGlmIChuZXdLZXkpIHJldHVybiBuZXdLZXk7XHJcbiAgfVxyXG4gIHJldHVybiBudWxsO1xyXG59XHJcblxyXG5mdW5jdGlvbiBwcm9taXNlV2l0aENhbGxiYWNrczxUPihwcm9taXNlOiBQcm9taXNlPFQ+LCBjYWxsYmFjaz86IENhbGxiYWNrLCBlcnJvckNhbGxiYWNrPzogRXJyb3JDYWxsYmFjaykge1xyXG4gIHByb21pc2UgPSBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKGRhdGEpIHtcclxuICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soZGF0YSk7XHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGRhdGEpO1xyXG4gIH0sIGZ1bmN0aW9uIChlcnJvcikge1xyXG4gICAgaWYgKGVycm9yQ2FsbGJhY2spIGVycm9yQ2FsbGJhY2soZXJyb3IpO1xyXG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcclxuICB9KTtcclxuICByZXR1cm4gcHJvbWlzZTtcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0RW50aXRpZXNUb1NhdmUoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0aWVzPzogRW50aXR5W10pIHtcclxuICBsZXQgZW50aXRpZXNUb1NhdmU6IEVudGl0eVtdO1xyXG4gIGlmIChlbnRpdGllcykge1xyXG4gICAgZW50aXRpZXNUb1NhdmUgPSBlbnRpdGllcy5maWx0ZXIoZnVuY3Rpb24gKGUpIHtcclxuICAgICAgaWYgKGUuZW50aXR5QXNwZWN0LmVudGl0eU1hbmFnZXIgIT09IGVtKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiT25seSBlbnRpdGllcyBpbiB0aGlzIGVudGl0eU1hbmFnZXIgbWF5IGJlIHNhdmVkXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiAhZS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUuaXNEZXRhY2hlZCgpO1xyXG4gICAgfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIGVudGl0aWVzVG9TYXZlID0gZW0uZ2V0Q2hhbmdlcygpO1xyXG4gIH1cclxuICByZXR1cm4gZW50aXRpZXNUb1NhdmU7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZpeHVwS2V5cyhlbTogRW50aXR5TWFuYWdlciwga2V5TWFwcGluZ3M6IEtleU1hcHBpbmdbXSkge1xyXG4gIGVtLl9pbktleUZpeHVwID0gdHJ1ZTtcclxuICBrZXlNYXBwaW5ncy5mb3JFYWNoKGZ1bmN0aW9uIChrbSkge1xyXG4gICAgbGV0IGdyb3VwID0gZW0uX2VudGl0eUdyb3VwTWFwW2ttLmVudGl0eVR5cGVOYW1lXTtcclxuICAgIGlmICghZ3JvdXApIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIGxvY2F0ZSB0aGUgZm9sbG93aW5nIGZ1bGx5IHF1YWxpZmllZCBFbnRpdHlUeXBlIG5hbWU6IFwiICsga20uZW50aXR5VHlwZU5hbWUpO1xyXG4gICAgfVxyXG4gICAgZ3JvdXAuX2ZpeHVwS2V5KGttLnRlbXBWYWx1ZSwga20ucmVhbFZhbHVlKTtcclxuICB9KTtcclxuICBlbS5faW5LZXlGaXh1cCA9IGZhbHNlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRFbnRpdHlHcm91cHMoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSkge1xyXG4gIGxldCBncm91cE1hcCA9IGVtLl9lbnRpdHlHcm91cE1hcDtcclxuICBpZiAoZW50aXR5VHlwZXMpIHtcclxuICAgIHJldHVybiBjb3JlLnRvQXJyYXkoZW50aXR5VHlwZXMpLm1hcChmdW5jdGlvbiAoZXQ6IEVudGl0eVR5cGUpIHtcclxuICAgICAgaWYgKGV0IGluc3RhbmNlb2YgRW50aXR5VHlwZSkge1xyXG4gICAgICAgIHJldHVybiBncm91cE1hcFtldC5uYW1lXTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgRW50aXR5TWFuYWdlci5nZXRDaGFuZ2VzKCkgJ2VudGl0eVR5cGVzJyBwYXJhbWV0ZXIgbXVzdCBiZSBlaXRoZXIgYW4gZW50aXR5VHlwZSBvciBhbiBhcnJheSBvZiBlbnRpdHlUeXBlcyBvciBudWxsXCIpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9IGVsc2Uge1xyXG4gICAgcmV0dXJuIGNvcmUuZ2V0T3duUHJvcGVydHlWYWx1ZXMoZ3JvdXBNYXApIGFzIEVudGl0eUdyb3VwW107XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBjaGVja0VudGl0eUtleShlbTogRW50aXR5TWFuYWdlciwgZW50aXR5OiBFbnRpdHkpIHtcclxuICBsZXQgZWsgPSBlbnRpdHkuZW50aXR5QXNwZWN0LmdldEtleSgpO1xyXG4gIC8vIHJldHVybiBwcm9wZXJ0aWVzIHRoYXQgYXJlID0gdG8gZGVmYXVsdFZhbHVlc1xyXG4gIGxldCBrZXlQcm9wc1dpdGhEZWZhdWx0VmFsdWVzID0gY29yZS5hcnJheVppcChlbnRpdHkuZW50aXR5VHlwZS5rZXlQcm9wZXJ0aWVzLCBlay52YWx1ZXMsIGZ1bmN0aW9uIChrcCwga3YpIHtcclxuICAgIHJldHVybiAoa3AuZGVmYXVsdFZhbHVlID09PSBrdikgPyBrcCA6IG51bGw7XHJcbiAgfSkuZmlsdGVyKGZ1bmN0aW9uIChrcCkge1xyXG4gICAgcmV0dXJuIGtwICE9PSBudWxsO1xyXG4gIH0pO1xyXG4gIGlmIChrZXlQcm9wc1dpdGhEZWZhdWx0VmFsdWVzLmxlbmd0aCkge1xyXG4gICAgaWYgKGVudGl0eS5lbnRpdHlUeXBlLmF1dG9HZW5lcmF0ZWRLZXlUeXBlICE9PSBBdXRvR2VuZXJhdGVkS2V5VHlwZS5Ob25lKSB7XHJcbiAgICAgIGVtLmdlbmVyYXRlVGVtcEtleVZhbHVlKGVudGl0eSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyB3ZSB3aWxsIGFsbG93IGF0dGFjaGVzIG9mIGVudGl0aWVzIHdoZXJlIG9ubHkgcGFydCBvZiB0aGUga2V5IGlzIHNldC5cclxuICAgICAgaWYgKGtleVByb3BzV2l0aERlZmF1bHRWYWx1ZXMubGVuZ3RoID09PSBlay52YWx1ZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGF0dGFjaCBhbiBvYmplY3Qgb2YgdHlwZSAgKFwiICsgZW50aXR5LmVudGl0eVR5cGUubmFtZSArIFwiKSB0byBhbiBFbnRpdHlNYW5hZ2VyIHdpdGhvdXQgZmlyc3Qgc2V0dGluZyBpdHMga2V5IG9yIHNldHRpbmcgaXRzIGVudGl0eVR5cGUgJ0F1dG9HZW5lcmF0ZWRLZXlUeXBlJyBwcm9wZXJ0eSB0byBzb21ldGhpbmcgb3RoZXIgdGhhbiAnTm9uZSdcIik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHZhbGlkYXRlRW50aXR5U3RhdGVzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHlTdGF0ZXM/OiBFbnRpdHlTdGF0ZSB8IEVudGl0eVN0YXRlW10pIHtcclxuICBpZiAoIWVudGl0eVN0YXRlcykgcmV0dXJuIFtdIGFzIEVudGl0eVN0YXRlW107XHJcbiAgbGV0IGVudFN0YXRlcyA9IGNvcmUudG9BcnJheShlbnRpdHlTdGF0ZXMpIGFzIEVudGl0eVN0YXRlW107XHJcbiAgZW50U3RhdGVzLmZvckVhY2goKGVzKSA9PiB7XHJcbiAgICBpZiAoIShlcyBpbnN0YW5jZW9mIEVudGl0eVN0YXRlKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgRW50aXR5TWFuYWdlci5nZXRDaGFuZ2VzKCkgJ2VudGl0eVN0YXRlcycgcGFyYW1ldGVyIG11c3QgZWl0aGVyIGJlIG51bGwsIGFuIGVudGl0eVN0YXRlIG9yIGFuIGFycmF5IG9mIGVudGl0eVN0YXRlc1wiKTtcclxuICAgIH1cclxuICB9KTtcclxuICByZXR1cm4gZW50U3RhdGVzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBhdHRhY2hSZWxhdGVkRW50aXRpZXMoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eTogRW50aXR5LCBlbnRpdHlTdGF0ZTogRW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3k6IE1lcmdlU3RyYXRlZ3kpIHtcclxuICBsZXQgbmF2UHJvcHMgPSBlbnRpdHkuZW50aXR5VHlwZS5uYXZpZ2F0aW9uUHJvcGVydGllcztcclxuICBuYXZQcm9wcy5mb3JFYWNoKGZ1bmN0aW9uIChucCkge1xyXG4gICAgbGV0IHJlbGF0ZWQgPSBlbnRpdHkuZ2V0UHJvcGVydHkobnAubmFtZSk7XHJcbiAgICBpZiAobnAuaXNTY2FsYXIpIHtcclxuICAgICAgaWYgKCFyZWxhdGVkKSByZXR1cm47XHJcbiAgICAgIGVtLmF0dGFjaEVudGl0eShyZWxhdGVkLCBlbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZWxhdGVkLmZvckVhY2goZnVuY3Rpb24gKGU6IEVudGl0eSkge1xyXG4gICAgICAgIGVtLmF0dGFjaEVudGl0eShlLCBlbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH0pO1xyXG59XHJcblxyXG4vLyByZXR1cm5zIGEgcHJvbWlzZVxyXG5mdW5jdGlvbiBleGVjdXRlUXVlcnlDb3JlKGVtOiBFbnRpdHlNYW5hZ2VyLCBxdWVyeTogRW50aXR5UXVlcnkgfCBzdHJpbmcsIHF1ZXJ5T3B0aW9uczogUXVlcnlPcHRpb25zLCBkYXRhU2VydmljZTogRGF0YVNlcnZpY2UpOiBQcm9taXNlPFF1ZXJ5UmVzdWx0PiB7XHJcbiAgdHJ5IHtcclxuICAgIGxldCByZXN1bHRzOiBhbnlbXTtcclxuICAgIGxldCBtZXRhZGF0YVN0b3JlID0gZW0ubWV0YWRhdGFTdG9yZTtcclxuXHJcbiAgICBpZiAobWV0YWRhdGFTdG9yZS5pc0VtcHR5KCkgJiYgZGF0YVNlcnZpY2UuaGFzU2VydmVyTWV0YWRhdGEpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY2Fubm90IGV4ZWN1dGUgX2V4ZWN1dGVRdWVyeUNvcmUgdW50aWwgbWV0YWRhdGFTdG9yZSBpcyBwb3B1bGF0ZWQuXCIpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChxdWVyeU9wdGlvbnMuZmV0Y2hTdHJhdGVneSA9PT0gRmV0Y2hTdHJhdGVneS5Gcm9tTG9jYWxDYWNoZSkge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgcXVlcnkgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjYW5ub3QgZXhlY3V0ZSAnc3RyaW5nJyBFbnRpdHlRdWVyeSBsb2NhbGx5LlwiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbGV0IHFyID0gZXhlY3V0ZVF1ZXJ5TG9jYWxseUNvcmUoZW0sIHF1ZXJ5KTtcclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgcmVzdWx0czogcXIucmVzdWx0cywgZW50aXR5TWFuYWdlcjogZW0sIGlubGluZUNvdW50OiBxci5pbmxpbmVDb3VudCwgcXVlcnk6IHF1ZXJ5IH0pO1xyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IG1hcHBpbmdDb250ZXh0OiBNYXBwaW5nQ29udGV4dCB8IHVuZGVmaW5lZCA9IG5ldyBNYXBwaW5nQ29udGV4dCh7XHJcbiAgICAgIHF1ZXJ5OiBxdWVyeSxcclxuICAgICAgZW50aXR5TWFuYWdlcjogZW0sXHJcbiAgICAgIGRhdGFTZXJ2aWNlOiBkYXRhU2VydmljZSxcclxuICAgICAgbWVyZ2VPcHRpb25zOiB7XHJcbiAgICAgICAgbWVyZ2VTdHJhdGVneTogcXVlcnlPcHRpb25zLm1lcmdlU3RyYXRlZ3ksXHJcbiAgICAgICAgbm9UcmFja2luZzogISEocXVlcnkgYXMgYW55KS5ub1RyYWNraW5nRW5hYmxlZCxcclxuICAgICAgICBpbmNsdWRlRGVsZXRlZDogcXVlcnlPcHRpb25zLmluY2x1ZGVEZWxldGVkXHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGxldCB2YWxpZGF0ZU9uUXVlcnkgPSBlbS52YWxpZGF0aW9uT3B0aW9ucy52YWxpZGF0ZU9uUXVlcnk7XHJcblxyXG4gICAgcmV0dXJuIGRhdGFTZXJ2aWNlLmFkYXB0ZXJJbnN0YW5jZSEuZXhlY3V0ZVF1ZXJ5KG1hcHBpbmdDb250ZXh0KS50aGVuKGZ1bmN0aW9uIChkYXRhOiBhbnkpIHtcclxuICAgICAgbGV0IHJlc3VsdCA9IGNvcmUud3JhcEV4ZWN1dGlvbihmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgbGV0IHN0YXRlID0geyBpc0xvYWRpbmc6IGVtLmlzTG9hZGluZyB9O1xyXG4gICAgICAgIGVtLmlzTG9hZGluZyA9IHRydWU7XHJcbiAgICAgICAgZW0uX3BlbmRpbmdQdWJzID0gW107XHJcbiAgICAgICAgcmV0dXJuIHN0YXRlO1xyXG4gICAgICB9LCBmdW5jdGlvbiAoc3RhdGUpIHtcclxuICAgICAgICAvLyBjbGVhbnVwXHJcbiAgICAgICAgZW0uaXNMb2FkaW5nID0gc3RhdGUuaXNMb2FkaW5nO1xyXG4gICAgICAgIGVtLl9wZW5kaW5nUHVicyEuZm9yRWFjaChmdW5jdGlvbiAoZm4pIHtcclxuICAgICAgICAgIGZuKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgZW0uX3BlbmRpbmdQdWJzID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIGVtLl9oYXNDaGFuZ2VzQWN0aW9uICYmIGVtLl9oYXNDaGFuZ2VzQWN0aW9uKCk7XHJcbiAgICAgICAgLy8gVE9ETzogcmVtb3ZlZCAtIG5vdCBzdXJlIHdoeSBuZWVkZWQgaW4gZmlyc3QgcGxhY2UuLi5cclxuICAgICAgICAvLyAvLyBIQUNLIGZvciBHQ1xyXG4gICAgICAgIC8vIHF1ZXJ5ID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIG1hcHBpbmdDb250ZXh0ID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIC8vIEhBQ0s6IHNvbWUgZXJyb3JzIHRocm93biBpbiBuZXh0IGZ1bmN0aW9uIGRvIG5vdCBwcm9wb2dhdGUgcHJvcGVybHkgLSB0aGlzIGNhdGNoZXMgdGhlbS5cclxuXHJcbiAgICAgICAgaWYgKHN0YXRlLmVycm9yKSB7XHJcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3Qoc3RhdGUuZXJyb3IpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgIH0sIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBsZXQgbm9kZXMgPSBkYXRhU2VydmljZS5qc29uUmVzdWx0c0FkYXB0ZXIuZXh0cmFjdFJlc3VsdHMoZGF0YSk7XHJcbiAgICAgICAgbm9kZXMgPSBjb3JlLnRvQXJyYXkobm9kZXMpO1xyXG5cclxuICAgICAgICByZXN1bHRzID0gbWFwcGluZ0NvbnRleHQhLnZpc2l0QW5kTWVyZ2Uobm9kZXMsIHsgbm9kZVR5cGU6IFwicm9vdFwiIH0pO1xyXG4gICAgICAgIGlmICh2YWxpZGF0ZU9uUXVlcnkpIHtcclxuICAgICAgICAgIHJlc3VsdHMuZm9yRWFjaChmdW5jdGlvbiAocjogYW55KSB7XHJcbiAgICAgICAgICAgIC8vIGFub24gdHlwZXMgYW5kIHNpbXBsZSB0eXBlcyB3aWxsIG5vdCBoYXZlIGFuIGVudGl0eUFzcGVjdC5cclxuICAgICAgICAgICAgci5lbnRpdHlBc3BlY3QgJiYgci5lbnRpdHlBc3BlY3QudmFsaWRhdGVFbnRpdHkoKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBtYXBwaW5nQ29udGV4dCEucHJvY2Vzc0RlZmVycmVkKCk7XHJcbiAgICAgICAgLy8gaWYgcXVlcnkgaGFzIGV4cGFuZCBjbGF1c2VzIHdhbGsgZWFjaCBvZiB0aGUgJ3Jlc3VsdHMnIGFuZCBtYXJrIHRoZSBleHBhbmRlZCBwcm9wcyBhcyBsb2FkZWQuXHJcbiAgICAgICAgaWYgKHF1ZXJ5IGluc3RhbmNlb2YgRW50aXR5UXVlcnkpIHtcclxuICAgICAgICAgIG1hcmtMb2FkZWROYXZQcm9wcyhyZXN1bHRzLCBxdWVyeSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGxldCByZXRyaWV2ZWRFbnRpdGllcyA9IGNvcmUub2JqZWN0TWFwKG1hcHBpbmdDb250ZXh0IS5yZWZNYXApO1xyXG4gICAgICAgIHJldHVybiB7IHJlc3VsdHM6IHJlc3VsdHMsIHF1ZXJ5OiBxdWVyeSwgZW50aXR5TWFuYWdlcjogZW0sIGh0dHBSZXNwb25zZTogZGF0YS5odHRwUmVzcG9uc2UsIGlubGluZUNvdW50OiBkYXRhLmlubGluZUNvdW50LCByZXRyaWV2ZWRFbnRpdGllczogcmV0cmlldmVkRW50aXRpZXMgfTtcclxuICAgICAgfSk7XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTtcclxuICAgIH0sIGZ1bmN0aW9uIChlOiBhbnkpIHtcclxuICAgICAgaWYgKGUpIHtcclxuICAgICAgICBlLnF1ZXJ5ID0gcXVlcnk7XHJcbiAgICAgICAgZS5lbnRpdHlNYW5hZ2VyID0gZW07XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO1xyXG4gICAgfSk7XHJcblxyXG4gIH0gY2F0Y2ggKGUpIHtcclxuICAgIGlmIChlKSB7XHJcbiAgICAgIGUucXVlcnkgPSBxdWVyeTtcclxuICAgIH1cclxuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIG1hcmtMb2FkZWROYXZQcm9wcyhlbnRpdGllczogRW50aXR5W10sIHF1ZXJ5OiBFbnRpdHlRdWVyeSkge1xyXG4gIGlmIChxdWVyeS5ub1RyYWNraW5nRW5hYmxlZCkgcmV0dXJuO1xyXG4gIGxldCBleHBhbmRDbGF1c2UgPSBxdWVyeS5leHBhbmRDbGF1c2U7XHJcbiAgaWYgKGV4cGFuZENsYXVzZSA9PSBudWxsKSByZXR1cm47XHJcbiAgZXhwYW5kQ2xhdXNlLnByb3BlcnR5UGF0aHMuZm9yRWFjaChmdW5jdGlvbiAocHJvcGVydHlQYXRoKSB7XHJcbiAgICBsZXQgcHJvcE5hbWVzID0gcHJvcGVydHlQYXRoLnNwbGl0KCcuJyk7XHJcbiAgICBtYXJrTG9hZGVkTmF2UGF0aChlbnRpdGllcywgcHJvcE5hbWVzKTtcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gbWFya0xvYWRlZE5hdlBhdGgoZW50aXRpZXM6IEVudGl0eVtdLCBwcm9wTmFtZXM6IHN0cmluZ1tdKSB7XHJcbiAgbGV0IHByb3BOYW1lID0gcHJvcE5hbWVzWzBdO1xyXG4gIGVudGl0aWVzLmZvckVhY2goKGVudGl0eSkgPT4ge1xyXG4gICAgbGV0IGVhID0gZW50aXR5LmVudGl0eUFzcGVjdDtcclxuICAgIGlmICghZWEpIHJldHVybjsgLy8gZW50aXR5IG1heSBub3QgYmUgYSAncmVhbCcgZW50aXR5IGluIHRoZSBjYXNlIG9mIGEgcHJvamVjdGlvbi5cclxuICAgIGVhLl9tYXJrQXNMb2FkZWQocHJvcE5hbWUpO1xyXG4gICAgaWYgKHByb3BOYW1lcy5sZW5ndGggPT09IDEpIHJldHVybjtcclxuICAgIGxldCBuZXh0ID0gZW50aXR5LmdldFByb3BlcnR5KHByb3BOYW1lKTtcclxuICAgIGlmICghbmV4dCkgcmV0dXJuOyAvLyBubyBjaGlsZHJlbiB0byBwcm9jZXNzLlxyXG4gICAgLy8gc3RyYW5nZSBsb2dpYyBiZWNhdXNlIG5vbnNjYWxhciBuYXYgdmFsdWVzIGFyZSBOT1QgcmVhbGx5IGFycmF5c1xyXG4gICAgLy8gb3RoZXJ3aXNlIHdlIGNvdWxkIHVzZSBBcnJheS5pc0FycmF5XHJcbiAgICBpZiAoIW5leHQuYXJyYXlDaGFuZ2VkKSBuZXh0ID0gW25leHRdO1xyXG4gICAgbWFya0xvYWRlZE5hdlBhdGgobmV4dCwgcHJvcE5hbWVzLnNsaWNlKDEpKTtcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gdXBkYXRlQ29uY3VycmVuY3lQcm9wZXJ0aWVzKGVudGl0aWVzOiBFbnRpdHlbXSkge1xyXG4gIGxldCBjYW5kaWRhdGVzID0gZW50aXRpZXMuZmlsdGVyKChlKSA9PiB7XHJcbiAgICBlLmVudGl0eUFzcGVjdC5pc0JlaW5nU2F2ZWQgPSB0cnVlO1xyXG4gICAgcmV0dXJuIGUuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlLmlzTW9kaWZpZWQoKVxyXG4gICAgICAmJiBlLmVudGl0eVR5cGUuY29uY3VycmVuY3lQcm9wZXJ0aWVzLmxlbmd0aCA+IDA7XHJcblxyXG4gIH0pO1xyXG4gIGlmIChjYW5kaWRhdGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xyXG4gIGNhbmRpZGF0ZXMuZm9yRWFjaChmdW5jdGlvbiAoYykge1xyXG4gICAgYy5lbnRpdHlUeXBlLmNvbmN1cnJlbmN5UHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChjcCkge1xyXG4gICAgICB1cGRhdGVDb25jdXJyZW5jeVByb3BlcnR5KGMsIGNwKTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiB1cGRhdGVDb25jdXJyZW5jeVByb3BlcnR5KGVudGl0eTogRW50aXR5LCBwcm9wZXJ0eTogRGF0YVByb3BlcnR5KSB7XHJcbiAgLy8gY2hlY2sgaWYgcHJvcGVydHkgaGFzIGFscmVhZHkgYmVlbiB1cGRhdGVkXHJcbiAgaWYgKGVudGl0eS5lbnRpdHlBc3BlY3Qub3JpZ2luYWxWYWx1ZXNbcHJvcGVydHkubmFtZV0pIHJldHVybjtcclxuICBsZXQgdmFsdWUgPSBlbnRpdHkuZ2V0UHJvcGVydHkocHJvcGVydHkubmFtZSk7XHJcbiAgbGV0IGRhdGFUeXBlID0gcHJvcGVydHkuZGF0YVR5cGUgYXMgRGF0YVR5cGU7XHJcbiAgaWYgKCF2YWx1ZSkgdmFsdWUgPSBkYXRhVHlwZS5kZWZhdWx0VmFsdWU7XHJcbiAgaWYgKGRhdGFUeXBlLmlzTnVtZXJpYykge1xyXG4gICAgZW50aXR5LnNldFByb3BlcnR5KHByb3BlcnR5Lm5hbWUsIHZhbHVlICsgMSk7XHJcbiAgfSBlbHNlIGlmIChkYXRhVHlwZS5nZXRDb25jdXJyZW5jeVZhbHVlKSB7XHJcbiAgICAvLyBEYXRhVHlwZSBoYXMgaXRzIG93biBpbXBsZW1lbnRhdGlvblxyXG4gICAgbGV0IG5leHRWYWx1ZSA9IGRhdGFUeXBlLmdldENvbmN1cnJlbmN5VmFsdWUodmFsdWUpO1xyXG4gICAgZW50aXR5LnNldFByb3BlcnR5KHByb3BlcnR5Lm5hbWUsIG5leHRWYWx1ZSk7XHJcbiAgfSBlbHNlIGlmIChkYXRhVHlwZSA9PT0gRGF0YVR5cGUuQmluYXJ5KSB7XHJcbiAgICAvLyBiZXN0IGd1ZXNzIC0gdGhhdCB0aGlzIGlzIGEgdGltZXN0YW1wIGNvbHVtbiBhbmQgaXMgY29tcHV0ZWQgb24gdGhlIHNlcnZlciBkdXJpbmcgc2F2ZVxyXG4gICAgLy8gLSBzbyBubyBuZWVkIHRvIHNldCBpdCBoZXJlLlxyXG4gICAgcmV0dXJuO1xyXG4gIH0gZWxzZSB7XHJcbiAgICAvLyB0aGlzIGp1c3QgbGVhdmVzIERhdGFUeXBlcyBvZiBCb29sZWFuLCBTdHJpbmcgYW5kIEJ5dGUgLSBub25lIG9mIHdoaWNoIHNob3VsZCBiZSB0aGVcclxuICAgIC8vIHR5cGUgZm9yIGEgY29uY3VycmVuY3kgY29sdW1uLlxyXG4gICAgLy8gTk9URTogdGhvdWdodCBhYm91dCBqdXN0IHJldHVybmluZyBoZXJlIGJ1dCB3b3VsZCByYXRoZXIgYmUgc2FmZSBmb3Igbm93LlxyXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIHVwZGF0ZSB0aGUgdmFsdWUgb2YgY29uY3VycmVuY3kgcHJvcGVydHkgYmVmb3JlIHNhdmluZzogXCIgKyBwcm9wZXJ0eS5uYW1lKTtcclxuICB9XHJcbn1cclxuXHJcblxyXG5mdW5jdGlvbiBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cChlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZTogRW50aXR5VHlwZSkge1xyXG4gIGxldCBncm91cCA9IGVtLl9lbnRpdHlHcm91cE1hcFtlbnRpdHlUeXBlLm5hbWVdO1xyXG4gIGlmICghZ3JvdXApIHtcclxuICAgIGdyb3VwID0gbmV3IEVudGl0eUdyb3VwKGVtLCBlbnRpdHlUeXBlKTtcclxuICAgIGVtLl9lbnRpdHlHcm91cE1hcFtlbnRpdHlUeXBlLm5hbWVdID0gZ3JvdXA7XHJcbiAgfVxyXG4gIHJldHVybiBncm91cDtcclxufVxyXG5cclxuZnVuY3Rpb24gZmluZE9yQ3JlYXRlRW50aXR5R3JvdXBzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgbGV0IGVudGl0eVR5cGVzID0gZW50aXR5VHlwZS5nZXRTZWxmQW5kU3VidHlwZXMoKTtcclxuICByZXR1cm4gZW50aXR5VHlwZXMubWFwKChldCkgPT4ge1xyXG4gICAgcmV0dXJuIGZpbmRPckNyZWF0ZUVudGl0eUdyb3VwKGVtLCBldCk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVud3JhcEluc3RhbmNlKHN0cnVjdE9iajogU3RydWN0dXJhbE9iamVjdCwgdHJhbnNmb3JtRm4/OiAoZHA6IERhdGFQcm9wZXJ0eSwgdmFsOiBhbnkpID0+IGFueSkge1xyXG5cclxuICBsZXQgcmF3T2JqZWN0OiBhbnkgPSB7fTtcclxuICBsZXQgc3R5cGUgPSBFbnRpdHlBc3BlY3QuaXNFbnRpdHkoc3RydWN0T2JqKSA/IHN0cnVjdE9iai5lbnRpdHlUeXBlIDogc3RydWN0T2JqLmNvbXBsZXhUeXBlO1xyXG4gIGxldCBzZXJpYWxpemVyRm4gPSBnZXRTZXJpYWxpemVyRm4oc3R5cGUpO1xyXG4gIGxldCB1bm1hcHBlZCA9IHt9O1xyXG4gIHN0eXBlLmRhdGFQcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKGRwKSB7XHJcbiAgICBpZiAoZHAuaXNDb21wbGV4UHJvcGVydHkpIHtcclxuICAgICAgcmF3T2JqZWN0W2RwLm5hbWVPblNlcnZlcl0gPSBjb3JlLm1hcChzdHJ1Y3RPYmouZ2V0UHJvcGVydHkoZHAubmFtZSksIGZ1bmN0aW9uIChjbykge1xyXG4gICAgICAgIHJldHVybiB1bndyYXBJbnN0YW5jZShjbywgdHJhbnNmb3JtRm4pO1xyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGxldCB2YWwgPSBzdHJ1Y3RPYmouZ2V0UHJvcGVydHkoZHAubmFtZSk7XHJcbiAgICAgIHZhbCA9IHRyYW5zZm9ybUZuID8gdHJhbnNmb3JtRm4oZHAsIHZhbCkgOiB2YWw7XHJcbiAgICAgIGlmICh2YWwgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xyXG4gICAgICB2YWwgPSBzZXJpYWxpemVyRm4gPyBzZXJpYWxpemVyRm4oZHAsIHZhbCkgOiB2YWw7XHJcbiAgICAgIGlmICh2YWwgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIGlmIChkcC5pc1VubWFwcGVkKSB7XHJcbiAgICAgICAgICB1bm1hcHBlZFtkcC5uYW1lT25TZXJ2ZXJdID0gY29yZS50b0pTT05TYWZlKHZhbCwgY29yZS50b0pTT05TYWZlUmVwbGFjZXIpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICByYXdPYmplY3RbZHAubmFtZU9uU2VydmVyXSA9IHZhbDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9KTtcclxuXHJcbiAgaWYgKCFjb3JlLmlzRW1wdHkodW5tYXBwZWQpKSB7XHJcbiAgICAvLyBUT0RPOiByZXZpZXcgdGhpcy5cclxuICAgIChyYXdPYmplY3QgYXMgYW55KS5fX3VubWFwcGVkID0gdW5tYXBwZWQ7XHJcbiAgfVxyXG4gIHJldHVybiByYXdPYmplY3Q7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVud3JhcE9yaWdpbmFsVmFsdWVzKHRhcmdldDogU3RydWN0dXJhbE9iamVjdCwgbWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSwgdHJhbnNmb3JtRm4/OiAoZHA6IERhdGFQcm9wZXJ0eSwgdmFsOiBhbnkpID0+IGFueSkge1xyXG4gIGxldCBzdHlwZSA9IEVudGl0eUFzcGVjdC5pc0VudGl0eSh0YXJnZXQpID8gdGFyZ2V0LmVudGl0eVR5cGUgOiB0YXJnZXQuY29tcGxleFR5cGU7XHJcbiAgbGV0IGFzcGVjdCA9IEVudGl0eUFzcGVjdC5pc0VudGl0eSh0YXJnZXQpID8gdGFyZ2V0LmVudGl0eUFzcGVjdCA6IHRhcmdldC5jb21wbGV4QXNwZWN0O1xyXG4gIGxldCBmbiA9IG1ldGFkYXRhU3RvcmUubmFtaW5nQ29udmVudGlvbi5jbGllbnRQcm9wZXJ0eU5hbWVUb1NlcnZlcjtcclxuICBsZXQgcmVzdWx0ID0ge307XHJcbiAgY29yZS5vYmplY3RGb3JFYWNoKGFzcGVjdC5vcmlnaW5hbFZhbHVlcywgZnVuY3Rpb24gKHByb3BOYW1lLCB2YWwpIHtcclxuICAgIGxldCBwcm9wID0gc3R5cGUuZ2V0UHJvcGVydHkocHJvcE5hbWUpIGFzIERhdGFQcm9wZXJ0eTtcclxuICAgIHZhbCA9IHRyYW5zZm9ybUZuID8gdHJhbnNmb3JtRm4ocHJvcCwgdmFsKSA6IHZhbDtcclxuICAgIGlmICh2YWwgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByZXN1bHRbZm4ocHJvcE5hbWUsIHByb3ApXSA9IHZhbDtcclxuICAgIH1cclxuICB9KTtcclxuICBzdHlwZS5jb21wbGV4UHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChjcCkge1xyXG4gICAgbGV0IG5leHRUYXJnZXQgPSB0YXJnZXQuZ2V0UHJvcGVydHkoY3AubmFtZSk7XHJcbiAgICBpZiAoY3AuaXNTY2FsYXIpIHtcclxuICAgICAgbGV0IHVud3JhcHBlZENvID0gdW53cmFwT3JpZ2luYWxWYWx1ZXMobmV4dFRhcmdldCwgbWV0YWRhdGFTdG9yZSwgdHJhbnNmb3JtRm4pO1xyXG4gICAgICBpZiAoIWNvcmUuaXNFbXB0eSh1bndyYXBwZWRDbykpIHtcclxuICAgICAgICByZXN1bHRbZm4oY3AubmFtZSwgY3ApXSA9IHVud3JhcHBlZENvO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXQgdW53cmFwcGVkQ29zID0gbmV4dFRhcmdldC5tYXAoKGl0ZW06IGFueSkgPT4ge1xyXG4gICAgICAgIHJldHVybiB1bndyYXBPcmlnaW5hbFZhbHVlcyhpdGVtLCBtZXRhZGF0YVN0b3JlLCB0cmFuc2Zvcm1Gbik7XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXN1bHRbZm4oY3AubmFtZSwgY3ApXSA9IHVud3JhcHBlZENvcztcclxuICAgIH1cclxuICB9KTtcclxuICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5mdW5jdGlvbiB1bndyYXBDaGFuZ2VkVmFsdWVzKGVudGl0eTogRW50aXR5LCBtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlLCB0cmFuc2Zvcm1GbjogKGRwOiBEYXRhUHJvcGVydHksIHZhbDogYW55KSA9PiBhbnkpIHtcclxuICBsZXQgc3R5cGUgPSBlbnRpdHkuZW50aXR5VHlwZTtcclxuICBsZXQgc2VyaWFsaXplckZuID0gZ2V0U2VyaWFsaXplckZuKHN0eXBlKTtcclxuICBsZXQgZm4gPSBtZXRhZGF0YVN0b3JlLm5hbWluZ0NvbnZlbnRpb24uY2xpZW50UHJvcGVydHlOYW1lVG9TZXJ2ZXI7XHJcbiAgbGV0IHJlc3VsdCA9IHt9O1xyXG4gIGNvcmUub2JqZWN0Rm9yRWFjaChlbnRpdHkuZW50aXR5QXNwZWN0Lm9yaWdpbmFsVmFsdWVzLCBmdW5jdGlvbiAocHJvcE5hbWUsIHZhbHVlKSB7XHJcbiAgICBsZXQgcHJvcCA9IHN0eXBlLmdldFByb3BlcnR5KHByb3BOYW1lKSBhcyBEYXRhUHJvcGVydHk7XHJcbiAgICBsZXQgdmFsID0gZW50aXR5LmdldFByb3BlcnR5KHByb3BOYW1lKTtcclxuICAgIHZhbCA9IHRyYW5zZm9ybUZuID8gdHJhbnNmb3JtRm4ocHJvcCwgdmFsKSA6IHZhbDtcclxuICAgIGlmICh2YWwgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xyXG4gICAgdmFsID0gc2VyaWFsaXplckZuID8gc2VyaWFsaXplckZuKHByb3AsIHZhbCkgOiB2YWw7XHJcbiAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmVzdWx0W2ZuKHByb3BOYW1lLCBwcm9wKV0gPSB2YWw7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgLy8gYW55IGNoYW5nZSB0byBhbnkgY29tcGxleCBvYmplY3Qgb3IgYXJyYXkgb2YgY29tcGxleCBvYmplY3RzIHJldHVybnMgdGhlIEVOVElSRVxyXG4gIC8vIGN1cnJlbnQgY29tcGxleCBvYmplY3Qgb3IgY29tcGxleCBvYmplY3QgYXJyYXkuICBUaGlzIGlzIGJ5IGRlc2lnbi4gQ29tcGxleCBPYmplY3RzXHJcbiAgLy8gYXJlIGF0b21pYy5cclxuICBzdHlwZS5jb21wbGV4UHJvcGVydGllcy5mb3JFYWNoKChjcCkgPT4ge1xyXG4gICAgaWYgKGNwSGFzT3JpZ2luYWxWYWx1ZXMoZW50aXR5LCBjcCkpIHtcclxuICAgICAgbGV0IGNvT3JDb3MgPSBlbnRpdHkuZ2V0UHJvcGVydHkoY3AubmFtZSk7XHJcbiAgICAgIHJlc3VsdFtmbihjcC5uYW1lLCBjcCldID0gY29yZS5tYXAoY29PckNvcywgZnVuY3Rpb24gKGNvKSB7XHJcbiAgICAgICAgcmV0dXJuIHVud3JhcEluc3RhbmNlKGNvLCB0cmFuc2Zvcm1Gbik7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNwSGFzT3JpZ2luYWxWYWx1ZXMoc3RydWN0dXJhbE9iamVjdDogU3RydWN0dXJhbE9iamVjdCwgY3A6IERhdGFQcm9wZXJ0eSk6IGJvb2xlYW4ge1xyXG4gIGxldCBjb09yQ29zID0gc3RydWN0dXJhbE9iamVjdC5nZXRQcm9wZXJ0eShjcC5uYW1lKTtcclxuICBpZiAoY3AuaXNTY2FsYXIpIHtcclxuICAgIHJldHVybiBjb0hhc09yaWdpbmFsVmFsdWVzKGNvT3JDb3MpO1xyXG4gIH0gZWxzZSB7XHJcbiAgICAvLyB0aGlzIG9jY3VycyB3aGVuIGEgbm9uc2NhbGFyIGNvIGFycmF5IGhhcyBoYWQgY29zIGFkZGVkIG9yIHJlbW92ZWQuXHJcbiAgICBpZiAoY29PckNvcy5fb3JpZ1ZhbHVlcykgcmV0dXJuIHRydWU7XHJcbiAgICByZXR1cm4gY29PckNvcy5zb21lKGZ1bmN0aW9uIChjbzogQ29tcGxleE9iamVjdCkge1xyXG4gICAgICByZXR1cm4gY29IYXNPcmlnaW5hbFZhbHVlcyhjbyk7XHJcbiAgICB9KTtcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGV4ZWN1dGVRdWVyeUxvY2FsbHlDb3JlKGVtOiBFbnRpdHlNYW5hZ2VyLCBxdWVyeTogRW50aXR5UXVlcnkpIHtcclxuICBhc3NlcnRQYXJhbShxdWVyeSwgXCJxdWVyeVwiKS5pc0luc3RhbmNlT2YoRW50aXR5UXVlcnkpLmNoZWNrKCk7XHJcblxyXG4gIGxldCBtZXRhZGF0YVN0b3JlID0gZW0ubWV0YWRhdGFTdG9yZTtcclxuICBsZXQgZW50aXR5VHlwZSA9IHF1ZXJ5Ll9nZXRGcm9tRW50aXR5VHlwZShtZXRhZGF0YVN0b3JlLCB0cnVlKTtcclxuICAvLyB0aGVyZSBtYXkgYmUgbXVsdGlwbGUgZ3JvdXBzIGlzIHRoaXMgaXMgYSBiYXNlIGVudGl0eSB0eXBlLlxyXG4gIGxldCBncm91cHMgPSBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cHMoZW0sIGVudGl0eVR5cGUhKTtcclxuICAvLyBmaWx0ZXIgdGhlbiBvcmRlciB0aGVuIHNraXAgdGhlbiB0YWtlXHJcbiAgbGV0IGZpbHRlckZ1bmMgPSBxdWVyeS53aGVyZVByZWRpY2F0ZSAmJiBxdWVyeS53aGVyZVByZWRpY2F0ZS50b0Z1bmN0aW9uKHsgZW50aXR5VHlwZTogZW50aXR5VHlwZSB9KTtcclxuXHJcbiAgbGV0IHF1ZXJ5T3B0aW9ucyA9IFF1ZXJ5T3B0aW9ucy5yZXNvbHZlKFtxdWVyeS5xdWVyeU9wdGlvbnMsIGVtLnF1ZXJ5T3B0aW9ucywgUXVlcnlPcHRpb25zLmRlZmF1bHRJbnN0YW5jZV0pO1xyXG4gIGxldCBpbmNsdWRlRGVsZXRlZCA9IHF1ZXJ5T3B0aW9ucy5pbmNsdWRlRGVsZXRlZCA9PT0gdHJ1ZTtcclxuXHJcbiAgbGV0IG5ld0ZpbHRlckZ1bmMgPSBmdW5jdGlvbiAoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIHJldHVybiBlbnRpdHkgJiYgKGluY2x1ZGVEZWxldGVkIHx8ICFlbnRpdHkuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlLmlzRGVsZXRlZCgpKSAmJiAoZmlsdGVyRnVuYyA/IGZpbHRlckZ1bmMoZW50aXR5KSA6IHRydWUpO1xyXG4gIH07XHJcblxyXG4gIGxldCByZXN1bHQ6IGFueVtdID0gW107XHJcbiAgLy8gVE9ETzogbWFwTWFueVxyXG4gIGdyb3Vwcy5mb3JFYWNoKChncm91cCkgPT4ge1xyXG4gICAgbGV0IGVudGl0aWVzID0gZ3JvdXAuX2VudGl0aWVzLmZpbHRlcihuZXdGaWx0ZXJGdW5jKSBhcyBFbnRpdHlbXTtcclxuICAgIGlmIChlbnRpdGllcy5sZW5ndGgpIHtcclxuICAgICAgcmVzdWx0ID0gcmVzdWx0Lmxlbmd0aCA/IHJlc3VsdC5jb25jYXQoZW50aXRpZXMpIDogZW50aXRpZXM7XHJcbiAgICB9XHJcbiAgfSk7XHJcblxyXG4gIGxldCBvcmRlckJ5Q29tcGFyZXIgPSBxdWVyeS5vcmRlckJ5Q2xhdXNlICYmIHF1ZXJ5Lm9yZGVyQnlDbGF1c2UuZ2V0Q29tcGFyZXIoZW50aXR5VHlwZSEpO1xyXG4gIGlmIChvcmRlckJ5Q29tcGFyZXIpIHtcclxuICAgIHJlc3VsdC5zb3J0KG9yZGVyQnlDb21wYXJlcik7XHJcbiAgfVxyXG5cclxuICBsZXQgaW5saW5lQ291bnQgPSBxdWVyeS5pbmxpbmVDb3VudEVuYWJsZWQgPyByZXN1bHQubGVuZ3RoIDogdW5kZWZpbmVkO1xyXG5cclxuICBsZXQgc2tpcENvdW50ID0gcXVlcnkuc2tpcENvdW50O1xyXG4gIGlmIChza2lwQ291bnQpIHtcclxuICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZShza2lwQ291bnQpO1xyXG4gIH1cclxuICBsZXQgdGFrZUNvdW50ID0gcXVlcnkudGFrZUNvdW50O1xyXG4gIGlmICh0YWtlQ291bnQpIHtcclxuICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZSgwLCB0YWtlQ291bnQpO1xyXG4gIH1cclxuXHJcbiAgbGV0IHNlbGVjdENsYXVzZSA9IHF1ZXJ5LnNlbGVjdENsYXVzZTtcclxuICBpZiAoc2VsZWN0Q2xhdXNlKSB7XHJcbiAgICBsZXQgc2VsZWN0Rm4gPSBzZWxlY3RDbGF1c2UudG9GdW5jdGlvbigpO1xyXG4gICAgcmVzdWx0ID0gcmVzdWx0Lm1hcChzZWxlY3RGbik7XHJcbiAgfVxyXG4gIHJldHVybiB7IHJlc3VsdHM6IHJlc3VsdCwgaW5saW5lQ291bnQ6IGlubGluZUNvdW50IH07XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNvSGFzT3JpZ2luYWxWYWx1ZXMoY286IENvbXBsZXhPYmplY3QpIHtcclxuICAvLyBuZXh0IGxpbmUgY2hlY2tzIGFsbCBub24gY29tcGxleCBwcm9wZXJ0aWVzIG9mIHRoZSBjby5cclxuICBpZiAoIWNvcmUuaXNFbXB0eShjby5jb21wbGV4QXNwZWN0Lm9yaWdpbmFsVmFsdWVzKSkgcmV0dXJuIHRydWU7XHJcbiAgLy8gbm93IG5lZWQgdG8gcmVjdXJzaXZlbHkgY2hlY2sgZWFjaCBvZiB0aGUgY3BzXHJcbiAgcmV0dXJuIGNvLmNvbXBsZXhUeXBlLmNvbXBsZXhQcm9wZXJ0aWVzLnNvbWUoZnVuY3Rpb24gKGNwKSB7XHJcbiAgICByZXR1cm4gY3BIYXNPcmlnaW5hbFZhbHVlcyhjbywgY3ApO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRTZXJpYWxpemVyRm4oc3R5cGU6IEVudGl0eVR5cGUgfCBDb21wbGV4VHlwZSkge1xyXG4gIHJldHVybiBzdHlwZS5zZXJpYWxpemVyRm4gfHwgKHN0eXBlLm1ldGFkYXRhU3RvcmUgJiYgc3R5cGUubWV0YWRhdGFTdG9yZS5zZXJpYWxpemVyRm4pO1xyXG59XHJcblxyXG4iXX0=