breeze-client 2.1.7 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/README.md +8 -4
  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/esm2022/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +135 -0
  14. package/esm2022/adapter-ajax-angularjs/adapter-core.mjs +49 -0
  15. package/esm2022/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +5 -0
  16. package/esm2022/adapter-ajax-fetch/adapter-ajax-fetch.mjs +135 -0
  17. package/esm2022/adapter-ajax-fetch/adapter-core.mjs +49 -0
  18. package/esm2022/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +5 -0
  19. package/esm2022/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +139 -0
  20. package/esm2022/adapter-ajax-httpclient/adapter-core.mjs +49 -0
  21. package/esm2022/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +5 -0
  22. package/esm2022/adapter-ajax-jquery/adapter-ajax-jquery.mjs +107 -0
  23. package/esm2022/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +5 -0
  24. package/esm2022/adapter-ajax-post/adapter-ajax-post.mjs +77 -0
  25. package/esm2022/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +5 -0
  26. package/esm2022/adapter-data-service-odata/adapter-core.mjs +49 -0
  27. package/{esm5/adapter-data-service-odata/adapter-data-service-odata.js → esm2022/adapter-data-service-odata/adapter-data-service-odata.mjs} +138 -147
  28. package/esm2022/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +5 -0
  29. package/esm2022/adapter-data-service-webapi/adapter-data-service-webapi.mjs +100 -0
  30. package/esm2022/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +5 -0
  31. package/esm2022/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +269 -0
  32. package/esm2022/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +5 -0
  33. package/esm2022/adapter-model-library-ko/adapter-model-library-ko.mjs +241 -0
  34. package/esm2022/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +5 -0
  35. package/esm2022/adapter-uri-builder-json/adapter-core.mjs +49 -0
  36. package/esm2022/adapter-uri-builder-json/adapter-uri-builder-json.mjs +37 -0
  37. package/esm2022/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +5 -0
  38. package/esm2022/adapter-uri-builder-odata/adapter-core.mjs +49 -0
  39. package/esm2022/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +191 -0
  40. package/esm2022/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +5 -0
  41. package/esm2022/breeze-client.mjs +5 -0
  42. package/esm2022/index.mjs +2 -0
  43. package/esm2022/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +5 -0
  44. package/esm2022/mixin-get-entity-graph/mixin-get-entity-graph.mjs +269 -0
  45. package/esm2022/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +5 -0
  46. package/esm2022/mixin-save-queuing/mixin-save-queuing.mjs +421 -0
  47. package/esm2022/src/abstract-data-service-adapter.mjs +325 -0
  48. package/esm2022/src/array.mjs +4 -0
  49. package/esm2022/src/assert-param.mjs +330 -0
  50. package/esm2022/src/breeze.mjs +85 -0
  51. package/esm2022/src/complex-array.mjs +117 -0
  52. package/esm2022/src/config.mjs +232 -0
  53. package/esm2022/src/core.mjs +712 -0
  54. package/esm2022/src/csdl-metadata-parser.mjs +385 -0
  55. package/esm2022/src/data-service.mjs +239 -0
  56. package/{esm2015/src/data-type.js → esm2022/src/data-type.mjs} +131 -124
  57. package/esm2022/src/default-property-interceptor.mjs +460 -0
  58. package/{esm2015/src/entity-action.js → esm2022/src/entity-action.mjs} +25 -25
  59. package/esm2022/src/entity-aspect.mjs +897 -0
  60. package/esm2022/src/entity-group.mjs +192 -0
  61. package/esm2022/src/entity-key.mjs +127 -0
  62. package/esm2022/src/entity-manager.mjs +2183 -0
  63. package/esm2022/src/entity-metadata.mjs +2242 -0
  64. package/esm2022/src/entity-query.mjs +1024 -0
  65. package/esm2022/src/entity-state.mjs +107 -0
  66. package/esm2022/src/enum.mjs +143 -0
  67. package/esm2022/src/event.mjs +264 -0
  68. package/esm2022/src/interface-registry.mjs +39 -0
  69. package/esm2022/src/key-generator.mjs +110 -0
  70. package/esm2022/src/local-query-comparison-options.mjs +75 -0
  71. package/esm2022/src/mapping-context.mjs +422 -0
  72. package/{esm5/src/naming-convention.js → esm2022/src/naming-convention.mjs} +35 -29
  73. package/esm2022/src/observable-array.mjs +183 -0
  74. package/esm2022/src/predicate.mjs +1259 -0
  75. package/esm2022/src/primitive-array.mjs +85 -0
  76. package/esm2022/src/query-options.mjs +160 -0
  77. package/esm2022/src/relation-array.mjs +173 -0
  78. package/esm2022/src/save-options.mjs +51 -0
  79. package/esm2022/src/unattached-children-map.mjs +56 -0
  80. package/{esm5/src/validate.js → esm2022/src/validate.mjs} +116 -110
  81. package/esm2022/src/validation-options.mjs +78 -0
  82. package/{fesm2015/breeze-client-adapter-ajax-angularjs.js → fesm2022/breeze-client-adapter-ajax-angularjs.mjs} +6 -1
  83. package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs.map +1 -0
  84. package/{fesm2015/breeze-client-adapter-ajax-fetch.js → fesm2022/breeze-client-adapter-ajax-fetch.mjs} +9 -4
  85. package/fesm2022/breeze-client-adapter-ajax-fetch.mjs.map +1 -0
  86. package/{fesm2015/breeze-client-adapter-ajax-httpclient.js → fesm2022/breeze-client-adapter-ajax-httpclient.mjs} +6 -4
  87. package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs.map +1 -0
  88. package/{fesm2015/breeze-client-adapter-ajax-jquery.js → fesm2022/breeze-client-adapter-ajax-jquery.mjs} +6 -2
  89. package/fesm2022/breeze-client-adapter-ajax-jquery.mjs.map +1 -0
  90. package/{fesm2015/breeze-client-adapter-ajax-post.js → fesm2022/breeze-client-adapter-ajax-post.mjs} +1 -1
  91. package/fesm2022/breeze-client-adapter-ajax-post.mjs.map +1 -0
  92. package/{fesm2015/breeze-client-adapter-data-service-odata.js → fesm2022/breeze-client-adapter-data-service-odata.mjs} +68 -69
  93. package/fesm2022/breeze-client-adapter-data-service-odata.mjs.map +1 -0
  94. package/{fesm2015/breeze-client-adapter-data-service-webapi.js → fesm2022/breeze-client-adapter-data-service-webapi.mjs} +30 -30
  95. package/fesm2022/breeze-client-adapter-data-service-webapi.mjs.map +1 -0
  96. package/{fesm2015/breeze-client-adapter-model-library-backing-store.js → fesm2022/breeze-client-adapter-model-library-backing-store.mjs} +14 -13
  97. package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs.map +1 -0
  98. package/{fesm2015/breeze-client-adapter-model-library-ko.js → fesm2022/breeze-client-adapter-model-library-ko.mjs} +14 -13
  99. package/fesm2022/breeze-client-adapter-model-library-ko.mjs.map +1 -0
  100. package/{fesm2015/breeze-client-adapter-uri-builder-json.js → fesm2022/breeze-client-adapter-uri-builder-json.mjs} +9 -8
  101. package/fesm2022/breeze-client-adapter-uri-builder-json.mjs.map +1 -0
  102. package/{fesm2015/breeze-client-adapter-uri-builder-odata.js → fesm2022/breeze-client-adapter-uri-builder-odata.mjs} +86 -86
  103. package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs.map +1 -0
  104. package/{fesm2015/breeze-client-mixin-get-entity-graph.js → fesm2022/breeze-client-mixin-get-entity-graph.mjs} +1 -1
  105. package/fesm2022/breeze-client-mixin-get-entity-graph.mjs.map +1 -0
  106. package/{fesm2015/breeze-client-mixin-save-queuing.js → fesm2022/breeze-client-mixin-save-queuing.mjs} +23 -2
  107. package/fesm2022/breeze-client-mixin-save-queuing.mjs.map +1 -0
  108. package/{fesm2015/breeze-client.js → fesm2022/breeze-client.mjs} +2039 -1537
  109. package/fesm2022/breeze-client.mjs.map +1 -0
  110. package/mixin-get-entity-graph/{breeze-client-mixin-get-entity-graph.d.ts → index.d.ts} +1 -0
  111. package/mixin-save-queuing/{breeze-client-mixin-save-queuing.d.ts → index.d.ts} +1 -0
  112. package/package.json +94 -12
  113. package/src/config.d.ts +1 -1
  114. package/src/core.d.ts +1 -1
  115. package/src/entity-aspect.d.ts +1 -1
  116. package/src/entity-metadata.d.ts +8 -6
  117. package/src/entity-query.d.ts +1 -1
  118. package/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.metadata.json +0 -1
  119. package/adapter-ajax-angularjs/package.json +0 -13
  120. package/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.metadata.json +0 -1
  121. package/adapter-ajax-fetch/package.json +0 -13
  122. package/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.metadata.json +0 -1
  123. package/adapter-ajax-httpclient/package.json +0 -13
  124. package/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.metadata.json +0 -1
  125. package/adapter-ajax-jquery/package.json +0 -13
  126. package/adapter-ajax-post/breeze-client-adapter-ajax-post.metadata.json +0 -1
  127. package/adapter-ajax-post/package.json +0 -13
  128. package/adapter-data-service-odata/breeze-client-adapter-data-service-odata.metadata.json +0 -1
  129. package/adapter-data-service-odata/package.json +0 -13
  130. package/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.metadata.json +0 -1
  131. package/adapter-data-service-webapi/package.json +0 -13
  132. package/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.metadata.json +0 -1
  133. package/adapter-model-library-backing-store/package.json +0 -13
  134. package/adapter-model-library-ko/breeze-client-adapter-model-library-ko.metadata.json +0 -1
  135. package/adapter-model-library-ko/package.json +0 -13
  136. package/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.metadata.json +0 -1
  137. package/adapter-uri-builder-json/package.json +0 -13
  138. package/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.metadata.json +0 -1
  139. package/adapter-uri-builder-odata/package.json +0 -13
  140. package/breeze-client.d.ts +0 -8
  141. package/breeze-client.metadata.json +0 -1
  142. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js +0 -190
  143. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js.map +0 -1
  144. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js +0 -2
  145. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js.map +0 -1
  146. package/bundles/breeze-client-adapter-ajax-fetch.umd.js +0 -190
  147. package/bundles/breeze-client-adapter-ajax-fetch.umd.js.map +0 -1
  148. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js +0 -2
  149. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js.map +0 -1
  150. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js +0 -195
  151. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js.map +0 -1
  152. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js +0 -2
  153. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js.map +0 -1
  154. package/bundles/breeze-client-adapter-ajax-jquery.umd.js +0 -115
  155. package/bundles/breeze-client-adapter-ajax-jquery.umd.js.map +0 -1
  156. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js +0 -2
  157. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js.map +0 -1
  158. package/bundles/breeze-client-adapter-ajax-post.umd.js +0 -92
  159. package/bundles/breeze-client-adapter-ajax-post.umd.js.map +0 -1
  160. package/bundles/breeze-client-adapter-ajax-post.umd.min.js +0 -2
  161. package/bundles/breeze-client-adapter-ajax-post.umd.min.js.map +0 -1
  162. package/bundles/breeze-client-adapter-data-service-odata.umd.js +0 -747
  163. package/bundles/breeze-client-adapter-data-service-odata.umd.js.map +0 -1
  164. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js +0 -16
  165. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js.map +0 -1
  166. package/bundles/breeze-client-adapter-data-service-webapi.umd.js +0 -333
  167. package/bundles/breeze-client-adapter-data-service-webapi.umd.js.map +0 -1
  168. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js +0 -16
  169. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js.map +0 -1
  170. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js +0 -280
  171. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js.map +0 -1
  172. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js +0 -2
  173. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js.map +0 -1
  174. package/bundles/breeze-client-adapter-model-library-ko.umd.js +0 -252
  175. package/bundles/breeze-client-adapter-model-library-ko.umd.js.map +0 -1
  176. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js +0 -2
  177. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js.map +0 -1
  178. package/bundles/breeze-client-adapter-uri-builder-json.umd.js +0 -96
  179. package/bundles/breeze-client-adapter-uri-builder-json.umd.js.map +0 -1
  180. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js +0 -2
  181. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js.map +0 -1
  182. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js +0 -262
  183. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js.map +0 -1
  184. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js +0 -2
  185. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js.map +0 -1
  186. package/bundles/breeze-client-mixin-get-entity-graph.umd.js +0 -258
  187. package/bundles/breeze-client-mixin-get-entity-graph.umd.js.map +0 -1
  188. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js +0 -2
  189. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js.map +0 -1
  190. package/bundles/breeze-client-mixin-save-queuing.umd.js +0 -579
  191. package/bundles/breeze-client-mixin-save-queuing.umd.js.map +0 -1
  192. package/bundles/breeze-client-mixin-save-queuing.umd.min.js +0 -16
  193. package/bundles/breeze-client-mixin-save-queuing.umd.min.js.map +0 -1
  194. package/bundles/breeze-client.umd.js +0 -14231
  195. package/bundles/breeze-client.umd.js.map +0 -1
  196. package/bundles/breeze-client.umd.min.js +0 -16
  197. package/bundles/breeze-client.umd.min.js.map +0 -1
  198. package/esm2015/adapter-ajax-angularjs/adapter-ajax-angularjs.js +0 -130
  199. package/esm2015/adapter-ajax-angularjs/adapter-core.js +0 -49
  200. package/esm2015/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +0 -5
  201. package/esm2015/adapter-ajax-fetch/adapter-ajax-fetch.js +0 -130
  202. package/esm2015/adapter-ajax-fetch/adapter-core.js +0 -49
  203. package/esm2015/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +0 -5
  204. package/esm2015/adapter-ajax-httpclient/adapter-ajax-httpclient.js +0 -137
  205. package/esm2015/adapter-ajax-httpclient/adapter-core.js +0 -49
  206. package/esm2015/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +0 -5
  207. package/esm2015/adapter-ajax-jquery/adapter-ajax-jquery.js +0 -103
  208. package/esm2015/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +0 -5
  209. package/esm2015/adapter-ajax-post/adapter-ajax-post.js +0 -77
  210. package/esm2015/adapter-ajax-post/breeze-client-adapter-ajax-post.js +0 -5
  211. package/esm2015/adapter-data-service-odata/adapter-core.js +0 -49
  212. package/esm2015/adapter-data-service-odata/adapter-data-service-odata.js +0 -463
  213. package/esm2015/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +0 -5
  214. package/esm2015/adapter-data-service-webapi/adapter-data-service-webapi.js +0 -100
  215. package/esm2015/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +0 -5
  216. package/esm2015/adapter-model-library-backing-store/adapter-model-library-backing-store.js +0 -268
  217. package/esm2015/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +0 -5
  218. package/esm2015/adapter-model-library-ko/adapter-model-library-ko.js +0 -240
  219. package/esm2015/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +0 -5
  220. package/esm2015/adapter-uri-builder-json/adapter-core.js +0 -49
  221. package/esm2015/adapter-uri-builder-json/adapter-uri-builder-json.js +0 -36
  222. package/esm2015/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +0 -5
  223. package/esm2015/adapter-uri-builder-odata/adapter-core.js +0 -49
  224. package/esm2015/adapter-uri-builder-odata/adapter-uri-builder-odata.js +0 -192
  225. package/esm2015/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +0 -5
  226. package/esm2015/breeze-client.js +0 -9
  227. package/esm2015/index.js +0 -2
  228. package/esm2015/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +0 -5
  229. package/esm2015/mixin-get-entity-graph/mixin-get-entity-graph.js +0 -269
  230. package/esm2015/mixin-save-queuing/breeze-client-mixin-save-queuing.js +0 -5
  231. package/esm2015/mixin-save-queuing/mixin-save-queuing.js +0 -400
  232. package/esm2015/src/abstract-data-service-adapter.js +0 -327
  233. package/esm2015/src/array.js +0 -4
  234. package/esm2015/src/assert-param.js +0 -312
  235. package/esm2015/src/breeze.js +0 -85
  236. package/esm2015/src/complex-array.js +0 -119
  237. package/esm2015/src/config.js +0 -223
  238. package/esm2015/src/core.js +0 -714
  239. package/esm2015/src/csdl-metadata-parser.js +0 -385
  240. package/esm2015/src/data-service.js +0 -203
  241. package/esm2015/src/default-property-interceptor.js +0 -460
  242. package/esm2015/src/entity-aspect.js +0 -804
  243. package/esm2015/src/entity-group.js +0 -187
  244. package/esm2015/src/entity-key.js +0 -116
  245. package/esm2015/src/entity-manager.js +0 -2094
  246. package/esm2015/src/entity-metadata.js +0 -2109
  247. package/esm2015/src/entity-query.js +0 -1015
  248. package/esm2015/src/entity-state.js +0 -107
  249. package/esm2015/src/enum.js +0 -141
  250. package/esm2015/src/event.js +0 -256
  251. package/esm2015/src/interface-registry.js +0 -41
  252. package/esm2015/src/key-generator.js +0 -108
  253. package/esm2015/src/local-query-comparison-options.js +0 -65
  254. package/esm2015/src/mapping-context.js +0 -411
  255. package/esm2015/src/naming-convention.js +0 -88
  256. package/esm2015/src/observable-array.js +0 -185
  257. package/esm2015/src/predicate.js +0 -1242
  258. package/esm2015/src/primitive-array.js +0 -87
  259. package/esm2015/src/query-options.js +0 -152
  260. package/esm2015/src/relation-array.js +0 -175
  261. package/esm2015/src/save-options.js +0 -41
  262. package/esm2015/src/unattached-children-map.js +0 -58
  263. package/esm2015/src/validate.js +0 -991
  264. package/esm2015/src/validation-options.js +0 -64
  265. package/esm5/adapter-ajax-angularjs/adapter-ajax-angularjs.js +0 -132
  266. package/esm5/adapter-ajax-angularjs/adapter-core.js +0 -49
  267. package/esm5/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +0 -5
  268. package/esm5/adapter-ajax-fetch/adapter-ajax-fetch.js +0 -132
  269. package/esm5/adapter-ajax-fetch/adapter-core.js +0 -49
  270. package/esm5/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +0 -5
  271. package/esm5/adapter-ajax-httpclient/adapter-ajax-httpclient.js +0 -139
  272. package/esm5/adapter-ajax-httpclient/adapter-core.js +0 -49
  273. package/esm5/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +0 -5
  274. package/esm5/adapter-ajax-jquery/adapter-ajax-jquery.js +0 -105
  275. package/esm5/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +0 -5
  276. package/esm5/adapter-ajax-post/adapter-ajax-post.js +0 -81
  277. package/esm5/adapter-ajax-post/breeze-client-adapter-ajax-post.js +0 -5
  278. package/esm5/adapter-data-service-odata/adapter-core.js +0 -49
  279. package/esm5/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +0 -5
  280. package/esm5/adapter-data-service-webapi/adapter-data-service-webapi.js +0 -105
  281. package/esm5/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +0 -5
  282. package/esm5/adapter-model-library-backing-store/adapter-model-library-backing-store.js +0 -270
  283. package/esm5/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +0 -5
  284. package/esm5/adapter-model-library-ko/adapter-model-library-ko.js +0 -242
  285. package/esm5/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +0 -5
  286. package/esm5/adapter-uri-builder-json/adapter-core.js +0 -49
  287. package/esm5/adapter-uri-builder-json/adapter-uri-builder-json.js +0 -38
  288. package/esm5/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +0 -5
  289. package/esm5/adapter-uri-builder-odata/adapter-core.js +0 -49
  290. package/esm5/adapter-uri-builder-odata/adapter-uri-builder-odata.js +0 -197
  291. package/esm5/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +0 -5
  292. package/esm5/breeze-client.js +0 -9
  293. package/esm5/index.js +0 -2
  294. package/esm5/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +0 -5
  295. package/esm5/mixin-get-entity-graph/mixin-get-entity-graph.js +0 -269
  296. package/esm5/mixin-save-queuing/breeze-client-mixin-save-queuing.js +0 -5
  297. package/esm5/mixin-save-queuing/mixin-save-queuing.js +0 -412
  298. package/esm5/src/abstract-data-service-adapter.js +0 -333
  299. package/esm5/src/array.js +0 -4
  300. package/esm5/src/assert-param.js +0 -317
  301. package/esm5/src/breeze.js +0 -85
  302. package/esm5/src/complex-array.js +0 -119
  303. package/esm5/src/config.js +0 -228
  304. package/esm5/src/core.js +0 -722
  305. package/esm5/src/csdl-metadata-parser.js +0 -385
  306. package/esm5/src/data-service.js +0 -207
  307. package/esm5/src/data-type.js +0 -510
  308. package/esm5/src/default-property-interceptor.js +0 -460
  309. package/esm5/src/entity-action.js +0 -52
  310. package/esm5/src/entity-aspect.js +0 -810
  311. package/esm5/src/entity-group.js +0 -189
  312. package/esm5/src/entity-key.js +0 -118
  313. package/esm5/src/entity-manager.js +0 -2112
  314. package/esm5/src/entity-metadata.js +0 -2144
  315. package/esm5/src/entity-query.js +0 -1042
  316. package/esm5/src/entity-state.js +0 -114
  317. package/esm5/src/enum.js +0 -144
  318. package/esm5/src/event.js +0 -259
  319. package/esm5/src/interface-registry.js +0 -43
  320. package/esm5/src/key-generator.js +0 -111
  321. package/esm5/src/local-query-comparison-options.js +0 -67
  322. package/esm5/src/mapping-context.js +0 -413
  323. package/esm5/src/observable-array.js +0 -201
  324. package/esm5/src/predicate.js +0 -1307
  325. package/esm5/src/primitive-array.js +0 -87
  326. package/esm5/src/query-options.js +0 -167
  327. package/esm5/src/relation-array.js +0 -175
  328. package/esm5/src/save-options.js +0 -43
  329. package/esm5/src/unattached-children-map.js +0 -60
  330. package/esm5/src/validation-options.js +0 -66
  331. package/fesm2015/breeze-client-adapter-ajax-angularjs.js.map +0 -1
  332. package/fesm2015/breeze-client-adapter-ajax-fetch.js.map +0 -1
  333. package/fesm2015/breeze-client-adapter-ajax-httpclient.js.map +0 -1
  334. package/fesm2015/breeze-client-adapter-ajax-jquery.js.map +0 -1
  335. package/fesm2015/breeze-client-adapter-ajax-post.js.map +0 -1
  336. package/fesm2015/breeze-client-adapter-data-service-odata.js.map +0 -1
  337. package/fesm2015/breeze-client-adapter-data-service-webapi.js.map +0 -1
  338. package/fesm2015/breeze-client-adapter-model-library-backing-store.js.map +0 -1
  339. package/fesm2015/breeze-client-adapter-model-library-ko.js.map +0 -1
  340. package/fesm2015/breeze-client-adapter-uri-builder-json.js.map +0 -1
  341. package/fesm2015/breeze-client-adapter-uri-builder-odata.js.map +0 -1
  342. package/fesm2015/breeze-client-mixin-get-entity-graph.js.map +0 -1
  343. package/fesm2015/breeze-client-mixin-save-queuing.js.map +0 -1
  344. package/fesm2015/breeze-client.js.map +0 -1
  345. package/fesm5/breeze-client-adapter-ajax-angularjs.js +0 -186
  346. package/fesm5/breeze-client-adapter-ajax-angularjs.js.map +0 -1
  347. package/fesm5/breeze-client-adapter-ajax-fetch.js +0 -186
  348. package/fesm5/breeze-client-adapter-ajax-fetch.js.map +0 -1
  349. package/fesm5/breeze-client-adapter-ajax-httpclient.js +0 -193
  350. package/fesm5/breeze-client-adapter-ajax-httpclient.js.map +0 -1
  351. package/fesm5/breeze-client-adapter-ajax-jquery.js +0 -111
  352. package/fesm5/breeze-client-adapter-ajax-jquery.js.map +0 -1
  353. package/fesm5/breeze-client-adapter-ajax-post.js +0 -86
  354. package/fesm5/breeze-client-adapter-ajax-post.js.map +0 -1
  355. package/fesm5/breeze-client-adapter-data-service-odata.js +0 -523
  356. package/fesm5/breeze-client-adapter-data-service-odata.js.map +0 -1
  357. package/fesm5/breeze-client-adapter-data-service-webapi.js +0 -111
  358. package/fesm5/breeze-client-adapter-data-service-webapi.js.map +0 -1
  359. package/fesm5/breeze-client-adapter-model-library-backing-store.js +0 -276
  360. package/fesm5/breeze-client-adapter-model-library-backing-store.js.map +0 -1
  361. package/fesm5/breeze-client-adapter-model-library-ko.js +0 -248
  362. package/fesm5/breeze-client-adapter-model-library-ko.js.map +0 -1
  363. package/fesm5/breeze-client-adapter-uri-builder-json.js +0 -92
  364. package/fesm5/breeze-client-adapter-uri-builder-json.js.map +0 -1
  365. package/fesm5/breeze-client-adapter-uri-builder-odata.js +0 -250
  366. package/fesm5/breeze-client-adapter-uri-builder-odata.js.map +0 -1
  367. package/fesm5/breeze-client-mixin-get-entity-graph.js +0 -254
  368. package/fesm5/breeze-client-mixin-get-entity-graph.js.map +0 -1
  369. package/fesm5/breeze-client-mixin-save-queuing.js +0 -356
  370. package/fesm5/breeze-client-mixin-save-queuing.js.map +0 -1
  371. package/fesm5/breeze-client.js +0 -13953
  372. package/fesm5/breeze-client.js.map +0 -1
  373. package/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.metadata.json +0 -1
  374. package/mixin-get-entity-graph/package.json +0 -13
  375. package/mixin-save-queuing/breeze-client-mixin-save-queuing.metadata.json +0 -1
  376. package/mixin-save-queuing/package.json +0 -13
@@ -1,2094 +0,0 @@
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LW1hbmFnZXIuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9icmVlemUtY2xpZW50LyIsInNvdXJjZXMiOlsic3JjL2VudGl0eS1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxJQUFJLEVBQTJCLE1BQU0sUUFBUSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxZQUFZLEVBQXFFLE1BQU0saUJBQWlCLENBQUM7QUFDbEgsT0FBTyxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQWUsWUFBWSxFQUFzQixvQkFBb0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25JLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekMsT0FBTyxFQUFFLFlBQVksRUFBRyxNQUFNLGlCQUFpQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFB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QUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUN2RCxDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxFQUFpQjtJQUM1Qyx5REFBeUQ7SUFDekQsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNoRSxnREFBZ0Q7SUFDaEQsT0FBTyxFQUFFLENBQUMsV0FBVyxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7UUFDdkQsT0FBTyxtQkFBbUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckMsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsS0FBK0I7SUFDdEQsT0FBTyxLQUFLLENBQUMsWUFBWSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsSUFBSSxLQUFLLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3pGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEYXRhU2VydmljZUFkYXB0ZXIgfSBmcm9tICcuL2ludGVyZmFjZS1yZWdpc3RyeSc7XHJcbmltcG9ydCB7IGNvcmUsIENhbGxiYWNrLCBFcnJvckNhbGxiYWNrIH0gZnJvbSAnLi9jb3JlJztcclxuaW1wb3J0IHsgYXNzZXJ0UGFyYW0sIGFzc2VydENvbmZpZyB9IGZyb20gJy4vYXNzZXJ0LXBhcmFtJztcclxuaW1wb3J0IHsgY29uZmlnIH0gZnJvbSAnLi9jb25maWcnO1xyXG5pbXBvcnQgeyBCcmVlemVFdmVudCB9IGZyb20gJy4vZXZlbnQnO1xyXG5pbXBvcnQgeyBFbnRpdHlBc3BlY3QsIEVudGl0eSwgQ29tcGxleE9iamVjdCwgU3RydWN0dXJhbE9iamVjdCwgUHJvcGVydHlDaGFuZ2VkRXZlbnRBcmdzIH0gZnJvbSAnLi9lbnRpdHktYXNwZWN0JztcclxuaW1wb3J0IHsgTWV0YWRhdGFTdG9yZSwgRW50aXR5VHlwZSwgQ29tcGxleFR5cGUsIERhdGFQcm9wZXJ0eSwgTmF2aWdhdGlvblByb3BlcnR5LCBBdXRvR2VuZXJhdGVkS2V5VHlwZSB9IGZyb20gJy4vZW50aXR5LW1ldGFkYXRhJztcclxuaW1wb3J0IHsgRW50aXR5S2V5IH0gZnJvbSAnLi9lbnRpdHkta2V5JztcclxuaW1wb3J0IHsgRW50aXR5QWN0aW9uICB9IGZyb20gJy4vZW50aXR5LWFjdGlvbic7XHJcbmltcG9ydCB7IEVudGl0eVN0YXRlIH0gZnJvbSAnLi9lbnRpdHktc3RhdGUnO1xyXG5pbXBvcnQgeyBEYXRhU2VydmljZSB9IGZyb20gJy4vZGF0YS1zZXJ2aWNlJztcclxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuL2RhdGEtdHlwZSc7XHJcbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4vdmFsaWRhdGUnO1xyXG5pbXBvcnQgeyBWYWxpZGF0aW9uT3B0aW9ucyB9IGZyb20gJy4vdmFsaWRhdGlvbi1vcHRpb25zJztcclxuaW1wb3J0IHsgUXVlcnlPcHRpb25zLCBNZXJnZVN0cmF0ZWd5LCBGZXRjaFN0cmF0ZWd5IH0gZnJvbSAnLi9xdWVyeS1vcHRpb25zJztcclxuaW1wb3J0IHsgU2F2ZU9wdGlvbnMgfSBmcm9tICcuL3NhdmUtb3B0aW9ucyc7XHJcbmltcG9ydCB7IEtleUdlbmVyYXRvciB9IGZyb20gJy4va2V5LWdlbmVyYXRvcic7XHJcbmltcG9ydCB7IEVudGl0eUdyb3VwIH0gZnJvbSAnLi9lbnRpdHktZ3JvdXAnO1xyXG5pbXBvcnQgeyBNYXBwaW5nQ29udGV4dCB9IGZyb20gJy4vbWFwcGluZy1jb250ZXh0JztcclxuaW1wb3J0IHsgRW50aXR5UXVlcnkgfSBmcm9tICcuL2VudGl0eS1xdWVyeSc7XHJcbmltcG9ydCB7IFVuYXR0YWNoZWRDaGlsZHJlbk1hcCB9IGZyb20gJy4vdW5hdHRhY2hlZC1jaGlsZHJlbi1tYXAnO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBIdHRwUmVzcG9uc2Uge1xyXG4gIGNvbmZpZzogYW55O1xyXG4gIGRhdGE6IGFueTtcclxuICBlcnJvcj86IGFueTtcclxuICBzYXZlQ29udGV4dD86IGFueTtcclxuICBzdGF0dXM6IG51bWJlcjtcclxuICBnZXRIZWFkZXJzKGhlYWRlck5hbWU6IHN0cmluZyk6IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBJbXBvcnRSZXN1bHQge1xyXG4gIGVudGl0aWVzOiBFbnRpdHlbXTtcclxuICB0ZW1wS2V5TWFwcGluZzogSVRlbXBLZXlNYXA7XHJcbn1cclxuXHJcbi8vIHN1YmNsYXNzZXMgb2YgRXJyb3JcclxuXHJcbi8qKiBCYXNlIHNoYXBlIG9mIGFueSBlcnJvcnMgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZlckVycm9yIGV4dGVuZHMgRXJyb3Ige1xyXG4gIGh0dHBSZXNwb25zZTogSHR0cFJlc3BvbnNlO1xyXG4gIHN0YXR1czogbnVtYmVyO1xyXG4gIG1lc3NhZ2U6IHN0cmluZztcclxuICBzdGF0dXNUZXh0Pzogc3RyaW5nO1xyXG4gIGJvZHk/OiBhbnk7XHJcbiAgdXJsPzogc3RyaW5nO1xyXG59XHJcblxyXG4vKiogU2hhcGUgb2YgYSBzYXZlIGVycm9yIHJldHVybmVkIGZyb20gdGhlIHNlcnZlci4gXHJcbkZvciB1c2UgYnkgYnJlZXplIHBsdWdpbiBhdXRob3JzIG9ubHkuIFRoZSBjbGFzcyBpcyBmb3IgdXNlIGluIGJ1aWxkaW5nIGEgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0gaW1wbGVtZW50YXRpb24uIFxyXG5AYWRhcHRlciAoc2VlIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBAaW50ZXJuYWwgXHJcbiovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZUVycm9yRnJvbVNlcnZlciBleHRlbmRzIFNlcnZlckVycm9yIHtcclxuICBlbnRpdHlFcnJvcnM6IEVudGl0eUVycm9yRnJvbVNlcnZlcltdO1xyXG59XHJcblxyXG4vKiogU2hhcGUgb2YgYSBzYXZlIGVycm9yIHdoZW4gcmV0dXJuZWQgdG8gdGhlIGNsaWVudC4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBTYXZlRXJyb3IgZXh0ZW5kcyBTZXJ2ZXJFcnJvciB7XHJcbiAgZW50aXR5RXJyb3JzOiBFbnRpdHlFcnJvcltdO1xyXG59XHJcblxyXG4vLyBub3Qgc3ViY2xhc3NlcyBvZiBFcnJvclxyXG4vKiogXHJcbkZvciB1c2UgYnkgYnJlZXplIHBsdWdpbiBhdXRob3JzIG9ubHkuIFRoZSBjbGFzcyBpcyBmb3IgdXNlIGluIGJ1aWxkaW5nIGEgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0gaW1wbGVtZW50YXRpb24uIFxyXG5AYWRhcHRlciAoc2VlIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBAaW50ZXJuYWwgXHJcbiovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5RXJyb3JGcm9tU2VydmVyIHtcclxuICBlbnRpdHlUeXBlTmFtZTogc3RyaW5nO1xyXG4gIGtleVZhbHVlczogYW55W107XHJcblxyXG4gIGVycm9yTmFtZTogc3RyaW5nO1xyXG4gIGVycm9yTWVzc2FnZTogc3RyaW5nO1xyXG4gIHByb3BlcnR5TmFtZTogc3RyaW5nO1xyXG4gIGN1c3RvbT86IGFueTtcclxufVxyXG5cclxuLyoqIFNoYXBlIG9mIGFuIGVycm9yIG9uIGEgc3BlY2lmaWMgZW50aXR5LiAgUGFydCBvZiBhIFtbSVNhdmVFcnJvcl1dICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5RXJyb3Ige1xyXG4gIGVudGl0eTogRW50aXR5O1xyXG4gIGVycm9yTmFtZTogc3RyaW5nO1xyXG4gIGVycm9yTWVzc2FnZTogc3RyaW5nO1xyXG4gIHByb3BlcnR5TmFtZTogc3RyaW5nO1xyXG4gIGlzU2VydmVyRXJyb3I6IGJvb2xlYW47XHJcbiAgY3VzdG9tPzogYW55O1xyXG59XHJcblxyXG4vKiogVGhlIHNoYXBlIG9mIHRoZSBQcm9taXNlIHJldHVybmVkIGJ5IGFuIFtbRW50aXR5TWFuYWdlci5leGVjdXRlUXVlcnldXSBjYWxsLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXJ5UmVzdWx0IHtcclxuICAvKiogVG9wIGxldmVsIGVudGl0aWVzIHJldHVybmVkLiAgRXhjbHVkZXMgZW50aXRpZXMgdGhhdCBhcmUgRGVsZXRlZC4gKi9cclxuICByZXN1bHRzOiBhbnlbXTtcclxuICAvKiogUXVlcnkgdGhhdCB3YXMgZXhlY3V0ZWQgKi9cclxuICBxdWVyeTogRW50aXR5UXVlcnkgfCBzdHJpbmc7XHJcbiAgLyoqIEVudGl0eU1hbmFnZXIgdGhhdCBleGVjdXRlZCB0aGUgcXVlcnkgKi9cclxuICBlbnRpdHlNYW5hZ2VyPzogRW50aXR5TWFuYWdlcjtcclxuICAvKiogVG90YWwgbnVtYmVyIG9mIHJlc3VsdHMgYXZhaWxhYmxlIG9uIHRoZSBzZXJ2ZXIgKi9cclxuICBpbmxpbmVDb3VudD86IG51bWJlcjtcclxuICAvKiogQWxsIGVudGl0aWVzIHJldHVybmVkIGJ5IHRoZSBxdWVyeS4gIERpZmZlcnMgZnJvbSBgcmVzdWx0c2Agd2hlbiBhbiBleHBhbmQgaXMgdXNlZC4gIEluY2x1ZGVzIGVudGl0aWVzIHRoYXQgYXJlIERlbGV0ZWQuICovXHJcbiAgcmV0cmlldmVkRW50aXRpZXM/OiBFbnRpdHlbXTtcclxuICAgIC8qKiBSYXcgcmVzcG9uc2UgZnJvbSB0aGUgc2VydmVyICovXHJcbiAgaHR0cFJlc3BvbnNlPzogSHR0cFJlc3BvbnNlO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXJ5U3VjY2Vzc0NhbGxiYWNrIHtcclxuICAoZGF0YTogUXVlcnlSZXN1bHQpOiB2b2lkO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXJ5RXJyb3JDYWxsYmFjayB7XHJcbiAgKGVycm9yOiB7IHF1ZXJ5OiBFbnRpdHlRdWVyeTsgaHR0cFJlc3BvbnNlOiBIdHRwUmVzcG9uc2U7IGVudGl0eU1hbmFnZXI6IEVudGl0eU1hbmFnZXI7IG1lc3NhZ2U/OiBzdHJpbmc7IHN0YWNrPzogc3RyaW5nIH0pOiB2b2lkO1xyXG59XHJcblxyXG4vKiogS2V5IG1hcHBpbmcgaW5mb3JtYXRpb24gcmV0dXJuZWQgYXMgcGFydCBvZiBhbiBbW0lTYXZlUmVzdWx0XV0uICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgS2V5TWFwcGluZyB7XHJcbiAgZW50aXR5VHlwZU5hbWU6IHN0cmluZztcclxuICB0ZW1wVmFsdWU6IGFueTtcclxuICByZWFsVmFsdWU6IGFueTtcclxufVxyXG5cclxuaW50ZXJmYWNlIElUZW1wS2V5TWFwIHtcclxuICBbaW5kZXg6IHN0cmluZ106IEVudGl0eUtleTtcclxufVxyXG5cclxuLyoqIENvbmZpZ3VyYXRpb24gaW5mbyB0byBiZSBwYXNzZWQgdG8gdGhlIFtbRW50aXR5TWFuYWdlci5pbXBvcnRFbnRpdGllc11dIG1ldGhvZCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEltcG9ydENvbmZpZyB7XHJcbiAgLyoqIElmIHRydWUsIG1lcmdlIEFkZGVkIGVudGl0aWVzICh3aXRoIHRlbXAga2V5cykgYXMgd2VsbC4gIFRoaXMgY2FuIGJlIGRhbmdlcm91cy4gKi9cclxuICBtZXJnZUFkZHM/OiBib29sZWFuO1xyXG4gIG1lcmdlU3RyYXRlZ3k/OiBNZXJnZVN0cmF0ZWd5OyAgXHJcbiAgbWV0YWRhdGFWZXJzaW9uRm4/OiAoYXJnOiB7IG1ldGFkYXRhVmVyc2lvbjogYW55LCBtZXRhZGF0YVN0b3JlTmFtZTogYW55IH0pID0+IHZvaWQ7XHJcbn1cclxuXHJcbmludGVyZmFjZSBJbXBvcnRDb25maWdFeHQgZXh0ZW5kcyBJbXBvcnRDb25maWcge1xyXG4gIHRlbXBLZXlNYXA/OiBJVGVtcEtleU1hcDtcclxufVxyXG5cclxuLyoqIFRoZSBzaGFwZSBvZiB0aGUgUHJvbWlzZSByZXR1cm5lZCBieSBhbiBbW0VudGl0eU1hbmFnZXIuc2F2ZUNoYW5nZXNdXSBjYWxsLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFNhdmVSZXN1bHQge1xyXG4gIGVudGl0aWVzOiBFbnRpdHlbXTtcclxuICBrZXlNYXBwaW5nczogS2V5TWFwcGluZ1tdO1xyXG4gIGRlbGV0ZWRLZXlzPzogeyBlbnRpdHlUeXBlTmFtZTogc3RyaW5nLCBrZXlWYWx1ZXM6IGFueVtdfVtdO1xyXG4gIGh0dHBSZXNwb25zZT86IEh0dHBSZXNwb25zZTtcclxufVxyXG5cclxuLyoqIEZvciB1c2UgYnkgYnJlZXplIHBsdWdpbiBhdXRob3JzIG9ubHkuIFRoZSBjbGFzcyBpcyBmb3IgdXNlIGluIGJ1aWxkaW5nIGEgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0gaW1wbGVtZW50YXRpb24uIFxyXG5AYWRhcHRlciAoc2VlIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBcclxuKi9cclxuZXhwb3J0IGludGVyZmFjZSBTYXZlQ29udGV4dCB7XHJcbiAgZW50aXR5TWFuYWdlcjogRW50aXR5TWFuYWdlcjtcclxuICBkYXRhU2VydmljZTogRGF0YVNlcnZpY2U7XHJcbiAgcHJvY2Vzc1NhdmVkRW50aXRpZXM6IChzYXZlUmVzdWx0OiBTYXZlUmVzdWx0KSA9PiBFbnRpdHlbXTtcclxuICByZXNvdXJjZU5hbWU6IHN0cmluZztcclxuICBhZGFwdGVyPzogRGF0YVNlcnZpY2VBZGFwdGVyO1xyXG4gIHJvdXRlUHJlZml4Pzogc3RyaW5nO1xyXG59XHJcblxyXG4vKiogRm9yIHVzZSBieSBicmVlemUgcGx1Z2luIGF1dGhvcnMgb25seS4gVGhlIGNsYXNzIGlzIGZvciB1c2UgaW4gYnVpbGRpbmcgYSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSBpbXBsZW1lbnRhdGlvbi4gXHJcbkBhZGFwdGVyIChzZWUgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0pICAgIFxyXG5AaGlkZGVuIFxyXG4qL1xyXG5leHBvcnQgaW50ZXJmYWNlIFNhdmVCdW5kbGUge1xyXG4gIGVudGl0aWVzOiBFbnRpdHlbXTtcclxuICBzYXZlT3B0aW9uczogU2F2ZU9wdGlvbnM7XHJcbn1cclxuXHJcbi8qKiBDb25maWd1cmF0aW9uIGluZm8gdG8gYmUgcGFzc2VkIHRvIHRoZSBbW0VudGl0eU1hbmFnZXJdXSBjb25zdHJ1Y3RvciAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEVudGl0eU1hbmFnZXJDb25maWcge1xyXG4gIC8qKiBUaGUgc2VydmljZSBuYW1lIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICAqKi9cclxuICBzZXJ2aWNlTmFtZT86IHN0cmluZztcclxuICAvKiogVGhlIERhdGFTZXJ2aWNlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICoqL1xyXG4gIGRhdGFTZXJ2aWNlPzogRGF0YVNlcnZpY2U7XHJcbiAgLyoqIFRoZSBbW1F1ZXJ5T3B0aW9uc11dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICAqKi9cclxuICBxdWVyeU9wdGlvbnM/OiBRdWVyeU9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW1NhdmVPcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gKiovXHJcbiAgc2F2ZU9wdGlvbnM/OiBTYXZlT3B0aW9ucztcclxuICAvKiogVGhlIFtbVmFsaWRhdGlvbk9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAgKiovXHJcbiAgdmFsaWRhdGlvbk9wdGlvbnM/OiBWYWxpZGF0aW9uT3B0aW9ucztcclxuICAvKiogVGhlIFtbS2V5R2VuZXJhdG9yXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gKiovXHJcbiAga2V5R2VuZXJhdG9yPzogS2V5R2VuZXJhdG9yO1xyXG4gIC8qKiBUaGUgW1tLZXlHZW5lcmF0b3JdXSBjb25zdHJ1Y3RvciBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAqKi9cclxuICBrZXlHZW5lcmF0b3JDdG9yPzogeyBuZXcgKCk6IEtleUdlbmVyYXRvciB9OyAvLyBUT0RPOiByZXZpZXcgdGhpc1xyXG4gIC8qKiBUaGUgW1tNZXRhZGF0YVN0b3JlXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gKiovXHJcbiAgbWV0YWRhdGFTdG9yZT86IE1ldGFkYXRhU3RvcmU7XHJcbn1cclxuXHJcbi8qKiBUaGUgc2hhcGUgcmV0dXJuZWQgYnkgY2FsbGJhY2tzIHJlZ2lzdGVyZWQgd2l0aCBbW0VudGl0eU1hbmFnZXIuZW50aXR5Q2hhbmdlZF1dIGV2ZW50ICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5Q2hhbmdlZEV2ZW50QXJncyB7XHJcbiAgZW50aXR5QWN0aW9uOiBFbnRpdHlBY3Rpb247XHJcbiAgZW50aXR5PzogRW50aXR5O1xyXG4gIGFyZ3M/OiBQcm9wZXJ0eUNoYW5nZWRFdmVudEFyZ3M7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVmFsaWRhdGlvbkVycm9yc0NoYW5nZWRFdmVudEFyZ3Mge1xyXG4gIGVudGl0eTogRW50aXR5OyBcclxuICBhZGRlZDogVmFsaWRhdGlvbkVycm9yW107IFxyXG4gIHJlbW92ZWQ6IFZhbGlkYXRpb25FcnJvcltdO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEhhc0NoYW5nZXNDaGFuZ2VkRXZlbnRBcmdzIHtcclxuICBlbnRpdHlNYW5hZ2VyOiBFbnRpdHlNYW5hZ2VyOyBcclxuICBoYXNDaGFuZ2VzOiBib29sZWFuO1xyXG59XHJcblxyXG4vKipcclxuSW5zdGFuY2VzIG9mIHRoZSBFbnRpdHlNYW5hZ2VyIGNvbnRhaW4gYW5kIG1hbmFnZSBjb2xsZWN0aW9ucyBvZiBlbnRpdGllcywgZWl0aGVyIHJldHJpZXZlZCBmcm9tIGEgYmFja2VuZCBkYXRhc3RvcmUgb3IgY3JlYXRlZCBvbiB0aGUgY2xpZW50LlxyXG4qKi9cclxuZXhwb3J0IGNsYXNzIEVudGl0eU1hbmFnZXIge1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF8kdHlwZU5hbWU6IHN0cmluZzsgLy8gYWN0dWFsbHkgZGVmaW5lZCBvbiBwcm90b3R5cGVcclxuXHJcbiAgLyoqIFRoZSBzZXJ2aWNlIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBzZXJ2aWNlTmFtZTogc3RyaW5nO1xyXG4gIC8qKiBUaGUgRGF0YVNlcnZpY2UgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBkYXRhU2VydmljZTogRGF0YVNlcnZpY2U7XHJcbiAgLyoqIFRoZSBbW1F1ZXJ5T3B0aW9uc11dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgcXVlcnlPcHRpb25zOiBRdWVyeU9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW1NhdmVPcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBzYXZlT3B0aW9uczogU2F2ZU9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW1ZhbGlkYXRpb25PcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICB2YWxpZGF0aW9uT3B0aW9uczogVmFsaWRhdGlvbk9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW0tleUdlbmVyYXRvcl1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAga2V5R2VuZXJhdG9yOiBLZXlHZW5lcmF0b3I7XHJcbiAgLyoqIFRoZSBbW0tleUdlbmVyYXRvcl1dIGNvbnN0cnVjdG9yIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAga2V5R2VuZXJhdG9yQ3RvcjogeyBuZXcgKCk6IEtleUdlbmVyYXRvciB9OyAvLyBUT0RPOiByZXZpZXcgdGhpc1xyXG4gIC8qKiBUaGUgW1tNZXRhZGF0YVN0b3JlXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlO1xyXG4gIGlzTG9hZGluZzogYm9vbGVhbjtcclxuICBpc1JlamVjdGluZ0NoYW5nZXM6IGJvb2xlYW47XHJcblxyXG4gIC8vIGV2ZW50c1xyXG4gIC8qKlxyXG4gIEEgW1tCcmVlemVFdmVudF1dIHRoYXQgZmlyZXMgd2hlbmV2ZXIgYSBjaGFuZ2UgdG8gYW55IGVudGl0eSBpbiB0aGlzIEVudGl0eU1hbmFnZXIgb2NjdXJzLiBfX1JlYWQgT25seV9fXHJcblxyXG4gIEBldmVudEFyZ3MgLSBcclxuICAtIGVudGl0eUFjdGlvbiAtIFRoZSBbW0VudGl0eUFjdGlvbl1dIHRoYXQgb2NjdXJlZC5cclxuICAtIGVudGl0eSAtIFRoZSBlbnRpdHkgdGhhdCBjaGFuZ2VkLiAgSWYgdGhpcyBpcyBudWxsLCB0aGVuIGFsbCBlbnRpdGllcyBpbiB0aGUgZW50aXR5TWFuYWdlciB3ZXJlIGFmZmVjdGVkLlxyXG4gIC0gYXJncyAtIEFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgdGhpcyBldmVudC4gVGhpcyB3aWxsIGRpZmZlciBiYXNlZCBvbiB0aGUgZW50aXR5QWN0aW9uLlxyXG5cclxuICA+ICAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoIHtzZXJ2aWNlTmFtZTogXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiIH0pO1xyXG4gID4gICAgICBlbS5lbnRpdHlDaGFuZ2VkLnN1YnNjcmliZShmdW5jdGlvbihjaGFuZ2VBcmdzKSB7XHJcbiAgPiAgICAgICAgICAvLyBUaGlzIGNvZGUgd2lsbCBiZSBleGVjdXRlZCBhbnkgdGltZSBhbnkgZW50aXR5IHdpdGhpbiB0aGUgZW50aXR5TWFuYWdlciBcclxuICA+ICAgICAgICAgIC8vIGlzIGFkZGVkLCBtb2RpZmllZCwgZGVsZXRlZCBvciBkZXRhY2hlZCBmb3IgYW55IHJlYXNvbi5cclxuICA+ICAgICAgICAgIGxldCBhY3Rpb24gPSBjaGFuZ2VBcmdzLmVudGl0eUFjdGlvbjtcclxuICA+ICAgICAgICAgIGxldCBlbnRpdHkgPSBjaGFuZ2VBcmdzLmVudGl0eTtcclxuICA+ICAgICAgICAgIC8vIC4uIGRvIHNvbWV0aGluZyB0byB0aGlzIGVudGl0eSB3aGVuIGl0IGlzIGNoYW5nZWQuXHJcbiAgPiAgICAgIH0pO1xyXG4gID4gIH0pO1xyXG4gIEBldmVudFxyXG4gICoqL1xyXG4gIGVudGl0eUNoYW5nZWQ6IEJyZWV6ZUV2ZW50PEVudGl0eUNoYW5nZWRFdmVudEFyZ3M+O1xyXG5cclxuICAvKipcclxuICBBbiBbW0JyZWV6ZUV2ZW50XV0gdGhhdCBmaXJlcyB3aGVuZXZlciB2YWxpZGF0aW9uRXJyb3JzIGNoYW5nZSBmb3IgYW55IGVudGl0eSBpbiB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X19cclxuICBAZXZlbnRBcmdzIC1cclxuICAgIC0gZW50aXR5IC0gVGhlIGVudGl0eSBvbiB3aGljaCB0aGUgdmFsaWRhdGlvbiBlcnJvcnMgaGF2ZSBiZWVuIGFkZGVkIG9yIHJlbW92ZWQuXHJcbiAgICAtIGFkZGVkIC0gQW4gYXJyYXkgY29udGFpbmluZyBhbnkgbmV3bHkgYWRkZWQgW1tWYWxpZGF0aW9uRXJyb3JdXXNcclxuICAgIC0gcmVtb3ZlZCAtIEFuIGFycmF5IGNvbnRhaW5pbmcgYW55IG5ld2x5IHJlbW92ZWQgW1tWYWxpZGF0aW9uRXJyb3JdXXMuIFRoaXMgaXMgdGhvc2UgZXJyb3JzIHRoYXQgaGF2ZSBiZWVuICdmaXhlZCcgIFxyXG5cclxuICA+ICAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoIHtzZXJ2aWNlTmFtZTogXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiIH0pO1xyXG4gID4gICAgICBlbS52YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZC5zdWJzY3JpYmUoZnVuY3Rpb24oY2hhbmdlQXJncykge1xyXG4gID4gICAgICAgICAgICAgIC8vIFRoaXMgY29kZSB3aWxsIGJlIGV4ZWN1dGVkIGFueSB0aW1lIGFueSBlbnRpdHkgd2l0aGluIHRoZSBlbnRpdHlNYW5hZ2VyIGV4cGVyaWVuY2VzIGEgY2hhbmdlIHRvIGl0cyB2YWxpZGF0aW9uRXJyb3JzIGNvbGxlY3Rpb24uXHJcbiAgPiAgICAgICAgICAgICAgZnVuY3Rpb24gKHZhbGlkYXRpb25DaGFuZ2VBcmdzKSB7XHJcbiAgPiAgICAgICAgICAgICAgICAgIGxldCBlbnRpdHkgPT0gdmFsaWRhdGlvbkNoYW5nZUFyZ3MuZW50aXR5O1xyXG4gID4gICAgICAgICAgICAgICAgICBsZXQgZXJyb3JzQWRkZWQgPSB2YWxpZGF0aW9uQ2hhbmdlQXJncy5hZGRlZDtcclxuICA+ICAgICAgICAgICAgICAgICAgbGV0IGVycm9yc0NsZWFyZWQgPSB2YWxpZGF0aW9uQ2hhbmdlQXJncy5yZW1vdmVkO1xyXG4gID4gICAgICAgICAgICAgICAgICAvLyAuLi4gZG8gc29tZXRoaW5nIGludGVyZXN0aW5nIHdpdGggdGhlIG9yZGVyLlxyXG4gID4gICAgICAgICAgICAgIH0pO1xyXG4gID4gICAgICAgICAgfSk7XHJcbiAgPiAgICAgIH0pO1xyXG4gIEBldmVudFxyXG4gICoqL1xyXG4gIHZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkOiBCcmVlemVFdmVudDxWYWxpZGF0aW9uRXJyb3JzQ2hhbmdlZEV2ZW50QXJncz47XHJcblxyXG4gIC8qKlxyXG4gIEEgW1tCcmVlemVFdmVudF1dIHRoYXQgZmlyZXMgd2hlbmV2ZXIgYW4gRW50aXR5TWFuYWdlciB0cmFuc2l0aW9ucyB0byBvciBmcm9tIGhhdmluZyBjaGFuZ2VzLiBfX1JlYWQgT25seV9fXHJcbiAgQGV2ZW50QXJncyAtXHJcbiAgICAtIGVudGl0eU1hbmFnZXIgLSBUaGUgRW50aXR5TWFuYWdlciB3aG9zZSAnaGFzQ2hhbmdlcycgc3RhdHVzIGhhcyBjaGFuZ2VkLlxyXG4gICAgLSBoYXNDaGFuZ2VzIC0gV2hldGhlciBvciBub3QgdGhpcyBFbnRpdHlNYW5hZ2VyIGhhcyBjaGFuZ2VzLlxyXG5cclxuICA+ICAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoIHtzZXJ2aWNlTmFtZTogXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiIH0pO1xyXG4gID4gICAgICBlbS5oYXNDaGFuZ2VzQ2hhbmdlZC5zdWJzY3JpYmUoZnVuY3Rpb24oYXJncykge1xyXG4gID4gICAgICAgICAgICAgIGxldCBoYXNDaGFuZ2VzQ2hhbmdlZCA9IGFyZ3MuaGFzQ2hhbmdlcztcclxuICA+ICAgICAgICAgICAgICBsZXQgZW50aXR5TWFuYWdlciA9IGFyZ3MuZW50aXR5TWFuYWdlcjtcclxuICA+ICAgICAgICAgIH0pO1xyXG4gID4gICAgICB9KTtcclxuICBAZXZlbnQgXHJcbiAgKiovXHJcbiAgaGFzQ2hhbmdlc0NoYW5nZWQ6IEJyZWV6ZUV2ZW50PEhhc0NoYW5nZXNDaGFuZ2VkRXZlbnRBcmdzPjtcclxuXHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9wZW5kaW5nUHVicz86IGFueVtdOyAvLyBUT0RPOiByZWZpbmUgbGF0ZXJcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfaGFzQ2hhbmdlc0FjdGlvbj86ICgoKSA9PiBib29sZWFuKTsgLy8gVE9ETyByZWZpbmUgbGF0ZXJcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfaGFzQ2hhbmdlczogYm9vbGVhbjtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZW50aXR5R3JvdXBNYXA6IHsgW2luZGV4OiBzdHJpbmddOiBFbnRpdHlHcm91cCB9O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF91bmF0dGFjaGVkQ2hpbGRyZW5NYXA6IFVuYXR0YWNoZWRDaGlsZHJlbk1hcDtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfaW5LZXlGaXh1cDogYm9vbGVhbjtcclxuXHJcbiAgaGVscGVyID0ge1xyXG4gICAgdW53cmFwSW5zdGFuY2U6IHVud3JhcEluc3RhbmNlLFxyXG4gICAgdW53cmFwT3JpZ2luYWxWYWx1ZXM6IHVud3JhcE9yaWdpbmFsVmFsdWVzLFxyXG4gICAgdW53cmFwQ2hhbmdlZFZhbHVlczogdW53cmFwQ2hhbmdlZFZhbHVlc1xyXG4gIH07XHJcblxyXG4gIC8qKlxyXG4gIEVudGl0eU1hbmFnZXIgY29uc3RydWN0b3IuXHJcblxyXG4gIEF0IGl0cyBtb3N0IGJhc2ljIGFuIEVudGl0eU1hbmFnZXIgY2FuIGJlIGNvbnN0cnVjdGVkIHdpdGgganVzdCBhIHNlcnZpY2UgbmFtZVxyXG4gID4gICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gbmV3IEVudGl0eU1hbmFnZXIoIFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIik7XHJcblxyXG4gIFRoaXMgaXMgdGhlIHNhbWUgYXMgY2FsbGluZyBpdCB3aXRoIHRoZSBmb2xsb3dpbmcgY29uZmlndXJhdGlvbiBvYmplY3RcclxuICA+ICAgICBsZXQgZW50aXR5TWFuYWdlciA9IG5ldyBFbnRpdHlNYW5hZ2VyKCB7c2VydmljZU5hbWU6IFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIiB9KTtcclxuXHJcbiAgVXN1YWxseSBob3dldmVyLCBjb25maWd1cmF0aW9uIG9iamVjdHMgd2lsbCBjb250YWluIG1vcmUgdGhhbiBqdXN0IHRoZSAnc2VydmljZU5hbWUnO1xyXG4gID4gICAgIGxldCBtZXRhZGF0YVN0b3JlID0gbmV3IE1ldGFkYXRhU3RvcmUoKTtcclxuICA+ICAgICBsZXQgZW50aXR5TWFuYWdlciA9IG5ldyBFbnRpdHlNYW5hZ2VyKCB7XHJcbiAgPiAgICAgICBzZXJ2aWNlTmFtZTogXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiLFxyXG4gID4gICAgICAgbWV0YWRhdGFTdG9yZTogbWV0YWRhdGFTdG9yZVxyXG4gID4gICAgIH0pO1xyXG5cclxuICBvclxyXG4gID4gICAgIHJldHVybiBuZXcgUXVlcnlPcHRpb25zKHtcclxuICA+ICAgICAgICAgbWVyZ2VTdHJhdGVneTogb2JqLFxyXG4gID4gICAgICAgICBmZXRjaFN0cmF0ZWd5OiB0aGlzLmZldGNoU3RyYXRlZ3lcclxuICA+ICAgICB9KTtcclxuICA+ICAgICBsZXQgcXVlcnlPcHRpb25zID0gbmV3IFF1ZXJ5T3B0aW9ucyh7XHJcbiAgPiAgICAgICAgIG1lcmdlU3RyYXRlZ3k6IE1lcmdlU3RyYXRlZ3kuT3ZlcndyaXRlQ2hhbmdlcyxcclxuICA+ICAgICAgICAgZmV0Y2hTdHJhdGVneTogRmV0Y2hTdHJhdGVneS5Gcm9tU2VydmVyXHJcbiAgPiAgICAgfSk7XHJcbiAgPiAgICAgbGV0IHZhbGlkYXRpb25PcHRpb25zID0gbmV3IFZhbGlkYXRpb25PcHRpb25zKHtcclxuICA+ICAgICAgICAgdmFsaWRhdGVPbkF0dGFjaDogdHJ1ZSxcclxuICA+ICAgICAgICAgdmFsaWRhdGVPblNhdmU6IHRydWUsXHJcbiAgPiAgICAgICAgIHZhbGlkYXRlT25RdWVyeTogZmFsc2VcclxuICA+ICAgICB9KTtcclxuICA+ICAgICBsZXQgZW50aXR5TWFuYWdlciA9IG5ldyBFbnRpdHlNYW5hZ2VyKHtcclxuICA+ICAgICAgICAgc2VydmljZU5hbWU6IFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIixcclxuICA+ICAgICAgICAgcXVlcnlPcHRpb25zOiBxdWVyeU9wdGlvbnMsXHJcbiAgPiAgICAgICAgIHZhbGlkYXRpb25PcHRpb25zOiB2YWxpZGF0aW9uT3B0aW9uc1xyXG4gID4gICAgIH0pO1xyXG4gIEBwYXJhbSBlbUNvbmZpZyAtIENvbmZpZ3VyYXRpb24gc2V0dGluZ3Mgb3IgYSBzZXJ2aWNlIG5hbWUuICBcclxuICAqKi9cclxuICBjb25zdHJ1Y3RvcihlbUNvbmZpZz86IEVudGl0eU1hbmFnZXJDb25maWcgfCBzdHJpbmcpIHtcclxuXHJcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIEVudGl0eU1hbmFnZXIgY3RvciBoYXMgYSBzaW5nbGUgb3B0aW9uYWwgYXJndW1lbnQgdGhhdCBpcyBlaXRoZXIgYSAnc2VydmljZU5hbWUnIG9yIGEgY29uZmlndXJhdGlvbiBvYmplY3QuXCIpO1xyXG4gICAgfVxyXG4gICAgbGV0IGNvbmZpZzogRW50aXR5TWFuYWdlckNvbmZpZztcclxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIGNvbmZpZyA9IHsgc2VydmljZU5hbWU6IFwiXCIgfTtcclxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGVtQ29uZmlnID09PSAnc3RyaW5nJykge1xyXG4gICAgICBjb25maWcgPSB7IHNlcnZpY2VOYW1lOiBlbUNvbmZpZyB9O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uZmlnID0gZW1Db25maWcgfHwge307XHJcbiAgICB9XHJcblxyXG4gICAgRW50aXR5TWFuYWdlci5fdXBkYXRlV2l0aENvbmZpZyh0aGlzLCBjb25maWcsIHRydWUpO1xyXG5cclxuICAgIHRoaXMuZW50aXR5Q2hhbmdlZCA9IG5ldyBCcmVlemVFdmVudChcImVudGl0eUNoYW5nZWRcIiwgdGhpcyk7XHJcbiAgICB0aGlzLnZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkID0gbmV3IEJyZWV6ZUV2ZW50KFwidmFsaWRhdGlvbkVycm9yc0NoYW5nZWRcIiwgdGhpcyk7XHJcbiAgICB0aGlzLmhhc0NoYW5nZXNDaGFuZ2VkID0gbmV3IEJyZWV6ZUV2ZW50KFwiaGFzQ2hhbmdlc0NoYW5nZWRcIiwgdGhpcyk7XHJcblxyXG4gICAgdGhpcy5jbGVhcigpO1xyXG5cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEdlbmVyYWwgcHVycG9zZSBwcm9wZXJ0eSBzZXQgbWV0aG9kLiAgQW55IG9mIHRoZSBwcm9wZXJ0aWVzIGluIHRoZSBbW0VudGl0eU1hbmFnZXJDb25maWddXVxyXG4gIG1heSBiZSBzZXQuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmV2aW91c2x5IGNyZWF0ZWQgRW50aXR5TWFuYWdlclxyXG4gID4gICAgICAvLyB3aGVyZSB3ZSB3YW50IHRvIGNoYW5nZSBzb21lIG9mIGl0cyBzZXR0aW5ncy5cclxuICA+ICAgICAgZW0xLnNldFByb3BlcnRpZXMoIHtcclxuICA+ICAgICAgICAgIHNlcnZpY2VOYW1lOiBcImJyZWV6ZS9mb29cIlxyXG4gID4gICAgICB9KTtcclxuICBAcGFyYW0gY29uZmlnIC0gQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHNlbGVjdGVkIHByb3BlcnRpZXMgYW5kIHZhbHVlcyB0byBzZXQuXHJcbiAgKiovXHJcbiAgc2V0UHJvcGVydGllcyhjb25maWc6IEVudGl0eU1hbmFnZXJDb25maWcpIHtcclxuICAgIEVudGl0eU1hbmFnZXIuX3VwZGF0ZVdpdGhDb25maWcodGhpcywgY29uZmlnLCBmYWxzZSk7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBzdGF0aWMgX3VwZGF0ZVdpdGhDb25maWcoZW06IEVudGl0eU1hbmFnZXIsIGNvbmZpZzogRW50aXR5TWFuYWdlckNvbmZpZywgaXNDdG9yOiBib29sZWFuKSB7XHJcbiAgICBsZXQgZGVmYXVsdFF1ZXJ5T3B0aW9ucyA9IGlzQ3RvciA/IFF1ZXJ5T3B0aW9ucy5kZWZhdWx0SW5zdGFuY2UgOiBlbS5xdWVyeU9wdGlvbnM7XHJcbiAgICBsZXQgZGVmYXVsdFNhdmVPcHRpb25zID0gaXNDdG9yID8gU2F2ZU9wdGlvbnMuZGVmYXVsdEluc3RhbmNlIDogZW0uc2F2ZU9wdGlvbnM7XHJcbiAgICBsZXQgZGVmYXVsdFZhbGlkYXRpb25PcHRpb25zID0gaXNDdG9yID8gVmFsaWRhdGlvbk9wdGlvbnMuZGVmYXVsdEluc3RhbmNlIDogZW0udmFsaWRhdGlvbk9wdGlvbnM7XHJcblxyXG4gICAgbGV0IGNvbmZpZ1BhcmFtID0gYXNzZXJ0Q29uZmlnKGNvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJzZXJ2aWNlTmFtZVwiKS5pc09wdGlvbmFsKCkuaXNTdHJpbmcoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImRhdGFTZXJ2aWNlXCIpLmlzT3B0aW9uYWwoKS5pc0luc3RhbmNlT2YoRGF0YVNlcnZpY2UpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwicXVlcnlPcHRpb25zXCIpLmlzSW5zdGFuY2VPZihRdWVyeU9wdGlvbnMpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChkZWZhdWx0UXVlcnlPcHRpb25zKVxyXG4gICAgICAud2hlcmVQYXJhbShcInNhdmVPcHRpb25zXCIpLmlzSW5zdGFuY2VPZihTYXZlT3B0aW9ucykuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KGRlZmF1bHRTYXZlT3B0aW9ucylcclxuICAgICAgLndoZXJlUGFyYW0oXCJ2YWxpZGF0aW9uT3B0aW9uc1wiKS5pc0luc3RhbmNlT2YoVmFsaWRhdGlvbk9wdGlvbnMpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChkZWZhdWx0VmFsaWRhdGlvbk9wdGlvbnMpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwia2V5R2VuZXJhdG9yQ3RvclwiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpO1xyXG4gICAgaWYgKGlzQ3Rvcikge1xyXG4gICAgICBjb25maWdQYXJhbSA9IGNvbmZpZ1BhcmFtXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJtZXRhZGF0YVN0b3JlXCIpLmlzSW5zdGFuY2VPZihNZXRhZGF0YVN0b3JlKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQobmV3IE1ldGFkYXRhU3RvcmUoKSk7XHJcbiAgICB9XHJcbiAgICBjb25maWdQYXJhbS5hcHBseUFsbChlbSk7XHJcblxyXG4gICAgLy8gaW5zdXJlIHRoYXQgZW50aXR5TWFuYWdlcidzIG9wdGlvbnMgdmVyc2lvbnMgYXJlIGNvbXBsZXRlbHkgcG9wdWxhdGVkXHJcbiAgICBjb3JlLnVwZGF0ZVdpdGhEZWZhdWx0cyhlbS5xdWVyeU9wdGlvbnMsIGRlZmF1bHRRdWVyeU9wdGlvbnMpO1xyXG4gICAgY29yZS51cGRhdGVXaXRoRGVmYXVsdHMoZW0uc2F2ZU9wdGlvbnMsIGRlZmF1bHRTYXZlT3B0aW9ucyk7XHJcbiAgICBjb3JlLnVwZGF0ZVdpdGhEZWZhdWx0cyhlbS52YWxpZGF0aW9uT3B0aW9ucywgZGVmYXVsdFZhbGlkYXRpb25PcHRpb25zKTtcclxuXHJcbiAgICBpZiAoY29uZmlnLnNlcnZpY2VOYW1lKSB7XHJcbiAgICAgIGVtLmRhdGFTZXJ2aWNlID0gbmV3IERhdGFTZXJ2aWNlKHtcclxuICAgICAgICBzZXJ2aWNlTmFtZTogZW0uc2VydmljZU5hbWVcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgICBlbS5zZXJ2aWNlTmFtZSA9IGVtLmRhdGFTZXJ2aWNlICYmIGVtLmRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lO1xyXG5cclxuICAgIGVtLmtleUdlbmVyYXRvckN0b3IgPSBlbS5rZXlHZW5lcmF0b3JDdG9yIHx8IEtleUdlbmVyYXRvcjtcclxuICAgIGlmIChpc0N0b3IgfHwgY29uZmlnLmtleUdlbmVyYXRvckN0b3IpIHtcclxuICAgICAgZW0ua2V5R2VuZXJhdG9yID0gbmV3IGVtLmtleUdlbmVyYXRvckN0b3IoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNyZWF0ZUVudGl0eSh0eXBlTmFtZTogc3RyaW5nLCBpbml0aWFsVmFsdWVzPzogT2JqZWN0LCBlbnRpdHlTdGF0ZT86IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5PzogTWVyZ2VTdHJhdGVneSk6IEVudGl0eTtcclxuICBjcmVhdGVFbnRpdHkoZW50aXR5VHlwZTogRW50aXR5VHlwZSwgaW5pdGlhbFZhbHVlcz86IE9iamVjdCwgZW50aXR5U3RhdGU/OiBFbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneT86IE1lcmdlU3RyYXRlZ3kpOiBFbnRpdHk7XHJcbiAgLyoqXHJcbiAgQ3JlYXRlcyBhIG5ldyBlbnRpdHkgb2YgYSBzcGVjaWZpZWQgdHlwZSBhbmQgb3B0aW9uYWxseSBpbml0aWFsaXplcyBpdC4gQnkgZGVmYXVsdCB0aGUgbmV3IGVudGl0eSBpcyBjcmVhdGVkIHdpdGggYW4gRW50aXR5U3RhdGUgb2YgQWRkZWRcclxuICBidXQgeW91IGNhbiBhbHNvIG9wdGlvbmFsbHkgc3BlY2lmeSBhbiBFbnRpdHlTdGF0ZS4gIEFuIEVudGl0eVN0YXRlIG9mICdEZXRhY2hlZCcgd2lsbCBpbnN1cmUgdGhhdCB0aGUgZW50aXR5IGlzIGNyZWF0ZWQgYnV0IG5vdCB5ZXQgYWRkZWRcclxuICB0byB0aGUgRW50aXR5TWFuYWdlci4gXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICAvLyBjcmVhdGUgYW5kIGFkZCBhbiBlbnRpdHk7XHJcbiAgPiAgICAgIGxldCBlbXAxID0gZW0xLmNyZWF0ZUVudGl0eShcIkVtcGxveWVlXCIpO1xyXG4gID4gICAgICAvLyBjcmVhdGUgYW5kIGFkZCBhbiBpbml0aWFsaXplZCBlbnRpdHk7XHJcbiAgPiAgICAgIGxldCBlbXAyID0gZW0xLmNyZWF0ZUVudGl0eShcIkVtcGxveWVlXCIsIHsgbGFzdE5hbWU6IFwiU21pdGhcIiwgZmlyc3ROYW1lOiBcIkpvaG5cIiB9KTtcclxuICA+ICAgICAgLy8gY3JlYXRlIGFuZCBhdHRhY2ggKG5vdCBhZGQpIGFuIGluaXRpYWxpemVkIGVudGl0eVxyXG4gID4gICAgICBsZXQgZW1wMyA9IGVtMS5jcmVhdGVFbnRpdHkoXCJFbXBsb3llZVwiLCB7IGlkOiA0MzUsIGxhc3ROYW1lOiBcIlNtaXRoXCIsIGZpcnN0TmFtZTogXCJKb2huXCIgfSwgRW50aXR5U3RhdGUuVW5jaGFuZ2VkKTtcclxuICA+ICAgICAgLy8gY3JlYXRlIGJ1dCBkb24ndCBhdHRhY2ggYW4gZW50aXR5O1xyXG4gID4gICAgICBsZXQgZW1wNCA9IGVtMS5jcmVhdGVFbnRpdHkoXCJFbXBsb3llZVwiLCB7IGlkOiA0MzUsIGxhc3ROYW1lOiBcIlNtaXRoXCIsIGZpcnN0TmFtZTogXCJKb2huXCIgfSwgRW50aXR5U3RhdGUuRGV0YWNoZWQpO1xyXG4gIEBwYXJhbSB0eXBlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBFbnRpdHlUeXBlIGZvciB3aGljaCBhbiBpbnN0YW5jZSBzaG91bGQgYmUgY3JlYXRlZC5cclxuICBAcGFyYW0gZW50aXR5VHlwZSAtIFRoZSBFbnRpdHlUeXBlIG9mIHRoZSB0eXBlIGZvciB3aGljaCBhbiBpbnN0YW5jZSBzaG91bGQgYmUgY3JlYXRlZC5cclxuICBAcGFyYW0gaW5pdGlhbFZhbHVlcyAtIChkZWZhdWx0PW51bGwpIENvbmZpZ3VyYXRpb24gb2JqZWN0IG9mIHRoZSBwcm9wZXJ0aWVzIHRvIHNldCBpbW1lZGlhdGVseSBhZnRlciBjcmVhdGlvbi5cclxuICBAcGFyYW0gZW50aXR5U3RhdGUgLSAoZGVmYXVsdCA9IFtbRW50aXR5U3RhdGUuQWRkZWRdXSkgVGhlIEVudGl0eVN0YXRlIG9mIHRoZSBlbnRpdHkgYWZ0ZXIgYmVpbmcgY3JlYXRlZCBhbmQgYWRkZWQgdG8gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gIEBwYXJhbSBtZXJnZVN0cmF0ZWd5IC0gKGRlZmF1bHQgPSBbW01lcmdlU3RyYXRlZ3kuRGlzYWxsb3dlZF1dKSAtIEhvdyB0byBoYW5kbGUgY29uZmxpY3RzIGlmIGFuIGVudGl0eSB3aXRoIHRoZSBzYW1lIGtleSBhbHJlYWR5IGV4aXN0cyB3aXRoaW4gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gIEByZXR1cm4ge0VudGl0eX0gQSBuZXcgRW50aXR5IG9mIHRoZSBzcGVjaWZpZWQgdHlwZS4gXHJcbiAgKi9cclxuICBjcmVhdGVFbnRpdHkoZW50aXR5VHlwZTogRW50aXR5VHlwZSB8IHN0cmluZywgaW5pdGlhbFZhbHVlczogT2JqZWN0LCBlbnRpdHlTdGF0ZTogRW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3k6IE1lcmdlU3RyYXRlZ3kpIHtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eVR5cGUsIFwiZW50aXR5VHlwZVwiKS5pc1N0cmluZygpLm9yKCkuaXNJbnN0YW5jZU9mKEVudGl0eVR5cGUpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHlTdGF0ZSwgXCJlbnRpdHlTdGF0ZVwiKS5pc0VudW1PZihFbnRpdHlTdGF0ZSkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShtZXJnZVN0cmF0ZWd5LCBcIm1lcmdlU3RyYXRlZ3lcIikuaXNFbnVtT2YoTWVyZ2VTdHJhdGVneSkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcblxyXG4gICAgbGV0IGV0ID0gKHR5cGVvZiBlbnRpdHlUeXBlID09PSBcInN0cmluZ1wiKSA/IHRoaXMubWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoZW50aXR5VHlwZSkgYXMgRW50aXR5VHlwZSA6IGVudGl0eVR5cGU7XHJcbiAgICBlbnRpdHlTdGF0ZSA9IGVudGl0eVN0YXRlIHx8IEVudGl0eVN0YXRlLkFkZGVkO1xyXG4gICAgbGV0IGVudGl0eSA9IHt9IGFzIEVudGl0eTtcclxuICAgIGNvcmUudXNpbmcodGhpcywgXCJpc0xvYWRpbmdcIiwgdHJ1ZSwgZnVuY3Rpb24gKCkge1xyXG4gICAgICBlbnRpdHkgPSBldC5jcmVhdGVFbnRpdHkoaW5pdGlhbFZhbHVlcyk7XHJcbiAgICB9KTtcclxuICAgIGlmIChlbnRpdHlTdGF0ZSAhPT0gRW50aXR5U3RhdGUuRGV0YWNoZWQpIHtcclxuICAgICAgZW50aXR5ID0gdGhpcy5hdHRhY2hFbnRpdHkoZW50aXR5LCBlbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZW50aXR5O1xyXG4gIH1cclxuXHJcbiAgc3RhdGljIGltcG9ydEVudGl0aWVzKGV4cG9ydGVkU3RyaW5nOiBzdHJpbmcsIGNvbmZpZz86IEltcG9ydENvbmZpZyk6IEVudGl0eU1hbmFnZXI7XHJcbiAgc3RhdGljIGltcG9ydEVudGl0aWVzKGV4cG9ydGVkRGF0YTogT2JqZWN0LCBjb25maWc/OiBJbXBvcnRDb25maWcpOiBFbnRpdHlNYW5hZ2VyO1xyXG4gIC8qKlxyXG4gIENyZWF0ZXMgYSBuZXcgRW50aXR5TWFuYWdlciBhbmQgaW1wb3J0cyBhIHByZXZpb3VzbHkgZXhwb3J0ZWQgcmVzdWx0IGludG8gaXQuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKCk7XHJcbiAgPiAgICAgIC8vIGNhbiBiZSBzdG9yZWQgdmlhIHRoZSB3ZWIgc3RvcmFnZSBhcGlcclxuICA+ICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKFwibXlFbnRpdHlNYW5hZ2VyXCIsIGJ1bmRsZSk7XHJcbiAgPiAgICAgIC8vIGFzc3VtZSB0aGUgY29kZSBiZWxvdyBvY2N1cnMgaW4gYSBkaWZmZXJlbnQgc2Vzc2lvbi5cclxuICA+ICAgICAgbGV0IGJ1bmRsZUZyb21TdG9yYWdlID0gd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKFwibXlFbnRpdHlNYW5hZ2VyXCIpO1xyXG4gID4gICAgICAvLyBhbmQgaW1wb3J0ZWRcclxuICA+ICAgICAgbGV0IGVtMiA9IEVudGl0eU1hbmFnZXIuaW1wb3J0RW50aXRpZXMoYnVuZGxlRnJvbVN0b3JhZ2UpO1xyXG4gID4gICAgICAvLyBlbTIgd2lsbCBub3cgaGF2ZSBhIGNvbXBsZXRlIGNvcHkgb2Ygd2hhdCB3YXMgaW4gZW0xXHJcbiAgQHBhcmFtIGV4cG9ydGVkU3RyaW5nIC0gVGhlIHJlc3VsdCBvZiBhIHByZXZpb3VzICdleHBvcnRFbnRpdGllcycgY2FsbCBhcyBhIHN0cmluZ1xyXG4gIEBwYXJhbSBleHBvcnRlZERhdGEgLSBUaGUgcmVzdWx0IG9mIGEgcHJldmlvdXMgJ2V4cG9ydEVudGl0aWVzJyBjYWxsIGFzIGFuIE9iamVjdC5cclxuICBAcGFyYW0gY29uZmlnIC0gQSBjb25maWd1cmF0aW9uIG9iamVjdC5cclxuICBAcGFyYW0gY29uZmlnLm1lcmdlU3RyYXRlZ3kgLSBBICBbW01lcmdlU3RyYXRlZ3ldXSB0byB1c2Ugd2hlbiBcclxuICBtZXJnaW5nIGludG8gYW4gZXhpc3RpbmcgRW50aXR5TWFuYWdlci5cclxuICBAcGFyYW0gY29uZmlnLm1ldGFkYXRhVmVyc2lvbkZuIC0gQSBmdW5jdGlvbiB0aGF0IHRha2VzIHR3byBhcmd1bWVudHMgKHRoZSBjdXJyZW50IG1ldGFkYXRhVmVyc2lvbiBhbmQgdGhlIGltcG9ydGVkIHN0b3JlJ3MgJ25hbWUnKVxyXG4gIGFuZCBtYXkgYmUgdXNlZCB0byBwZXJmb3JtIHZlcnNpb24gY2hlY2tpbmcuXHJcbiAgQHJldHVybiBBIG5ldyBFbnRpdHlNYW5hZ2VyLiAgTm90ZSB0aGF0IHRoZSByZXR1cm4gdmFsdWUgb2YgdGhpcyBtZXRob2QgY2FsbCBpcyBkaWZmZXJlbnQgZnJvbSB0aGF0XHJcbiAgcHJvdmlkZWQgYnkgdGhlIHNhbWUgbmFtZWQgbWV0aG9kIG9uIGFuIEVudGl0eU1hbmFnZXIgaW5zdGFuY2UuIFVzZSB0aGF0IG1ldGhvZCBpZiB5b3UgbmVlZCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uXHJcbiAgcmVnYXJkaW5nIHRoZSBpbXBvcnRlZCBlbnRpdGllcy5cclxuICAqKi9cclxuICBzdGF0aWMgaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWQ6IHN0cmluZyB8IE9iamVjdCwgY29uZmlnPzogSW1wb3J0Q29uZmlnKSB7XHJcbiAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcigpO1xyXG4gICAgZW0uaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWQsIGNvbmZpZyk7XHJcbiAgICByZXR1cm4gZW07XHJcbiAgfVxyXG5cclxuICAvLyBpbnN0YW5jZSBtZXRob2RzXHJcblxyXG4gIC8qKlxyXG4gIENhbGxzIFtbRW50aXR5QXNwZWN0LmFjY2VwdENoYW5nZXNdXSBvbiBldmVyeSBjaGFuZ2VkIGVudGl0eSBpbiB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgKiovXHJcbiAgYWNjZXB0Q2hhbmdlcygpIHtcclxuICAgIHRoaXMuZ2V0Q2hhbmdlcygpLm1hcChmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICAgIHJldHVybiBlbnRpdHkuZW50aXR5QXNwZWN0Ll9jaGVja09wZXJhdGlvbihcImFjY2VwdENoYW5nZXNcIik7XHJcbiAgICB9KS5mb3JFYWNoKGZ1bmN0aW9uIChhc3BlY3QpIHtcclxuICAgICAgYXNwZWN0LmFjY2VwdENoYW5nZXMoKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgRXhwb3J0cyBzZWxlY3RlZCBlbnRpdGllcywgYWxsIGVudGl0aWVzIG9mIHNlbGVjdGVkIHR5cGVzLCBvciBhbiBlbnRpcmUgRW50aXR5TWFuYWdlciBjYWNoZS5cclxuXHJcbiAgVGhpcyBtZXRob2QgdGFrZXMgYSBzbmFwc2hvdCBvZiBhbiBFbnRpdHlNYW5hZ2VyIHRoYXQgY2FuIGJlIHN0b3JlZCBvZmZsaW5lIG9yIGhlbGQgaW4gbWVtb3J5LlxyXG4gIFVzZSB0aGUgW1tFbnRpdHlNYW5hZ2VyLmltcG9ydEVudGl0aWVzXV0gbWV0aG9kIHRvIHJlc3RvcmUgb3IgbWVyZ2UgdGhlIHNuYXBzaG90XHJcbiAgaW50byBhbm90aGVyIEVudGl0eU1hbmFnZXIgYXQgc29tZSBsYXRlciB0aW1lLlxyXG4gID4gICAgICAvLyBsZXQgZW0xIGJlIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAvLyBleHBvcnQgZXZlcnkgZW50aXR5IGluIGVtMS5cclxuICA+ICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKCk7XHJcbiAgPiAgICAgLy8gc2F2ZSB0byB0aGUgYnJvd3NlcidzIGxvY2FsIHN0b3JhZ2VcclxuICA+ICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJteUVudGl0eU1hbmFnZXJcIiwgYnVuZGxlKTtcclxuICA+ICAgICAvLyBsYXRlciByZXRyaWV2ZSB0aGUgZXhwb3J0XHJcbiAgPiAgICAgbGV0IGJ1bmRsZUZyb21TdG9yYWdlID0gd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKFwibXlFbnRpdHlNYW5hZ2VyXCIpO1xyXG4gID4gICAgIC8vIGltcG9ydCB0aGUgcmV0cmlldmVkIGV4cG9ydCBidW5kbGUgaW50byBhbm90aGVyIG1hbmFnZXJcclxuICA+ICAgICBsZXQgZW0yID0gZW0xLmNyZWF0ZUVtcHR5Q29weSgpO1xyXG4gID4gICAgIGVtMi5pbXBvcnRFbnRpdGllcyhidW5kbGVGcm9tU3RvcmFnZSk7XHJcbiAgPiAgICAgLy8gZW0yIG5vdyBoYXMgYSBjb21wbGV0ZSwgZmFpdGhmdWwgY29weSBvZiB0aGUgZW50aXRpZXMgdGhhdCB3ZXJlIGluIGVtMVxyXG5cclxuICBZb3UgY2FuIGFsc28gY29udHJvbCBleGFjdGx5IHdoaWNoIGVudGl0aWVzIGFyZSBleHBvcnRlZC5cclxuICA+ICAgICAvLyBnZXQgZW0xJ3MgdW5zYXZlZCBjaGFuZ2VzIChhbiBhcnJheSkgYW5kIGV4cG9ydCB0aGVtLlxyXG4gID4gICAgIGxldCBjaGFuZ2VzID0gZW0xLmdldENoYW5nZXMoKTtcclxuICA+ICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKGNoYW5nZXMpO1xyXG4gID4gICAgIC8vIG1lcmdlIHRoZXNlIGVudGl0aWVzIGludG8gZW0yIHdoaWNoIG1heSBjb250YWlucyBzb21lIG9mIHRoZSBzYW1lIGVudGl0aWVzLlxyXG4gID4gICAgIC8vIGRvIE5PVCBvdmVyd3JpdGUgdGhlIGVudGl0aWVzIGluIGVtMiBpZiB0aGV5IHRoZW1zZWx2ZXMgaGF2ZSB1bnNhdmVkIGNoYW5nZXMuXHJcbiAgPiAgICAgZW0yLmltcG9ydEVudGl0aWVzKGJ1bmRsZSwgeyBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5LlByZXNlcnZlQ2hhbmdlc30gKTtcclxuXHJcbiAgTWV0YWRhdGEgYXJlIGluY2x1ZGVkIGluIGFuIGV4cG9ydCBieSBkZWZhdWx0LiBZb3UgbWF5IHdhbnQgdG8gZXhjbHVkZSB0aGUgbWV0YWRhdGFcclxuICBlc3BlY2lhbGx5IGlmIHlvdSdyZSBleHBvcnRpbmcganVzdCBhIGZldyBlbnRpdGllcyBmb3IgbG9jYWwgc3RvcmFnZS5cclxuICA+ICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKGFycmF5T2ZTZWxlY3RlZEVudGl0aWVzLCB7aW5jbHVkZU1ldGFkYXRhOiBmYWxzZX0pO1xyXG4gID4gICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShcImdvb2RTdHVmZlwiLCBidW5kbGUpO1xyXG5cclxuICBZb3UgbWF5IHN0aWxsIGV4cHJlc3MgdGhpcyBvcHRpb24gYXMgYSBib29sZWFuIHZhbHVlIGFsdGhvdWdoIHRoaXMgb2xkZXIgc3ludGF4IGlzIGRlcHJlY2F0ZWQuXHJcbiAgPiAgICAgLy8gRXhjbHVkZSB0aGUgbWV0YWRhdGEgKGRlcHJlY2F0ZWQgc3ludGF4KVxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoYXJyYXlPZlNlbGVjdGVkRW50aXRpZXMsIGZhbHNlKTtcclxuXHJcbiAgWW91IGNhbiBleHBvcnQgYWxsIGVudGl0aWVzIG9mIG9uZSBvciBtb3JlIHNwZWNpZmllZCBFbnRpdHlUeXBlcy5cclxuICA+ICAgICAvLyBFeHBvcnQgYWxsIEN1c3RvbWVyIGFuZCBFbXBsb3llZSBlbnRpdGllcyAoYW5kIGFsc28gZXhjbHVkZSBtZXRhZGF0YSlcclxuICA+ICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKFsnQ3VzdG9tZXInLCAnRW1wbG95ZWUnXSwge2luY2x1ZGVNZXRhZGF0YTogZmFsc2V9KTtcclxuXHJcbiAgQWxsIG9mIHRoZSBhYm92ZSBleGFtcGxlcyByZXR1cm4gYW4gZXhwb3J0IGJ1bmRsZSBhcyBhIHN0cmluZyB3aGljaCBpcyB0aGUgZGVmYXVsdCBmb3JtYXQuXHJcbiAgWW91IGNhbiBleHBvcnQgdGhlIGJ1bmRsZSBhcyBKU09OIGlmIHlvdSBwcmVmZXIgYnkgc2V0dGluZyB0aGUgYGFzU3RyaW5nYCBvcHRpb24gdG8gZmFsc2UuXHJcbiAgPiAgICAgLy8gRXhwb3J0IGFsbCBDdXN0b21lciBhbmQgRW1wbG95ZWUgZW50aXRpZXMgYXMgSlNPTiBhbmQgZXhjbHVkZSB0aGUgbWV0YWRhdGFcclxuICA+ICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKFsnQ3VzdG9tZXInLCAnRW1wbG95ZWUnXSxcclxuICA+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHthc1N0cmluZzogZmFsc2UsIGluY2x1ZGVNZXRhZGF0YTogZmFsc2V9KTtcclxuICA+ICAgICAvLyBzdG9yZSBKU09OIGJ1bmRsZSBzb21ld2hlcmUgLi4uIHBlcmhhcHMgaW5kZXhEYiAuLi4gYW5kIGxhdGVyIGltcG9ydCBhcyB3ZSBkbyBoZXJlLlxyXG4gID4gICAgIGVtMi5pbXBvcnRFbnRpdGllcyhidW5kbGUpO1xyXG4gIEBwYXJhbSBlbnRpdGllcyAtIFRoZSBlbnRpdGllcyB0byBleHBvcnQgb3IgdGhlIEVudGl0eVR5cGUocykgb2YgdGhlIGVudGl0aWVzIHRvIGV4cG9ydDtcclxuICAgIGFsbCBlbnRpdGllcyBhcmUgZXhwb3J0ZWQgaWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCBvciBudWxsLlxyXG4gIEBwYXJhbSBleHBvcnRDb25maWcgLSBFeHBvcnQgY29uZmlndXJhdGlvbiBvcHRpb25zIG9yIGEgYm9vbGVhblxyXG4gICAgLSBhc1N0cmluZyAtIChib29sZWFuKSAtIElmIHRydWUgKGRlZmF1bHQpLCByZXR1cm4gZXhwb3J0IGJ1bmRsZSBhcyBhIHN0cmluZy5cclxuICAgIC0gaW5jbHVkZU1ldGFkYXRhIC0gKGJvb2xlYW4pIC0gSWYgdHJ1ZSAoZGVmYXVsdCksIGluY2x1ZGUgbWV0YWRhdGEgaW4gdGhlIGV4cG9ydCBidW5kbGUuXHJcbiAgQHJldHVybiBUaGUgZXhwb3J0IGJ1bmRsZSBlaXRoZXIgc2VyaWFsaXplZCBhcyBhIHN0cmluZyAoZGVmYXVsdCkgb3IgYXMgYSBKU09OIG9iamVjdC5cclxuICBUaGUgYnVuZGxlIGNvbnRhaW5zIHRoZSBtZXRhZGF0YSAodW5sZXNzIGV4Y2x1ZGVkKSBhbmQgdGhlIGVudGl0eSBkYXRhIGdyb3VwZWQgYnkgdHlwZS5cclxuICBUaGUgZW50aXR5IGRhdGEgaW5jbHVkZSBwcm9wZXJ0eSB2YWx1ZXMsIGNoYW5nZS1zdGF0ZSwgYW5kIHRlbXBvcmFyeSBrZXkgbWFwcGluZ3MgKGlmIGFueSkuXHJcblxyXG4gIFRoZSBleHBvcnQgYnVuZGxlIGludGVybmFscyBhcmUgZGVsaWJlcmF0ZWx5IHVuZG9jdW1lbnRlZC4gIFRoaXMgQnJlZXplLWludGVybmFsIHJlcHJlc2VudGF0aW9uIG9mIGVudGl0eSBkYXRhIGlzXHJcbiAgc3VpdGFibGUgZm9yIGV4cG9ydCwgc3RvcmFnZSwgYW5kIGltcG9ydC4gVGhlIHNjaGVtYSBhbmQgY29udGVudHMgb2YgdGhlIGJ1bmRsZSBtYXkgY2hhbmdlIGluIGZ1dHVyZSB2ZXJzaW9ucyBvZiBCcmVlemUuXHJcbiAgTWFuaXB1bGF0ZSBpdCBhdCB5b3VyIG93biByaXNrIHdpdGggYXBwcm9wcmlhdGUgY2F1dGlvbi5cclxuICAqKi9cclxuICBleHBvcnRFbnRpdGllcyhlbnRpdGllcz86IEVudGl0eVtdIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nW10sIGV4cG9ydENvbmZpZz86IHsgYXNTdHJpbmc/OiBib29sZWFuLCBpbmNsdWRlTWV0YWRhdGE/OiBib29sZWFuIH0gfCBib29sZWFuKTogc3RyaW5nIHwgT2JqZWN0IHtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0aWVzLCBcImVudGl0aWVzXCIpLmlzQXJyYXkoKS5pc0VudGl0eSgpXHJcbiAgICAgIC5vcigpLmlzTm9uRW1wdHlBcnJheSgpLmlzSW5zdGFuY2VPZihFbnRpdHlUeXBlKVxyXG4gICAgICAub3IoKS5pc05vbkVtcHR5QXJyYXkoKS5pc1N0cmluZygpXHJcbiAgICAgIC5vcigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG5cclxuICAgIC8vIGFzc2VydFBhcmFtKGV4cG9ydENvbmZpZywgXCJleHBvcnRDb25maWdcIikuaXNPYmplY3QoKVxyXG4gICAgLy8gICAub3IoKS5pc0Jvb2xlYW4oKVxyXG4gICAgLy8gICAub3IoKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuXHJcbiAgICBpZiAoZXhwb3J0Q29uZmlnID09IG51bGwpIHtcclxuICAgICAgZXhwb3J0Q29uZmlnID0geyBpbmNsdWRlTWV0YWRhdGE6IHRydWUsIGFzU3RyaW5nOiB0cnVlIH07XHJcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBvcnRDb25maWcgPT09ICdib29sZWFuJykgeyAvLyBkZXByZWNhdGVkXHJcbiAgICAgIGV4cG9ydENvbmZpZyA9IHsgaW5jbHVkZU1ldGFkYXRhOiBleHBvcnRDb25maWcsIGFzU3RyaW5nOiB0cnVlIH07XHJcbiAgICB9XHJcblxyXG4gICAgYXNzZXJ0Q29uZmlnKGV4cG9ydENvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJhc1N0cmluZ1wiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQodHJ1ZSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJpbmNsdWRlTWV0YWRhdGFcIikuaXNCb29sZWFuKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KHRydWUpXHJcbiAgICAgIC5hcHBseUFsbChleHBvcnRDb25maWcpO1xyXG5cclxuICAgIGxldCBleHBvcnRCdW5kbGUgPSBleHBvcnRFbnRpdHlHcm91cHModGhpcywgZW50aXRpZXMpO1xyXG4gICAgbGV0IGpzb24gPSBjb3JlLmV4dGVuZCh7fSwgZXhwb3J0QnVuZGxlLCBbXCJ0ZW1wS2V5c1wiLCBcImVudGl0eUdyb3VwTWFwXCJdKTtcclxuXHJcbiAgICBpZiAoZXhwb3J0Q29uZmlnLmluY2x1ZGVNZXRhZGF0YSkge1xyXG4gICAgICBqc29uID0gY29yZS5leHRlbmQoanNvbiwgdGhpcywgW1wiZGF0YVNlcnZpY2VcIiwgXCJzYXZlT3B0aW9uc1wiLCBcInF1ZXJ5T3B0aW9uc1wiLCBcInZhbGlkYXRpb25PcHRpb25zXCJdKTtcclxuICAgICAgKGpzb24gYXMgYW55KS5tZXRhZGF0YVN0b3JlID0gdGhpcy5tZXRhZGF0YVN0b3JlLmV4cG9ydE1ldGFkYXRhKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAoanNvbiBhcyBhbnkpLm1ldGFkYXRhVmVyc2lvbiA9IE1ldGFkYXRhU3RvcmUubWV0YWRhdGFWZXJzaW9uO1xyXG4gICAgICAoanNvbiBhcyBhbnkpLm1ldGFkYXRhU3RvcmVOYW1lID0gdGhpcy5tZXRhZGF0YVN0b3JlLm5hbWU7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHJlc3VsdCA9IGV4cG9ydENvbmZpZy5hc1N0cmluZyA/IEpTT04uc3RyaW5naWZ5KGpzb24sIG51bGwsIGNvbmZpZy5zdHJpbmdpZnlQYWQpIDoganNvbjtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvLyBUT0RPOiB0eXBlIHRoZSByZXR1cm4gdmFsdWUgeyBlbnRpdGllczogZW50aXRpZXNUb0xpbmssIHRlbXBLZXlNYXBwaW5nOiB0ZW1wS2V5TWFwIH1cclxuICBpbXBvcnRFbnRpdGllcyhleHBvcnRlZFN0cmluZzogc3RyaW5nLCBjb25maWc/OiBJbXBvcnRDb25maWcpOiBJbXBvcnRSZXN1bHQ7XHJcbiAgaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWREYXRhOiBPYmplY3QsIGNvbmZpZz86IEltcG9ydENvbmZpZyk6IEltcG9ydFJlc3VsdDtcclxuICAvKipcclxuICBJbXBvcnRzIGEgcHJldmlvdXNseSBleHBvcnRlZCByZXN1bHQgaW50byB0aGlzIEVudGl0eU1hbmFnZXIuXHJcblxyXG4gIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIG1ha2UgYSBjb21wbGV0ZSBjb3B5IG9mIGFueSBwcmV2aW91c2x5IGNyZWF0ZWQgZW50aXR5TWFuYWdlciwgZXZlbiBpZiBjcmVhdGVkXHJcbiAgaW4gYSBwcmV2aW91cyBzZXNzaW9uIGFuZCBzdG9yZWQgaW4gbG9jYWxTdG9yYWdlLiBUaGUgc3RhdGljIHZlcnNpb24gb2YgdGhpcyBtZXRob2QgcGVyZm9ybXMgYVxyXG4gIHZlcnkgc2ltaWxhciBwcm9jZXNzLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoKTtcclxuICA+ICAgICAvLyBidW5kbGUgY2FuIGJlIHN0b3JlZCBpbiB3aW5kb3cubG9jYWxTdG9yYWdlIG9yIGp1c3QgaGVsZCBpbiBtZW1vcnkuXHJcbiAgPiAgICAgbGV0IGVtMiA9IG5ldyBFbnRpdHlNYW5hZ2VyKHtcclxuICA+ICAgICAgICAgc2VydmljZU5hbWU6IGVtMS5zZXJ2aWNlTmFtZSxcclxuICA+ICAgICAgICAgbWV0YWRhdGFTdG9yZTogZW0xLm1ldGFkYXRhU3RvcmVcclxuICA+ICAgICB9KTtcclxuICA+ICAgICBlbTIuaW1wb3J0RW50aXRpZXMoYnVuZGxlKTtcclxuICA+ICAgICAvLyBlbTIgd2lsbCBub3cgaGF2ZSBhIGNvbXBsZXRlIGNvcHkgb2Ygd2hhdCB3YXMgaW4gZW0xXHJcblxyXG4gIEl0IGNhbiBhbHNvIGJlIHVzZWQgdG8gbWVyZ2UgdGhlIGNvbnRlbnRzIG9mIGEgcHJldmlvdXNseSBjcmVhdGVkIEVudGl0eU1hbmFnZXIgd2l0aCBhblxyXG4gIGV4aXN0aW5nIEVudGl0eU1hbmFnZXIgd2l0aCBjb250cm9sIG92ZXIgaG93IHRoZSB0d28gYXJlIG1lcmdlZC5cclxuICA+ICAgICBsZXQgYnVuZGxlID0gZW0xLmV4cG9ydEVudGl0aWVzKCk7XHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMiBpcyBhbm90aGVyIGVudGl0eU1hbmFnZXIgY29udGFpbmluZyBzb21lIG9mIHRoZSBzYW1lIGVudGl0aWVzIHBvc3NpYmx5IHdpdGggbW9kaWZpY2F0aW9ucy5cclxuICA+ICAgICBlbTIuaW1wb3J0RW50aXRpZXMoYnVuZGxlLCB7IG1lcmdlU3RyYXRlZ3k6IE1lcmdlU3RyYXRlZ3kuUHJlc2VydmVDaGFuZ2VzfSApO1xyXG4gID4gICAgIC8vIGVtMiB3aWxsIG5vdyBjb250YWluIGFsbCBvZiB0aGUgZW50aXRpZXMgZnJvbSBib3RoIGVtMSBhbmQgZW0yLiAgQW55IGVtMiBlbnRpdGllcyB3aXRoIHByZXZpb3VzbHlcclxuICA+ICAgICAvLyBtYWRlIG1vZGlmaWNhdGlvbnMgd2lsbCBub3QgaGF2ZSBiZWVuIHRvdWNoZWQsIGJ1dCBhbGwgb3RoZXIgZW50aXRpZXMgZnJvbSBlbTEgd2lsbCBoYXZlIGJlZW4gaW1wb3J0ZWQuXHJcbiAgQHBhcmFtIGV4cG9ydGVkU3RyaW5nIC0gVGhlIHJlc3VsdCBvZiBhIHByZXZpb3VzICdleHBvcnQnIGNhbGwuXHJcbiAgQHBhcmFtIGltcG9ydENvbmZpZyAtIEEgY29uZmlndXJhdGlvbiBvYmplY3QuXHJcbiAgQHBhcmFtIGltcG9ydENvbmZpZy5tZXJnZVN0cmF0ZWd5IC0gIEEgW1tNZXJnZVN0cmF0ZWd5XV0gdG8gdXNlIHdoZW5cclxuICBtZXJnaW5nIGludG8gYW4gZXhpc3RpbmcgRW50aXR5TWFuYWdlci5cclxuICBAcGFyYW0gaW1wb3J0Q29uZmlnLm1ldGFkYXRhVmVyc2lvbkZuIC0gQSBmdW5jdGlvbiB0aGF0IHRha2VzIHR3byBhcmd1bWVudHMgKHRoZSBjdXJyZW50IG1ldGFkYXRhVmVyc2lvbiBhbmQgdGhlIGltcG9ydGVkIHN0b3JlJ3MgJ25hbWUnKVxyXG4gIGFuZCBtYXkgYmUgdXNlZCB0byBwZXJmb3JtIHZlcnNpb24gY2hlY2tpbmcuXHJcbiAgQHJldHVybiByZXN1bHQgXHJcbiAgICAtIHJlc3VsdC5lbnRpdGllcyB7QXJyYXkgb2YgRW50aXRpZXN9IFRoZSBlbnRpdGllcyB0aGF0IHdlcmUgaW1wb3J0ZWQuXHJcbiAgICAtIHJlc3VsdC50ZW1wS2V5TWFwIHtPYmplY3R9IE1hcHBpbmcgZnJvbSBvcmlnaW5hbCBFbnRpdHlLZXkgaW4gdGhlIGltcG9ydCBidW5kbGUgdG8gaXRzIGNvcnJlc3BvbmRpbmcgRW50aXR5S2V5IGluIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICAqKi9cclxuICBpbXBvcnRFbnRpdGllcyhleHBvcnRlZDogc3RyaW5nIHwgT2JqZWN0LCBpbXBvcnRDb25maWc/OiBJbXBvcnRDb25maWcpIHtcclxuICAgIGltcG9ydENvbmZpZyA9IGltcG9ydENvbmZpZyB8fCB7fTtcclxuICAgIGFzc2VydENvbmZpZyhpbXBvcnRDb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwibWVyZ2VTdHJhdGVneVwiKS5pc0VudW1PZihNZXJnZVN0cmF0ZWd5KS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQodGhpcy5xdWVyeU9wdGlvbnMubWVyZ2VTdHJhdGVneSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJtZXRhZGF0YVZlcnNpb25GblwiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwibWVyZ2VBZGRzXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAuYXBwbHlBbGwoaW1wb3J0Q29uZmlnKTtcclxuXHJcbiAgICBsZXQganNvbiA9ICh0eXBlb2YgZXhwb3J0ZWQgPT09IFwic3RyaW5nXCIpID8gSlNPTi5wYXJzZShleHBvcnRlZCkgOiBleHBvcnRlZDtcclxuICAgIGlmIChqc29uLm1ldGFkYXRhU3RvcmUpIHtcclxuICAgICAgdGhpcy5tZXRhZGF0YVN0b3JlLmltcG9ydE1ldGFkYXRhKGpzb24ubWV0YWRhdGFTdG9yZSk7XHJcbiAgICAgIC8vIHRoZSB8fCBjbGF1c2UgaXMgZm9yIGJhY2t3YXJkcyBjb21wYXQgd2l0aCBhbiBlYXJsaWVyIHNlcmlhbGl6YXRpb24gZm9ybWF0LlxyXG4gICAgICB0aGlzLmRhdGFTZXJ2aWNlID0gKGpzb24uZGF0YVNlcnZpY2UgJiYgRGF0YVNlcnZpY2UuZnJvbUpTT04oanNvbi5kYXRhU2VydmljZSkpIHx8IG5ldyBEYXRhU2VydmljZSh7IHNlcnZpY2VOYW1lOiBqc29uLnNlcnZpY2VOYW1lIH0pO1xyXG5cclxuICAgICAgdGhpcy5zYXZlT3B0aW9ucyA9IG5ldyBTYXZlT3B0aW9ucyhqc29uLnNhdmVPcHRpb25zKTtcclxuICAgICAgdGhpcy5xdWVyeU9wdGlvbnMgPSBRdWVyeU9wdGlvbnMuZnJvbUpTT04oanNvbi5xdWVyeU9wdGlvbnMpO1xyXG4gICAgICB0aGlzLnZhbGlkYXRpb25PcHRpb25zID0gbmV3IFZhbGlkYXRpb25PcHRpb25zKGpzb24udmFsaWRhdGlvbk9wdGlvbnMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaW1wb3J0Q29uZmlnLm1ldGFkYXRhVmVyc2lvbkZuICYmIGltcG9ydENvbmZpZy5tZXRhZGF0YVZlcnNpb25Gbih7XHJcbiAgICAgICAgbWV0YWRhdGFWZXJzaW9uOiBqc29uLm1ldGFkYXRhVmVyc2lvbixcclxuICAgICAgICBtZXRhZGF0YVN0b3JlTmFtZToganNvbi5tZXRhZGF0YVN0b3JlTmFtZVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgdGVtcEtleU1hcDogSVRlbXBLZXlNYXAgPSB7fTtcclxuICAgIGpzb24udGVtcEtleXMuZm9yRWFjaCgoazogYW55KSA9PiB7XHJcbiAgICAgIGxldCBvbGRLZXkgPSBFbnRpdHlLZXkuZnJvbUpTT04oaywgdGhpcy5tZXRhZGF0YVN0b3JlKTtcclxuICAgICAgLy8gdHJ5IHRvIHVzZSBvbGRLZXkgaWYgbm90IGFscmVhZHkgdXNlZCBpbiB0aGlzIGtleUdlbmVyYXRvci5cclxuICAgICAgdGVtcEtleU1hcFtvbGRLZXkudG9TdHJpbmcoKV0gPSBuZXcgRW50aXR5S2V5KG9sZEtleS5lbnRpdHlUeXBlLCB0aGlzLmtleUdlbmVyYXRvci5nZW5lcmF0ZVRlbXBLZXlWYWx1ZShvbGRLZXkuZW50aXR5VHlwZSwgb2xkS2V5LnZhbHVlc1swXSkpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgbGV0IGVudGl0aWVzVG9MaW5rOiBFbnRpdHlbXSA9IFtdO1xyXG4gICAgbGV0IGltcENvbmZpZyA9IGltcG9ydENvbmZpZyBhcyBJbXBvcnRDb25maWdFeHQ7XHJcblxyXG4gICAgaW1wQ29uZmlnLnRlbXBLZXlNYXAgPSB0ZW1wS2V5TWFwO1xyXG4gICAgY29yZS53cmFwRXhlY3V0aW9uKCgpID0+IHtcclxuICAgICAgdGhpcy5fcGVuZGluZ1B1YnMgPSBbXTtcclxuICAgIH0sIChzdGF0ZSkgPT4ge1xyXG4gICAgICB0aGlzLl9wZW5kaW5nUHVicyEuZm9yRWFjaCgoZm4pID0+IGZuKCkpO1xyXG4gICAgICB0aGlzLl9wZW5kaW5nUHVicyA9IHVuZGVmaW5lZDtcclxuICAgICAgdGhpcy5faGFzQ2hhbmdlc0FjdGlvbiAmJiB0aGlzLl9oYXNDaGFuZ2VzQWN0aW9uKCk7XHJcbiAgICB9LCAoKSA9PiB7XHJcbiAgICAgIGNvcmUub2JqZWN0Rm9yRWFjaChqc29uLmVudGl0eUdyb3VwTWFwLCAoZW50aXR5VHlwZU5hbWUsIGpzb25Hcm91cCkgPT4ge1xyXG4gICAgICAgIGxldCBlbnRpdHlUeXBlID0gdGhpcy5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShlbnRpdHlUeXBlTmFtZSwgZmFsc2UpIGFzIEVudGl0eVR5cGU7XHJcbiAgICAgICAgbGV0IHRhcmdldEVudGl0eUdyb3VwID0gZmluZE9yQ3JlYXRlRW50aXR5R3JvdXAodGhpcywgZW50aXR5VHlwZSk7XHJcbiAgICAgICAgbGV0IGVudGl0aWVzID0gaW1wb3J0RW50aXR5R3JvdXAodGFyZ2V0RW50aXR5R3JvdXAsIGpzb25Hcm91cCwgaW1wQ29uZmlnKTtcclxuICAgICAgICBpZiAoZW50aXRpZXMgJiYgZW50aXRpZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICBlbnRpdGllc1RvTGluayA9IGVudGl0aWVzVG9MaW5rLmNvbmNhdChlbnRpdGllcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgICAgZW50aXRpZXNUb0xpbmsuZm9yRWFjaCgoZW50aXR5KSA9PiB7XHJcbiAgICAgICAgaWYgKCFlbnRpdHkuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlLmlzRGVsZXRlZCgpKSB7XHJcbiAgICAgICAgICB0aGlzLl9saW5rUmVsYXRlZEVudGl0aWVzKGVudGl0eSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZW50aXRpZXM6IGVudGl0aWVzVG9MaW5rLFxyXG4gICAgICB0ZW1wS2V5TWFwcGluZzogdGVtcEtleU1hcFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIENsZWFycyB0aGlzIEVudGl0eU1hbmFnZXIncyBjYWNoZSBidXQga2VlcHMgYWxsIG90aGVyIHNldHRpbmdzLiBOb3RlIHRoYXQgdGhpc1xyXG4gIG1ldGhvZCBpcyBub3QgYXMgZmFzdCBhcyBjcmVhdGluZyBhIG5ldyBFbnRpdHlNYW5hZ2VyIHZpYSAnbmV3IEVudGl0eU1hbmFnZXInLlxyXG4gIFRoaXMgaXMgYmVjYXVzZSBjbGVhciBhY3R1YWxseSBkZXRhY2hlcyBhbGwgb2YgdGhlIGVudGl0aWVzIGZyb20gdGhlIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgZW0xLmNsZWFyKCk7XHJcbiAgPiAgICAgLy8gZW0xIGlzIHdpbGwgbm93IGNvbnRhaW4gbm8gZW50aXRpZXMsIGJ1dCBhbGwgb3RoZXIgc2V0dGluZyB3aWxsIGJlIG1haW50YWluZWQuXHJcbiAgKiovXHJcbiAgY2xlYXIoKSB7XHJcbiAgICBjb3JlLm9iamVjdE1hcCh0aGlzLl9lbnRpdHlHcm91cE1hcCwgZnVuY3Rpb24gKGtleTogc3RyaW5nLCBlbnRpdHlHcm91cDogRW50aXR5R3JvdXApIHtcclxuICAgICAgcmV0dXJuIGVudGl0eUdyb3VwLl9jaGVja09wZXJhdGlvbignY2xlYXInKTtcclxuICAgIH0pLmZvckVhY2goKGVudGl0eUdyb3VwOiBFbnRpdHlHcm91cCkgPT4ge1xyXG4gICAgICBlbnRpdHlHcm91cC5fY2xlYXIoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuX2VudGl0eUdyb3VwTWFwID0ge307XHJcbiAgICB0aGlzLl91bmF0dGFjaGVkQ2hpbGRyZW5NYXAgPSBuZXcgVW5hdHRhY2hlZENoaWxkcmVuTWFwKCk7XHJcbiAgICB0aGlzLmtleUdlbmVyYXRvciA9IG5ldyB0aGlzLmtleUdlbmVyYXRvckN0b3IoKTtcclxuICAgIHRoaXMuZW50aXR5Q2hhbmdlZC5wdWJsaXNoKHsgZW50aXR5QWN0aW9uOiBFbnRpdHlBY3Rpb24uQ2xlYXIgfSk7XHJcbiAgICB0aGlzLl9zZXRIYXNDaGFuZ2VzKGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIENyZWF0ZXMgYW4gZW1wdHkgY29weSBvZiB0aGlzIEVudGl0eU1hbmFnZXIgYnV0IHdpdGggdGhlIHNhbWUgRGF0YVNlcnZpY2UsIE1ldGFkYXRhU3RvcmUsIFF1ZXJ5T3B0aW9ucywgU2F2ZU9wdGlvbnMsIFZhbGlkYXRpb25PcHRpb25zLCBldGMuIFxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBlbTIgPSBlbTEuY3JlYXRlRW1wdHlDb3B5KCk7XHJcbiAgPiAgICAgLy8gZW0yIGlzIGEgbmV3IEVudGl0eU1hbmFnZXIgd2l0aCBhbGwgb2YgZW0xJ3Mgc2V0dGluZ3NcclxuICA+ICAgICAvLyBidXQgbm8gZW50aXRpZXMuXHJcbiAgQHJldHVybiBBIG5ldyBFbnRpdHlNYW5hZ2VyLlxyXG4gICoqL1xyXG4gIGNyZWF0ZUVtcHR5Q29weSgpIHtcclxuICAgIGxldCBjb3B5ID0gbmV3IEVudGl0eU1hbmFnZXIoY29yZS5leHRlbmQoe30sIHRoaXMsXHJcbiAgICAgIFtcImRhdGFTZXJ2aWNlXCIsIFwibWV0YWRhdGFTdG9yZVwiLCBcInF1ZXJ5T3B0aW9uc1wiLCBcInNhdmVPcHRpb25zXCIsIFwidmFsaWRhdGlvbk9wdGlvbnNcIiwgXCJrZXlHZW5lcmF0b3JDdG9yXCJdKSk7XHJcbiAgICByZXR1cm4gY29weTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEF0dGFjaGVzIGFuIGVudGl0eSB0byB0aGlzIEVudGl0eU1hbmFnZXIgd2l0aCBhbiAgW1tFbnRpdHlTdGF0ZV1dIG9mICdBZGRlZCcuXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgIGxldCBjdXN0MSA9IGN1c3RUeXBlLmNyZWF0ZUVudGl0eSgpO1xyXG4gID4gICAgIGVtMS5hZGRFbnRpdHkoY3VzdDEpO1xyXG5cclxuICBOb3RlIHRoYXQgdGhpcyBpcyB0aGUgc2FtZSBhcyB1c2luZyAnYXR0YWNoRW50aXR5JyB3aXRoIGFuIFtbRW50aXR5U3RhdGVdXSBvZiAnQWRkZWQnLlxyXG5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgbGV0IGN1c3QxID0gY3VzdFR5cGUuY3JlYXRlRW50aXR5KCk7XHJcbiAgPiAgICAgZW0xLmF0dGFjaEVudGl0eShjdXN0MSwgRW50aXR5U3RhdGUuQWRkZWQpO1xyXG4gIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIGFkZC5cclxuICBAcmV0dXJuIFRoZSBhZGRlZCBlbnRpdHkuXHJcbiAgKiovXHJcbiAgYWRkRW50aXR5KGVudGl0eTogRW50aXR5KSB7XHJcbiAgICByZXR1cm4gdGhpcy5hdHRhY2hFbnRpdHkoZW50aXR5LCBFbnRpdHlTdGF0ZS5BZGRlZCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBBdHRhY2hlcyBhbiBlbnRpdHkgdG8gdGhpcyBFbnRpdHlNYW5hZ2VyIHdpdGggYSBzcGVjaWZpZWQgW1tFbnRpdHlTdGF0ZV1dLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICBsZXQgY3VzdDEgPSBjdXN0VHlwZS5jcmVhdGVFbnRpdHkoKTtcclxuICA+ICAgICBlbTEuYXR0YWNoRW50aXR5KGN1c3QxLCBFbnRpdHlTdGF0ZS5BZGRlZCk7XHJcbiAgQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gYWRkLlxyXG4gIEBwYXJhbSBlbnRpdHlTdGF0ZSAtIChkZWZhdWx0PUVudGl0eVN0YXRlLlVuY2hhbmdlZCkgVGhlIEVudGl0eVN0YXRlIG9mIHRoZSBuZXdseSBhdHRhY2hlZCBlbnRpdHkuIElmIG9taXR0ZWQgdGhpcyBkZWZhdWx0cyB0byBFbnRpdHlTdGF0ZS5VbmNoYW5nZWQuXHJcbiAgQHBhcmFtIG1lcmdlU3RyYXRlZ3kgLSAoZGVmYXVsdCA9IE1lcmdlU3RyYXRlZ3kuRGlzYWxsb3dlZCkgSG93IHRoZSBzcGVjaWZpZWQgZW50aXR5IHNob3VsZCBiZSBtZXJnZWQgaW50byB0aGUgRW50aXR5TWFuYWdlciBpZiB0aGlzIEVudGl0eU1hbmFnZXIgYWxyZWFkeSBjb250YWlucyBhbiBlbnRpdHkgd2l0aCB0aGUgc2FtZSBrZXkuXHJcbiAgQHJldHVybiBUaGUgYXR0YWNoZWQgZW50aXR5LlxyXG4gICoqL1xyXG4gIGF0dGFjaEVudGl0eShlbnRpdHk6IEVudGl0eSwgZW50aXR5U3RhdGU/OiBFbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneT86IE1lcmdlU3RyYXRlZ3kpIHtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eSwgXCJlbnRpdHlcIikuaXNSZXF1aXJlZCgpLmNoZWNrKCk7XHJcbiAgICB0aGlzLm1ldGFkYXRhU3RvcmUuX2NoZWNrRW50aXR5VHlwZShlbnRpdHkpO1xyXG4gICAgbGV0IGVzU3ltYm9sID0gYXNzZXJ0UGFyYW0oZW50aXR5U3RhdGUsIFwiZW50aXR5U3RhdGVcIikuaXNFbnVtT2YoRW50aXR5U3RhdGUpLmlzT3B0aW9uYWwoKS5jaGVjayhFbnRpdHlTdGF0ZS5VbmNoYW5nZWQpIGFzIEVudGl0eVN0YXRlO1xyXG4gICAgbGV0IG1zU3ltYm9sID0gYXNzZXJ0UGFyYW0obWVyZ2VTdHJhdGVneSwgXCJtZXJnZVN0cmF0ZWd5XCIpLmlzRW51bU9mKE1lcmdlU3RyYXRlZ3kpLmlzT3B0aW9uYWwoKS5jaGVjayhNZXJnZVN0cmF0ZWd5LkRpc2FsbG93ZWQpIGFzIE1lcmdlU3RyYXRlZ3k7XHJcblxyXG4gICAgaWYgKGVudGl0eS5lbnRpdHlUeXBlLm1ldGFkYXRhU3RvcmUgIT09IHRoaXMubWV0YWRhdGFTdG9yZSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgYXR0YWNoIHRoaXMgZW50aXR5IGJlY2F1c2UgdGhlIEVudGl0eVR5cGUgKFwiICsgZW50aXR5LmVudGl0eVR5cGUubmFtZSArXHJcbiAgICAgICAgXCIpIGFuZCBNZXRhZGF0YVN0b3JlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGVudGl0eSBkb2VzIG5vdCBtYXRjaCB0aGlzIEVudGl0eU1hbmFnZXIncyBNZXRhZGF0YVN0b3JlLlwiKTtcclxuICAgIH1cclxuICAgIGxldCBhc3BlY3QgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgaWYgKGFzcGVjdCkge1xyXG4gICAgICAvLyB0byBhdm9pZCByZWF0dGFjaGluZyBhbiBlbnRpdHkgaW4gcHJvZ3Jlc3NcclxuICAgICAgaWYgKGFzcGVjdC5faW5Qcm9jZXNzRW50aXR5KSByZXR1cm4gYXNwZWN0Ll9pblByb2Nlc3NFbnRpdHk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyB0aGlzIG9jY3VyJ3Mgd2hlbiBhdHRhY2hpbmcgYW4gZW50aXR5IGNyZWF0ZWQgdmlhIG5ldyBpbnN0ZWFkIG9mIHZpYSBjcmVhdGVFbnRpdHkuXHJcbiAgICAgIGFzcGVjdCA9IG5ldyBFbnRpdHlBc3BlY3QoZW50aXR5KTtcclxuICAgIH1cclxuICAgIGxldCBtYW5hZ2VyID0gYXNwZWN0LmVudGl0eU1hbmFnZXI7XHJcbiAgICBpZiAobWFuYWdlcikge1xyXG4gICAgICBpZiAobWFuYWdlciA9PT0gdGhpcykge1xyXG4gICAgICAgIHJldHVybiBlbnRpdHk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBlbnRpdHkgYWxyZWFkeSBiZWxvbmdzIHRvIGFub3RoZXIgRW50aXR5TWFuYWdlclwiKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBhdHRhY2hlZEVudGl0eSA9IHt9IGFzIEVudGl0eTtcclxuICAgIGNvcmUudXNpbmcodGhpcywgXCJpc0xvYWRpbmdcIiwgdHJ1ZSwgKCkgPT4ge1xyXG4gICAgICBpZiAoZXNTeW1ib2wuaXNBZGRlZCgpKSB7XHJcbiAgICAgICAgY2hlY2tFbnRpdHlLZXkodGhpcywgZW50aXR5KTtcclxuICAgICAgfVxyXG4gICAgICAvLyBhdHRhY2hlZEVudGl0eSA9PT0gZW50aXR5IEVYQ0VQVCBpbiB0aGUgY2FzZSBvZiBhIG1lcmdlLlxyXG4gICAgICBhdHRhY2hlZEVudGl0eSA9IHRoaXMuX2F0dGFjaEVudGl0eUNvcmUoZW50aXR5LCBlc1N5bWJvbCwgbXNTeW1ib2wpO1xyXG4gICAgICBhc3BlY3QuX2luUHJvY2Vzc0VudGl0eSA9IGF0dGFjaGVkRW50aXR5O1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIC8vIGVudGl0eSAoIG5vdCBhdHRhY2hlZEVudGl0eSkgaXMgZGVsaWJlcmF0ZSBoZXJlLlxyXG4gICAgICAgIGF0dGFjaFJlbGF0ZWRFbnRpdGllcyh0aGlzLCBlbnRpdHksIGVzU3ltYm9sLCBtc1N5bWJvbCk7XHJcbiAgICAgIH0gZmluYWxseSB7XHJcbiAgICAgICAgLy8gaW5zdXJlIHRoYXQgX2luUHJvY2Vzc0VudGl0eSBpcyBjbGVhcmVkLlxyXG4gICAgICAgIGFzcGVjdC5faW5Qcm9jZXNzRW50aXR5ID0gdW5kZWZpbmVkO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIGlmICh0aGlzLnZhbGlkYXRpb25PcHRpb25zLnZhbGlkYXRlT25BdHRhY2gpIHtcclxuICAgICAgYXR0YWNoZWRFbnRpdHkuZW50aXR5QXNwZWN0LnZhbGlkYXRlRW50aXR5KCk7XHJcbiAgICB9XHJcbiAgICBpZiAoIWVzU3ltYm9sLmlzVW5jaGFuZ2VkKCkpIHtcclxuICAgICAgdGhpcy5fbm90aWZ5U3RhdGVDaGFuZ2UoYXR0YWNoZWRFbnRpdHksIHRydWUpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5lbnRpdHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5BdHRhY2gsIGVudGl0eTogYXR0YWNoZWRFbnRpdHkgfSk7XHJcblxyXG4gICAgcmV0dXJuIGF0dGFjaGVkRW50aXR5O1xyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gIERldGFjaGVzIGFuIGVudGl0eSBmcm9tIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAvLyBhc3N1bWUgY3VzdDEgaXMgYSBjdXN0b21lciBFbnRpdHkgcHJldmlvdXNseSBhdHRhY2hlZCB0byBlbTFcclxuICA+ICAgICBlbTEuZGV0YWNoRW50aXR5KGN1c3QxKTtcclxuICA+ICAgICAvLyBlbTEgd2lsbCBub3cgbm8gbG9uZ2VyIGNvbnRhaW4gY3VzdDEgYW5kIGN1c3QxIHdpbGwgaGF2ZSBhblxyXG4gID4gICAgIC8vIGVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZSBvZiBFbnRpdHlTdGF0ZS5EZXRhY2hlZFxyXG4gIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIGRldGFjaC5cclxuICBAcmV0dXJuIFdoZXRoZXIgdGhlIGVudGl0eSBjb3VsZCBiZSBkZXRhY2hlZC4gVGhpcyB3aWxsIHJldHVybiBmYWxzZSBpZiB0aGUgZW50aXR5IGlzIGFscmVhZHkgZGV0YWNoZWQgb3Igd2FzIG5ldmVyIGF0dGFjaGVkLlxyXG4gICoqL1xyXG4gIGRldGFjaEVudGl0eShlbnRpdHk6IEVudGl0eSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5LCBcImVudGl0eVwiKS5pc0VudGl0eSgpLmNoZWNrKCk7XHJcbiAgICBsZXQgYXNwZWN0ID0gZW50aXR5LmVudGl0eUFzcGVjdDtcclxuICAgIGlmICghYXNwZWN0KSB7XHJcbiAgICAgIC8vIG5vIGFzcGVjdCBtZWFucyBpbiBjb3VsZG4ndCBhcHBlYXIgaW4gYW55IGdyb3VwXHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoYXNwZWN0LmVudGl0eU1hbmFnZXIgIT09IHRoaXMpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBlbnRpdHkgZG9lcyBub3QgYmVsb25nIHRvIHRoaXMgRW50aXR5TWFuYWdlci5cIik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXNwZWN0LnNldERldGFjaGVkKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBGZXRjaGVzIHRoZSBtZXRhZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhlIEVudGl0eU1hbmFnZXIncyBjdXJyZW50ICdzZXJ2aWNlTmFtZScuICBUaGlzIGNhbGxcclxuICBvY2N1cnMgaW50ZXJuYWxseSBiZWZvcmUgdGhlIGZpcnN0IHF1ZXJ5IHRvIGFueSBzZXJ2aWNlIGlmIHRoZSBtZXRhZGF0YSBoYXNuJ3QgYWxyZWFkeSBiZWVuXHJcbiAgbG9hZGVkLiBfX0FzeW5jX19cclxuXHJcbiAgVXN1YWxseSB5b3Ugd2lsbCBub3QgYWN0dWFsbHkgcHJvY2VzcyB0aGUgcmVzdWx0cyBvZiBhIGZldGNoTWV0YWRhdGEgY2FsbCBkaXJlY3RseSwgYnV0IHdpbGwgaW5zdGVhZFxyXG4gIGFzayBmb3IgdGhlIG1ldGFkYXRhIGZyb20gdGhlIEVudGl0eU1hbmFnZXIgYWZ0ZXIgdGhlIGZldGNoTWV0YWRhdGEgY2FsbCByZXR1cm5zLlxyXG4gID4gICAgIGxldCBlbTEgPSBuZXcgRW50aXR5TWFuYWdlciggXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiKTtcclxuICA+ICAgICBlbTEuZmV0Y2hNZXRhZGF0YSgpXHJcbiAgPiAgICAgICAudGhlbihmdW5jdGlvbigpIHtcclxuICA+ICAgICAgICAgICBsZXQgbWV0YWRhdGFTdG9yZSA9IGVtMS5tZXRhZGF0YVN0b3JlO1xyXG4gID4gICAgICAgICAgIC8vIGRvIHNvbWV0aGluZyB3aXRoIHRoZSBtZXRhZGF0YVxyXG4gID4gICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oZXhjZXB0aW9uKSB7XHJcbiAgPiAgICAgICAgICAgLy8gaGFuZGxlIGV4Y2VwdGlvbiBoZXJlXHJcbiAgPiAgICAgICB9KTtcclxuICBcclxuICBAcGFyYW0gY2FsbGJhY2sgLSBGdW5jdGlvbiBjYWxsZWQgb24gc3VjY2Vzcy5cclxuICBAcGFyYW0gZXJyb3JDYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBmYWlsdXJlLlxyXG4gIEByZXR1cm4ge1Byb21pc2V9XHJcbiAgICAtIHNjaGVtYSB7T2JqZWN0fSBUaGUgcmF3IFNjaGVtYSBvYmplY3QgZnJvbSBtZXRhZGF0YSBwcm92aWRlciAtIEJlY2F1c2UgdGhpcyBzY2hlbWEgd2lsbCBkaWZmZXIgZGVwZW5kaW5nIG9uIHRoZSBtZXRhZGF0YSBwcm92aWRlclxyXG4gICAgICAgIGl0IGlzIHVzdWFsbHkgYmV0dGVyIHRvIGFjY2VzcyBtZXRhZGF0YSB2aWEgdGhlICdtZXRhZGF0YVN0b3JlJyBwcm9wZXJ0eSBvZiB0aGUgRW50aXR5TWFuYWdlciBpbnN0ZWFkIG9mIHVzaW5nIHRoaXMgJ3JhdycgZGF0YS5cclxuICAqKi9cclxuICBmZXRjaE1ldGFkYXRhKGRhdGFTZXJ2aWNlPzogRGF0YVNlcnZpY2UsIGNhbGxiYWNrPzogQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s/OiBFcnJvckNhbGxiYWNrKSB7XHJcbiAgICBpZiAodHlwZW9mIChkYXRhU2VydmljZSkgPT09IFwiZnVuY3Rpb25cIikge1xyXG4gICAgICAvLyBsZWdhY3kgc3VwcG9ydCBmb3Igd2hlbiBkYXRhU2VydmljZSB3YXMgbm90IGFuIGFyZy4gaS5lLiBmaXJzdCBhcmcgd2FzIGNhbGxiYWNrXHJcbiAgICAgIGVycm9yQ2FsbGJhY2sgPSBjYWxsYmFjaztcclxuICAgICAgY2FsbGJhY2sgPSBkYXRhU2VydmljZTtcclxuICAgICAgZGF0YVNlcnZpY2UgPSB1bmRlZmluZWQ7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBhc3NlcnRQYXJhbShkYXRhU2VydmljZSwgXCJkYXRhU2VydmljZVwiKS5pc0luc3RhbmNlT2YoRGF0YVNlcnZpY2UpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgICBhc3NlcnRQYXJhbShjYWxsYmFjaywgXCJjYWxsYmFja1wiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICAgIGFzc2VydFBhcmFtKGVycm9yQ2FsbGJhY2ssIFwiZXJyb3JDYWxsYmFja1wiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHByb21pc2UgPSB0aGlzLm1ldGFkYXRhU3RvcmUuZmV0Y2hNZXRhZGF0YShkYXRhU2VydmljZSB8fCB0aGlzLmRhdGFTZXJ2aWNlKTtcclxuICAgIHJldHVybiBwcm9taXNlV2l0aENhbGxiYWNrcyhwcm9taXNlLCBjYWxsYmFjaywgZXJyb3JDYWxsYmFjayk7XHJcbiAgfVxyXG5cclxuXHJcbiAgZXhlY3V0ZVF1ZXJ5KHF1ZXJ5OiBzdHJpbmcsIGNhbGxiYWNrPzogUXVlcnlTdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s/OiBRdWVyeUVycm9yQ2FsbGJhY2spOiBQcm9taXNlPFF1ZXJ5UmVzdWx0PjtcclxuICBleGVjdXRlUXVlcnkocXVlcnk6IEVudGl0eVF1ZXJ5LCBjYWxsYmFjaz86IFF1ZXJ5U3VjY2Vzc0NhbGxiYWNrLCBlcnJvckNhbGxiYWNrPzogUXVlcnlFcnJvckNhbGxiYWNrKTogUHJvbWlzZTxRdWVyeVJlc3VsdD47XHJcbiAgLyoqXHJcbiAgRXhlY3V0ZXMgdGhlIHNwZWNpZmllZCBxdWVyeS4gX19Bc3luY19fIFxyXG4gIFxyXG4gID4gICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKHNlcnZpY2VOYW1lKTtcclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJPcmRlcnNcIik7XHJcbiAgPiAgICAgZW0uZXhlY3V0ZVF1ZXJ5KHF1ZXJ5KS50aGVuKCBmdW5jdGlvbihkYXRhKSB7XHJcbiAgPiAgICAgICAgIGxldCBvcmRlcnMgPSBkYXRhLnJlc3VsdHM7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSByZXN1bHRzIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgfSkuY2F0Y2goIGZ1bmN0aW9uKGVycikge1xyXG4gID4gICAgICAgICAuLi4gcXVlcnkgZmFpbHVyZSBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgIH0pO1xyXG5cclxuICBvciB3aXRoIGNhbGxiYWNrc1xyXG4gID4gICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKHNlcnZpY2VOYW1lKTtcclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJPcmRlcnNcIik7XHJcbiAgPiAgICAgZW0uZXhlY3V0ZVF1ZXJ5KHF1ZXJ5LFxyXG4gID4gICAgICAgICBmdW5jdGlvbihkYXRhKSB7XHJcbiAgPiAgICAgICAgICAgICBsZXQgb3JkZXJzID0gZGF0YS5yZXN1bHRzO1xyXG4gID4gICAgICAgICAgICAgLi4uIHF1ZXJ5IHJlc3VsdHMgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICAgICAgfSxcclxuICA+ICAgICAgICAgZnVuY3Rpb24oZXJyKSB7XHJcbiAgPiAgICAgICAgICAgICAuLi4gcXVlcnkgZmFpbHVyZSBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgICAgICB9KTtcclxuXHJcbiAgRWl0aGVyIHdheSB0aGlzIG1ldGhvZCBpcyB0aGUgc2FtZSBhcyBjYWxsaW5nIHRoZSBUaGUgW1tFbnRpdHlRdWVyeV1dICdleGVjdXRlJyBtZXRob2QuXHJcbiAgPiAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKS51c2luZyhlbSk7XHJcbiAgPiAgICAgcXVlcnkuZXhlY3V0ZSgpLnRoZW4oIGZ1bmN0aW9uKGRhdGEpIHtcclxuICA+ICAgICAgICAgbGV0IG9yZGVycyA9IGRhdGEucmVzdWx0cztcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IHJlc3VsdHMgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KS5jYXRjaCggZnVuY3Rpb24oZXJyKSB7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSBmYWlsdXJlIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgfSk7XHJcbiAgQHBhcmFtIHF1ZXJ5IC0gVGhlIFtbRW50aXR5UXVlcnldXSBvciBPRGF0YSBxdWVyeSBzdHJpbmcgdG8gZXhlY3V0ZS5cclxuICBAcGFyYW0gY2FsbGJhY2sgLSBGdW5jdGlvbiBjYWxsZWQgb24gc3VjY2Vzcy5cclxuICBAcGFyYW0gZXJyb3JDYWxsYmFjayAtIHtGdW5jdGlvbn0gRnVuY3Rpb24gY2FsbGVkIG9uIGZhaWx1cmUuXHJcbiAgQHJldHVybiBQcm9taXNlIG9mIFxyXG4gICAgLSByZXN1bHRzIC0gQW4gYXJyYXkgb2YgZW50aXRpZXNcclxuICAgIC0gcmV0cmlldmVkRW50aXRpZXMgLSBBIGFycmF5IG9mIGFsbCBvZiB0aGUgZW50aXRpZXMgcmV0dXJuZWQgYnkgdGhlIHF1ZXJ5LiAgRGlmZmVycyBmcm9tIHJlc3VsdHMgKGFib3ZlKSB3aGVuIC5leHBhbmQoKSBpcyB1c2VkLlxyXG4gICAgLSBxdWVyeSAtIFRoZSBvcmlnaW5hbCBbW0VudGl0eVF1ZXJ5XV0gb3IgcXVlcnkgc3RyaW5nXHJcbiAgICAtIGVudGl0eU1hbmFnZXIgLSAgVGhlIEVudGl0eU1hbmFnZXIuXHJcbiAgICAtIGh0dHBSZXNwb25zZSAtIFRoZSBbW0lIdHRwUmVzcG9uc2VdXSByZXR1cm5lZCBmcm9tIHRoZSBzZXJ2ZXIuXHJcbiAgICAtIGlubGluZUNvdW50IC0gIE9ubHkgYXZhaWxhYmxlIGlmICdpbmxpbmVDb3VudCh0cnVlKScgd2FzIGFwcGxpZWQgdG8gdGhlIHF1ZXJ5LiAgUmV0dXJucyB0aGUgY291bnQgb2ZcclxuICAgIGl0ZW1zIHRoYXQgd291bGQgaGF2ZSBiZWVuIHJldHVybmVkIGJ5IHRoZSBxdWVyeSBiZWZvcmUgYXBwbHlpbmcgYW55IHNraXAgb3IgdGFrZSBvcGVyYXRvcnMsIGJ1dCBhZnRlciBhbnkgZmlsdGVyL3doZXJlIHByZWRpY2F0ZXNcclxuICAgIHdvdWxkIGhhdmUgYmVlbiBhcHBsaWVkLlxyXG4gICoqL1xyXG4gIGV4ZWN1dGVRdWVyeShxdWVyeTogRW50aXR5UXVlcnkgfCBzdHJpbmcsIGNhbGxiYWNrPzogUXVlcnlTdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s/OiBRdWVyeUVycm9yQ2FsbGJhY2spIHtcclxuICAgIGFzc2VydFBhcmFtKHF1ZXJ5LCBcInF1ZXJ5XCIpLmlzSW5zdGFuY2VPZihFbnRpdHlRdWVyeSkub3IoKS5pc1N0cmluZygpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShjYWxsYmFjaywgXCJjYWxsYmFja1wiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShlcnJvckNhbGxiYWNrLCBcImVycm9yQ2FsbGJhY2tcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgbGV0IHByb21pc2U6IFByb21pc2U8YW55PjtcclxuICAgIC8vICdyZXNvbHZlJyBtZXRob2RzIGNyZWF0ZSBhIG5ldyB0eXBlZCBvYmplY3Qgd2l0aCBhbGwgb2YgaXRzIHByb3BlcnRpZXMgZnVsbHkgcmVzb2x2ZWQgYWdhaW5zdCBhIGxpc3Qgb2Ygc291cmNlcy5cclxuICAgIC8vIFRob3VnaHQgYWJvdXQgY3JlYXRpbmcgYSAnbm9ybWFsaXplZCcgcXVlcnkgd2l0aCB0aGVzZSAncmVzb2x2ZWQnIG9iamVjdHNcclxuICAgIC8vIGJ1dCBkZWNpZGVkIG5vdCB0byBiZWNhdXNlIHRoZSAncXVlcnknIG1heSBub3QgYmUgYW4gRW50aXR5UXVlcnkgKGl0IGNhbiBiZSBhIHN0cmluZykgYW5kIGhlbmNlIG1pZ2h0IG5vdCBoYXZlIGEgcXVlcnlPcHRpb25zIG9yIGRhdGFTZXJ2aWNlcyBwcm9wZXJ0eSBvbiBpdC5cclxuICAgIGxldCBxdWVyeU9wdGlvbnMgPSBRdWVyeU9wdGlvbnMucmVzb2x2ZShbKHF1ZXJ5IGFzIGFueSkucXVlcnlPcHRpb25zLCB0aGlzLnF1ZXJ5T3B0aW9ucywgUXVlcnlPcHRpb25zLmRlZmF1bHRJbnN0YW5jZV0pO1xyXG4gICAgbGV0IGRhdGFTZXJ2aWNlID0gRGF0YVNlcnZpY2UucmVzb2x2ZShbKHF1ZXJ5IGFzIGFueSkuZGF0YVNlcnZpY2UhLCB0aGlzLmRhdGFTZXJ2aWNlXSk7XHJcblxyXG4gICAgaWYgKCghZGF0YVNlcnZpY2UuaGFzU2VydmVyTWV0YWRhdGEpIHx8IHRoaXMubWV0YWRhdGFTdG9yZS5oYXNNZXRhZGF0YUZvcihkYXRhU2VydmljZS5zZXJ2aWNlTmFtZSkpIHtcclxuICAgICAgcHJvbWlzZSA9IGV4ZWN1dGVRdWVyeUNvcmUodGhpcywgcXVlcnksIHF1ZXJ5T3B0aW9ucywgZGF0YVNlcnZpY2UpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcHJvbWlzZSA9IHRoaXMuZmV0Y2hNZXRhZGF0YShkYXRhU2VydmljZSkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgcmV0dXJuIGV4ZWN1dGVRdWVyeUNvcmUodGhpcywgcXVlcnksIHF1ZXJ5T3B0aW9ucywgZGF0YVNlcnZpY2UpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gcHJvbWlzZVdpdGhDYWxsYmFja3MocHJvbWlzZSwgY2FsbGJhY2ssIGVycm9yQ2FsbGJhY2sgYXMgRXJyb3JDYWxsYmFjayk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBFeGVjdXRlcyB0aGUgc3BlY2lmaWVkIHF1ZXJ5IGFnYWluc3QgdGhpcyBFbnRpdHlNYW5hZ2VyJ3MgbG9jYWwgY2FjaGUuXHJcblxyXG4gIEJlY2F1c2UgdGhpcyBtZXRob2QgaXMgZXhlY3V0ZWQgaW1tZWRpYXRlbHkgdGhlcmUgaXMgbm8gbmVlZCBmb3IgYSBwcm9taXNlIG9yIGEgY2FsbGJhY2tcclxuICA+ICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcihzZXJ2aWNlTmFtZSk7XHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiT3JkZXJzXCIpO1xyXG4gID4gICAgIGxldCBvcmRlcnMgPSBlbS5leGVjdXRlUXVlcnlMb2NhbGx5KHF1ZXJ5KTtcclxuXHJcbiAgTm90ZSB0aGF0IHRoaXMgY2FuIGFsc28gYmUgYWNjb21wbGlzaGVkIHVzaW5nIHRoZSAnZXhlY3V0ZVF1ZXJ5JyBtZXRob2Qgd2l0aFxyXG4gIGEgRmV0Y2hTdHJhdGVneSBvZiBGcm9tTG9jYWxDYWNoZSBhbmQgbWFraW5nIHVzZSBvZiB0aGUgUHJvbWlzZSBvciBjYWxsYmFja1xyXG4gID4gICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKHNlcnZpY2VOYW1lKTtcclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJPcmRlcnNcIikudXNpbmcoRmV0Y2hTdHJhdGVneS5Gcm9tTG9jYWxDYWNoZSk7XHJcbiAgPiAgICAgZW0uZXhlY3V0ZVF1ZXJ5KHF1ZXJ5KS50aGVuKCBmdW5jdGlvbihkYXRhKSB7XHJcbiAgPiAgICAgICAgIGxldCBvcmRlcnMgPSBkYXRhLnJlc3VsdHM7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSByZXN1bHRzIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgfSkuY2F0Y2goIGZ1bmN0aW9uKGVycikge1xyXG4gID4gICAgICAgICAuLi4gcXVlcnkgZmFpbHVyZSBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgIH0pO1xyXG4gIEBwYXJhbSBxdWVyeSAtIFRoZSBbW0VudGl0eVF1ZXJ5XV0gdG8gZXhlY3V0ZS5cclxuICBAcmV0dXJuICB7QXJyYXkgb2YgRW50aXR5fSAgQXJyYXkgb2YgZW50aXRpZXMgZnJvbSBjYWNoZSB0aGF0IHNhdGlzZnkgdGhlIHF1ZXJ5XHJcbiAgKiovXHJcbiAgZXhlY3V0ZVF1ZXJ5TG9jYWxseShxdWVyeTogRW50aXR5UXVlcnkpIHtcclxuICAgIHJldHVybiBleGVjdXRlUXVlcnlMb2NhbGx5Q29yZSh0aGlzLCBxdWVyeSkucmVzdWx0cztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFNhdmVzIGVpdGhlciBhIGxpc3Qgb2Ygc3BlY2lmaWVkIGVudGl0aWVzIG9yIGFsbCBjaGFuZ2VkIGVudGl0aWVzIHdpdGhpbiB0aGlzIEVudGl0eU1hbmFnZXIuIElmIHRoZXJlIGFyZSBubyBjaGFuZ2VzIHRvIGFueSBvZiB0aGUgZW50aXRpZXNcclxuICBzcGVjaWZpZWQgdGhlbiB0aGVyZSB3aWxsIGJlIG5vIHNlcnZlciBzaWRlIGNhbGwgbWFkZSBidXQgYSB2YWxpZCAnZW1wdHknIHNhdmVSZXN1bHQgd2lsbCBzdGlsbCBiZSByZXR1cm5lZC4gX19Bc3luY19fXHJcblxyXG4gIE9mdGVuIHdlIHdpbGwgYmUgc2F2aW5nIGFsbCBvZiB0aGUgZW50aXRpZXMgd2l0aGluIGFuIEVudGl0eU1hbmFnZXIgdGhhdCBhcmUgZWl0aGVyIGFkZGVkLCBtb2RpZmllZCBvciBkZWxldGVkXHJcbiAgYW5kIHdlIHdpbGwgbGV0IHRoZSAnc2F2ZUNoYW5nZXMnIGNhbGwgZGV0ZXJtaW5lIHdoaWNoIGVudGl0aWVzIHRoZXNlIGFyZS5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIC8vIFRoaXMgY291bGQgaW5jbHVkZSBhZGRlZCwgbW9kaWZpZWQgYW5kIGRlbGV0ZWQgZW50aXRpZXMuXHJcbiAgPiAgICAgIGVtLnNhdmVDaGFuZ2VzKCkudGhlbihmdW5jdGlvbihzYXZlUmVzdWx0KSB7XHJcbiAgPiAgICAgICAgICBsZXQgc2F2ZWRFbnRpdGllcyA9IHNhdmVSZXN1bHQuZW50aXRpZXM7XHJcbiAgPiAgICAgICAgICBsZXQga2V5TWFwcGluZ3MgPSBzYXZlUmVzdWx0LmtleU1hcHBpbmdzO1xyXG4gID4gICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZSkge1xyXG4gID4gICAgICAgICAgLy8gZSBpcyBhbnkgZXhjZXB0aW9uIHRoYXQgd2FzIHRocm93bi5cclxuICA+ICAgICAgfSk7XHJcblxyXG4gIEJ1dCB3ZSBjYW4gYWxzbyBjb250cm9sIGV4YWN0bHkgd2hpY2ggZW50aXRpZXMgdG8gc2F2ZSBhbmQgY2FuIHNwZWNpZnkgc3BlY2lmaWMgU2F2ZU9wdGlvbnNcclxuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbnRpdGllc1RvU2F2ZSBpcyBhbiBhcnJheSBvZiBlbnRpdGllcyB0byBzYXZlLlxyXG4gID4gICAgICBsZXQgc2F2ZU9wdGlvbnMgPSBuZXcgU2F2ZU9wdGlvbnMoeyBhbGxvd0NvbmN1cnJlbnRTYXZlczogdHJ1ZSB9KTtcclxuICA+ICAgICAgZW0uc2F2ZUNoYW5nZXMoZW50aXRpZXNUb1NhdmUsIHNhdmVPcHRpb25zKS50aGVuKGZ1bmN0aW9uKHNhdmVSZXN1bHQpIHtcclxuICA+ICAgICAgICAgIGxldCBzYXZlZEVudGl0aWVzID0gc2F2ZVJlc3VsdC5lbnRpdGllcztcclxuICA+ICAgICAgICAgIGxldCBrZXlNYXBwaW5ncyA9IHNhdmVSZXN1bHQua2V5TWFwcGluZ3M7XHJcbiAgPiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlKSB7XHJcbiAgPiAgICAgICAgICAvLyBlIGlzIGFueSBleGNlcHRpb24gdGhhdCB3YXMgdGhyb3duLlxyXG4gID4gICAgICB9KTtcclxuXHJcbiAgQ2FsbGJhY2sgbWV0aG9kcyBjYW4gYWxzbyBiZSB1c2VkXHJcbiAgPiAgICAgIGVtLnNhdmVDaGFuZ2VzKGVudGl0aWVzVG9TYXZlLCBudWxsLFxyXG4gID4gICAgICAgICAgZnVuY3Rpb24oc2F2ZVJlc3VsdCkge1xyXG4gID4gICAgICAgICAgICAgIGxldCBzYXZlZEVudGl0aWVzID0gc2F2ZVJlc3VsdC5lbnRpdGllcztcclxuICA+ICAgICAgICAgICAgICBsZXQga2V5TWFwcGluZ3MgPSBzYXZlUmVzdWx0LmtleU1hcHBpbmdzO1xyXG4gID4gICAgICAgICAgfSwgZnVuY3Rpb24gKGUpIHtcclxuICA+ICAgICAgICAgICAgICAvLyBlIGlzIGFueSBleGNlcHRpb24gdGhhdCB3YXMgdGhyb3duLlxyXG4gID4gICAgICAgICAgfVxyXG4gID4gICAgICApO1xyXG5cclxuICBAcGFyYW0gZW50aXRpZXMgLSBUaGUgbGlzdCBvZiBlbnRpdGllcyB0byBzYXZlLlxyXG4gIEV2ZXJ5IGVudGl0eSBpbiB0aGF0IGxpc3Qgd2lsbCBiZSBzZW50IHRvIHRoZSBzZXJ2ZXIsIHdoZXRoZXIgY2hhbmdlZCBvciB1bmNoYW5nZWQsXHJcbiAgYXMgbG9uZyBhcyBpdCBpcyBhdHRhY2hlZCB0byB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgSWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCwgbnVsbCBvciBlbXB0eSAodGhlIHVzdWFsIGNhc2UpLFxyXG4gIGV2ZXJ5IGVudGl0eSB3aXRoIHBlbmRpbmcgY2hhbmdlcyBpbiB0aGlzIEVudGl0eU1hbmFnZXIgd2lsbCBiZSBzYXZlZC5cclxuICBAcGFyYW0gc2F2ZU9wdGlvbnMgLSBbW1NhdmVPcHRpb25zXV0gZm9yIHRoZSBzYXZlIC0gd2lsbCBkZWZhdWx0IHRvXHJcbiAgW1tFbnRpdHlNYW5hZ2VyLnNhdmVPcHRpb25zXV0gaWYgbnVsbC5cclxuICBAcGFyYW0gY2FsbGJhY2sgLSAgRnVuY3Rpb24gY2FsbGVkIG9uIHN1Y2Nlc3MuXHJcbiAgQHBhcmFtIGVycm9yQ2FsbGJhY2sgLSBGdW5jdGlvbiBjYWxsZWQgb24gZmFpbHVyZS5cclxuICBAcmV0dXJuIHtQcm9taXNlfSBQcm9taXNlXHJcbiAgKiovXHJcbiAgc2F2ZUNoYW5nZXMoZW50aXRpZXM/OiBFbnRpdHlbXSB8IG51bGwsIHNhdmVPcHRpb25zPzogU2F2ZU9wdGlvbnMsIGNhbGxiYWNrPzogRnVuY3Rpb24sIGVycm9yQ2FsbGJhY2s/OiBGdW5jdGlvbikge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXRpZXMsIFwiZW50aXRpZXNcIikuaXNPcHRpb25hbCgpLmlzQXJyYXkoKS5pc0VudGl0eSgpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShzYXZlT3B0aW9ucywgXCJzYXZlT3B0aW9uc1wiKS5pc0luc3RhbmNlT2YoU2F2ZU9wdGlvbnMpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oY2FsbGJhY2ssIFwiY2FsbGJhY2tcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oZXJyb3JDYWxsYmFjaywgXCJlcnJvckNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuXHJcbiAgICBzYXZlT3B0aW9ucyA9IHNhdmVPcHRpb25zIHx8IHRoaXMuc2F2ZU9wdGlvbnMgfHwgU2F2ZU9wdGlvbnMuZGVmYXVsdEluc3RhbmNlO1xyXG5cclxuICAgIGxldCBlbnRpdGllc1RvU2F2ZSA9IGdldEVudGl0aWVzVG9TYXZlKHRoaXMsIGVudGl0aWVzID8gZW50aXRpZXMgOiB1bmRlZmluZWQpO1xyXG5cclxuICAgIGlmIChlbnRpdGllc1RvU2F2ZS5sZW5ndGggPT09IDApIHtcclxuICAgICAgbGV0IHJlc3VsdCA9IHsgZW50aXRpZXM6IFtdLCBrZXlNYXBwaW5nczogW10gfSBhcyBTYXZlUmVzdWx0O1xyXG4gICAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKHJlc3VsdCk7XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXNhdmVPcHRpb25zLmFsbG93Q29uY3VycmVudFNhdmVzKSB7XHJcbiAgICAgIGxldCBhbnlQZW5kaW5nU2F2ZXMgPSBlbnRpdGllc1RvU2F2ZS5zb21lKGZ1bmN0aW9uIChlbnRpdHkpIHtcclxuICAgICAgICByZXR1cm4gZW50aXR5LmVudGl0eUFzcGVjdC5pc0JlaW5nU2F2ZWQ7XHJcbiAgICAgIH0pO1xyXG4gICAgICBpZiAoYW55UGVuZGluZ1NhdmVzKSB7XHJcbiAgICAgICAgbGV0IGVyciA9IG5ldyBFcnJvcihcIkNvbmN1cnJlbnQgc2F2ZXMgbm90IGFsbG93ZWQgLSBTYXZlT3B0aW9ucy5hbGxvd0NvbmN1cnJlbnRTYXZlcyBpcyBmYWxzZVwiKTtcclxuICAgICAgICBpZiAoZXJyb3JDYWxsYmFjaykgZXJyb3JDYWxsYmFjayhlcnIpO1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY2xlYXJTZXJ2ZXJFcnJvcnMoZW50aXRpZXNUb1NhdmUpO1xyXG5cclxuICAgIGxldCB2YWxFcnJvciA9IHRoaXMuc2F2ZUNoYW5nZXNWYWxpZGF0ZU9uQ2xpZW50KGVudGl0aWVzVG9TYXZlKTtcclxuICAgIGlmICh2YWxFcnJvcikge1xyXG4gICAgICBpZiAoZXJyb3JDYWxsYmFjaykgZXJyb3JDYWxsYmFjayh2YWxFcnJvcik7XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCh2YWxFcnJvcik7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGRhdGFTZXJ2aWNlID0gRGF0YVNlcnZpY2UucmVzb2x2ZShbc2F2ZU9wdGlvbnMuZGF0YVNlcnZpY2UsIHRoaXMuZGF0YVNlcnZpY2VdKTtcclxuICAgIGxldCBzYXZlQ29udGV4dDogU2F2ZUNvbnRleHQgPSB7XHJcbiAgICAgIGVudGl0eU1hbmFnZXI6IHRoaXMsXHJcbiAgICAgIGRhdGFTZXJ2aWNlOiBkYXRhU2VydmljZSxcclxuICAgICAgcHJvY2Vzc1NhdmVkRW50aXRpZXM6IHByb2Nlc3NTYXZlZEVudGl0aWVzLFxyXG4gICAgICByZXNvdXJjZU5hbWU6IHNhdmVPcHRpb25zLnJlc291cmNlTmFtZSB8fCB0aGlzLnNhdmVPcHRpb25zLnJlc291cmNlTmFtZSB8fCBcIlNhdmVDaGFuZ2VzXCJcclxuICAgIH07XHJcblxyXG4gICAgLy8gVE9ETzogbmVlZCB0byBjaGVjayB0aGF0IGlmIHdlIGFyZSBkb2luZyBhIHBhcnRpYWwgc2F2ZSB0aGF0IGFsbCBlbnRpdGllcyB3aG9zZSB0ZW1wIGtleXNcclxuICAgIC8vIGFyZSByZWZlcmVuY2VkIGFyZSBhbHNvIGluIHRoZSBwYXJ0aWFsIHNhdmUgZ3JvdXBcclxuXHJcbiAgICBsZXQgc2F2ZUJ1bmRsZSA9IHsgZW50aXRpZXM6IGVudGl0aWVzVG9TYXZlLCBzYXZlT3B0aW9uczogc2F2ZU9wdGlvbnMgfTtcclxuXHJcblxyXG4gICAgdHJ5IHsgLy8gR3VhcmQgYWdhaW5zdCBleGNlcHRpb24gdGhyb3duIGluIGRhdGFzZXJ2aWNlIGFkYXB0ZXIgYmVmb3JlIGl0IGdvZXMgYXN5bmNcclxuICAgICAgdXBkYXRlQ29uY3VycmVuY3lQcm9wZXJ0aWVzKGVudGl0aWVzVG9TYXZlKTtcclxuICAgICAgcmV0dXJuIGRhdGFTZXJ2aWNlLmFkYXB0ZXJJbnN0YW5jZSEuc2F2ZUNoYW5nZXMoc2F2ZUNvbnRleHQsIHNhdmVCdW5kbGUpXHJcbiAgICAgICAgLnRoZW4oc2F2ZVN1Y2Nlc3MpLnRoZW4oKHIpID0+IHIsIHNhdmVGYWlsKTtcclxuICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICAvLyB1bmRvIHRoZSBtYXJraW5nIGJ5IHVwZGF0ZUNvbmN1cnJlbmN5UHJvcGVydGllc1xyXG4gICAgICBtYXJrSXNCZWluZ1NhdmVkKGVudGl0aWVzVG9TYXZlLCBmYWxzZSk7XHJcbiAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGVycik7XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIHNhdmVTdWNjZXNzKHNhdmVSZXN1bHQ6IFNhdmVSZXN1bHQpIHtcclxuICAgICAgbGV0IGVtID0gc2F2ZUNvbnRleHQuZW50aXR5TWFuYWdlcjtcclxuICAgICAgbWFya0lzQmVpbmdTYXZlZChlbnRpdGllc1RvU2F2ZSwgZmFsc2UpO1xyXG4gICAgICBsZXQgc2F2ZWRFbnRpdGllcyA9IHNhdmVDb250ZXh0LnByb2Nlc3NTYXZlZEVudGl0aWVzKHNhdmVSZXN1bHQpO1xyXG4gICAgICBzYXZlUmVzdWx0LmVudGl0aWVzID0gc2F2ZWRFbnRpdGllcztcclxuXHJcbiAgICAgIC8vIHVwZGF0ZSBfaGFzQ2hhbmdlcyBhZnRlciBzYXZlLlxyXG4gICAgICBlbS5fc2V0SGFzQ2hhbmdlcygpO1xyXG5cclxuICAgICAgLy8gY2FuJ3QgZG8gdGhpcyBhbnltb3JlIGJlY2F1c2Ugb3RoZXIgY2hhbmdlcyBtaWdodCBoYXZlIGJlZW4gbWFkZSB3aGlsZSBzYXZlZCBlbnRpdGllcyBpbiBmbGlnaHQuXHJcbiAgICAgIC8vICAgICAgbGV0IGhhc0NoYW5nZXMgPSAoaXNGdWxsU2F2ZSAmJiBoYXZlU2FtZUNvbnRlbnRzKGVudGl0aWVzVG9TYXZlLCBzYXZlZEVudGl0aWVzKSkgPyBmYWxzZSA6IG51bGw7XHJcbiAgICAgIC8vICAgICAgZW0uX3NldEhhc0NoYW5nZXMoaGFzQ2hhbmdlcyk7XHJcblxyXG4gICAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKHNhdmVSZXN1bHQpO1xyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHNhdmVSZXN1bHQpO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIHByb2Nlc3NTYXZlZEVudGl0aWVzKHNhdmVSZXN1bHQ6IFNhdmVSZXN1bHQpIHtcclxuICAgICAgbGV0IHNhdmVkRW50aXRpZXMgPSBzYXZlUmVzdWx0LmVudGl0aWVzO1xyXG4gICAgICBsZXQgZGVsZXRlZEtleXMgPSBzYXZlUmVzdWx0LmRlbGV0ZWRLZXlzIHx8IFtdO1xyXG4gICAgICBpZiAoc2F2ZWRFbnRpdGllcy5sZW5ndGggPT09IDAgJiYgZGVsZXRlZEtleXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgcmV0dXJuIFtdO1xyXG4gICAgICB9XHJcbiAgICAgIGxldCBrZXlNYXBwaW5ncyA9IHNhdmVSZXN1bHQua2V5TWFwcGluZ3M7XHJcbiAgICAgIGxldCBlbSA9IHNhdmVDb250ZXh0LmVudGl0eU1hbmFnZXI7XHJcblxyXG4gICAgICAvLyBtdXN0IG9jY3VyIG91dHNpZGUgb2YgaXNMb2FkaW5nIGJsb2NrXHJcbiAgICAgIGZpeHVwS2V5cyhlbSwga2V5TWFwcGluZ3MpO1xyXG5cclxuICAgICAgY29yZS51c2luZyhlbSwgXCJpc0xvYWRpbmdcIiwgdHJ1ZSwgKCkgPT4ge1xyXG5cclxuICAgICAgICBsZXQgbWFwcGluZ0NvbnRleHQgPSBuZXcgTWFwcGluZ0NvbnRleHQoe1xyXG4gICAgICAgICAgcXVlcnk6IHVuZGVmaW5lZCwgLy8gdGVsbHMgdmlzaXRBbmRNZXJnZSB0aGlzIGlzIGEgc2F2ZSBpbnN0ZWFkIG9mIGEgcXVlcnlcclxuICAgICAgICAgIGVudGl0eU1hbmFnZXI6IGVtLFxyXG4gICAgICAgICAgbWVyZ2VPcHRpb25zOiB7IG1lcmdlU3RyYXRlZ3k6IE1lcmdlU3RyYXRlZ3kuT3ZlcndyaXRlQ2hhbmdlcyB9LFxyXG4gICAgICAgICAgZGF0YVNlcnZpY2U6IGRhdGFTZXJ2aWNlXHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIC8vIFRoZSB2aXNpdEFuZE1lcmdlIG9wZXJhdGlvbiBoYXMgYmVlbiBvcHRpbWl6ZWQgc28gdGhhdCB3ZSBkbyBub3QgYWN0dWFsbHkgcGVyZm9ybSBhIG1lcmdlIGlmIHRoZVxyXG4gICAgICAgIC8vIHRoZSBzYXZlIG9wZXJhdGlvbiBkaWQgbm90IGFjdHVhbGx5IHJldHVybiB0aGUgZW50aXR5IC0gaS5lLiBkdXJpbmcgT0RhdGEgYW5kIE1vbmdvIHVwZGF0ZXMgYW5kIGRlbGV0ZXMuXHJcbiAgICAgICAgc2F2ZWRFbnRpdGllcyA9IG1hcHBpbmdDb250ZXh0LnZpc2l0QW5kTWVyZ2Uoc2F2ZWRFbnRpdGllcywgeyBub2RlVHlwZTogXCJyb290XCIgfSk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy8gZGV0YWNoIGFueSBlbnRpdGllcyBmb3VuZCBpbiB0aGUgZW0gdGhhdCBhcHBlYXIgaW4gdGhlIGRlbGV0ZWRLZXlzIGxpc3QuIFxyXG4gICAgICBkZWxldGVkS2V5cy5mb3JFYWNoKGtleSA9PiB7XHJcbiAgICAgICAgbGV0IGVudGl0eVR5cGUgPSBlbS5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShrZXkuZW50aXR5VHlwZU5hbWUpIGFzIEVudGl0eVR5cGU7XHJcbiAgICAgICAgbGV0IGVrZXkgPSBuZXcgRW50aXR5S2V5KGVudGl0eVR5cGUsIGtleS5rZXlWYWx1ZXMpO1xyXG4gICAgICAgIGxldCBlbnRpdHkgPSBlbS5nZXRFbnRpdHlCeUtleShla2V5KTtcclxuICAgICAgICBpZiAoZW50aXR5KSB7XHJcbiAgICAgICAgICBlbnRpdHkuZW50aXR5QXNwZWN0LnNldERldGFjaGVkKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHJldHVybiBzYXZlZEVudGl0aWVzO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIHNhdmVGYWlsKHNlcnZlckVycm9yOiBTYXZlRXJyb3JGcm9tU2VydmVyKSB7XHJcbiAgICAgIG1hcmtJc0JlaW5nU2F2ZWQoZW50aXRpZXNUb1NhdmUsIGZhbHNlKTtcclxuICAgICAgbGV0IGNsaWVudEVycm9yID0gcHJvY2Vzc1NlcnZlckVycm9ycyhzYXZlQ29udGV4dCwgc2VydmVyRXJyb3IpO1xyXG4gICAgICBpZiAoZXJyb3JDYWxsYmFjaykgZXJyb3JDYWxsYmFjayhjbGllbnRFcnJvcik7XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChjbGllbnRFcnJvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSdW4gdGhlIFwic2F2ZUNoYW5nZXNcIiBwcmUtc2F2ZSBjbGllbnQgdmFsaWRhdGlvbiBsb2dpYy5cclxuICBcclxuICBUaGlzIGlzIE5PVCBhIGdlbmVyYWwgcHVycG9zZSB2YWxpZGF0aW9uIG1ldGhvZC5cclxuICBJdCBpcyBpbnRlbmRlZCBmb3IgdXRpbGl0aWVzIHRoYXQgbXVzdCBrbm93IGlmIHNhdmVDaGFuZ2VzXHJcbiAgd291bGQgcmVqZWN0IHRoZSBzYXZlIGR1ZSB0byBjbGllbnQgdmFsaWRhdGlvbiBlcnJvcnMuXHJcbiAgXHJcbiAgSXQgb25seSB2YWxpZGF0ZXMgZW50aXRpZXMgaWYgdGhlIEVudGl0eU1hbmFnZXInc1xyXG4gIFtbVmFsaWRhdGlvbk9wdGlvbnNdXS52YWxpZGF0ZU9uU2F2ZSBpcyB0cnVlLlxyXG4gIFxyXG4gIEBwYXJhbSBlbnRpdGllc1RvU2F2ZSB7QXJyYXkgb2YgRW50aXR5fSBUaGUgbGlzdCBvZiBlbnRpdGllcyB0byBzYXZlICh0byB2YWxpZGF0ZSkuXHJcbiAgQHJldHVybiB7RXJyb3J9IFZhbGlkYXRpb24gZXJyb3Igb3IgbnVsbCBpZiBubyBlcnJvclxyXG4gICoqL1xyXG4gIHNhdmVDaGFuZ2VzVmFsaWRhdGVPbkNsaWVudChlbnRpdGllc1RvU2F2ZTogRW50aXR5W10pIHtcclxuXHJcbiAgICBpZiAodGhpcy52YWxpZGF0aW9uT3B0aW9ucy52YWxpZGF0ZU9uU2F2ZSkge1xyXG4gICAgICBsZXQgZmFpbGVkRW50aXRpZXMgPSBlbnRpdGllc1RvU2F2ZS5maWx0ZXIoZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgICAgIGxldCBhc3BlY3QgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgICAgIGxldCBpc1ZhbGlkID0gYXNwZWN0LmVudGl0eVN0YXRlLmlzRGVsZXRlZCgpIHx8IGFzcGVjdC52YWxpZGF0ZUVudGl0eSgpO1xyXG4gICAgICAgIHJldHVybiAhaXNWYWxpZDtcclxuICAgICAgfSk7XHJcbiAgICAgIGlmIChmYWlsZWRFbnRpdGllcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgbGV0IHZhbEVycm9yID0gbmV3IEVycm9yKFwiQ2xpZW50IHNpZGUgdmFsaWRhdGlvbiBlcnJvcnMgZW5jb3VudGVyZWQgLSBzZWUgdGhlIGVudGl0eUVycm9ycyBjb2xsZWN0aW9uIG9uIHRoaXMgb2JqZWN0IGZvciBtb3JlIGRldGFpbFwiKTtcclxuICAgICAgICAodmFsRXJyb3IgYXMgYW55KS5lbnRpdHlFcnJvcnMgPSBjcmVhdGVFbnRpdHlFcnJvcnMoZmFpbGVkRW50aXRpZXMpO1xyXG4gICAgICAgIHJldHVybiB2YWxFcnJvcjsgLy8gVE9ETzogdHlwZSB0aGlzLlxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9maW5kRW50aXR5R3JvdXAoZW50aXR5VHlwZTogRW50aXR5VHlwZSkge1xyXG4gICAgcmV0dXJuIHRoaXMuX2VudGl0eUdyb3VwTWFwW2VudGl0eVR5cGUubmFtZV07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBlbXBsb3llZVR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiRW1wbG95ZWVcIik7XHJcbiAgPiAgICAgIGxldCBlbXBsb3llZUtleSA9IG5ldyBFbnRpdHlLZXkoZW1wbG95ZWVUeXBlLCAxKTtcclxuICA+ICAgICAgbGV0IGVtcGxveWVlID0gZW0xLmdldEVudGl0eUJ5S2V5KGVtcGxveWVlS2V5KTtcclxuICA+ICAgICAgLy8gZW1wbG95ZWUgd2lsbCBlaXRoZXIgYmUgYW4gZW50aXR5IG9yIG51bGwuXHJcbiAgKiovXHJcbiAgZ2V0RW50aXR5QnlLZXkoZW50aXR5S2V5OiBFbnRpdHlLZXkpOiBFbnRpdHkgfCBudWxsO1xyXG5cclxuICAvKiogIFxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGVtcGxveWVlID0gZW0xLmdldEVudGl0eUJ5S2V5KFwiRW1wbG95ZWVcIiwgMSk7XHJcbiAgPiAgICAgIC8vIGVtcGxveWVlIHdpbGwgZWl0aGVyIGJlIGFuIGVudGl0eSBvciBudWxsLlxyXG4gICoqL1xyXG4gIGdldEVudGl0eUJ5S2V5KHR5cGVOYW1lOiBzdHJpbmcsIGtleVZhbHVlczogYW55IHwgYW55W10pOiBFbnRpdHkgfCBudWxsO1xyXG5cclxuICAvKiogIFxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGVtcGxveWVlVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJFbXBsb3llZVwiKTtcclxuICA+ICAgICAgbGV0IGVtcGxveWVlID0gZW0xLmdldEVudGl0eUJ5S2V5KGVtcGxveWVlVHlwZSwgMSk7XHJcbiAgPiAgICAgIC8vIGVtcGxveWVlIHdpbGwgZWl0aGVyIGJlIGFuIGVudGl0eSBvciBudWxsLlxyXG4gICoqL1xyXG4gIGdldEVudGl0eUJ5S2V5KHR5cGU6IEVudGl0eVR5cGUsIGtleVZhbHVlczogYW55IHwgYW55W10pOiBFbnRpdHkgfCBudWxsO1xyXG5cclxuICAvKiogIFxyXG4gIEF0dGVtcHRzIHRvIGxvY2F0ZSBhbiBlbnRpdHkgd2l0aGluIHRoaXMgRW50aXR5TWFuYWdlciBieSBpdHMgW0VudGl0eUtleV0uXHJcbiAgQHBhcmFtIGVudGl0eUtleSAtIFRoZSBbW0VudGl0eUtleV1dIG9mIHRoZSBFbnRpdHkgdG8gYmUgbG9jYXRlZC5cclxuICBAcGFyYW0gdHlwZSAtIFRoZSBbW0VudGl0eVR5cGVdXSBmb3IgdGhpcyBrZXkuXHJcbiAgQHBhcmFtIHR5cGVOYW1lIC0gVGhlIEVudGl0eVR5cGUgbmFtZSBmb3IgdGhpcyBrZXkuXHJcbiAgQHBhcmFtIGtleVZhbHVlcyAtIFRoZSB2YWx1ZXMgZm9yIHRoaXMga2V5IC0gd2lsbCB1c3VhbGx5IGp1c3QgYmUgYSBzaW5nbGUgdmFsdWU7IGFuIGFycmF5IGlzIG9ubHkgbmVlZGVkIGZvciBtdWx0aXBhcnQga2V5cy4gIFxyXG4gIEByZXR1cm4gQW4gRW50aXR5IG9yIG51bGw7XHJcbiAgKiovXHJcbiAgZ2V0RW50aXR5QnlLZXkoLi4uYXJnczogYW55W10pIHtcclxuICAgIGxldCBlbnRpdHlLZXkgPSBjcmVhdGVFbnRpdHlLZXkodGhpcywgYXJncykuZW50aXR5S2V5O1xyXG4gICAgbGV0IGVudGl0eVR5cGVzID0gZW50aXR5S2V5Ll9zdWJ0eXBlcyB8fCBbZW50aXR5S2V5LmVudGl0eVR5cGVdO1xyXG4gICAgbGV0IGU6IEVudGl0eSB8IHVuZGVmaW5lZDtcclxuICAgIC8vIGhhY2sgdXNlIG9mIHNvbWUgdG8gc2ltdWxhdGUgbWFwRmlyc3QgbG9naWMuXHJcbiAgICBlbnRpdHlUeXBlcy5zb21lKChldCkgPT4ge1xyXG4gICAgICBsZXQgZ3JvdXAgPSB0aGlzLl9maW5kRW50aXR5R3JvdXAoZXQpO1xyXG4gICAgICAvLyBncm91cCB2ZXJzaW9uIG9mIGZpbmRFbnRpdHlCeUtleSBkb2Vzbid0IGNhcmUgYWJvdXQgZW50aXR5VHlwZVxyXG4gICAgICBlID0gZ3JvdXAgJiYgZ3JvdXAuZmluZEVudGl0eUJ5S2V5KGVudGl0eUtleSk7XHJcbiAgICAgIHJldHVybiBlICE9IG51bGw7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBlIHx8IG51bGw7XHJcbiAgfVxyXG5cclxuICBmZXRjaEVudGl0eUJ5S2V5KHR5cGVOYW1lOiBzdHJpbmcsIGtleVZhbHVlczogYW55IHwgYW55W10sIGNoZWNrTG9jYWxDYWNoZUZpcnN0PzogYm9vbGVhbik6IFByb21pc2U8SUVudGl0eUJ5S2V5UmVzdWx0PjtcclxuICBmZXRjaEVudGl0eUJ5S2V5KGVudGl0eVR5cGU6IEVudGl0eVR5cGUsIGtleVZhbHVlczogYW55IHwgYW55W10sIGNoZWNrTG9jYWxDYWNoZUZpcnN0PzogYm9vbGVhbik6IFByb21pc2U8SUVudGl0eUJ5S2V5UmVzdWx0PjtcclxuICBmZXRjaEVudGl0eUJ5S2V5KGVudGl0eUtleTogRW50aXR5S2V5LCBjaGVja0xvY2FsQ2FjaGVGaXJzdD86IGJvb2xlYW4pOiBQcm9taXNlPElFbnRpdHlCeUtleVJlc3VsdD47XHJcbiAgLyoqXHJcbiAgQXR0ZW1wdHMgdG8gZmV0Y2ggYW4gZW50aXR5IGZyb20gdGhlIHNlcnZlciBieSBpdHMgW1tFbnRpdHlLZXldXSB3aXRoXHJcbiAgYW4gb3B0aW9uIHRvIGNoZWNrIHRoZSBsb2NhbCBjYWNoZSBmaXJzdC4gTm90ZSB0aGUgdGhpcyBFbnRpdHlNYW5hZ2VyJ3MgcXVlcnlPcHRpb25zLm1lcmdlU3RyYXRlZ3lcclxuICB3aWxsIGJlIHVzZWQgdG8gbWVyZ2UgYW55IHNlcnZlciBzaWRlIGVudGl0eSByZXR1cm5lZCBieSB0aGlzIG1ldGhvZC5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgZW1wbG95ZWVUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkVtcGxveWVlXCIpO1xyXG4gID4gICAgIGxldCBlbXBsb3llZUtleSA9IG5ldyBFbnRpdHlLZXkoZW1wbG95ZWVUeXBlLCAxKTtcclxuICA+ICAgICBlbTEuZmV0Y2hFbnRpdHlCeUtleShlbXBsb3llZUtleSkudGhlbihmdW5jdGlvbihyZXN1bHQpIHtcclxuICA+ICAgICAgIGxldCBlbXBsb3llZSA9IHJlc3VsdC5lbnRpdHk7XHJcbiAgPiAgICAgICBsZXQgZW50aXR5S2V5ID0gcmVzdWx0LmVudGl0eUtleTtcclxuICA+ICAgICAgIGxldCBmcm9tQ2FjaGUgPSByZXN1bHQuZnJvbUNhY2hlO1xyXG4gID4gICAgIH0pO1xyXG4gIEBwYXJhbSB0eXBlTmFtZSAgLSBUaGUgRW50aXR5VHlwZSBuYW1lIGZvciB0aGlzIGtleS5cclxuICBAcGFyYW0gZW50aXR5VHlwZSAgLSBUaGUgRW50aXR5VHlwZSBmb3IgdGhpcyBrZXkuXHJcbiAgQHBhcmFtIGtleVZhbHVlcyAtIFRoZSB2YWx1ZXMgZm9yIHRoaXMga2V5IC0gd2lsbCB1c3VhbGx5IGp1c3QgYmUgYSBzaW5nbGUgdmFsdWU7IGFuIGFycmF5IGlzIG9ubHkgbmVlZGVkIGZvciBtdWx0aXBhcnQga2V5cy5cclxuICBAcGFyYW0gZW50aXR5S2V5IC0gVGhlIFtbRW50aXR5S2V5XV0gb2YgdGhlIEVudGl0eSB0byBiZSBsb2NhdGVkLlxyXG4gIEBwYXJhbSBjaGVja0xvY2FsQ2FjaGVGaXJzdCAtIChkZWZhdWx0ID0gZmFsc2UpIC0gV2hldGhlciB0byBjaGVjayB0aGlzIEVudGl0eU1hbmFnZXIgZmlyc3QgYmVmb3JlIGdvaW5nIHRvIHRoZSBzZXJ2ZXIuIEJ5IGRlZmF1bHQsIHRoZSBxdWVyeSB3aWxsIE5PVCBkbyB0aGlzLlxyXG4gIEByZXR1cm4ge1Byb21pc2V9XHJcbiAgICAtIFByb3BlcnRpZXMgb24gdGhlIHByb21pc2Ugc3VjY2VzcyByZXN1bHRcclxuICAgICAgLSBlbnRpdHkge09iamVjdH0gVGhlIGVudGl0eSByZXR1cm5lZCBvciBudWxsXHJcbiAgICAgIC0gZW50aXR5S2V5IHtFbnRpdHlLZXl9IFRoZSBlbnRpdHlLZXkgb2YgdGhlIGVudGl0eSB0byBmZXRjaC5cclxuICAgICAgLSBmcm9tQ2FjaGUge0Jvb2xlYW59IFdoZXRoZXIgdGhpcyBlbnRpdHkgd2FzIGZldGNoZWQgZnJvbSB0aGUgc2VydmVyIG9yIHdhcyBmb3VuZCBpbiB0aGUgbG9jYWwgY2FjaGUuXHJcbiAgKiovXHJcbiAgZmV0Y2hFbnRpdHlCeUtleSguLi5hcmdzOiBhbnlbXSkge1xyXG4gICAgbGV0IGRhdGFTZXJ2aWNlID0gRGF0YVNlcnZpY2UucmVzb2x2ZShbdGhpcy5kYXRhU2VydmljZV0pO1xyXG4gICAgaWYgKCghZGF0YVNlcnZpY2UuaGFzU2VydmVyTWV0YWRhdGEpIHx8IHRoaXMubWV0YWRhdGFTdG9yZS5oYXNNZXRhZGF0YUZvcihkYXRhU2VydmljZS5zZXJ2aWNlTmFtZSkpIHtcclxuICAgICAgcmV0dXJuIGZldGNoRW50aXR5QnlLZXlDb3JlKHRoaXMsIGFyZ3MpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIHRoaXMuZmV0Y2hNZXRhZGF0YShkYXRhU2VydmljZSkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgcmV0dXJuIGZldGNoRW50aXR5QnlLZXlDb3JlKHRoaXMsIGFyZ3MpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFtEZXByZWNhdGVkXSAtIEF0dGVtcHRzIHRvIGxvY2F0ZSBhbiBlbnRpdHkgd2l0aGluIHRoaXMgRW50aXR5TWFuYWdlciBieSBpdHMgIFtbRW50aXR5S2V5XV0uXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGVtcGxveWVlVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJFbXBsb3llZVwiKTtcclxuICA+ICAgICBsZXQgZW1wbG95ZWVLZXkgPSBuZXcgRW50aXR5S2V5KGVtcGxveWVlVHlwZSwgMSk7XHJcbiAgPiAgICAgbGV0IGVtcGxveWVlID0gZW0xLmZpbmRFbnRpdHlCeUtleShlbXBsb3llZUtleSk7XHJcbiAgPiAgICAgLy8gZW1wbG95ZWUgd2lsbCBlaXRoZXIgYmUgYW4gZW50aXR5IG9yIG51bGwuXHJcbiAgQGRlcHJlY2F0ZWQgICAgVXNlIGdldEVudGl0eUJ5S2V5IGluc3RlYWRcclxuICBAcGFyYW0gZW50aXR5S2V5IC0gVGhlICBbW0VudGl0eUtleV1dIG9mIHRoZSBFbnRpdHkgdG8gYmUgbG9jYXRlZC5cclxuICBAcmV0dXJuIEFuIEVudGl0eSBvciBudWxsO1xyXG4gICoqL1xyXG4gIGZpbmRFbnRpdHlCeUtleShlbnRpdHlLZXk6IEVudGl0eUtleSkge1xyXG4gICAgcmV0dXJuIHRoaXMuZ2V0RW50aXR5QnlLZXkoZW50aXR5S2V5KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEdlbmVyYXRlcyBhIHRlbXBvcmFyeSBrZXkgZm9yIHRoZSBzcGVjaWZpZWQgZW50aXR5LiAgVGhpcyBpcyB1c2VkIHRvIGluc3VyZSB0aGF0IG5ld2x5XHJcbiAgY3JlYXRlZCBlbnRpdGllcyBoYXZlIHVuaXF1ZSBrZXlzIGFuZCB0byByZWdpc3RlciB0aGF0IHRoZXNlIGtleXMgYXJlIHRlbXBvcmFyeSBhbmRcclxuICBuZWVkIHRvIGJlIGF1dG9tYXRpY2FsbHkgcmVwbGFjZWQgd2l0aCAncmVhbCcga2V5IHZhbHVlcyBvbmNlIHRoZXNlIGVudGl0aWVzIGFyZSBzYXZlZC5cclxuICBcclxuICBUaGUgW1tFbnRpdHlNYW5hZ2VyLmtleUdlbmVyYXRvckN0b3JdXSBwcm9wZXJ0eSBpcyB1c2VkIGludGVybmFsbHkgYnkgdGhpcyBtZXRob2QgdG8gYWN0dWFsbHkgZ2VuZXJhdGVcclxuICB0aGUga2V5cyAtIFNlZSB0aGUgIEtleUdlbmVyYXRvciBpbnRlcmZhY2UgaW50ZXJmYWNlIGRlc2NyaXB0aW9uIHRvIHNlZVxyXG4gIGhvdyBhIGN1c3RvbSBrZXkgZ2VuZXJhdG9yIGNhbiBiZSBwbHVnZ2VkIGluLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgY3VzdG9tZXIgPSBjdXN0VHlwZS5jcmVhdGVFbnRpdHkoKTtcclxuICA+ICAgICAgbGV0IGN1c3RvbWVySWQgPSBlbS5nZW5lcmF0ZVRlbXBLZXlWYWx1ZShjdXN0b21lcik7XHJcbiAgPiAgICAgIC8vIFRoZSAnY3VzdG9tZXInIGVudGl0eSAnQ3VzdG9tZXJJRCcgcHJvcGVydHkgaXMgbm93IHNldCB0byBhIG5ld2x5IGdlbmVyYXRlZCB1bmlxdWUgaWQgdmFsdWVcclxuICA+ICAgICAgLy8gVGhpcyBwcm9wZXJ0eSB3aWxsIGNoYW5nZSBhZ2FpbiBhZnRlciBhIHN1Y2Nlc3NmdWwgc2F2ZSBvZiB0aGUgJ2N1c3RvbWVyJyBlbnRpdHkuXHJcbiAgPiAgXHJcbiAgPiAgICAgIGVtMS5zYXZlQ2hhbmdlcygpLnRoZW4oIGZ1bmN0aW9uKCBkYXRhKSB7XHJcbiAgPiAgICAgICAgICBsZXQgc2FtZUN1c3QxID0gZGF0YS5yZXN1bHRzWzBdO1xyXG4gID4gICAgICAgICAgLy8gY3VzdDEgPT09IHNhbWVDdXN0MTtcclxuICA+ICAgICAgICAgIC8vIGJ1dCBjdXN0MS5nZXRQcm9wZXJ0eShcIkN1c3RvbWVySWRcIikgIT0gY3VzdG9tZXJJZFxyXG4gID4gICAgICAgICAgLy8gYmVjYXVzZSB0aGUgc2VydmVyIHdpbGwgaGF2ZSBnZW5lcmF0ZWQgYSBuZXcgaWRcclxuICA+ICAgICAgICAgIC8vIGFuZCB0aGUgY2xpZW50IHdpbGwgaGF2ZSBiZWVuIHVwZGF0ZWQgd2l0aCB0aGlzXHJcbiAgPiAgICAgICAgICAvLyBuZXcgaWQuXHJcbiAgPiAgICAgIH0pXHJcbiAgQHBhcmFtIGVudGl0eSAtIFRoZSBFbnRpdHkgdG8gZ2VuZXJhdGUgYSBrZXkgZm9yLlxyXG4gIEByZXR1cm4gVGhlIG5ldyBrZXkgdmFsdWVcclxuICAqKi9cclxuICBnZW5lcmF0ZVRlbXBLZXlWYWx1ZShlbnRpdHk6IEVudGl0eSkge1xyXG4gICAgLy8gVE9ETyAtIGNoZWNrIGlmIHRoaXMgZW50aXR5IGlzIGF0dGFjaGVkIHRvIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICAgIGFzc2VydFBhcmFtKGVudGl0eSwgXCJlbnRpdHlcIikuaXNFbnRpdHkoKS5jaGVjaygpO1xyXG4gICAgbGV0IGVudGl0eVR5cGUgPSBlbnRpdHkuZW50aXR5VHlwZTtcclxuICAgIGxldCBuZXh0S2V5VmFsdWUgPSB0aGlzLmtleUdlbmVyYXRvci5nZW5lcmF0ZVRlbXBLZXlWYWx1ZShlbnRpdHlUeXBlKTtcclxuICAgIGxldCBrZXlQcm9wID0gZW50aXR5VHlwZS5rZXlQcm9wZXJ0aWVzWzBdO1xyXG4gICAgZW50aXR5LnNldFByb3BlcnR5KGtleVByb3AubmFtZSwgbmV4dEtleVZhbHVlKTtcclxuICAgIGVudGl0eS5lbnRpdHlBc3BlY3QuaGFzVGVtcEtleSA9IHRydWU7XHJcbiAgICByZXR1cm4gbmV4dEtleVZhbHVlO1xyXG4gIH1cclxuXHJcbiAgaGFzQ2hhbmdlcygpOiBib29sZWFuO1xyXG4gIGhhc0NoYW5nZXMoZW50aXR5VHlwZU5hbWVzOiBzdHJpbmcgfCBzdHJpbmdbXSk6IGJvb2xlYW47XHJcbiAgaGFzQ2hhbmdlcyhlbnRpdHlUeXBlczogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSk6IGJvb2xlYW47XHJcbiAgLyoqXHJcbiAgUmV0dXJucyB3aGV0aGVyIHRoZXJlIGFyZSBhbnkgY2hhbmdlZCBlbnRpdGllcyBvZiB0aGUgc3BlY2lmaWVkIFtbRW50aXR5VHlwZV1dcy4gQSAnY2hhbmdlZCcgRW50aXR5IGhhc1xyXG4gIGhhcyBhbiBbW0VudGl0eVN0YXRlXV0gb2YgZWl0aGVyIEFkZGVkLCBNb2RpZmllZCBvciBEZWxldGVkLlxyXG5cclxuICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBkZXRlcm1pbmUgaWYgYW4gRW50aXR5TWFuYWdlciBoYXMgYW55IGNoYW5nZXNcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGlmICggZW0xLmhhc0NoYW5nZXMoKSB7XHJcbiAgPiAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgaW50ZXJlc3RpbmdcclxuICA+ICAgICAgfVxyXG5cclxuICBvciBpZiBpdCBoYXMgYW55IGNoYW5nZXMgb24gdG8gYSBzcGVjaWZpYyBbW0VudGl0eVR5cGVdXS5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgaWYgKCBlbTEuaGFzQ2hhbmdlcyhjdXN0VHlwZSkge1xyXG4gID4gICAgICAgICAgLy8gZG8gc29tZXRoaW5nIGludGVyZXN0aW5nXHJcbiAgPiAgICAgIH1cclxuXHJcbiAgb3IgdG8gYSBjb2xsZWN0aW9uIG9mIFtbRW50aXR5VHlwZV1dc1xyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gID4gICAgICBpZiAoIGVtMS5oYXNDaGFuZ2VzKCBbY3VzdFR5cGUsIG9yZGVyVHlwZV0pIHtcclxuICA+ICAgICAgICAgIC8vIGRvIHNvbWV0aGluZyBpbnRlcmVzdGluZ1xyXG4gID4gICAgICB9XHJcbiAgQHBhcmFtIGVudGl0eVR5cGVzIC0gVGhlIFtbRW50aXR5VHlwZV1dIG9yIEVudGl0eVR5cGVzIGZvciB3aGljaCAnY2hhbmdlZCcgZW50aXRpZXMgd2lsbCBiZSBmb3VuZC5cclxuICBAcGFyYW0gZW50aXR5VHlwZU5hbWVzIC0gVGhlIFtbRW50aXR5VHlwZV1dIG5hbWUgb3IgbmFtZXMgZm9yIHdoaWNoICdjaGFuZ2VkJyBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIEByZXR1cm4gV2hldGhlciB0aGVyZSBhcmUgYW55IGNoYW5nZWQgZW50aXRpZXMgdGhhdCBtYXRjaCB0aGUgdHlwZXMgc3BlY2lmaWVkLi5cclxuICAqKi9cclxuICBoYXNDaGFuZ2VzKGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZyB8IHN0cmluZ1tdKSB7XHJcbiAgICBpZiAoIXRoaXMuX2hhc0NoYW5nZXMpIHJldHVybiBmYWxzZTtcclxuICAgIGlmIChlbnRpdHlUeXBlcyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdGhpcy5faGFzQ2hhbmdlcztcclxuICAgIHJldHVybiB0aGlzLl9oYXNDaGFuZ2VzQ29yZShlbnRpdHlUeXBlcyk7XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgLy8gYmFja2Rvb3IgdG8gXCJyZWFsbHlcIiBjaGVjayBmb3IgY2hhbmdlcy5cclxuICBfaGFzQ2hhbmdlc0NvcmUoZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICAgIGxldCBldHMgPSBjaGVja0VudGl0eVR5cGVzKHRoaXMsIGVudGl0eVR5cGVzKTtcclxuICAgIGxldCBlbnRpdHlHcm91cHMgPSBnZXRFbnRpdHlHcm91cHModGhpcywgZXRzKTtcclxuICAgIHJldHVybiBlbnRpdHlHcm91cHMuc29tZShmdW5jdGlvbiAoZWcpIHtcclxuICAgICAgcmV0dXJuIGVnICYmIGVnLmhhc0NoYW5nZXMoKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q2hhbmdlcygpOiBFbnRpdHlbXTtcclxuICBnZXRDaGFuZ2VzKGVudGl0eVR5cGVOYW1lczogc3RyaW5nIHwgc3RyaW5nW10pOiBFbnRpdHlbXTtcclxuICBnZXRDaGFuZ2VzKGVudGl0eVR5cGVzOiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdKTogRW50aXR5W107XHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIGFycmF5IG9mIGFsbCBjaGFuZ2VkIGVudGl0aWVzIG9mIHRoZSBzcGVjaWZpZWQgW1tFbnRpdHlUeXBlXV1zLiBBICdjaGFuZ2VkJyBFbnRpdHkgaGFzXHJcbiAgaGFzIGFuIFtbRW50aXR5U3RhdGVdXSBvZiBlaXRoZXIgQWRkZWQsIE1vZGlmaWVkIG9yIERlbGV0ZWQuXHJcbiAgXHJcbiAgVGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gZ2V0IGFsbCBvZiB0aGUgY2hhbmdlZCBlbnRpdGllcyB3aXRoaW4gYW4gRW50aXR5TWFuYWdlclxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGNoYW5nZWRFbnRpdGllcyA9IGVtMS5nZXRDaGFuZ2VzKCk7XHJcblxyXG4gIG9yIHlvdSBjYW4gc3BlY2lmeSB0aGF0IHlvdSBvbmx5IHdhbnQgdGhlIGNoYW5nZXMgb24gYSBzcGVjaWZpYyBbW0VudGl0eVR5cGVdXVxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgY2hhbmdlZEN1c3RvbWVycyA9IGVtMS5nZXRDaGFuZ2VzKGN1c3RUeXBlKTtcclxuXHJcbiAgb3IgdG8gYSBjb2xsZWN0aW9uIG9mIFtbRW50aXR5VHlwZV1dc1xyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gID4gICAgICBsZXQgY2hhbmdlZEN1c3RvbWVyc0FuZE9yZGVycyA9IGVtMS5nZXRDaGFuZ2VzKFtjdXN0VHlwZSwgb3JkZXJUeXBlXSk7XHJcbiAgQHBhcmFtIGVudGl0eVR5cGVzIC0gVGhlIFtbRW50aXR5VHlwZV1dIG9yIEVudGl0eVR5cGVzIGZvciB3aGljaCAnY2hhbmdlZCcgZW50aXRpZXMgd2lsbCBiZSBmb3VuZC5cclxuICBAcGFyYW0gZW50aXR5VHlwZU5hbWVzIC0gVGhlIFtbRW50aXR5VHlwZV1dIG5hbWUgb3IgbmFtZXMgZm9yIHdoaWNoICdjaGFuZ2VkJyBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIEByZXR1cm4gQW4gYXJyYXkgb2YgRW50aXRpZXNcclxuICAqKi9cclxuICBnZXRDaGFuZ2VzKGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZyB8IHN0cmluZ1tdKSB7XHJcbiAgICBsZXQgZXRzID0gY2hlY2tFbnRpdHlUeXBlcyh0aGlzLCBlbnRpdHlUeXBlcyk7XHJcbiAgICByZXR1cm4gZ2V0Q2hhbmdlc0NvcmUodGhpcywgZXRzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJlamVjdHMgKHJldmVyc2VzIHRoZSBlZmZlY3RzKSBhbGwgb2YgdGhlIGFkZGl0aW9ucywgbW9kaWZpY2F0aW9ucyBhbmQgZGVsZXRlcyBmcm9tIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICBDYWxscyBbW0VudGl0eUFzcGVjdC5yZWplY3RDaGFuZ2VzXV0gb24gZXZlcnkgY2hhbmdlZCBlbnRpdHkgaW4gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGVudGl0aWVzID0gZW0xLnJlamVjdENoYW5nZXMoKTtcclxuICBAcmV0dXJuIFRoZSBlbnRpdGllcyB3aG9zZSBjaGFuZ2VzIHdlcmUgcmVqZWN0ZWQuIFRoZXNlIGVudGl0aWVzIHdpbGwgYWxsIGhhdmUgRW50aXR5U3RhdGVzIG9mXHJcbiAgZWl0aGVyICdVbmNoYW5nZWQnIG9yICdEZXRhY2hlZCdcclxuICAqKi9cclxuICByZWplY3RDaGFuZ2VzKCkge1xyXG4gICAgaWYgKCF0aGlzLl9oYXNDaGFuZ2VzKSByZXR1cm4gW107XHJcbiAgICBsZXQgY2hhbmdlcyA9IGdldENoYW5nZXNDb3JlKHRoaXMpO1xyXG4gICAgLy8gbmV4dCBsaW5lIHN0b3BzIGluZGl2aWR1YWwgcmVqZWN0IGNoYW5nZXMgZnJvbSBlYWNoIGNhbGxpbmcgX2hhc0NoYW5nZXNDb3JlXHJcbiAgICBsZXQgYXNwZWN0cyA9IGNoYW5nZXMubWFwKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIHJldHVybiBlLmVudGl0eUFzcGVjdC5fY2hlY2tPcGVyYXRpb24oXCJyZWplY3RDaGFuZ2VzXCIpO1xyXG4gICAgfSk7XHJcbiAgICB0aGlzLl9oYXNDaGFuZ2VzID0gZmFsc2U7XHJcbiAgICBhc3BlY3RzLmZvckVhY2goZnVuY3Rpb24gKGFzcGVjdCkge1xyXG4gICAgICBhc3BlY3QucmVqZWN0Q2hhbmdlcygpO1xyXG4gICAgfSk7XHJcbiAgICB0aGlzLmhhc0NoYW5nZXNDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlNYW5hZ2VyOiB0aGlzLCBoYXNDaGFuZ2VzOiBmYWxzZSB9KTtcclxuICAgIHJldHVybiBjaGFuZ2VzO1xyXG4gIH1cclxuXHJcbiAgZ2V0RW50aXRpZXMoZW50aXR5VHlwZU5hbWVzPzogc3RyaW5nIHwgc3RyaW5nW10sIGVudGl0eVN0YXRlcz86IEVudGl0eVN0YXRlIHwgRW50aXR5U3RhdGVbXSk6IEVudGl0eVtdO1xyXG4gIGdldEVudGl0aWVzKGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSwgZW50aXR5U3RhdGVzPzogRW50aXR5U3RhdGUgfCBFbnRpdHlTdGF0ZVtdKTogRW50aXR5W107XHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIGFycmF5IG9mIGFsbCBlbnRpdGllcyBvZiB0aGUgc3BlY2lmaWVkIFtbRW50aXR5VHlwZV1dcyB3aXRoIHRoZSBzcGVjaWZpZWQgW1tFbnRpdHlTdGF0ZV1dcy5cclxuXHJcbiAgVGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gZ2V0IGFsbCBvZiB0aGUgZW50aXRpZXMgd2l0aGluIGFuIEVudGl0eU1hbmFnZXJcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBlbnRpdGllcyA9IGVtMS5nZXRFbnRpdGllcygpO1xyXG5cclxuICBvciB5b3UgY2FuIHNwZWNpZnkgdGhhdCB5b3Ugb25seSB3YW50IHRoZSBjaGFuZ2VzIG9uIGEgc3BlY2lmaWMgW1tFbnRpdHlUeXBlXV1cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IGN1c3RvbWVycyA9IGVtMS5nZXRFbnRpdGllcyhjdXN0VHlwZSk7XHJcblxyXG4gIG9yIHRvIGEgY29sbGVjdGlvbiBvZiBbW0VudGl0eVR5cGVdXXNcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IG9yZGVyVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJPcmRlclwiKTtcclxuICA+ICAgICAgbGV0IGN1c3RvbWVyc0FuZE9yZGVycyA9IGVtMS5nZXRDaGFuZ2VzKFtjdXN0VHlwZSwgb3JkZXJUeXBlXSk7XHJcblxyXG4gIFlvdSBjYW4gYWxzbyBhc2sgZm9yIGVudGl0aWVzIHdpdGggYSBwYXJ0aWN1bGFyIFtbRW50aXR5U3RhdGVdXSBvciBFbnRpdHlTdGF0ZXMuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBvcmRlclR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiT3JkZXJcIik7XHJcbiAgPiAgICAgIGxldCBhZGRlZEN1c3RvbWVyc0FuZE9yZGVycyA9IGVtMS5nZXRFbnRpdGllcyhbY3VzdFR5cGUsIG9yZGVyVHlwZV0sIEVudGl0eVN0YXRlLkFkZGVkKTtcclxuIFxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlTmFtZSAtIFRoZSBbW0VudGl0eVR5cGVdXSBuYW1lIG9yIG5hbWVzIGZvciB3aGljaCBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIElmIHRoaXMgcGFyYW1ldGVyIGlzIG9taXR0ZWQsIGFsbCBFbnRpdHlUeXBlcyBhcmUgc2VhcmNoZWQuICBcclxuICBAcGFyYW0gZW50aXR5VHlwZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gb3IgRW50aXR5VHlwZXMgZm9yIHdoaWNoIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgSWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCwgYWxsIEVudGl0eVR5cGVzIGFyZSBzZWFyY2hlZC4gXHJcbiAgQHBhcmFtIGVudGl0eVN0YXRlcyAtIFRoZSBbW0VudGl0eVN0YXRlXV1zIGZvciB3aGljaCBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIElmIHRoaXMgcGFyYW1ldGVyIGlzIG9taXR0ZWQsIGVudGl0aWVzIG9mIGFsbCBFbnRpdHlTdGF0ZXMgYXJlIHJldHVybmVkLlxyXG4gIEByZXR1cm4gQW4gYXJyYXkgb2YgRW50aXRpZXNcclxuICAqKi9cclxuICBnZXRFbnRpdGllcyhlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCBzdHJpbmcgfCBzdHJpbmdbXSwgZW50aXR5U3RhdGVzPzogRW50aXR5U3RhdGUgfCBFbnRpdHlTdGF0ZVtdKSB7XHJcbiAgICBsZXQgZW50VHlwZXMgPSBjaGVja0VudGl0eVR5cGVzKHRoaXMsIGVudGl0eVR5cGVzKTtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eVN0YXRlcywgXCJlbnRpdHlTdGF0ZXNcIikuaXNPcHRpb25hbCgpLmlzRW51bU9mKEVudGl0eVN0YXRlKS5vcigpLmlzTm9uRW1wdHlBcnJheSgpLmlzRW51bU9mKEVudGl0eVN0YXRlKS5jaGVjaygpO1xyXG5cclxuICAgIGxldCBzdGF0ZXMgPSB2YWxpZGF0ZUVudGl0eVN0YXRlcyh0aGlzLCBlbnRpdHlTdGF0ZXMpO1xyXG4gICAgcmV0dXJuIGdldEVudGl0aWVzQ29yZSh0aGlzLCBlbnRUeXBlcywgc3RhdGVzKTtcclxuICB9XHJcblxyXG5cclxuICAvLyBwcm90ZWN0ZWQgbWV0aG9kc1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9ub3RpZnlTdGF0ZUNoYW5nZShlbnRpdHk6IEVudGl0eSwgbmVlZHNTYXZlOiBib29sZWFuKSB7XHJcbiAgICBsZXQgZWNBcmdzID0geyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5FbnRpdHlTdGF0ZUNoYW5nZSwgZW50aXR5OiBlbnRpdHkgfTtcclxuXHJcbiAgICBpZiAobmVlZHNTYXZlKSB7XHJcbiAgICAgIGlmICghdGhpcy5faGFzQ2hhbmdlcykgdGhpcy5fc2V0SGFzQ2hhbmdlcyh0cnVlKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIGNhbGxlZCB3aGVuIHJlamVjdGluZyBhIGNoYW5nZSBvciBtZXJnaW5nIGFuIHVuY2hhbmdlZCByZWNvcmQuXHJcbiAgICAgIC8vIE5PVEU6IHRoaXMgY2FuIGJlIHNsb3cgd2l0aCBsb3RzIG9mIGVudGl0aWVzIGluIHRoZSBjYWNoZS5cclxuICAgICAgLy8gc28gZGVmZXIgaXQgZHVyaW5nIGEgcXVlcnkvaW1wb3J0IG9yIHNhdmUgYW5kIGNhbGwgaXQgb25jZSB3aGVuIGNvbXBsZXRlICggaWYgbmVlZGVkKS5cclxuICAgICAgaWYgKHRoaXMuX2hhc0NoYW5nZXMpIHtcclxuICAgICAgICBpZiAodGhpcy5pc0xvYWRpbmcpIHtcclxuICAgICAgICAgIHRoaXMuX2hhc0NoYW5nZXNBY3Rpb24gPSB0aGlzLl9oYXNDaGFuZ2VzQWN0aW9uIHx8IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdGhpcy5fc2V0SGFzQ2hhbmdlcyhudWxsKTtcclxuICAgICAgICAgICAgdGhpcy5lbnRpdHlDaGFuZ2VkLnB1Ymxpc2goZWNBcmdzKTtcclxuICAgICAgICAgIH0uYmluZCh0aGlzKTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdGhpcy5fc2V0SGFzQ2hhbmdlcygpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5lbnRpdHlDaGFuZ2VkLnB1Ymxpc2goZWNBcmdzKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9zZXRIYXNDaGFuZ2VzKGhhc0NoYW5nZXM/OiBib29sZWFuKSB7XHJcbiAgICBpZiAoaGFzQ2hhbmdlcyA9PSBudWxsKSBoYXNDaGFuZ2VzID0gdGhpcy5faGFzQ2hhbmdlc0NvcmUoKTtcclxuICAgIGxldCBoYWRDaGFuZ2VzID0gdGhpcy5faGFzQ2hhbmdlcztcclxuICAgIHRoaXMuX2hhc0NoYW5nZXMgPSBoYXNDaGFuZ2VzO1xyXG4gICAgaWYgKGhhc0NoYW5nZXMgIT09IGhhZENoYW5nZXMpIHtcclxuICAgICAgdGhpcy5oYXNDaGFuZ2VzQ2hhbmdlZC5wdWJsaXNoKHsgZW50aXR5TWFuYWdlcjogdGhpcywgaGFzQ2hhbmdlczogaGFzQ2hhbmdlcyB9KTtcclxuICAgIH1cclxuICAgIHRoaXMuX2hhc0NoYW5nZXNBY3Rpb24gPSB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfbGlua1JlbGF0ZWRFbnRpdGllcyhlbnRpdHk6IEVudGl0eSkge1xyXG4gICAgbGV0IGVtID0gdGhpcztcclxuICAgIGxldCBlbnRpdHlBc3BlY3QgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgLy8gd2UgZG8gbm90IHdhbnQgZW50aXR5U3RhdGUgdG8gY2hhbmdlIGFzIGEgcmVzdWx0IG9mIGxpbmthZ2UuXHJcbiAgICBjb3JlLnVzaW5nKGVtLCBcImlzTG9hZGluZ1wiLCB0cnVlLCBmdW5jdGlvbiAoKSB7XHJcblxyXG4gICAgICBsZXQgdW5hdHRhY2hlZE1hcCA9IGVtLl91bmF0dGFjaGVkQ2hpbGRyZW5NYXA7XHJcbiAgICAgIGxldCBlbnRpdHlLZXkgPSBlbnRpdHlBc3BlY3QuZ2V0S2V5KCk7XHJcbiAgICAgIGxldCBlbnRpdHlUeXBlID0gZW50aXR5S2V5LmVudGl0eVR5cGU7XHJcblxyXG4gICAgICB3aGlsZSAoZW50aXR5VHlwZSkge1xyXG4gICAgICAgIGxldCBrZXlzdHJpbmcgPSBlbnRpdHlLZXkudG9TdHJpbmcoZW50aXR5VHlwZSk7XHJcblxyXG4gICAgICAgIC8vIGF0dGFjaCBhbnkgdW5hdHRhY2hlZENoaWxkcmVuXHJcbiAgICAgICAgbGV0IHR1cGxlcyA9IHVuYXR0YWNoZWRNYXAuZ2V0VHVwbGVzQnlTdHJpbmcoa2V5c3RyaW5nKTtcclxuICAgICAgICBpZiAodHVwbGVzKSB7XHJcbiAgICAgICAgICB0dXBsZXMuc2xpY2UoMCkuZm9yRWFjaChmdW5jdGlvbiAodHBsKSB7XHJcblxyXG4gICAgICAgICAgICBsZXQgdW5hdHRhY2hlZENoaWxkcmVuID0gdHBsLmNoaWxkcmVuLmZpbHRlcihmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgIHJldHVybiBlLmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZSAhPT0gRW50aXR5U3RhdGUuRGV0YWNoZWQ7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgbGV0IGNoaWxkVG9QYXJlbnROcDogTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gICAgICAgICAgICBsZXQgcGFyZW50VG9DaGlsZE5wOiBOYXZpZ2F0aW9uUHJvcGVydHk7XHJcblxyXG4gICAgICAgICAgICAvLyBucCBpcyB1c3VhbGx5IGNoaWxkVG9QYXJlbnROcFxyXG4gICAgICAgICAgICAvLyBleGNlcHQgd2l0aCB1bmlkaXJlY3Rpb25hbCAxLW4gd2hlcmUgaXQgaXMgcGFyZW50VG9DaGlsZE5wO1xyXG4gICAgICAgICAgICBsZXQgbnAgPSB0cGwubmF2aWdhdGlvblByb3BlcnR5O1xyXG5cclxuICAgICAgICAgICAgbGV0IGludmVyc2VOcCA9IG5wLmludmVyc2U7XHJcbiAgICAgICAgICAgIGlmIChpbnZlcnNlTnApIHtcclxuICAgICAgICAgICAgICAvLyBiaWRpcmVjdGlvbmFsXHJcbiAgICAgICAgICAgICAgY2hpbGRUb1BhcmVudE5wID0gbnA7XHJcbiAgICAgICAgICAgICAgcGFyZW50VG9DaGlsZE5wID0gaW52ZXJzZU5wO1xyXG5cclxuICAgICAgICAgICAgICBpZiAocGFyZW50VG9DaGlsZE5wLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgb25seUNoaWxkID0gdW5hdHRhY2hlZENoaWxkcmVuWzBdO1xyXG4gICAgICAgICAgICAgICAgZW50aXR5LnNldFByb3BlcnR5KHBhcmVudFRvQ2hpbGROcC5uYW1lLCBvbmx5Q2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgb25seUNoaWxkLnNldFByb3BlcnR5KGNoaWxkVG9QYXJlbnROcC5uYW1lLCBlbnRpdHkpO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudENoaWxkcmVuID0gZW50aXR5LmdldFByb3BlcnR5KHBhcmVudFRvQ2hpbGROcC5uYW1lKTtcclxuICAgICAgICAgICAgICAgIHVuYXR0YWNoZWRDaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICAgICAgICBjdXJyZW50Q2hpbGRyZW4ucHVzaChjaGlsZCk7XHJcbiAgICAgICAgICAgICAgICAgIGNoaWxkLnNldFByb3BlcnR5KGNoaWxkVG9QYXJlbnROcC5uYW1lLCBlbnRpdHkpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIHVuYXR0YWNoZWRNYXAucmVtb3ZlQ2hpbGRyZW4oa2V5c3RyaW5nLCBjaGlsZFRvUGFyZW50TnApO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIC8vIHVuaWRpcmVjdGlvbmFsXHJcbiAgICAgICAgICAgICAgLy8gaWYgKG5wLmlzU2NhbGFyIHx8IG5wLnBhcmVudFR5cGUgIT09IGVudGl0eS5lbnRpdHlUeXBlKSB7XHJcbiAgICAgICAgICAgICAgaWYgKG5wLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBuIC0+IDEgIGVnOiBjaGlsZDogT3JkZXJEZXRhaWwgcGFyZW50OiBQcm9kdWN0XHJcbiAgICAgICAgICAgICAgICAvLyAxIC0+IDEgZWcgY2hpbGQ6IEVtcGxveWVlIHBhcmVudDogRW1wbG95ZWUgKCBvbmx5IE1hbmFnZXIsIG5vIERpcmVjdFJlcG9ydHMgcHJvcGVydHkpXHJcbiAgICAgICAgICAgICAgICBjaGlsZFRvUGFyZW50TnAgPSBucDtcclxuICAgICAgICAgICAgICAgIHVuYXR0YWNoZWRDaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICAgICAgICBjaGlsZC5zZXRQcm9wZXJ0eShjaGlsZFRvUGFyZW50TnAubmFtZSwgZW50aXR5KTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgdW5hdHRhY2hlZE1hcC5yZW1vdmVDaGlsZHJlbihrZXlzdHJpbmcsIGNoaWxkVG9QYXJlbnROcCk7XHJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vIDEgLT4gbiAgZWc6IHBhcmVudDogUmVnaW9uIGNoaWxkOiBUZXJyXHJcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBuZWVkIHRvIHJlbW92ZSB1bmF0dGFjaGVkIGNoaWxkcmVuIGZyb20gdGhlIG1hcCBhZnRlciB0aGlzOyBvbmx5IGEgcGVyZiBpc3N1ZS5cclxuICAgICAgICAgICAgICAgIHBhcmVudFRvQ2hpbGROcCA9IG5wO1xyXG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRDaGlsZHJlbiA9IGVudGl0eS5nZXRQcm9wZXJ0eShwYXJlbnRUb0NoaWxkTnAubmFtZSk7XHJcbiAgICAgICAgICAgICAgICB1bmF0dGFjaGVkQ2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgICAgLy8gd2Uga25vdyBpZiBjYW4ndCBhbHJlYWR5IGJlIHRoZXJlLlxyXG4gICAgICAgICAgICAgICAgICBjdXJyZW50Q2hpbGRyZW4uX3B1c2goY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZW50aXR5VHlwZSA9IGVudGl0eVR5cGUuYmFzZUVudGl0eVR5cGU7IC8vIGxvb2sgZm9yIHJlbGF0aW9uc2hpcHMgdXAgdGhlIGhpZXJhcmNoeVxyXG4gICAgICB9XHJcblxyXG5cclxuICAgICAgLy8gbm93IGFkZCB0byB1bmF0dGFjaGVkTWFwIGlmIG5lZWRlZC5cclxuICAgICAgZW50aXR5LmVudGl0eVR5cGUubmF2aWdhdGlvblByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAobnApIHtcclxuICAgICAgICBpZiAobnAuaXNTY2FsYXIpIHtcclxuICAgICAgICAgIGxldCB2YWx1ZSA9IGVudGl0eS5nZXRQcm9wZXJ0eShucC5uYW1lKTtcclxuICAgICAgICAgIC8vIHByb3BlcnR5IGlzIGFscmVhZHkgbGlua2VkIHVwXHJcbiAgICAgICAgICBpZiAodmFsdWUpIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGZpcnN0IGRldGVybWluZSBpZiBucCBjb250YWlucyBhIHBhcmVudCBvciBjaGlsZFxyXG4gICAgICAgIC8vIGhhdmluZyBhIHBhcmVudEtleSBtZWFucyB0aGF0IHRoaXMgaXMgYSBjaGlsZFxyXG4gICAgICAgIC8vIGlmIGEgcGFyZW50IHRoZW4gbm8gbmVlZCBmb3IgbW9yZSB3b3JrIGJlY2F1c2UgY2hpbGRyZW4gd2lsbCBhdHRhY2ggdG8gaXQuXHJcbiAgICAgICAgbGV0IHBhcmVudEtleSA9IGVudGl0eUFzcGVjdC5nZXRQYXJlbnRLZXkobnApO1xyXG4gICAgICAgIGlmIChwYXJlbnRLZXkpIHtcclxuICAgICAgICAgIC8vIGNoZWNrIGZvciBlbXB0eSBrZXlzIC0gbWVhbmluZyB0aGF0IHBhcmVudCBpZCdzIGFyZSBub3QgeWV0IHNldC5cclxuICAgICAgICAgIGlmIChwYXJlbnRLZXkuX2lzRW1wdHkoKSkgcmV0dXJuO1xyXG4gICAgICAgICAgLy8gaWYgYSBjaGlsZCAtIGxvb2sgZm9yIHBhcmVudCBpbiB0aGUgZW0gY2FjaGVcclxuICAgICAgICAgIGlmIChucC5pbnZGb3JlaWduS2V5TmFtZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIC8vIG5wIHJlbGF0ZXMgdG8gbm9uLVBLIHByb3BlcnR5IG9mIHBhcmVudCBlbnRpdHlcclxuICAgICAgICAgICAgY29uc3QgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkocGFyZW50S2V5LmVudGl0eVR5cGUuZGVmYXVsdFJlc291cmNlTmFtZSkud2hlcmUobnAuaW52Rm9yZWlnbktleU5hbWVzWzBdLCAnZXEnLCBwYXJlbnRLZXkudmFsdWVzWzBdKTtcclxuICAgICAgICAgICAgY29uc3QgcXJlc3VsdCA9IGVtLmV4ZWN1dGVRdWVyeUxvY2FsbHkocXVlcnkpO1xyXG4gICAgICAgICAgICBpZiAocXJlc3VsdC5sZW5ndGggPT09IDEpIHtcclxuICAgICAgICAgICAgICBsZXQgcGFyZW50ID0gcXJlc3VsdFswXTtcclxuICAgICAgICAgICAgICBlbnRpdHkuc2V0UHJvcGVydHkobnAubmFtZSwgcGFyZW50KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gbnAgcmVsYXRlcyB0byBQSyBvZiBwYXJlbnQgZW50aXR5XHJcbiAgICAgICAgICAgIGxldCBwYXJlbnQgPSBlbS5nZXRFbnRpdHlCeUtleShwYXJlbnRLZXkpO1xyXG4gICAgICAgICAgICBpZiAocGFyZW50KSB7XHJcbiAgICAgICAgICAgICAgLy8gaWYgZm91bmQgaG9vayBpdCB1cFxyXG4gICAgICAgICAgICAgIGVudGl0eS5zZXRQcm9wZXJ0eShucC5uYW1lLCBwYXJlbnQpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIC8vIGVsc2UgYWRkIHBhcmVudCB0byB1bnJlc29sdmVkUGFyZW50TWFwO1xyXG4gICAgICAgICAgICAgIHVuYXR0YWNoZWRNYXAuYWRkQ2hpbGQocGFyZW50S2V5LCBucCwgZW50aXR5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSBpZiAobnAuaW52ZXJzZSAmJiBucC5pbnZlcnNlLmludkZvcmVpZ25LZXlOYW1lcy5sZW5ndGgpIHtcclxuICAgICAgICAgIC8vIG5wIHJlbGF0ZXMgdG8gbm9uLVBLIHByb3BlcnR5IG9mIHBhcmVudCBlbnRpdHk7IHF1ZXJ5IGVudGl0aWVzIGJ5IEZLXHJcbiAgICAgICAgICBjb25zdCBha1ZhbHVlID0gZW50aXR5LmdldFByb3BlcnR5KG5wLmludmVyc2UuaW52Rm9yZWlnbktleU5hbWVzWzBdKTtcclxuICAgICAgICAgIGNvbnN0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KG5wLmVudGl0eVR5cGUuZGVmYXVsdFJlc291cmNlTmFtZSkud2hlcmUobnAuaW52Rm9yZWlnbktleU5hbWVzWzBdLCAnZXEnLCBha1ZhbHVlKTtcclxuICAgICAgICAgIGNvbnN0IHFyZXN1bHQgPSBlbS5leGVjdXRlUXVlcnlMb2NhbGx5KHF1ZXJ5KTtcclxuICAgICAgICAgIHFyZXN1bHQuZm9yRWFjaCgoY2hpbGQ6IEVudGl0eSkgPT4ge1xyXG4gICAgICAgICAgICBjaGlsZC5zZXRQcm9wZXJ0eShucC5pbnZlcnNlLm5hbWUsIGVudGl0eSk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy8gaGFuZGxlIHVuaWRpcmVjdGlvbmFsIDEteCB3aGVyZSB3ZSBzZXQgeC5ma1xyXG4gICAgICBlbnRpdHkuZW50aXR5VHlwZS5mb3JlaWduS2V5UHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChma1Byb3ApIHtcclxuICAgICAgICBsZXQgaW52TnAgPSBma1Byb3AuaW52ZXJzZU5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuICAgICAgICBpZiAoIWludk5wKSByZXR1cm47XHJcbiAgICAgICAgLy8gdW5pZGlyZWN0aW9uYWwgZmsgcHJvcHMgb25seVxyXG4gICAgICAgIGxldCBma1ZhbHVlID0gZW50aXR5LmdldFByb3BlcnR5KGZrUHJvcC5uYW1lKTtcclxuICAgICAgICBsZXQgcGFyZW50S2V5ID0gbmV3IEVudGl0eUtleShpbnZOcC5wYXJlbnRUeXBlLCBbZmtWYWx1ZV0pO1xyXG4gICAgICAgIGxldCBwYXJlbnQgPSBlbS5nZXRFbnRpdHlCeUtleShwYXJlbnRLZXkpO1xyXG5cclxuICAgICAgICBpZiAocGFyZW50KSB7XHJcbiAgICAgICAgICBpZiAoaW52TnAuaXNTY2FsYXIpIHtcclxuICAgICAgICAgICAgcGFyZW50LnNldFByb3BlcnR5KGludk5wLm5hbWUsIGVudGl0eSk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpZiAoZW0uaXNMb2FkaW5nKSB7XHJcbiAgICAgICAgICAgICAgcGFyZW50LmdldFByb3BlcnR5KGludk5wLm5hbWUpLl9wdXNoKGVudGl0eSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgcGFyZW50LmdldFByb3BlcnR5KGludk5wLm5hbWUpLnB1c2goZW50aXR5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAvLyBlbHNlIGFkZCBwYXJlbnQgdG8gdW5yZXNvbHZlZFBhcmVudE1hcDtcclxuICAgICAgICAgIHVuYXR0YWNoZWRNYXAuYWRkQ2hpbGQocGFyZW50S2V5LCBpbnZOcCwgZW50aXR5KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcblxyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2F0dGFjaEVudGl0eUNvcmUoZW50aXR5OiBFbnRpdHksIGVudGl0eVN0YXRlOiBFbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneSkge1xyXG4gICAgbGV0IGdyb3VwID0gZmluZE9yQ3JlYXRlRW50aXR5R3JvdXAodGhpcywgZW50aXR5LmVudGl0eVR5cGUpO1xyXG4gICAgbGV0IGF0dGFjaGVkRW50aXR5ID0gZ3JvdXAuYXR0YWNoRW50aXR5KGVudGl0eSwgZW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3kpO1xyXG4gICAgdGhpcy5fbGlua1JlbGF0ZWRFbnRpdGllcyhhdHRhY2hlZEVudGl0eSk7XHJcbiAgICByZXR1cm4gYXR0YWNoZWRFbnRpdHk7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfdXBkYXRlRmtWYWwoZmtQcm9wOiBEYXRhUHJvcGVydHksIG9sZFZhbHVlOiBhbnksIG5ld1ZhbHVlOiBhbnkpIHtcclxuICAgIGxldCBncm91cCA9IHRoaXMuX2VudGl0eUdyb3VwTWFwW2ZrUHJvcC5wYXJlbnRUeXBlLm5hbWVdO1xyXG4gICAgaWYgKCFncm91cCkgcmV0dXJuO1xyXG4gICAgZ3JvdXAuX3VwZGF0ZUZrVmFsKGZrUHJvcCwgb2xkVmFsdWUsIG5ld1ZhbHVlKTtcclxuICB9XHJcbn1cclxuXHJcbkVudGl0eU1hbmFnZXIucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIkVudGl0eU1hbmFnZXJcIjtcclxuXHJcbkJyZWV6ZUV2ZW50LmJ1YmJsZUV2ZW50KEVudGl0eU1hbmFnZXIucHJvdG90eXBlKTtcclxuXHJcbmZ1bmN0aW9uIGNsZWFyU2VydmVyRXJyb3JzKGVudGl0aWVzOiBFbnRpdHlbXSkge1xyXG4gIGVudGl0aWVzLmZvckVhY2goZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgbGV0IHNlcnZlcktleXM6IHN0cmluZ1tdID0gW107XHJcbiAgICBsZXQgYXNwZWN0ID0gZW50aXR5LmVudGl0eUFzcGVjdDtcclxuICAgIGNvcmUub2JqZWN0Rm9yRWFjaChhc3BlY3QuX3ZhbGlkYXRpb25FcnJvcnMsIGZ1bmN0aW9uIChrZXksIHZlKSB7XHJcbiAgICAgIGlmICh2ZS5pc1NlcnZlckVycm9yKSBzZXJ2ZXJLZXlzLnB1c2goa2V5KTtcclxuICAgIH0pO1xyXG4gICAgaWYgKHNlcnZlcktleXMubGVuZ3RoID09PSAwKSByZXR1cm47XHJcbiAgICBhc3BlY3QuX3Byb2Nlc3NWYWxpZGF0aW9uT3BBbmRQdWJsaXNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgc2VydmVyS2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcclxuICAgICAgICBhc3BlY3QuX3JlbW92ZVZhbGlkYXRpb25FcnJvcihrZXkpO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVFbnRpdHlFcnJvcnMoZW50aXRpZXM6IEVudGl0eVtdKSB7XHJcbiAgbGV0IGVudGl0eUVycm9yczogRW50aXR5RXJyb3JbXSA9IFtdO1xyXG4gIGVudGl0aWVzLmZvckVhY2goKGVudGl0eSkgPT4ge1xyXG4gICAgY29yZS5vYmplY3RGb3JFYWNoKGVudGl0eS5lbnRpdHlBc3BlY3QuX3ZhbGlkYXRpb25FcnJvcnMsIGZ1bmN0aW9uIChrZXksIHZlKSB7XHJcbiAgICAgIGxldCBjZmcgPSBjb3JlLmV4dGVuZCh7XHJcbiAgICAgICAgZW50aXR5OiBlbnRpdHksXHJcbiAgICAgICAgZXJyb3JOYW1lOiB2ZS52YWxpZGF0b3IubmFtZVxyXG4gICAgICB9LCB2ZSwgW1wiZXJyb3JNZXNzYWdlXCIsIFwicHJvcGVydHlOYW1lXCIsIFwiaXNTZXJ2ZXJFcnJvclwiLCBcImN1c3RvbVwiXSkgYXMgRW50aXR5RXJyb3I7XHJcbiAgICAgIGVudGl0eUVycm9ycy5wdXNoKGNmZyk7XHJcbiAgICB9KTtcclxuICB9KTtcclxuICByZXR1cm4gZW50aXR5RXJyb3JzO1xyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gcHJvY2Vzc1NlcnZlckVycm9ycyhzYXZlQ29udGV4dDogU2F2ZUNvbnRleHQsIHNhdmVFcnJvcjogU2F2ZUVycm9yRnJvbVNlcnZlcikge1xyXG4gIC8vIGNvbnZlcnRpbmcgSVNhdmVFcnJvckZyb21TZXJ2ZXIgLT4gSVNhdmVFcnJvclxyXG4gIGxldCBzZXJ2ZXJFcnJvcnMgPSBzYXZlRXJyb3IuZW50aXR5RXJyb3JzO1xyXG4gIGlmICghc2VydmVyRXJyb3JzKSByZXR1cm4gPFNhdmVFcnJvcj4gPGFueT4gc2F2ZUVycm9yO1xyXG4gIGxldCBlbnRpdHlNYW5hZ2VyID0gc2F2ZUNvbnRleHQuZW50aXR5TWFuYWdlcjtcclxuICBsZXQgbWV0YWRhdGFTdG9yZSA9IGVudGl0eU1hbmFnZXIubWV0YWRhdGFTdG9yZTtcclxuICBsZXQgZW50aXR5RXJyb3JzID0gc2VydmVyRXJyb3JzLm1hcCgoc2VycikgPT4ge1xyXG4gICAgbGV0IGVudGl0eTogRW50aXR5IHwgbnVsbCA9IG51bGw7XHJcbiAgICBsZXQgZW50aXR5VHlwZTogRW50aXR5VHlwZSB8IHVuZGVmaW5lZDtcclxuICAgIGlmIChzZXJyLmtleVZhbHVlcykge1xyXG4gICAgICBlbnRpdHlUeXBlID0gbWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoc2Vyci5lbnRpdHlUeXBlTmFtZSkgYXMgRW50aXR5VHlwZTtcclxuICAgICAgbGV0IGVrZXkgPSBuZXcgRW50aXR5S2V5KGVudGl0eVR5cGUsIHNlcnIua2V5VmFsdWVzKTtcclxuICAgICAgZW50aXR5ID0gZW50aXR5TWFuYWdlci5nZXRFbnRpdHlCeUtleShla2V5KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoZW50aXR5VHlwZSAmJiBlbnRpdHkpIHtcclxuICAgICAgbGV0IGNvbnRleHQgPSBzZXJyLnByb3BlcnR5TmFtZSA/XHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvcGVydHlOYW1lOiBzZXJyLnByb3BlcnR5TmFtZSxcclxuICAgICAgICAgIHByb3BlcnR5OiBlbnRpdHlUeXBlLmdldFByb3BlcnR5KHNlcnIucHJvcGVydHlOYW1lKVxyXG4gICAgICAgIH0gOiB7XHJcbiAgICAgICAgfTtcclxuICAgICAgbGV0IGtleSA9IFZhbGlkYXRpb25FcnJvci5nZXRLZXkoc2Vyci5lcnJvck5hbWUgfHwgc2Vyci5lcnJvck1lc3NhZ2UsIHNlcnIucHJvcGVydHlOYW1lKTtcclxuXHJcbiAgICAgIGxldCB2ZSA9IG5ldyBWYWxpZGF0aW9uRXJyb3IobnVsbCwgY29udGV4dCwgc2Vyci5lcnJvck1lc3NhZ2UsIGtleSk7XHJcbiAgICAgIHZlLmlzU2VydmVyRXJyb3IgPSB0cnVlO1xyXG4gICAgICBlbnRpdHkuZW50aXR5QXNwZWN0LmFkZFZhbGlkYXRpb25FcnJvcih2ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGVudGl0eUVycm9yID0gY29yZS5leHRlbmQoe1xyXG4gICAgICBlbnRpdHk6IGVudGl0eSxcclxuICAgICAgaXNTZXJ2ZXJFcnJvcjogdHJ1ZVxyXG4gICAgfSwgc2VyciwgW1wiZXJyb3JOYW1lXCIsIFwiZXJyb3JNZXNzYWdlXCIsIFwicHJvcGVydHlOYW1lXCIsIFwiY3VzdG9tXCJdKSBhcyBFbnRpdHlFcnJvcjtcclxuICAgIHJldHVybiBlbnRpdHlFcnJvcjtcclxuICB9KTtcclxuICAvLyBjb252ZXJ0aW5nIElTYXZlRXJyb3JGcm9tU2VydmVyIC0+IElTYXZlRXJyb3IgXHJcbiAgc2F2ZUVycm9yLmVudGl0eUVycm9ycyA9IGVudGl0eUVycm9ycyBhcyBhbnk7XHJcbiAgcmV0dXJuIDxTYXZlRXJyb3I+IDxhbnk+IHNhdmVFcnJvcjtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBJRW50aXR5QnlLZXlSZXN1bHQge1xyXG4gIGVudGl0eT86IEVudGl0eTtcclxuICBlbnRpdHlLZXk6IEVudGl0eUtleTtcclxuICBmcm9tQ2FjaGU6IGJvb2xlYW47XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZldGNoRW50aXR5QnlLZXlDb3JlKGVtOiBFbnRpdHlNYW5hZ2VyLCBhcmdzOiBhbnlbXSk6IFByb21pc2U8SUVudGl0eUJ5S2V5UmVzdWx0PiB7XHJcbiAgbGV0IHRwbCA9IGNyZWF0ZUVudGl0eUtleShlbSwgYXJncyk7XHJcbiAgbGV0IGVudGl0eUtleSA9IHRwbC5lbnRpdHlLZXk7XHJcblxyXG4gIGxldCBjaGVja0xvY2FsQ2FjaGVGaXJzdCA9IHRwbC5yZW1haW5pbmdBcmdzLmxlbmd0aCA9PT0gMCA/IGZhbHNlIDogISF0cGwucmVtYWluaW5nQXJnc1swXTtcclxuICBsZXQgZW50aXR5OiBFbnRpdHkgfCBudWxsID0gbnVsbDtcclxuICBsZXQgZm91bmRJdCA9IGZhbHNlO1xyXG4gIGlmIChjaGVja0xvY2FsQ2FjaGVGaXJzdCkge1xyXG4gICAgZW50aXR5ID0gZW0uZ2V0RW50aXR5QnlLZXkoZW50aXR5S2V5KTtcclxuICAgIGZvdW5kSXQgPSBlbnRpdHkgIT0gbnVsbDtcclxuICAgIGlmIChlbnRpdHkgIT0gbnVsbCAmJlxyXG4gICAgICAvLyBudWxsIHRoZSBlbnRpdHkgaWYgaXQgaXMgZGVsZXRlZCBhbmQgd2Ugc2hvdWxkIGV4Y2x1ZGUgZGVsZXRlZCBlbnRpdGllc1xyXG4gICAgICAhZW0ucXVlcnlPcHRpb25zLmluY2x1ZGVEZWxldGVkICYmIGVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUuaXNEZWxldGVkKCkpIHtcclxuICAgICAgZW50aXR5ID0gbnVsbDtcclxuICAgICAgLy8gYnV0IHJlc3VtZSBsb29raW5nIGlmIHdlJ2Qgb3ZlcndyaXRlIGRlbGV0ZWQgZW50aXR5IHdpdGggYSByZW1vdGUgZW50aXR5XHJcbiAgICAgIC8vIG5vdGU6IGVtLnF1ZXJ5T3B0aW9ucyBpcyBhbHdheXMgZnVsbHkgcmVzb2x2ZWQgYnkgbm93XHJcbiAgICAgIGZvdW5kSXQgPSBlbS5xdWVyeU9wdGlvbnMubWVyZ2VTdHJhdGVneSAhPT0gTWVyZ2VTdHJhdGVneS5PdmVyd3JpdGVDaGFuZ2VzO1xyXG4gICAgfVxyXG4gIH1cclxuICBpZiAoZm91bmRJdCkge1xyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGVudGl0eTogZW50aXR5IHx8IHVuZGVmaW5lZCwgZW50aXR5S2V5OiBlbnRpdHlLZXksIGZyb21DYWNoZTogdHJ1ZSB9KTtcclxuICB9IGVsc2Uge1xyXG4gICAgcmV0dXJuIEVudGl0eVF1ZXJ5LmZyb21FbnRpdHlLZXkoZW50aXR5S2V5KS51c2luZyhlbSkuZXhlY3V0ZSgpLnRoZW4oZnVuY3Rpb24gKGRhdGE6IGFueSkge1xyXG4gICAgICBlbnRpdHkgPSAoZGF0YS5yZXN1bHRzLmxlbmd0aCA9PT0gMCkgPyBudWxsIDogZGF0YS5yZXN1bHRzWzBdO1xyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgZW50aXR5OiBlbnRpdHkgfHwgdW5kZWZpbmVkLCBlbnRpdHlLZXk6IGVudGl0eUtleSwgZnJvbUNhY2hlOiBmYWxzZSB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxufVxyXG5cclxuXHJcbi8vIHByaXZhdGUgZm5zXHJcblxyXG4vLyB0YWtlcyBpbiBlbnRpdHlUeXBlcyBhcyBlaXRoZXIgc3RyaW5ncyBvciBlbnRpdHlUeXBlcyBvciBhcnJheXMgb2YgZWl0aGVyXHJcbi8vIGFuZCByZXR1cm5zIGVpdGhlciBhbiBlbnRpdHlUeXBlIG9yIGFuIGFycmF5IG9mIGVudGl0eVR5cGVzIG9yIHRocm93cyBhbiBlcnJvclxyXG5mdW5jdGlvbiBjaGVja0VudGl0eVR5cGVzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCBzdHJpbmcgfCBzdHJpbmdbXSkge1xyXG4gIGFzc2VydFBhcmFtKGVudGl0eVR5cGVzLCBcImVudGl0eVR5cGVzXCIpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpLm9yKCkuaXNOb25FbXB0eUFycmF5KCkuaXNTdHJpbmcoKVxyXG4gICAgLm9yKCkuaXNJbnN0YW5jZU9mKEVudGl0eVR5cGUpLm9yKCkuaXNOb25FbXB0eUFycmF5KCkuaXNJbnN0YW5jZU9mKEVudGl0eVR5cGUpLmNoZWNrKCk7XHJcbiAgbGV0IHJlc3VsdFR5cGVzOiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgdW5kZWZpbmVkO1xyXG4gIGlmICh0eXBlb2YgZW50aXR5VHlwZXMgPT09IFwic3RyaW5nXCIpIHtcclxuICAgIHJlc3VsdFR5cGVzID0gZW0ubWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoZW50aXR5VHlwZXMsIGZhbHNlKSBhcyAoRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSk7XHJcbiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGVudGl0eVR5cGVzKSAmJiB0eXBlb2YgZW50aXR5VHlwZXNbMF0gPT09IFwic3RyaW5nXCIpIHtcclxuICAgIHJlc3VsdFR5cGVzID0gKGVudGl0eVR5cGVzIGFzIHN0cmluZ1tdKS5tYXAoZnVuY3Rpb24gKGV0TmFtZSkge1xyXG4gICAgICByZXR1cm4gZW0ubWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoZXROYW1lLCBmYWxzZSkgYXMgRW50aXR5VHlwZTtcclxuICAgIH0pO1xyXG4gIH0gZWxzZSB7XHJcbiAgICByZXN1bHRUeXBlcyA9IGVudGl0eVR5cGVzIGFzIChFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgdW5kZWZpbmVkKTtcclxuICB9XHJcblxyXG4gIHJldHVybiByZXN1bHRUeXBlcztcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0Q2hhbmdlc0NvcmUoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSkge1xyXG4gIGxldCBlbnRpdHlHcm91cHMgPSBnZXRFbnRpdHlHcm91cHMoZW0sIGVudGl0eVR5cGVzKTtcclxuXHJcbiAgLy8gVE9ETzogdGhpbmsgYWJvdXQgd3JpdGluZyBhIGNvcmUubWFwTWFueSBtZXRob2QgaWYgd2Ugc2VlIG1vcmUgb2YgdGhlc2UuXHJcbiAgbGV0IHNlbGVjdGVkOiBFbnRpdHlbXSA9IFtdO1xyXG4gIGVudGl0eUdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChlZykge1xyXG4gICAgLy8gZWcgbWF5IGJlIHVuZGVmaW5lZCBvciBudWxsXHJcbiAgICBpZiAoIWVnKSByZXR1cm47XHJcbiAgICBsZXQgZW50aXRpZXMgPSBlZy5nZXRDaGFuZ2VzKCk7XHJcbiAgICBpZiAoc2VsZWN0ZWQgJiYgc2VsZWN0ZWQubGVuZ3RoKSB7XHJcbiAgICAgIHNlbGVjdGVkID0gc2VsZWN0ZWQuY29uY2F0KGVudGl0aWVzKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHNlbGVjdGVkID0gZW50aXRpZXM7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIHNlbGVjdGVkO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRFbnRpdGllc0NvcmUoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVR5cGVzOiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgdW5kZWZpbmVkLCBlbnRpdHlTdGF0ZXM6IEVudGl0eVN0YXRlW10pIHtcclxuICBsZXQgZW50aXR5R3JvdXBzID0gZ2V0RW50aXR5R3JvdXBzKGVtLCBlbnRpdHlUeXBlcyk7XHJcblxyXG4gIC8vIFRPRE86IHRoaW5rIGFib3V0IHdyaXRpbmcgYSBjb3JlLm1hcE1hbnkgbWV0aG9kIGlmIHdlIHNlZSBtb3JlIG9mIHRoZXNlLlxyXG4gIGxldCBzZWxlY3RlZDogRW50aXR5W10gPSBbXTtcclxuICBlbnRpdHlHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZWcpIHtcclxuICAgIC8vIGVnIG1heSBiZSB1bmRlZmluZWQgb3IgbnVsbFxyXG4gICAgaWYgKCFlZykgcmV0dXJuO1xyXG4gICAgbGV0IGVudGl0aWVzID0gZWcuZ2V0RW50aXRpZXMoZW50aXR5U3RhdGVzKTtcclxuICAgIGlmIChzZWxlY3RlZCAmJiBzZWxlY3RlZC5sZW5ndGgpIHtcclxuICAgICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZW50aXRpZXMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgc2VsZWN0ZWQgPSBlbnRpdGllcztcclxuICAgIH1cclxuICB9KTtcclxuICByZXR1cm4gc2VsZWN0ZWQ7XHJcbn1cclxuXHJcblxyXG5mdW5jdGlvbiBjcmVhdGVFbnRpdHlLZXkoZW06IEVudGl0eU1hbmFnZXIsIGFyZ3M6IGFueVtdKSB7XHJcbiAgdHJ5IHtcclxuICAgIGlmIChhcmdzWzBdIGluc3RhbmNlb2YgRW50aXR5S2V5KSB7XHJcbiAgICAgIHJldHVybiB7IGVudGl0eUtleTogYXJnc1swXSBhcyBFbnRpdHlLZXksIHJlbWFpbmluZ0FyZ3M6IGNvcmUuYXJyYXlTbGljZShhcmdzLCAxKSB9O1xyXG4gICAgfSBlbHNlIGlmIChhcmdzLmxlbmd0aCA+PSAyKSB7XHJcbiAgICAgIGxldCBlbnRpdHlUeXBlID0gKHR5cGVvZiBhcmdzWzBdID09PSAnc3RyaW5nJykgPyBlbS5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShhcmdzWzBdLCBmYWxzZSkgOiBhcmdzWzBdO1xyXG4gICAgICByZXR1cm4geyBlbnRpdHlLZXk6IG5ldyBFbnRpdHlLZXkoZW50aXR5VHlwZSwgYXJnc1sxXSksIHJlbWFpbmluZ0FyZ3M6IGNvcmUuYXJyYXlTbGljZShhcmdzLCAyKSB9O1xyXG4gICAgfVxyXG4gIH0gY2F0Y2ggKGUpIHsvKiB0aHJvdyBiZWxvdyAqL1xyXG4gICAgLy8gdGhyb3cgbmV3IEVycm9yKFwiTXVzdCBzdXBwbHkgYW4gRW50aXR5S2V5IE9SIGFuIEVudGl0eVR5cGUgbmFtZSBvciBFbnRpdHlUeXBlIGZvbGxvd2VkIGJ5IGEga2V5IHZhbHVlIG9yIGFuIGFycmF5IG9mIGtleSB2YWx1ZXMuXCIpO1xyXG4gIH1cclxuICB0aHJvdyBuZXcgRXJyb3IoXCJNdXN0IHN1cHBseSBhbiBFbnRpdHlLZXkgT1IgYW4gRW50aXR5VHlwZSBuYW1lIG9yIEVudGl0eVR5cGUgZm9sbG93ZWQgYnkgYSBrZXkgdmFsdWUgb3IgYW4gYXJyYXkgb2Yga2V5IHZhbHVlcy5cIik7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIG1hcmtJc0JlaW5nU2F2ZWQoZW50aXRpZXM6IEVudGl0eVtdLCBmbGFnOiBib29sZWFuKSB7XHJcbiAgZW50aXRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICBlbnRpdHkuZW50aXR5QXNwZWN0LmlzQmVpbmdTYXZlZCA9IGZsYWc7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGV4cG9ydEVudGl0eUdyb3VwcyhlbTogRW50aXR5TWFuYWdlciwgZW50aXRpZXNPckVudGl0eVR5cGVzOiBFbnRpdHlbXSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZ1tdKSB7XHJcbiAgbGV0IGVudGl0eUdyb3VwTWFwOiB7IFtpbmRleDogc3RyaW5nXTogRW50aXR5R3JvdXAgfTtcclxuICBsZXQgZmlyc3QgPSBlbnRpdGllc09yRW50aXR5VHlwZXMgJiYgZW50aXRpZXNPckVudGl0eVR5cGVzWzBdO1xyXG4gIC8vIGNoZWNrIGlmIGFycmF5XHJcbiAgaWYgKGZpcnN0KSB7XHJcbiAgICAvLyBncm91cCBlbnRpdGllcyBieSBlbnRpdHlUeXBlIGFuZFxyXG4gICAgLy8gY3JlYXRlICdncm91cHMnIHRoYXQgbG9vayBsaWtlIGVudGl0eUdyb3Vwcy5cclxuICAgIGVudGl0eUdyb3VwTWFwID0ge307XHJcbiAgICBpZiAoKGZpcnN0IGFzIGFueSkuZW50aXR5VHlwZSkge1xyXG4gICAgICBsZXQgZW50aXRpZXMgPSBlbnRpdGllc09yRW50aXR5VHlwZXMgYXMgRW50aXR5W107XHJcbiAgICAgIC8vIGFzc3VtZSBcImVudGl0aWVzXCIgaXMgYW4gYXJyYXkgb2YgZW50aXRpZXM7XHJcbiAgICAgIGVudGl0aWVzLmZvckVhY2goZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBpZiAoZS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUgPT09IEVudGl0eVN0YXRlLkRldGFjaGVkKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gZXhwb3J0IGFuIGVudGl0eSB3aXRoIGFuIEVudGl0eVN0YXRlIG9mICdEZXRhY2hlZCdcIik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGxldCBncm91cCA9IGVudGl0eUdyb3VwTWFwW2UuZW50aXR5VHlwZS5uYW1lXTtcclxuICAgICAgICBpZiAoIWdyb3VwKSB7XHJcbiAgICAgICAgICBncm91cCA9IHt9IGFzIEVudGl0eUdyb3VwO1xyXG4gICAgICAgICAgZ3JvdXAuZW50aXR5VHlwZSA9IGUuZW50aXR5VHlwZTtcclxuICAgICAgICAgIGdyb3VwLl9lbnRpdGllcyA9IFtdO1xyXG4gICAgICAgICAgZW50aXR5R3JvdXBNYXBbZS5lbnRpdHlUeXBlLm5hbWVdID0gZ3JvdXA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGdyb3VwLl9lbnRpdGllcy5wdXNoKGUpO1xyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIGFzc3VtZSBcImVudGl0aWVzXCIgaXMgYW4gYXJyYXkgb2YgRW50aXR5VHlwZXMgKG9yIG5hbWVzKVxyXG4gICAgICBsZXQgZW50aXR5VHlwZXMgPSBjaGVja0VudGl0eVR5cGVzKGVtLCBlbnRpdGllc09yRW50aXR5VHlwZXMgYXMgRW50aXR5VHlwZVtdIHwgc3RyaW5nW10pIGFzIEVudGl0eVR5cGVbXTtcclxuICAgICAgaWYgKGVudGl0eVR5cGVzICE9IG51bGwpIHtcclxuICAgICAgICBlbnRpdHlUeXBlcy5mb3JFYWNoKChldCkgPT4ge1xyXG4gICAgICAgICAgbGV0IGdyb3VwID0gZW0uX2VudGl0eUdyb3VwTWFwW2V0Lm5hbWVdO1xyXG4gICAgICAgICAgaWYgKGdyb3VwICYmIGdyb3VwLl9lbnRpdGllcy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgZW50aXR5R3JvdXBNYXBbZXQubmFtZV0gPSBncm91cDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0gZWxzZSBpZiAoZW50aXRpZXNPckVudGl0eVR5cGVzICYmIGVudGl0aWVzT3JFbnRpdHlUeXBlcy5sZW5ndGggPT09IDApIHtcclxuICAgIC8vIGVtcHR5IGFycmF5ID0gZXhwb3J0IG5vdGhpbmdcclxuICAgIGVudGl0eUdyb3VwTWFwID0ge307XHJcbiAgfSBlbHNlIHtcclxuICAgIGVudGl0eUdyb3VwTWFwID0gZW0uX2VudGl0eUdyb3VwTWFwO1xyXG4gIH1cclxuXHJcbiAgbGV0IHRlbXBLZXlzOiBJVGVtcEtleVtdID0gW107XHJcbiAgbGV0IG5ld0dyb3VwTWFwID0ge307XHJcbiAgY29yZS5vYmplY3RGb3JFYWNoKGVudGl0eUdyb3VwTWFwLCAoZW50aXR5VHlwZU5hbWUsIGVudGl0eUdyb3VwKSA9PiB7XHJcbiAgICBuZXdHcm91cE1hcFtlbnRpdHlUeXBlTmFtZV0gPSBleHBvcnRFbnRpdHlHcm91cChlbnRpdHlHcm91cCwgdGVtcEtleXMpO1xyXG4gIH0pO1xyXG5cclxuICByZXR1cm4geyBlbnRpdHlHcm91cE1hcDogbmV3R3JvdXBNYXAsIHRlbXBLZXlzOiB0ZW1wS2V5cyB9O1xyXG59XHJcblxyXG5mdW5jdGlvbiBleHBvcnRFbnRpdHlHcm91cChlbnRpdHlHcm91cDogRW50aXR5R3JvdXAsIHRlbXBLZXlzOiBJVGVtcEtleVtdKSB7XHJcbiAgbGV0IHJlc3VsdEdyb3VwID0ge30gYXMgeyBlbnRpdGllczogYW55W10gfTtcclxuICBsZXQgZW50aXR5VHlwZSA9IGVudGl0eUdyb3VwLmVudGl0eVR5cGU7XHJcbiAgbGV0IGRwcyA9IGVudGl0eVR5cGUuZGF0YVByb3BlcnRpZXM7XHJcbiAgbGV0IHNlcmlhbGl6ZXJGbiA9IGdldFNlcmlhbGl6ZXJGbihlbnRpdHlUeXBlKTtcclxuICBsZXQgcmF3RW50aXRpZXM6IGFueVtdID0gW107XHJcbiAgZW50aXR5R3JvdXAuX2VudGl0aWVzLmZvckVhY2goKGVudGl0eSkgPT4ge1xyXG4gICAgaWYgKGVudGl0eSkge1xyXG4gICAgICBsZXQgcmF3RW50aXR5ID0gc3RydWN0dXJhbE9iamVjdFRvSnNvbihlbnRpdHksIGRwcywgc2VyaWFsaXplckZuLCB0ZW1wS2V5cyk7XHJcbiAgICAgIHJhd0VudGl0aWVzLnB1c2gocmF3RW50aXR5KTtcclxuICAgIH1cclxuICB9KTtcclxuICByZXN1bHRHcm91cC5lbnRpdGllcyA9IHJhd0VudGl0aWVzO1xyXG4gIHJldHVybiByZXN1bHRHcm91cDtcclxufVxyXG5cclxuZnVuY3Rpb24gc3RydWN0dXJhbE9iamVjdFRvSnNvbihzbzogU3RydWN0dXJhbE9iamVjdCwgZHBzOiBEYXRhUHJvcGVydHlbXSwgc2VyaWFsaXplckZuPzogKGRwOiBEYXRhUHJvcGVydHksIHZhbHVlOiBhbnkpID0+IGFueSwgdGVtcEtleXM/OiBJVGVtcEtleVtdKSB7XHJcblxyXG4gIGxldCByZXN1bHQgPSB7fTtcclxuICBkcHMuZm9yRWFjaChmdW5jdGlvbiAoZHApIHtcclxuICAgIGxldCBkcE5hbWUgPSBkcC5uYW1lO1xyXG4gICAgbGV0IHZhbHVlID0gc28uZ2V0UHJvcGVydHkoZHBOYW1lKTtcclxuICAgIGlmICh2YWx1ZSA9PSBudWxsICYmIGRwLmRlZmF1bHRWYWx1ZSA9PSBudWxsKSByZXR1cm47XHJcblxyXG4gICAgaWYgKHZhbHVlICYmIGRwLmlzQ29tcGxleFByb3BlcnR5KSB7XHJcbiAgICAgIGxldCBjb0RwcyA9IChkcC5kYXRhVHlwZSBhcyBDb21wbGV4VHlwZSkuZGF0YVByb3BlcnRpZXM7XHJcbiAgICAgIHZhbHVlID0gY29yZS5tYXAodmFsdWUsIGZ1bmN0aW9uICh2OiBDb21wbGV4T2JqZWN0KSB7XHJcbiAgICAgICAgcmV0dXJuIHN0cnVjdHVyYWxPYmplY3RUb0pzb24odiwgY29EcHMsIHNlcmlhbGl6ZXJGbik7XHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdmFsdWUgPSBzZXJpYWxpemVyRm4gPyBzZXJpYWxpemVyRm4oZHAsIHZhbHVlKSA6IHZhbHVlO1xyXG4gICAgICBpZiAoZHAuaXNVbm1hcHBlZCkge1xyXG4gICAgICAgIHZhbHVlID0gY29yZS50b0pTT05TYWZlKHZhbHVlLCBjb3JlLnRvSlNPTlNhZmVSZXBsYWNlcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XHJcbiAgICByZXN1bHRbZHBOYW1lXSA9IHZhbHVlO1xyXG4gIH0pO1xyXG5cclxuICAvLyBpZiAoc28uZW50aXR5QXNwZWN0KSB7XHJcbiAgaWYgKEVudGl0eUFzcGVjdC5pc0VudGl0eShzbykpIHtcclxuICAgIGxldCBhc3BlY3QgPSBzby5lbnRpdHlBc3BlY3Q7XHJcbiAgICBsZXQgZW50aXR5U3RhdGUgPSBhc3BlY3QuZW50aXR5U3RhdGU7XHJcbiAgICBsZXQgbmV3QXNwZWN0ID0ge1xyXG4gICAgICB0ZW1wTmF2UHJvcE5hbWVzOiBleHBvcnRUZW1wS2V5SW5mbyhhc3BlY3QsIHRlbXBLZXlzIHx8IFtdKSxcclxuICAgICAgZW50aXR5U3RhdGU6IGVudGl0eVN0YXRlLm5hbWVcclxuICAgIH0gYXMgYW55O1xyXG4gICAgaWYgKGFzcGVjdC5leHRyYU1ldGFkYXRhKSB7XHJcbiAgICAgIG5ld0FzcGVjdC5leHRyYU1ldGFkYXRhID0gYXNwZWN0LmV4dHJhTWV0YWRhdGE7XHJcbiAgICB9XHJcbiAgICBpZiAoZW50aXR5U3RhdGUuaXNNb2RpZmllZCgpIHx8IGVudGl0eVN0YXRlLmlzRGVsZXRlZCgpKSB7XHJcbiAgICAgIG5ld0FzcGVjdC5vcmlnaW5hbFZhbHVlc01hcCA9IGFzcGVjdC5vcmlnaW5hbFZhbHVlcztcclxuICAgIH1cclxuICAgIChyZXN1bHQgYXMgYW55KS5lbnRpdHlBc3BlY3QgPSBuZXdBc3BlY3Q7XHJcbiAgfSBlbHNlIHtcclxuICAgIGxldCBhc3BlY3QgPSBzby5jb21wbGV4QXNwZWN0O1xyXG4gICAgbGV0IG5ld0FzcGVjdCA9IHt9IGFzIGFueTtcclxuICAgIGlmIChhc3BlY3Qub3JpZ2luYWxWYWx1ZXMgJiYgIWNvcmUuaXNFbXB0eShhc3BlY3Qub3JpZ2luYWxWYWx1ZXMpKSB7XHJcbiAgICAgIG5ld0FzcGVjdC5vcmlnaW5hbFZhbHVlc01hcCA9IGFzcGVjdC5vcmlnaW5hbFZhbHVlcztcclxuICAgIH1cclxuXHJcbiAgICAocmVzdWx0IGFzIGFueSkuY29tcGxleEFzcGVjdCA9IG5ld0FzcGVjdDtcclxuICB9XHJcblxyXG4gIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmludGVyZmFjZSBJVGVtcEtleSB7XHJcbiAgZW50aXR5VHlwZTogc3RyaW5nO1xyXG4gIHZhbHVlczogYW55W107XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGV4cG9ydFRlbXBLZXlJbmZvKGVudGl0eUFzcGVjdDogRW50aXR5QXNwZWN0LCB0ZW1wS2V5czogSVRlbXBLZXlbXSkge1xyXG4gIGxldCBlbnRpdHkgPSBlbnRpdHlBc3BlY3QuZW50aXR5IGFzIEVudGl0eTtcclxuICBpZiAoZW50aXR5QXNwZWN0Lmhhc1RlbXBLZXkpIHtcclxuICAgIHRlbXBLZXlzLnB1c2goZW50aXR5QXNwZWN0LmdldEtleSgpLnRvSlNPTigpKTtcclxuICB9XHJcbiAgLy8gY3JlYXRlIG1hcCBmb3IgdGhpcyBlbnRpdHkgd2l0aCBmb3JlaWduS2V5cyB0aGF0IGFyZSAndGVtcG9yYXJ5J1xyXG4gIC8vIG1hcCAtPiBrZXk6IHRlbXBLZXksIHZhbHVlOiBma1Byb3BOYW1lXHJcbiAgbGV0IHRlbXBOYXZQcm9wTmFtZXM6IHN0cmluZ1tdID0gW107XHJcbiAgZW50aXR5LmVudGl0eVR5cGUubmF2aWdhdGlvblByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAobnApIHtcclxuICAgIGlmIChucC5yZWxhdGVkRGF0YVByb3BlcnRpZXMpIHtcclxuICAgICAgbGV0IHJlbGF0ZWRWYWx1ZSA9IGVudGl0eS5nZXRQcm9wZXJ0eShucC5uYW1lKTtcclxuICAgICAgaWYgKHJlbGF0ZWRWYWx1ZSAmJiByZWxhdGVkVmFsdWUuZW50aXR5QXNwZWN0Lmhhc1RlbXBLZXkpIHtcclxuICAgICAgICB0ZW1wTmF2UHJvcE5hbWVzLnB1c2gobnAubmFtZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9KTtcclxuICByZXR1cm4gdGVtcE5hdlByb3BOYW1lcztcclxufVxyXG5cclxuZnVuY3Rpb24gaW1wb3J0RW50aXR5R3JvdXAoZW50aXR5R3JvdXA6IEVudGl0eUdyb3VwLCBqc29uR3JvdXA6IHsgZW50aXRpZXM6IGFueVtdIH0sIGltcG9ydENvbmZpZzogSW1wb3J0Q29uZmlnRXh0KSB7XHJcblxyXG4gIGxldCB0ZW1wS2V5TWFwID0gaW1wb3J0Q29uZmlnLnRlbXBLZXlNYXA7XHJcbiAgbGV0IG1lcmdlQWRkcyA9ICEhaW1wb3J0Q29uZmlnLm1lcmdlQWRkcztcclxuXHJcbiAgbGV0IGVudGl0eVR5cGUgPSBlbnRpdHlHcm91cC5lbnRpdHlUeXBlO1xyXG4gIGxldCBtZXJnZVN0cmF0ZWd5ID0gaW1wb3J0Q29uZmlnLm1lcmdlU3RyYXRlZ3k7XHJcblxyXG4gIGxldCB0YXJnZXRFbnRpdHk6IEVudGl0eSB8IHVuZGVmaW5lZDtcclxuXHJcbiAgbGV0IGVtID0gZW50aXR5R3JvdXAuZW50aXR5TWFuYWdlcjtcclxuICBsZXQgZW50aXR5Q2hhbmdlZCA9IGVtLmVudGl0eUNoYW5nZWQ7XHJcbiAgbGV0IGVudGl0aWVzVG9MaW5rOiBFbnRpdHlbXSA9IFtdO1xyXG4gIGxldCByYXdWYWx1ZUZuID0gRGF0YVByb3BlcnR5LmdldFJhd1ZhbHVlRnJvbUNsaWVudDtcclxuICBqc29uR3JvdXAuZW50aXRpZXMuZm9yRWFjaChmdW5jdGlvbiAocmF3RW50aXR5OiBhbnkpIHtcclxuICAgIGxldCBuZXdBc3BlY3QgPSByYXdFbnRpdHkuZW50aXR5QXNwZWN0O1xyXG5cclxuICAgIGxldCBlbnRpdHlLZXkgPSBlbnRpdHlUeXBlLmdldEVudGl0eUtleUZyb21SYXdFbnRpdHkocmF3RW50aXR5LCByYXdWYWx1ZUZuKTtcclxuICAgIGxldCBlbnRpdHlTdGF0ZSA9IEVudGl0eVN0YXRlLmZyb21OYW1lKG5ld0FzcGVjdC5lbnRpdHlTdGF0ZSkgYXMgRW50aXR5U3RhdGU7XHJcbiAgICBpZiAoIWVudGl0eVN0YXRlIHx8IGVudGl0eVN0YXRlID09PSBFbnRpdHlTdGF0ZS5EZXRhY2hlZCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IGVudGl0aWVzIHdpdGggYSBub24gZGV0YWNoZWQgZW50aXR5IHN0YXRlIG1heSBiZSBpbXBvcnRlZC5cIik7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gTWVyZ2UgaWYgcmF3IGVudGl0eSBpcyBpbiBjYWNoZSBVTkxFU1MgdGhpcyBpcyBhIG5ldyBlbnRpdHkgdy8gYSB0ZW1wIGtleVxyXG4gICAgLy8gQ2Fubm90IHNhZmVseSBtZXJnZSBzdWNoIGVudGl0aWVzIGV2ZW4gaWYgY291bGQgbWF0Y2ggdGVtcCBrZXkgdG8gYW4gZW50aXR5IGluIGNhY2hlLlxyXG4gICAgLy8gQ2FuIGVuYWJsZSBtZXJnZSBvZiBlbnRpdGllcyB3L3RlbXAga2V5IHVzaW5nIFwibWVyZ2VBZGRzXCIgLSB1c2UgYXQgeW91ciBvd24gcmlzayFcclxuICAgIGxldCBuZXdUZW1wS2V5ID0gIW1lcmdlQWRkcyAmJiBlbnRpdHlTdGF0ZS5pc0FkZGVkKCkgJiYgZ2V0TWFwcGVkS2V5KHRlbXBLZXlNYXAhLCBlbnRpdHlLZXkpO1xyXG4gICAgdGFyZ2V0RW50aXR5ID0gbmV3VGVtcEtleSA/IHVuZGVmaW5lZCA6IGVudGl0eUdyb3VwLmZpbmRFbnRpdHlCeUtleShlbnRpdHlLZXkpO1xyXG5cclxuICAgIGlmICh0YXJnZXRFbnRpdHkpIHtcclxuICAgICAgaWYgKG1lcmdlU3RyYXRlZ3kgPT09IE1lcmdlU3RyYXRlZ3kuU2tpcE1lcmdlKSB7XHJcbiAgICAgICAgLy8gZGVsaWJlcmF0ZSBmYWxsIHRocnVcclxuICAgICAgfSBlbHNlIGlmIChtZXJnZVN0cmF0ZWd5ID09PSBNZXJnZVN0cmF0ZWd5LkRpc2FsbG93ZWQpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBIE1lcmdlU3RyYXRlZ3kgb2YgJ0Rpc2FsbG93ZWQnIHByZXZlbnRzIFwiICsgZW50aXR5S2V5LnRvU3RyaW5nKCkgKyBcIiBmcm9tIGJlaW5nIG1lcmdlZFwiKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBsZXQgdGFyZ2V0RW50aXR5U3RhdGUgPSB0YXJnZXRFbnRpdHkuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlO1xyXG4gICAgICAgIGxldCB3YXNVbmNoYW5nZWQgPSB0YXJnZXRFbnRpdHlTdGF0ZS5pc1VuY2hhbmdlZCgpO1xyXG4gICAgICAgIGlmIChtZXJnZVN0cmF0ZWd5ID09PSBNZXJnZVN0cmF0ZWd5Lk92ZXJ3cml0ZUNoYW5nZXMgfHwgd2FzVW5jaGFuZ2VkKSB7XHJcbiAgICAgICAgICBlbnRpdHlUeXBlLl91cGRhdGVUYXJnZXRGcm9tUmF3KHRhcmdldEVudGl0eSwgcmF3RW50aXR5LCByYXdWYWx1ZUZuKTtcclxuICAgICAgICAgIHRhcmdldEVudGl0eS5lbnRpdHlBc3BlY3Quc2V0RW50aXR5U3RhdGUoZW50aXR5U3RhdGUpO1xyXG4gICAgICAgICAgZW50aXR5Q2hhbmdlZC5wdWJsaXNoKHsgZW50aXR5QWN0aW9uOiBFbnRpdHlBY3Rpb24uTWVyZ2VPbkltcG9ydCwgZW50aXR5OiB0YXJnZXRFbnRpdHkgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0YXJnZXRFbnRpdHkgPSBlbnRpdHlUeXBlLl9jcmVhdGVJbnN0YW5jZUNvcmUoKSBhcyBFbnRpdHk7XHJcbiAgICAgIGVudGl0eVR5cGUuX3VwZGF0ZVRhcmdldEZyb21SYXcodGFyZ2V0RW50aXR5LCByYXdFbnRpdHksIHJhd1ZhbHVlRm4pO1xyXG4gICAgICBpZiAobmV3VGVtcEtleSkge1xyXG4gICAgICAgIHRhcmdldEVudGl0eS5lbnRpdHlBc3BlY3QuaGFzVGVtcEtleSA9IHRydWU7XHJcbiAgICAgICAgLy8gZml4dXAgcGtcclxuICAgICAgICB0YXJnZXRFbnRpdHkuc2V0UHJvcGVydHkoZW50aXR5VHlwZS5rZXlQcm9wZXJ0aWVzWzBdLm5hbWUsIG5ld1RlbXBLZXkudmFsdWVzWzBdKTtcclxuXHJcbiAgICAgICAgLy8gZml4dXAgZm9yZWlnbiBrZXlzXHJcbiAgICAgICAgLy8gVGhpcyBpcyBzYWZlIGJlY2F1c2UgdGhlIGVudGl0eSBpcyBkZXRhY2hlZCBoZXJlIGFuZCB0aGVyZWZvcmUgb3JpZ2luYWxWYWx1ZXMgd2lsbCBub3QgYmUgdXBkYXRlZC5cclxuICAgICAgICBpZiAobmV3QXNwZWN0LnRlbXBOYXZQcm9wTmFtZXMpIHtcclxuICAgICAgICAgIG5ld0FzcGVjdC50ZW1wTmF2UHJvcE5hbWVzLmZvckVhY2goZnVuY3Rpb24gKG5wTmFtZTogc3RyaW5nKSB7XHJcbiAgICAgICAgICAgIGxldCBucCA9IGVudGl0eVR5cGUuZ2V0TmF2aWdhdGlvblByb3BlcnR5KG5wTmFtZSk7XHJcbiAgICAgICAgICAgIGxldCBma1Byb3BOYW1lID0gbnAhLnJlbGF0ZWREYXRhUHJvcGVydGllc1swXS5uYW1lO1xyXG4gICAgICAgICAgICBsZXQgb2xkRmtWYWx1ZSA9IHRhcmdldEVudGl0eSEuZ2V0UHJvcGVydHkoZmtQcm9wTmFtZSk7XHJcbiAgICAgICAgICAgIGxldCBmayA9IG5ldyBFbnRpdHlLZXkobnAhLmVudGl0eVR5cGUsIFtvbGRGa1ZhbHVlXSk7XHJcbiAgICAgICAgICAgIGxldCBuZXdGayA9IGdldE1hcHBlZEtleSh0ZW1wS2V5TWFwISwgZmspO1xyXG4gICAgICAgICAgICB0YXJnZXRFbnRpdHkhLnNldFByb3BlcnR5KGZrUHJvcE5hbWUsIG5ld0ZrIS52YWx1ZXNbMF0pO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIC8vIE5vdyBwZXJmb3JtZWQgaW4gYXR0YWNoRW50aXR5XHJcbiAgICAgIHRhcmdldEVudGl0eSA9IGVudGl0eUdyb3VwLmF0dGFjaEVudGl0eSh0YXJnZXRFbnRpdHksIGVudGl0eVN0YXRlKTtcclxuICAgICAgZW50aXR5Q2hhbmdlZC5wdWJsaXNoKHsgZW50aXR5QWN0aW9uOiBFbnRpdHlBY3Rpb24uQXR0YWNoT25JbXBvcnQsIGVudGl0eTogdGFyZ2V0RW50aXR5IH0pO1xyXG4gICAgICBpZiAoIWVudGl0eVN0YXRlLmlzVW5jaGFuZ2VkKCkpIHtcclxuICAgICAgICBlbS5fbm90aWZ5U3RhdGVDaGFuZ2UodGFyZ2V0RW50aXR5LCB0cnVlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGVudGl0aWVzVG9MaW5rLnB1c2godGFyZ2V0RW50aXR5KTtcclxuICB9KTtcclxuICByZXR1cm4gZW50aXRpZXNUb0xpbms7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldE1hcHBlZEtleSh0ZW1wS2V5TWFwOiBJVGVtcEtleU1hcCwgZW50aXR5S2V5OiBFbnRpdHlLZXkpIHtcclxuICBsZXQgbmV3S2V5ID0gdGVtcEtleU1hcFtlbnRpdHlLZXkudG9TdHJpbmcoKV07XHJcbiAgaWYgKG5ld0tleSkgcmV0dXJuIG5ld0tleTtcclxuICBsZXQgc3VidHlwZXMgPSBlbnRpdHlLZXkuX3N1YnR5cGVzO1xyXG4gIGlmICghc3VidHlwZXMpIHJldHVybiBudWxsO1xyXG4gIGZvciAobGV0IGkgPSAwLCBqID0gc3VidHlwZXMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcbiAgICBuZXdLZXkgPSB0ZW1wS2V5TWFwW2VudGl0eUtleS50b1N0cmluZyhzdWJ0eXBlc1tpXSldO1xyXG4gICAgaWYgKG5ld0tleSkgcmV0dXJuIG5ld0tleTtcclxuICB9XHJcbiAgcmV0dXJuIG51bGw7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHByb21pc2VXaXRoQ2FsbGJhY2tzPFQ+KHByb21pc2U6IFByb21pc2U8VD4sIGNhbGxiYWNrPzogQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s/OiBFcnJvckNhbGxiYWNrKSB7XHJcbiAgcHJvbWlzZSA9IHByb21pc2UudGhlbihmdW5jdGlvbiAoZGF0YSkge1xyXG4gICAgaWYgKGNhbGxiYWNrKSBjYWxsYmFjayhkYXRhKTtcclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZGF0YSk7XHJcbiAgfSwgZnVuY3Rpb24gKGVycm9yKSB7XHJcbiAgICBpZiAoZXJyb3JDYWxsYmFjaykgZXJyb3JDYWxsYmFjayhlcnJvcik7XHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xyXG4gIH0pO1xyXG4gIHJldHVybiBwcm9taXNlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRFbnRpdGllc1RvU2F2ZShlbTogRW50aXR5TWFuYWdlciwgZW50aXRpZXM/OiBFbnRpdHlbXSkge1xyXG4gIGxldCBlbnRpdGllc1RvU2F2ZTogRW50aXR5W107XHJcbiAgaWYgKGVudGl0aWVzKSB7XHJcbiAgICBlbnRpdGllc1RvU2F2ZSA9IGVudGl0aWVzLmZpbHRlcihmdW5jdGlvbiAoZSkge1xyXG4gICAgICBpZiAoZS5lbnRpdHlBc3BlY3QuZW50aXR5TWFuYWdlciAhPT0gZW0pIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IGVudGl0aWVzIGluIHRoaXMgZW50aXR5TWFuYWdlciBtYXkgYmUgc2F2ZWRcIik7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuICFlLmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZS5pc0RldGFjaGVkKCk7XHJcbiAgICB9KTtcclxuICB9IGVsc2Uge1xyXG4gICAgZW50aXRpZXNUb1NhdmUgPSBlbS5nZXRDaGFuZ2VzKCk7XHJcbiAgfVxyXG4gIHJldHVybiBlbnRpdGllc1RvU2F2ZTtcclxufVxyXG5cclxuZnVuY3Rpb24gZml4dXBLZXlzKGVtOiBFbnRpdHlNYW5hZ2VyLCBrZXlNYXBwaW5nczogS2V5TWFwcGluZ1tdKSB7XHJcbiAgZW0uX2luS2V5Rml4dXAgPSB0cnVlO1xyXG4gIGtleU1hcHBpbmdzLmZvckVhY2goZnVuY3Rpb24gKGttKSB7XHJcbiAgICBsZXQgZ3JvdXAgPSBlbS5fZW50aXR5R3JvdXBNYXBba20uZW50aXR5VHlwZU5hbWVdO1xyXG4gICAgaWYgKCFncm91cCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gbG9jYXRlIHRoZSBmb2xsb3dpbmcgZnVsbHkgcXVhbGlmaWVkIEVudGl0eVR5cGUgbmFtZTogXCIgKyBrbS5lbnRpdHlUeXBlTmFtZSk7XHJcbiAgICB9XHJcbiAgICBncm91cC5fZml4dXBLZXkoa20udGVtcFZhbHVlLCBrbS5yZWFsVmFsdWUpO1xyXG4gIH0pO1xyXG4gIGVtLl9pbktleUZpeHVwID0gZmFsc2U7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEVudGl0eUdyb3VwcyhlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdKSB7XHJcbiAgbGV0IGdyb3VwTWFwID0gZW0uX2VudGl0eUdyb3VwTWFwO1xyXG4gIGlmIChlbnRpdHlUeXBlcykge1xyXG4gICAgcmV0dXJuIGNvcmUudG9BcnJheShlbnRpdHlUeXBlcykubWFwKGZ1bmN0aW9uIChldDogRW50aXR5VHlwZSkge1xyXG4gICAgICBpZiAoZXQgaW5zdGFuY2VvZiBFbnRpdHlUeXBlKSB7XHJcbiAgICAgICAgcmV0dXJuIGdyb3VwTWFwW2V0Lm5hbWVdO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBFbnRpdHlNYW5hZ2VyLmdldENoYW5nZXMoKSAnZW50aXR5VHlwZXMnIHBhcmFtZXRlciBtdXN0IGJlIGVpdGhlciBhbiBlbnRpdHlUeXBlIG9yIGFuIGFycmF5IG9mIGVudGl0eVR5cGVzIG9yIG51bGxcIik7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH0gZWxzZSB7XHJcbiAgICByZXR1cm4gY29yZS5nZXRPd25Qcm9wZXJ0eVZhbHVlcyhncm91cE1hcCkgYXMgRW50aXR5R3JvdXBbXTtcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNoZWNrRW50aXR5S2V5KGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHk6IEVudGl0eSkge1xyXG4gIGxldCBlayA9IGVudGl0eS5lbnRpdHlBc3BlY3QuZ2V0S2V5KCk7XHJcbiAgLy8gcmV0dXJuIHByb3BlcnRpZXMgdGhhdCBhcmUgPSB0byBkZWZhdWx0VmFsdWVzXHJcbiAgbGV0IGtleVByb3BzV2l0aERlZmF1bHRWYWx1ZXMgPSBjb3JlLmFycmF5WmlwKGVudGl0eS5lbnRpdHlUeXBlLmtleVByb3BlcnRpZXMsIGVrLnZhbHVlcywgZnVuY3Rpb24gKGtwLCBrdikge1xyXG4gICAgcmV0dXJuIChrcC5kZWZhdWx0VmFsdWUgPT09IGt2KSA/IGtwIDogbnVsbDtcclxuICB9KS5maWx0ZXIoZnVuY3Rpb24gKGtwKSB7XHJcbiAgICByZXR1cm4ga3AgIT09IG51bGw7XHJcbiAgfSk7XHJcbiAgaWYgKGtleVByb3BzV2l0aERlZmF1bHRWYWx1ZXMubGVuZ3RoKSB7XHJcbiAgICBpZiAoZW50aXR5LmVudGl0eVR5cGUuYXV0b0dlbmVyYXRlZEtleVR5cGUgIT09IEF1dG9HZW5lcmF0ZWRLZXlUeXBlLk5vbmUpIHtcclxuICAgICAgZW0uZ2VuZXJhdGVUZW1wS2V5VmFsdWUoZW50aXR5KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIHdlIHdpbGwgYWxsb3cgYXR0YWNoZXMgb2YgZW50aXRpZXMgd2hlcmUgb25seSBwYXJ0IG9mIHRoZSBrZXkgaXMgc2V0LlxyXG4gICAgICBpZiAoa2V5UHJvcHNXaXRoRGVmYXVsdFZhbHVlcy5sZW5ndGggPT09IGVrLnZhbHVlcy5sZW5ndGgpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgYXR0YWNoIGFuIG9iamVjdCBvZiB0eXBlICAoXCIgKyBlbnRpdHkuZW50aXR5VHlwZS5uYW1lICsgXCIpIHRvIGFuIEVudGl0eU1hbmFnZXIgd2l0aG91dCBmaXJzdCBzZXR0aW5nIGl0cyBrZXkgb3Igc2V0dGluZyBpdHMgZW50aXR5VHlwZSAnQXV0b0dlbmVyYXRlZEtleVR5cGUnIHByb3BlcnR5IHRvIHNvbWV0aGluZyBvdGhlciB0aGFuICdOb25lJ1wiKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gdmFsaWRhdGVFbnRpdHlTdGF0ZXMoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVN0YXRlcz86IEVudGl0eVN0YXRlIHwgRW50aXR5U3RhdGVbXSkge1xyXG4gIGlmICghZW50aXR5U3RhdGVzKSByZXR1cm4gW10gYXMgRW50aXR5U3RhdGVbXTtcclxuICBsZXQgZW50U3RhdGVzID0gY29yZS50b0FycmF5KGVudGl0eVN0YXRlcykgYXMgRW50aXR5U3RhdGVbXTtcclxuICBlbnRTdGF0ZXMuZm9yRWFjaCgoZXMpID0+IHtcclxuICAgIGlmICghKGVzIGluc3RhbmNlb2YgRW50aXR5U3RhdGUpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBFbnRpdHlNYW5hZ2VyLmdldENoYW5nZXMoKSAnZW50aXR5U3RhdGVzJyBwYXJhbWV0ZXIgbXVzdCBlaXRoZXIgYmUgbnVsbCwgYW4gZW50aXR5U3RhdGUgb3IgYW4gYXJyYXkgb2YgZW50aXR5U3RhdGVzXCIpO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiBlbnRTdGF0ZXM7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGF0dGFjaFJlbGF0ZWRFbnRpdGllcyhlbTogRW50aXR5TWFuYWdlciwgZW50aXR5OiBFbnRpdHksIGVudGl0eVN0YXRlOiBFbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneSkge1xyXG4gIGxldCBuYXZQcm9wcyA9IGVudGl0eS5lbnRpdHlUeXBlLm5hdmlnYXRpb25Qcm9wZXJ0aWVzO1xyXG4gIG5hdlByb3BzLmZvckVhY2goZnVuY3Rpb24gKG5wKSB7XHJcbiAgICBsZXQgcmVsYXRlZCA9IGVudGl0eS5nZXRQcm9wZXJ0eShucC5uYW1lKTtcclxuICAgIGlmIChucC5pc1NjYWxhcikge1xyXG4gICAgICBpZiAoIXJlbGF0ZWQpIHJldHVybjtcclxuICAgICAgZW0uYXR0YWNoRW50aXR5KHJlbGF0ZWQsIGVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJlbGF0ZWQuZm9yRWFjaChmdW5jdGlvbiAoZTogRW50aXR5KSB7XHJcbiAgICAgICAgZW0uYXR0YWNoRW50aXR5KGUsIGVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5KTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfSk7XHJcbn1cclxuXHJcbi8vIHJldHVybnMgYSBwcm9taXNlXHJcbmZ1bmN0aW9uIGV4ZWN1dGVRdWVyeUNvcmUoZW06IEVudGl0eU1hbmFnZXIsIHF1ZXJ5OiBFbnRpdHlRdWVyeSB8IHN0cmluZywgcXVlcnlPcHRpb25zOiBRdWVyeU9wdGlvbnMsIGRhdGFTZXJ2aWNlOiBEYXRhU2VydmljZSk6IFByb21pc2U8UXVlcnlSZXN1bHQ+IHtcclxuICB0cnkge1xyXG4gICAgbGV0IHJlc3VsdHM6IGFueVtdO1xyXG4gICAgbGV0IG1ldGFkYXRhU3RvcmUgPSBlbS5tZXRhZGF0YVN0b3JlO1xyXG5cclxuICAgIGlmIChtZXRhZGF0YVN0b3JlLmlzRW1wdHkoKSAmJiBkYXRhU2VydmljZS5oYXNTZXJ2ZXJNZXRhZGF0YSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjYW5ub3QgZXhlY3V0ZSBfZXhlY3V0ZVF1ZXJ5Q29yZSB1bnRpbCBtZXRhZGF0YVN0b3JlIGlzIHBvcHVsYXRlZC5cIik7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHF1ZXJ5T3B0aW9ucy5mZXRjaFN0cmF0ZWd5ID09PSBGZXRjaFN0cmF0ZWd5LkZyb21Mb2NhbENhY2hlKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBxdWVyeSA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImNhbm5vdCBleGVjdXRlICdzdHJpbmcnIEVudGl0eVF1ZXJ5IGxvY2FsbHkuXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBsZXQgcXIgPSBleGVjdXRlUXVlcnlMb2NhbGx5Q29yZShlbSwgcXVlcnkpO1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyByZXN1bHRzOiBxci5yZXN1bHRzLCBlbnRpdHlNYW5hZ2VyOiBlbSwgaW5saW5lQ291bnQ6IHFyLmlubGluZUNvdW50LCBxdWVyeTogcXVlcnkgfSk7XHJcbiAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBsZXQgbWFwcGluZ0NvbnRleHQ6IE1hcHBpbmdDb250ZXh0IHwgdW5kZWZpbmVkID0gbmV3IE1hcHBpbmdDb250ZXh0KHtcclxuICAgICAgcXVlcnk6IHF1ZXJ5LFxyXG4gICAgICBlbnRpdHlNYW5hZ2VyOiBlbSxcclxuICAgICAgZGF0YVNlcnZpY2U6IGRhdGFTZXJ2aWNlLFxyXG4gICAgICBtZXJnZU9wdGlvbnM6IHtcclxuICAgICAgICBtZXJnZVN0cmF0ZWd5OiBxdWVyeU9wdGlvbnMubWVyZ2VTdHJhdGVneSxcclxuICAgICAgICBub1RyYWNraW5nOiAhIShxdWVyeSBhcyBhbnkpLm5vVHJhY2tpbmdFbmFibGVkLFxyXG4gICAgICAgIGluY2x1ZGVEZWxldGVkOiBxdWVyeU9wdGlvbnMuaW5jbHVkZURlbGV0ZWRcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgbGV0IHZhbGlkYXRlT25RdWVyeSA9IGVtLnZhbGlkYXRpb25PcHRpb25zLnZhbGlkYXRlT25RdWVyeTtcclxuXHJcbiAgICByZXR1cm4gZGF0YVNlcnZpY2UuYWRhcHRlckluc3RhbmNlIS5leGVjdXRlUXVlcnkobWFwcGluZ0NvbnRleHQpLnRoZW4oZnVuY3Rpb24gKGRhdGE6IGFueSkge1xyXG4gICAgICBsZXQgcmVzdWx0ID0gY29yZS53cmFwRXhlY3V0aW9uKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBsZXQgc3RhdGUgPSB7IGlzTG9hZGluZzogZW0uaXNMb2FkaW5nIH07XHJcbiAgICAgICAgZW0uaXNMb2FkaW5nID0gdHJ1ZTtcclxuICAgICAgICBlbS5fcGVuZGluZ1B1YnMgPSBbXTtcclxuICAgICAgICByZXR1cm4gc3RhdGU7XHJcbiAgICAgIH0sIGZ1bmN0aW9uIChzdGF0ZSkge1xyXG4gICAgICAgIC8vIGNsZWFudXBcclxuICAgICAgICBlbS5pc0xvYWRpbmcgPSBzdGF0ZS5pc0xvYWRpbmc7XHJcbiAgICAgICAgZW0uX3BlbmRpbmdQdWJzIS5mb3JFYWNoKGZ1bmN0aW9uIChmbikge1xyXG4gICAgICAgICAgZm4oKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICBlbS5fcGVuZGluZ1B1YnMgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgZW0uX2hhc0NoYW5nZXNBY3Rpb24gJiYgZW0uX2hhc0NoYW5nZXNBY3Rpb24oKTtcclxuICAgICAgICAvLyBUT0RPOiByZW1vdmVkIC0gbm90IHN1cmUgd2h5IG5lZWRlZCBpbiBmaXJzdCBwbGFjZS4uLlxyXG4gICAgICAgIC8vIC8vIEhBQ0sgZm9yIEdDXHJcbiAgICAgICAgLy8gcXVlcnkgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgbWFwcGluZ0NvbnRleHQgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgLy8gSEFDSzogc29tZSBlcnJvcnMgdGhyb3duIGluIG5leHQgZnVuY3Rpb24gZG8gbm90IHByb3BvZ2F0ZSBwcm9wZXJseSAtIHRoaXMgY2F0Y2hlcyB0aGVtLlxyXG5cclxuICAgICAgICBpZiAoc3RhdGUuZXJyb3IpIHtcclxuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChzdGF0ZS5lcnJvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgfSwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGxldCBub2RlcyA9IGRhdGFTZXJ2aWNlLmpzb25SZXN1bHRzQWRhcHRlci5leHRyYWN0UmVzdWx0cyhkYXRhKTtcclxuICAgICAgICBub2RlcyA9IGNvcmUudG9BcnJheShub2Rlcyk7XHJcblxyXG4gICAgICAgIHJlc3VsdHMgPSBtYXBwaW5nQ29udGV4dCEudmlzaXRBbmRNZXJnZShub2RlcywgeyBub2RlVHlwZTogXCJyb290XCIgfSk7XHJcbiAgICAgICAgaWYgKHZhbGlkYXRlT25RdWVyeSkge1xyXG4gICAgICAgICAgcmVzdWx0cy5mb3JFYWNoKGZ1bmN0aW9uIChyOiBhbnkpIHtcclxuICAgICAgICAgICAgLy8gYW5vbiB0eXBlcyBhbmQgc2ltcGxlIHR5cGVzIHdpbGwgbm90IGhhdmUgYW4gZW50aXR5QXNwZWN0LlxyXG4gICAgICAgICAgICByLmVudGl0eUFzcGVjdCAmJiByLmVudGl0eUFzcGVjdC52YWxpZGF0ZUVudGl0eSgpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG1hcHBpbmdDb250ZXh0IS5wcm9jZXNzRGVmZXJyZWQoKTtcclxuICAgICAgICAvLyBpZiBxdWVyeSBoYXMgZXhwYW5kIGNsYXVzZXMgd2FsayBlYWNoIG9mIHRoZSAncmVzdWx0cycgYW5kIG1hcmsgdGhlIGV4cGFuZGVkIHByb3BzIGFzIGxvYWRlZC5cclxuICAgICAgICBpZiAocXVlcnkgaW5zdGFuY2VvZiBFbnRpdHlRdWVyeSkge1xyXG4gICAgICAgICAgbWFya0xvYWRlZE5hdlByb3BzKHJlc3VsdHMsIHF1ZXJ5KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbGV0IHJldHJpZXZlZEVudGl0aWVzID0gY29yZS5vYmplY3RNYXAobWFwcGluZ0NvbnRleHQhLnJlZk1hcCk7XHJcbiAgICAgICAgcmV0dXJuIHsgcmVzdWx0czogcmVzdWx0cywgcXVlcnk6IHF1ZXJ5LCBlbnRpdHlNYW5hZ2VyOiBlbSwgaHR0cFJlc3BvbnNlOiBkYXRhLmh0dHBSZXNwb25zZSwgaW5saW5lQ291bnQ6IGRhdGEuaW5saW5lQ291bnQsIHJldHJpZXZlZEVudGl0aWVzOiByZXRyaWV2ZWRFbnRpdGllcyB9O1xyXG4gICAgICB9KTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpO1xyXG4gICAgfSwgZnVuY3Rpb24gKGU6IGFueSkge1xyXG4gICAgICBpZiAoZSkge1xyXG4gICAgICAgIGUucXVlcnkgPSBxdWVyeTtcclxuICAgICAgICBlLmVudGl0eU1hbmFnZXIgPSBlbTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7XHJcbiAgICB9KTtcclxuXHJcbiAgfSBjYXRjaCAoZSkge1xyXG4gICAgaWYgKGUpIHtcclxuICAgICAgZS5xdWVyeSA9IHF1ZXJ5O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO1xyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gbWFya0xvYWRlZE5hdlByb3BzKGVudGl0aWVzOiBFbnRpdHlbXSwgcXVlcnk6IEVudGl0eVF1ZXJ5KSB7XHJcbiAgaWYgKHF1ZXJ5Lm5vVHJhY2tpbmdFbmFibGVkKSByZXR1cm47XHJcbiAgbGV0IGV4cGFuZENsYXVzZSA9IHF1ZXJ5LmV4cGFuZENsYXVzZTtcclxuICBpZiAoZXhwYW5kQ2xhdXNlID09IG51bGwpIHJldHVybjtcclxuICBleHBhbmRDbGF1c2UucHJvcGVydHlQYXRocy5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wZXJ0eVBhdGgpIHtcclxuICAgIGxldCBwcm9wTmFtZXMgPSBwcm9wZXJ0eVBhdGguc3BsaXQoJy4nKTtcclxuICAgIG1hcmtMb2FkZWROYXZQYXRoKGVudGl0aWVzLCBwcm9wTmFtZXMpO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBtYXJrTG9hZGVkTmF2UGF0aChlbnRpdGllczogRW50aXR5W10sIHByb3BOYW1lczogc3RyaW5nW10pIHtcclxuICBsZXQgcHJvcE5hbWUgPSBwcm9wTmFtZXNbMF07XHJcbiAgZW50aXRpZXMuZm9yRWFjaCgoZW50aXR5KSA9PiB7XHJcbiAgICBsZXQgZWEgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgaWYgKCFlYSkgcmV0dXJuOyAvLyBlbnRpdHkgbWF5IG5vdCBiZSBhICdyZWFsJyBlbnRpdHkgaW4gdGhlIGNhc2Ugb2YgYSBwcm9qZWN0aW9uLlxyXG4gICAgZWEuX21hcmtBc0xvYWRlZChwcm9wTmFtZSk7XHJcbiAgICBpZiAocHJvcE5hbWVzLmxlbmd0aCA9PT0gMSkgcmV0dXJuO1xyXG4gICAgbGV0IG5leHQgPSBlbnRpdHkuZ2V0UHJvcGVydHkocHJvcE5hbWUpO1xyXG4gICAgaWYgKCFuZXh0KSByZXR1cm47IC8vIG5vIGNoaWxkcmVuIHRvIHByb2Nlc3MuXHJcbiAgICAvLyBzdHJhbmdlIGxvZ2ljIGJlY2F1c2Ugbm9uc2NhbGFyIG5hdiB2YWx1ZXMgYXJlIE5PVCByZWFsbHkgYXJyYXlzXHJcbiAgICAvLyBvdGhlcndpc2Ugd2UgY291bGQgdXNlIEFycmF5LmlzQXJyYXlcclxuICAgIGlmICghbmV4dC5hcnJheUNoYW5nZWQpIG5leHQgPSBbbmV4dF07XHJcbiAgICBtYXJrTG9hZGVkTmF2UGF0aChuZXh0LCBwcm9wTmFtZXMuc2xpY2UoMSkpO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiB1cGRhdGVDb25jdXJyZW5jeVByb3BlcnRpZXMoZW50aXRpZXM6IEVudGl0eVtdKSB7XHJcbiAgbGV0IGNhbmRpZGF0ZXMgPSBlbnRpdGllcy5maWx0ZXIoKGUpID0+IHtcclxuICAgIGUuZW50aXR5QXNwZWN0LmlzQmVpbmdTYXZlZCA9IHRydWU7XHJcbiAgICByZXR1cm4gZS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUuaXNNb2RpZmllZCgpXHJcbiAgICAgICYmIGUuZW50aXR5VHlwZS5jb25jdXJyZW5jeVByb3BlcnRpZXMubGVuZ3RoID4gMDtcclxuXHJcbiAgfSk7XHJcbiAgaWYgKGNhbmRpZGF0ZXMubGVuZ3RoID09PSAwKSByZXR1cm47XHJcbiAgY2FuZGlkYXRlcy5mb3JFYWNoKGZ1bmN0aW9uIChjKSB7XHJcbiAgICBjLmVudGl0eVR5cGUuY29uY3VycmVuY3lQcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKGNwKSB7XHJcbiAgICAgIHVwZGF0ZUNvbmN1cnJlbmN5UHJvcGVydHkoYywgY3ApO1xyXG4gICAgfSk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVwZGF0ZUNvbmN1cnJlbmN5UHJvcGVydHkoZW50aXR5OiBFbnRpdHksIHByb3BlcnR5OiBEYXRhUHJvcGVydHkpIHtcclxuICAvLyBjaGVjayBpZiBwcm9wZXJ0eSBoYXMgYWxyZWFkeSBiZWVuIHVwZGF0ZWRcclxuICBpZiAoZW50aXR5LmVudGl0eUFzcGVjdC5vcmlnaW5hbFZhbHVlc1twcm9wZXJ0eS5uYW1lXSkgcmV0dXJuO1xyXG4gIGxldCB2YWx1ZSA9IGVudGl0eS5nZXRQcm9wZXJ0eShwcm9wZXJ0eS5uYW1lKTtcclxuICBsZXQgZGF0YVR5cGUgPSBwcm9wZXJ0eS5kYXRhVHlwZSBhcyBEYXRhVHlwZTtcclxuICBpZiAoIXZhbHVlKSB2YWx1ZSA9IGRhdGFUeXBlLmRlZmF1bHRWYWx1ZTtcclxuICBpZiAoZGF0YVR5cGUuaXNOdW1lcmljKSB7XHJcbiAgICBlbnRpdHkuc2V0UHJvcGVydHkocHJvcGVydHkubmFtZSwgdmFsdWUgKyAxKTtcclxuICB9IGVsc2UgaWYgKGRhdGFUeXBlLmdldENvbmN1cnJlbmN5VmFsdWUpIHtcclxuICAgIC8vIERhdGFUeXBlIGhhcyBpdHMgb3duIGltcGxlbWVudGF0aW9uXHJcbiAgICBsZXQgbmV4dFZhbHVlID0gZGF0YVR5cGUuZ2V0Q29uY3VycmVuY3lWYWx1ZSh2YWx1ZSk7XHJcbiAgICBlbnRpdHkuc2V0UHJvcGVydHkocHJvcGVydHkubmFtZSwgbmV4dFZhbHVlKTtcclxuICB9IGVsc2UgaWYgKGRhdGFUeXBlID09PSBEYXRhVHlwZS5CaW5hcnkpIHtcclxuICAgIC8vIGJlc3QgZ3Vlc3MgLSB0aGF0IHRoaXMgaXMgYSB0aW1lc3RhbXAgY29sdW1uIGFuZCBpcyBjb21wdXRlZCBvbiB0aGUgc2VydmVyIGR1cmluZyBzYXZlXHJcbiAgICAvLyAtIHNvIG5vIG5lZWQgdG8gc2V0IGl0IGhlcmUuXHJcbiAgICByZXR1cm47XHJcbiAgfSBlbHNlIHtcclxuICAgIC8vIHRoaXMganVzdCBsZWF2ZXMgRGF0YVR5cGVzIG9mIEJvb2xlYW4sIFN0cmluZyBhbmQgQnl0ZSAtIG5vbmUgb2Ygd2hpY2ggc2hvdWxkIGJlIHRoZVxyXG4gICAgLy8gdHlwZSBmb3IgYSBjb25jdXJyZW5jeSBjb2x1bW4uXHJcbiAgICAvLyBOT1RFOiB0aG91Z2h0IGFib3V0IGp1c3QgcmV0dXJuaW5nIGhlcmUgYnV0IHdvdWxkIHJhdGhlciBiZSBzYWZlIGZvciBub3cuXHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gdXBkYXRlIHRoZSB2YWx1ZSBvZiBjb25jdXJyZW5jeSBwcm9wZXJ0eSBiZWZvcmUgc2F2aW5nOiBcIiArIHByb3BlcnR5Lm5hbWUpO1xyXG4gIH1cclxufVxyXG5cclxuXHJcbmZ1bmN0aW9uIGZpbmRPckNyZWF0ZUVudGl0eUdyb3VwKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgbGV0IGdyb3VwID0gZW0uX2VudGl0eUdyb3VwTWFwW2VudGl0eVR5cGUubmFtZV07XHJcbiAgaWYgKCFncm91cCkge1xyXG4gICAgZ3JvdXAgPSBuZXcgRW50aXR5R3JvdXAoZW0sIGVudGl0eVR5cGUpO1xyXG4gICAgZW0uX2VudGl0eUdyb3VwTWFwW2VudGl0eVR5cGUubmFtZV0gPSBncm91cDtcclxuICB9XHJcbiAgcmV0dXJuIGdyb3VwO1xyXG59XHJcblxyXG5mdW5jdGlvbiBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cHMoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVR5cGU6IEVudGl0eVR5cGUpIHtcclxuICBsZXQgZW50aXR5VHlwZXMgPSBlbnRpdHlUeXBlLmdldFNlbGZBbmRTdWJ0eXBlcygpO1xyXG4gIHJldHVybiBlbnRpdHlUeXBlcy5tYXAoKGV0KSA9PiB7XHJcbiAgICByZXR1cm4gZmluZE9yQ3JlYXRlRW50aXR5R3JvdXAoZW0sIGV0KTtcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gdW53cmFwSW5zdGFuY2Uoc3RydWN0T2JqOiBTdHJ1Y3R1cmFsT2JqZWN0LCB0cmFuc2Zvcm1Gbj86IChkcDogRGF0YVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55KSB7XHJcblxyXG4gIGxldCByYXdPYmplY3Q6IGFueSA9IHt9O1xyXG4gIGxldCBzdHlwZSA9IEVudGl0eUFzcGVjdC5pc0VudGl0eShzdHJ1Y3RPYmopID8gc3RydWN0T2JqLmVudGl0eVR5cGUgOiBzdHJ1Y3RPYmouY29tcGxleFR5cGU7XHJcbiAgbGV0IHNlcmlhbGl6ZXJGbiA9IGdldFNlcmlhbGl6ZXJGbihzdHlwZSk7XHJcbiAgbGV0IHVubWFwcGVkID0ge307XHJcbiAgc3R5cGUuZGF0YVByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZHApIHtcclxuICAgIGlmIChkcC5pc0NvbXBsZXhQcm9wZXJ0eSkge1xyXG4gICAgICByYXdPYmplY3RbZHAubmFtZU9uU2VydmVyXSA9IGNvcmUubWFwKHN0cnVjdE9iai5nZXRQcm9wZXJ0eShkcC5uYW1lKSwgZnVuY3Rpb24gKGNvKSB7XHJcbiAgICAgICAgcmV0dXJuIHVud3JhcEluc3RhbmNlKGNvLCB0cmFuc2Zvcm1Gbik7XHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgbGV0IHZhbCA9IHN0cnVjdE9iai5nZXRQcm9wZXJ0eShkcC5uYW1lKTtcclxuICAgICAgdmFsID0gdHJhbnNmb3JtRm4gPyB0cmFuc2Zvcm1GbihkcCwgdmFsKSA6IHZhbDtcclxuICAgICAgaWYgKHZhbCA9PT0gdW5kZWZpbmVkKSByZXR1cm47XHJcbiAgICAgIHZhbCA9IHNlcmlhbGl6ZXJGbiA/IHNlcmlhbGl6ZXJGbihkcCwgdmFsKSA6IHZhbDtcclxuICAgICAgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgaWYgKGRwLmlzVW5tYXBwZWQpIHtcclxuICAgICAgICAgIHVubWFwcGVkW2RwLm5hbWVPblNlcnZlcl0gPSBjb3JlLnRvSlNPTlNhZmUodmFsLCBjb3JlLnRvSlNPTlNhZmVSZXBsYWNlcik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHJhd09iamVjdFtkcC5uYW1lT25TZXJ2ZXJdID0gdmFsO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0pO1xyXG5cclxuICBpZiAoIWNvcmUuaXNFbXB0eSh1bm1hcHBlZCkpIHtcclxuICAgIC8vIFRPRE86IHJldmlldyB0aGlzLlxyXG4gICAgKHJhd09iamVjdCBhcyBhbnkpLl9fdW5tYXBwZWQgPSB1bm1hcHBlZDtcclxuICB9XHJcbiAgcmV0dXJuIHJhd09iamVjdDtcclxufVxyXG5cclxuZnVuY3Rpb24gdW53cmFwT3JpZ2luYWxWYWx1ZXModGFyZ2V0OiBTdHJ1Y3R1cmFsT2JqZWN0LCBtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlLCB0cmFuc2Zvcm1Gbj86IChkcDogRGF0YVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55KSB7XHJcbiAgbGV0IHN0eXBlID0gRW50aXR5QXNwZWN0LmlzRW50aXR5KHRhcmdldCkgPyB0YXJnZXQuZW50aXR5VHlwZSA6IHRhcmdldC5jb21wbGV4VHlwZTtcclxuICBsZXQgYXNwZWN0ID0gRW50aXR5QXNwZWN0LmlzRW50aXR5KHRhcmdldCkgPyB0YXJnZXQuZW50aXR5QXNwZWN0IDogdGFyZ2V0LmNvbXBsZXhBc3BlY3Q7XHJcbiAgbGV0IGZuID0gbWV0YWRhdGFTdG9yZS5uYW1pbmdDb252ZW50aW9uLmNsaWVudFByb3BlcnR5TmFtZVRvU2VydmVyO1xyXG4gIGxldCByZXN1bHQgPSB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xyXG4gIGNvcmUub2JqZWN0Rm9yRWFjaChhc3BlY3Qub3JpZ2luYWxWYWx1ZXMsIGZ1bmN0aW9uIChwcm9wTmFtZSwgdmFsKSB7XHJcbiAgICBsZXQgcHJvcCA9IHN0eXBlLmdldFByb3BlcnR5KHByb3BOYW1lKSBhcyBEYXRhUHJvcGVydHk7XHJcbiAgICB2YWwgPSB0cmFuc2Zvcm1GbiA/IHRyYW5zZm9ybUZuKHByb3AsIHZhbCkgOiB2YWw7XHJcbiAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmVzdWx0W2ZuKHByb3BOYW1lLCBwcm9wKV0gPSB2YWw7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgc3R5cGUuY29tcGxleFByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAoY3ApIHtcclxuICAgIGxldCBuZXh0VGFyZ2V0ID0gdGFyZ2V0LmdldFByb3BlcnR5KGNwLm5hbWUpO1xyXG4gICAgaWYgKGNwLmlzU2NhbGFyKSB7XHJcbiAgICAgIGxldCB1bndyYXBwZWRDbyA9IHVud3JhcE9yaWdpbmFsVmFsdWVzKG5leHRUYXJnZXQsIG1ldGFkYXRhU3RvcmUsIHRyYW5zZm9ybUZuKTtcclxuICAgICAgaWYgKCFjb3JlLmlzRW1wdHkodW53cmFwcGVkQ28pKSB7XHJcbiAgICAgICAgcmVzdWx0W2ZuKGNwLm5hbWUsIGNwKV0gPSB1bndyYXBwZWRDbztcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgbGV0IHVud3JhcHBlZENvcyA9IG5leHRUYXJnZXQubWFwKChpdGVtOiBhbnkpID0+IHtcclxuICAgICAgICByZXR1cm4gdW53cmFwT3JpZ2luYWxWYWx1ZXMoaXRlbSwgbWV0YWRhdGFTdG9yZSwgdHJhbnNmb3JtRm4pO1xyXG4gICAgICB9KTtcclxuICAgICAgcmVzdWx0W2ZuKGNwLm5hbWUsIGNwKV0gPSB1bndyYXBwZWRDb3M7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZnVuY3Rpb24gdW53cmFwQ2hhbmdlZFZhbHVlcyhlbnRpdHk6IEVudGl0eSwgbWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSwgdHJhbnNmb3JtRm46IChkcDogRGF0YVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55KSB7XHJcbiAgbGV0IHN0eXBlID0gZW50aXR5LmVudGl0eVR5cGU7XHJcbiAgbGV0IHNlcmlhbGl6ZXJGbiA9IGdldFNlcmlhbGl6ZXJGbihzdHlwZSk7XHJcbiAgbGV0IGZuID0gbWV0YWRhdGFTdG9yZS5uYW1pbmdDb252ZW50aW9uLmNsaWVudFByb3BlcnR5TmFtZVRvU2VydmVyO1xyXG4gIGxldCByZXN1bHQgPSB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xyXG4gIGNvcmUub2JqZWN0Rm9yRWFjaChlbnRpdHkuZW50aXR5QXNwZWN0Lm9yaWdpbmFsVmFsdWVzLCBmdW5jdGlvbiAocHJvcE5hbWUsIHZhbHVlKSB7XHJcbiAgICBsZXQgcHJvcCA9IHN0eXBlLmdldFByb3BlcnR5KHByb3BOYW1lKSBhcyBEYXRhUHJvcGVydHk7XHJcbiAgICBsZXQgdmFsID0gZW50aXR5LmdldFByb3BlcnR5KHByb3BOYW1lKTtcclxuICAgIHZhbCA9IHRyYW5zZm9ybUZuID8gdHJhbnNmb3JtRm4ocHJvcCwgdmFsKSA6IHZhbDtcclxuICAgIGlmICh2YWwgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xyXG4gICAgdmFsID0gc2VyaWFsaXplckZuID8gc2VyaWFsaXplckZuKHByb3AsIHZhbCkgOiB2YWw7XHJcbiAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmVzdWx0W2ZuKHByb3BOYW1lLCBwcm9wKV0gPSB2YWw7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgLy8gYW55IGNoYW5nZSB0byBhbnkgY29tcGxleCBvYmplY3Qgb3IgYXJyYXkgb2YgY29tcGxleCBvYmplY3RzIHJldHVybnMgdGhlIEVOVElSRVxyXG4gIC8vIGN1cnJlbnQgY29tcGxleCBvYmplY3Qgb3IgY29tcGxleCBvYmplY3QgYXJyYXkuICBUaGlzIGlzIGJ5IGRlc2lnbi4gQ29tcGxleCBPYmplY3RzXHJcbiAgLy8gYXJlIGF0b21pYy5cclxuICBzdHlwZS5jb21wbGV4UHJvcGVydGllcy5mb3JFYWNoKChjcCkgPT4ge1xyXG4gICAgaWYgKGNwSGFzT3JpZ2luYWxWYWx1ZXMoZW50aXR5LCBjcCkpIHtcclxuICAgICAgbGV0IGNvT3JDb3MgPSBlbnRpdHkuZ2V0UHJvcGVydHkoY3AubmFtZSk7XHJcbiAgICAgIHJlc3VsdFtmbihjcC5uYW1lLCBjcCldID0gY29yZS5tYXAoY29PckNvcywgZnVuY3Rpb24gKGNvKSB7XHJcbiAgICAgICAgcmV0dXJuIHVud3JhcEluc3RhbmNlKGNvLCB0cmFuc2Zvcm1Gbik7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNwSGFzT3JpZ2luYWxWYWx1ZXMoc3RydWN0dXJhbE9iamVjdDogU3RydWN0dXJhbE9iamVjdCwgY3A6IERhdGFQcm9wZXJ0eSk6IGJvb2xlYW4ge1xyXG4gIGxldCBjb09yQ29zID0gc3RydWN0dXJhbE9iamVjdC5nZXRQcm9wZXJ0eShjcC5uYW1lKTtcclxuICBpZiAoY3AuaXNTY2FsYXIpIHtcclxuICAgIHJldHVybiBjb0hhc09yaWdpbmFsVmFsdWVzKGNvT3JDb3MpO1xyXG4gIH0gZWxzZSB7XHJcbiAgICAvLyB0aGlzIG9jY3VycyB3aGVuIGEgbm9uc2NhbGFyIGNvIGFycmF5IGhhcyBoYWQgY29zIGFkZGVkIG9yIHJlbW92ZWQuXHJcbiAgICBpZiAoY29PckNvcy5fb3JpZ1ZhbHVlcykgcmV0dXJuIHRydWU7XHJcbiAgICByZXR1cm4gY29PckNvcy5zb21lKGZ1bmN0aW9uIChjbzogQ29tcGxleE9iamVjdCkge1xyXG4gICAgICByZXR1cm4gY29IYXNPcmlnaW5hbFZhbHVlcyhjbyk7XHJcbiAgICB9KTtcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGV4ZWN1dGVRdWVyeUxvY2FsbHlDb3JlKGVtOiBFbnRpdHlNYW5hZ2VyLCBxdWVyeTogRW50aXR5UXVlcnkpIHtcclxuICBhc3NlcnRQYXJhbShxdWVyeSwgXCJxdWVyeVwiKS5pc0luc3RhbmNlT2YoRW50aXR5UXVlcnkpLmNoZWNrKCk7XHJcblxyXG4gIGxldCBtZXRhZGF0YVN0b3JlID0gZW0ubWV0YWRhdGFTdG9yZTtcclxuICBsZXQgZW50aXR5VHlwZSA9IHF1ZXJ5Ll9nZXRGcm9tRW50aXR5VHlwZShtZXRhZGF0YVN0b3JlLCB0cnVlKTtcclxuICAvLyB0aGVyZSBtYXkgYmUgbXVsdGlwbGUgZ3JvdXBzIGlzIHRoaXMgaXMgYSBiYXNlIGVudGl0eSB0eXBlLlxyXG4gIGxldCBncm91cHMgPSBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cHMoZW0sIGVudGl0eVR5cGUhKTtcclxuICAvLyBmaWx0ZXIgdGhlbiBvcmRlciB0aGVuIHNraXAgdGhlbiB0YWtlXHJcbiAgbGV0IGZpbHRlckZ1bmMgPSBxdWVyeS53aGVyZVByZWRpY2F0ZSAmJiBxdWVyeS53aGVyZVByZWRpY2F0ZS50b0Z1bmN0aW9uKHsgZW50aXR5VHlwZTogZW50aXR5VHlwZSB9KTtcclxuXHJcbiAgbGV0IHF1ZXJ5T3B0aW9ucyA9IFF1ZXJ5T3B0aW9ucy5yZXNvbHZlKFtxdWVyeS5xdWVyeU9wdGlvbnMsIGVtLnF1ZXJ5T3B0aW9ucywgUXVlcnlPcHRpb25zLmRlZmF1bHRJbnN0YW5jZV0pO1xyXG4gIGxldCBpbmNsdWRlRGVsZXRlZCA9IHF1ZXJ5T3B0aW9ucy5pbmNsdWRlRGVsZXRlZCA9PT0gdHJ1ZTtcclxuXHJcbiAgbGV0IG5ld0ZpbHRlckZ1bmMgPSBmdW5jdGlvbiAoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIHJldHVybiBlbnRpdHkgJiYgKGluY2x1ZGVEZWxldGVkIHx8ICFlbnRpdHkuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlLmlzRGVsZXRlZCgpKSAmJiAoZmlsdGVyRnVuYyA/IGZpbHRlckZ1bmMoZW50aXR5KSA6IHRydWUpO1xyXG4gIH07XHJcblxyXG4gIGxldCByZXN1bHQ6IGFueVtdID0gW107XHJcbiAgLy8gVE9ETzogbWFwTWFueVxyXG4gIGdyb3Vwcy5mb3JFYWNoKChncm91cCkgPT4ge1xyXG4gICAgbGV0IGVudGl0aWVzID0gZ3JvdXAuX2VudGl0aWVzLmZpbHRlcihuZXdGaWx0ZXJGdW5jKSBhcyBFbnRpdHlbXTtcclxuICAgIGlmIChlbnRpdGllcy5sZW5ndGgpIHtcclxuICAgICAgcmVzdWx0ID0gcmVzdWx0Lmxlbmd0aCA/IHJlc3VsdC5jb25jYXQoZW50aXRpZXMpIDogZW50aXRpZXM7XHJcbiAgICB9XHJcbiAgfSk7XHJcblxyXG4gIGxldCBvcmRlckJ5Q29tcGFyZXIgPSBxdWVyeS5vcmRlckJ5Q2xhdXNlICYmIHF1ZXJ5Lm9yZGVyQnlDbGF1c2UuZ2V0Q29tcGFyZXIoZW50aXR5VHlwZSEpO1xyXG4gIGlmIChvcmRlckJ5Q29tcGFyZXIpIHtcclxuICAgIHJlc3VsdC5zb3J0KG9yZGVyQnlDb21wYXJlcik7XHJcbiAgfVxyXG5cclxuICBsZXQgaW5saW5lQ291bnQgPSBxdWVyeS5pbmxpbmVDb3VudEVuYWJsZWQgPyByZXN1bHQubGVuZ3RoIDogdW5kZWZpbmVkO1xyXG5cclxuICBsZXQgc2tpcENvdW50ID0gcXVlcnkuc2tpcENvdW50O1xyXG4gIGlmIChza2lwQ291bnQpIHtcclxuICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZShza2lwQ291bnQpO1xyXG4gIH1cclxuICBsZXQgdGFrZUNvdW50ID0gcXVlcnkudGFrZUNvdW50O1xyXG4gIGlmICh0YWtlQ291bnQpIHtcclxuICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZSgwLCB0YWtlQ291bnQpO1xyXG4gIH1cclxuXHJcbiAgbGV0IHNlbGVjdENsYXVzZSA9IHF1ZXJ5LnNlbGVjdENsYXVzZTtcclxuICBpZiAoc2VsZWN0Q2xhdXNlKSB7XHJcbiAgICBsZXQgc2VsZWN0Rm4gPSBzZWxlY3RDbGF1c2UudG9GdW5jdGlvbigpO1xyXG4gICAgcmVzdWx0ID0gcmVzdWx0Lm1hcChzZWxlY3RGbik7XHJcbiAgfVxyXG4gIHJldHVybiB7IHJlc3VsdHM6IHJlc3VsdCwgaW5saW5lQ291bnQ6IGlubGluZUNvdW50IH07XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNvSGFzT3JpZ2luYWxWYWx1ZXMoY286IENvbXBsZXhPYmplY3QpIHtcclxuICAvLyBuZXh0IGxpbmUgY2hlY2tzIGFsbCBub24gY29tcGxleCBwcm9wZXJ0aWVzIG9mIHRoZSBjby5cclxuICBpZiAoIWNvcmUuaXNFbXB0eShjby5jb21wbGV4QXNwZWN0Lm9yaWdpbmFsVmFsdWVzKSkgcmV0dXJuIHRydWU7XHJcbiAgLy8gbm93IG5lZWQgdG8gcmVjdXJzaXZlbHkgY2hlY2sgZWFjaCBvZiB0aGUgY3BzXHJcbiAgcmV0dXJuIGNvLmNvbXBsZXhUeXBlLmNvbXBsZXhQcm9wZXJ0aWVzLnNvbWUoZnVuY3Rpb24gKGNwKSB7XHJcbiAgICByZXR1cm4gY3BIYXNPcmlnaW5hbFZhbHVlcyhjbywgY3ApO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRTZXJpYWxpemVyRm4oc3R5cGU6IEVudGl0eVR5cGUgfCBDb21wbGV4VHlwZSkge1xyXG4gIHJldHVybiBzdHlwZS5zZXJpYWxpemVyRm4gfHwgKHN0eXBlLm1ldGFkYXRhU3RvcmUgJiYgc3R5cGUubWV0YWRhdGFTdG9yZS5zZXJpYWxpemVyRm4pO1xyXG59XHJcblxyXG4iXX0=