breeze-client 2.1.2 → 2.1.3-mjs

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/LICENSE +1 -1
  2. package/adapter-ajax-angularjs/{breeze-client-adapter-ajax-angularjs.d.ts → index.d.ts} +1 -0
  3. package/adapter-ajax-fetch/{breeze-client-adapter-ajax-fetch.d.ts → index.d.ts} +1 -0
  4. package/adapter-ajax-httpclient/{breeze-client-adapter-ajax-httpclient.d.ts → index.d.ts} +1 -0
  5. package/adapter-ajax-jquery/{breeze-client-adapter-ajax-jquery.d.ts → index.d.ts} +1 -0
  6. package/adapter-ajax-post/{breeze-client-adapter-ajax-post.d.ts → index.d.ts} +1 -0
  7. package/adapter-data-service-odata/{breeze-client-adapter-data-service-odata.d.ts → index.d.ts} +1 -0
  8. package/adapter-data-service-webapi/{breeze-client-adapter-data-service-webapi.d.ts → index.d.ts} +1 -0
  9. package/adapter-model-library-backing-store/{breeze-client-adapter-model-library-backing-store.d.ts → index.d.ts} +1 -0
  10. package/adapter-model-library-ko/{breeze-client-adapter-model-library-ko.d.ts → index.d.ts} +1 -0
  11. package/adapter-uri-builder-json/{breeze-client-adapter-uri-builder-json.d.ts → index.d.ts} +1 -0
  12. package/adapter-uri-builder-odata/{breeze-client-adapter-uri-builder-odata.d.ts → index.d.ts} +1 -0
  13. package/esm2020/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +130 -0
  14. package/esm2020/adapter-ajax-angularjs/adapter-core.mjs +49 -0
  15. package/esm2020/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +5 -0
  16. package/esm2020/adapter-ajax-fetch/adapter-ajax-fetch.mjs +132 -0
  17. package/esm2020/adapter-ajax-fetch/adapter-core.mjs +49 -0
  18. package/esm2020/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +5 -0
  19. package/esm2020/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +137 -0
  20. package/esm2020/adapter-ajax-httpclient/adapter-core.mjs +49 -0
  21. package/esm2020/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +5 -0
  22. package/esm2020/adapter-ajax-jquery/adapter-ajax-jquery.mjs +103 -0
  23. package/esm2020/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +5 -0
  24. package/esm2020/adapter-ajax-post/adapter-ajax-post.mjs +77 -0
  25. package/esm2020/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +5 -0
  26. package/esm2020/adapter-data-service-odata/adapter-core.mjs +49 -0
  27. package/esm2020/adapter-data-service-odata/adapter-data-service-odata.mjs +456 -0
  28. package/esm2020/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +5 -0
  29. package/esm2020/adapter-data-service-webapi/adapter-data-service-webapi.mjs +93 -0
  30. package/esm2020/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +5 -0
  31. package/esm2020/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +268 -0
  32. package/esm2020/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +5 -0
  33. package/esm2020/adapter-model-library-ko/adapter-model-library-ko.mjs +240 -0
  34. package/esm2020/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +5 -0
  35. package/esm2020/adapter-uri-builder-json/adapter-core.mjs +49 -0
  36. package/esm2020/adapter-uri-builder-json/adapter-uri-builder-json.mjs +36 -0
  37. package/esm2020/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +5 -0
  38. package/esm2020/adapter-uri-builder-odata/adapter-core.mjs +49 -0
  39. package/esm2020/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +190 -0
  40. package/esm2020/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +5 -0
  41. package/esm2020/breeze-client.mjs +5 -0
  42. package/esm2020/index.mjs +2 -0
  43. package/esm2020/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +5 -0
  44. package/esm2020/mixin-get-entity-graph/mixin-get-entity-graph.mjs +269 -0
  45. package/esm2020/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +5 -0
  46. package/esm2020/mixin-save-queuing/mixin-save-queuing.mjs +400 -0
  47. package/esm2020/src/abstract-data-service-adapter.mjs +296 -0
  48. package/esm2020/src/array.mjs +4 -0
  49. package/esm2020/src/assert-param.mjs +312 -0
  50. package/esm2020/src/breeze.mjs +85 -0
  51. package/esm2020/src/complex-array.mjs +117 -0
  52. package/esm2020/src/config.mjs +223 -0
  53. package/esm2020/src/core.mjs +707 -0
  54. package/esm2020/src/csdl-metadata-parser.mjs +385 -0
  55. package/esm2020/src/data-service.mjs +203 -0
  56. package/esm2020/src/data-type.mjs +444 -0
  57. package/esm2020/src/default-property-interceptor.mjs +460 -0
  58. package/esm2020/src/entity-action.mjs +45 -0
  59. package/esm2020/src/entity-aspect.mjs +806 -0
  60. package/esm2020/src/entity-group.mjs +187 -0
  61. package/esm2020/src/entity-key.mjs +116 -0
  62. package/esm2020/src/entity-manager.mjs +2094 -0
  63. package/esm2020/src/entity-metadata.mjs +2109 -0
  64. package/esm2020/src/entity-query.mjs +996 -0
  65. package/esm2020/src/entity-state.mjs +99 -0
  66. package/esm2020/src/enum.mjs +141 -0
  67. package/esm2020/src/event.mjs +256 -0
  68. package/esm2020/src/interface-registry.mjs +41 -0
  69. package/esm2020/src/key-generator.mjs +108 -0
  70. package/esm2020/src/local-query-comparison-options.mjs +65 -0
  71. package/esm2020/src/mapping-context.mjs +405 -0
  72. package/esm2020/src/naming-convention.mjs +88 -0
  73. package/esm2020/src/observable-array.mjs +183 -0
  74. package/esm2020/src/predicate.mjs +1232 -0
  75. package/esm2020/src/primitive-array.mjs +85 -0
  76. package/esm2020/src/query-options.mjs +152 -0
  77. package/esm2020/src/relation-array.mjs +173 -0
  78. package/esm2020/src/save-options.mjs +41 -0
  79. package/esm2020/src/unattached-children-map.mjs +58 -0
  80. package/esm2020/src/validate.mjs +988 -0
  81. package/esm2020/src/validation-options.mjs +64 -0
  82. package/fesm2015/{breeze-client-adapter-ajax-angularjs.js → breeze-client-adapter-ajax-angularjs.mjs} +1 -1
  83. package/fesm2015/breeze-client-adapter-ajax-angularjs.mjs.map +1 -0
  84. package/fesm2015/{breeze-client-adapter-ajax-fetch.js → breeze-client-adapter-ajax-fetch.mjs} +5 -3
  85. package/fesm2015/breeze-client-adapter-ajax-fetch.mjs.map +1 -0
  86. package/fesm2015/{breeze-client-adapter-ajax-httpclient.js → breeze-client-adapter-ajax-httpclient.mjs} +1 -1
  87. package/fesm2015/breeze-client-adapter-ajax-httpclient.mjs.map +1 -0
  88. package/fesm2015/{breeze-client-adapter-ajax-jquery.js → breeze-client-adapter-ajax-jquery.mjs} +2 -2
  89. package/fesm2015/breeze-client-adapter-ajax-jquery.mjs.map +1 -0
  90. package/fesm2015/{breeze-client-adapter-ajax-post.js → breeze-client-adapter-ajax-post.mjs} +1 -1
  91. package/fesm2015/breeze-client-adapter-ajax-post.mjs.map +1 -0
  92. package/fesm2015/{breeze-client-adapter-data-service-odata.js → breeze-client-adapter-data-service-odata.mjs} +20 -22
  93. package/fesm2015/breeze-client-adapter-data-service-odata.mjs.map +1 -0
  94. package/fesm2015/{breeze-client-adapter-data-service-webapi.js → breeze-client-adapter-data-service-webapi.mjs} +13 -13
  95. package/fesm2015/breeze-client-adapter-data-service-webapi.mjs.map +1 -0
  96. package/fesm2015/{breeze-client-adapter-model-library-backing-store.js → breeze-client-adapter-model-library-backing-store.mjs} +13 -13
  97. package/fesm2015/breeze-client-adapter-model-library-backing-store.mjs.map +1 -0
  98. package/fesm2015/{breeze-client-adapter-model-library-ko.js → breeze-client-adapter-model-library-ko.mjs} +13 -13
  99. package/fesm2015/breeze-client-adapter-model-library-ko.mjs.map +1 -0
  100. package/fesm2015/{breeze-client-adapter-uri-builder-json.js → breeze-client-adapter-uri-builder-json.mjs} +8 -8
  101. package/fesm2015/breeze-client-adapter-uri-builder-json.mjs.map +1 -0
  102. package/fesm2015/{breeze-client-adapter-uri-builder-odata.js → breeze-client-adapter-uri-builder-odata.mjs} +85 -86
  103. package/fesm2015/breeze-client-adapter-uri-builder-odata.mjs.map +1 -0
  104. package/fesm2015/{breeze-client-mixin-get-entity-graph.js → breeze-client-mixin-get-entity-graph.mjs} +1 -1
  105. package/fesm2015/breeze-client-mixin-get-entity-graph.mjs.map +1 -0
  106. package/fesm2015/{breeze-client-mixin-save-queuing.js → breeze-client-mixin-save-queuing.mjs} +1 -1
  107. package/fesm2015/breeze-client-mixin-save-queuing.mjs.map +1 -0
  108. package/fesm2015/{breeze-client.js → breeze-client.mjs} +417 -422
  109. package/fesm2015/breeze-client.mjs.map +1 -0
  110. package/{fesm5/breeze-client-adapter-ajax-angularjs.js → fesm2020/breeze-client-adapter-ajax-angularjs.mjs} +41 -42
  111. package/fesm2020/breeze-client-adapter-ajax-angularjs.mjs.map +1 -0
  112. package/{fesm5/breeze-client-adapter-ajax-fetch.js → fesm2020/breeze-client-adapter-ajax-fetch.mjs} +44 -43
  113. package/fesm2020/breeze-client-adapter-ajax-fetch.mjs.map +1 -0
  114. package/{fesm5/breeze-client-adapter-ajax-httpclient.js → fesm2020/breeze-client-adapter-ajax-httpclient.mjs} +43 -44
  115. package/fesm2020/breeze-client-adapter-ajax-httpclient.mjs.map +1 -0
  116. package/{fesm5/breeze-client-adapter-ajax-jquery.js → fesm2020/breeze-client-adapter-ajax-jquery.mjs} +18 -19
  117. package/fesm2020/breeze-client-adapter-ajax-jquery.mjs.map +1 -0
  118. package/{fesm5/breeze-client-adapter-ajax-post.js → fesm2020/breeze-client-adapter-ajax-post.mjs} +8 -11
  119. package/fesm2020/breeze-client-adapter-ajax-post.mjs.map +1 -0
  120. package/{fesm5/breeze-client-adapter-data-service-odata.js → fesm2020/breeze-client-adapter-data-service-odata.mjs} +126 -134
  121. package/fesm2020/breeze-client-adapter-data-service-odata.mjs.map +1 -0
  122. package/{fesm5/breeze-client-adapter-data-service-webapi.js → fesm2020/breeze-client-adapter-data-service-webapi.mjs} +38 -42
  123. package/fesm2020/breeze-client-adapter-data-service-webapi.mjs.map +1 -0
  124. package/{fesm5/breeze-client-adapter-model-library-backing-store.js → fesm2020/breeze-client-adapter-model-library-backing-store.mjs} +63 -64
  125. package/fesm2020/breeze-client-adapter-model-library-backing-store.mjs.map +1 -0
  126. package/{fesm5/breeze-client-adapter-model-library-ko.js → fesm2020/breeze-client-adapter-model-library-ko.mjs} +57 -58
  127. package/fesm2020/breeze-client-adapter-model-library-ko.mjs.map +1 -0
  128. package/fesm2020/breeze-client-adapter-uri-builder-json.mjs +91 -0
  129. package/fesm2020/breeze-client-adapter-uri-builder-json.mjs.map +1 -0
  130. package/fesm2020/breeze-client-adapter-uri-builder-odata.mjs +245 -0
  131. package/fesm2020/breeze-client-adapter-uri-builder-odata.mjs.map +1 -0
  132. package/{fesm5/breeze-client-mixin-get-entity-graph.js → fesm2020/breeze-client-mixin-get-entity-graph.mjs} +45 -45
  133. package/fesm2020/breeze-client-mixin-get-entity-graph.mjs.map +1 -0
  134. package/{fesm5/breeze-client-mixin-save-queuing.js → fesm2020/breeze-client-mixin-save-queuing.mjs} +116 -126
  135. package/fesm2020/breeze-client-mixin-save-queuing.mjs.map +1 -0
  136. package/{fesm5/breeze-client.js → fesm2020/breeze-client.mjs} +3403 -3615
  137. package/fesm2020/breeze-client.mjs.map +1 -0
  138. package/mixin-get-entity-graph/{breeze-client-mixin-get-entity-graph.d.ts → index.d.ts} +1 -0
  139. package/mixin-save-queuing/{breeze-client-mixin-save-queuing.d.ts → index.d.ts} +1 -0
  140. package/package.json +126 -12
  141. package/src/entity-metadata.d.ts +6 -4
  142. package/src/entity-query.d.ts +1 -1
  143. package/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.metadata.json +0 -1
  144. package/adapter-ajax-angularjs/package.json +0 -13
  145. package/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.metadata.json +0 -1
  146. package/adapter-ajax-fetch/package.json +0 -13
  147. package/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.metadata.json +0 -1
  148. package/adapter-ajax-httpclient/package.json +0 -17
  149. package/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.metadata.json +0 -1
  150. package/adapter-ajax-jquery/package.json +0 -13
  151. package/adapter-ajax-post/breeze-client-adapter-ajax-post.metadata.json +0 -1
  152. package/adapter-ajax-post/package.json +0 -13
  153. package/adapter-data-service-odata/breeze-client-adapter-data-service-odata.metadata.json +0 -1
  154. package/adapter-data-service-odata/package.json +0 -13
  155. package/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.metadata.json +0 -1
  156. package/adapter-data-service-webapi/package.json +0 -13
  157. package/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.metadata.json +0 -1
  158. package/adapter-model-library-backing-store/package.json +0 -13
  159. package/adapter-model-library-ko/breeze-client-adapter-model-library-ko.metadata.json +0 -1
  160. package/adapter-model-library-ko/package.json +0 -13
  161. package/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.metadata.json +0 -1
  162. package/adapter-uri-builder-json/package.json +0 -13
  163. package/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.metadata.json +0 -1
  164. package/adapter-uri-builder-odata/package.json +0 -13
  165. package/breeze-client.d.ts +0 -8
  166. package/breeze-client.metadata.json +0 -1
  167. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js +0 -190
  168. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js.map +0 -1
  169. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js +0 -2
  170. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js.map +0 -1
  171. package/bundles/breeze-client-adapter-ajax-fetch.umd.js +0 -190
  172. package/bundles/breeze-client-adapter-ajax-fetch.umd.js.map +0 -1
  173. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js +0 -2
  174. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js.map +0 -1
  175. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js +0 -195
  176. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js.map +0 -1
  177. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js +0 -2
  178. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js.map +0 -1
  179. package/bundles/breeze-client-adapter-ajax-jquery.umd.js +0 -115
  180. package/bundles/breeze-client-adapter-ajax-jquery.umd.js.map +0 -1
  181. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js +0 -2
  182. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js.map +0 -1
  183. package/bundles/breeze-client-adapter-ajax-post.umd.js +0 -92
  184. package/bundles/breeze-client-adapter-ajax-post.umd.js.map +0 -1
  185. package/bundles/breeze-client-adapter-ajax-post.umd.min.js +0 -2
  186. package/bundles/breeze-client-adapter-ajax-post.umd.min.js.map +0 -1
  187. package/bundles/breeze-client-adapter-data-service-odata.umd.js +0 -743
  188. package/bundles/breeze-client-adapter-data-service-odata.umd.js.map +0 -1
  189. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js +0 -16
  190. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js.map +0 -1
  191. package/bundles/breeze-client-adapter-data-service-webapi.umd.js +0 -326
  192. package/bundles/breeze-client-adapter-data-service-webapi.umd.js.map +0 -1
  193. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js +0 -16
  194. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js.map +0 -1
  195. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js +0 -280
  196. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js.map +0 -1
  197. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js +0 -2
  198. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js.map +0 -1
  199. package/bundles/breeze-client-adapter-model-library-ko.umd.js +0 -252
  200. package/bundles/breeze-client-adapter-model-library-ko.umd.js.map +0 -1
  201. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js +0 -2
  202. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js.map +0 -1
  203. package/bundles/breeze-client-adapter-uri-builder-json.umd.js +0 -96
  204. package/bundles/breeze-client-adapter-uri-builder-json.umd.js.map +0 -1
  205. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js +0 -2
  206. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js.map +0 -1
  207. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js +0 -262
  208. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js.map +0 -1
  209. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js +0 -2
  210. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js.map +0 -1
  211. package/bundles/breeze-client-mixin-get-entity-graph.umd.js +0 -258
  212. package/bundles/breeze-client-mixin-get-entity-graph.umd.js.map +0 -1
  213. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js +0 -2
  214. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js.map +0 -1
  215. package/bundles/breeze-client-mixin-save-queuing.umd.js +0 -579
  216. package/bundles/breeze-client-mixin-save-queuing.umd.js.map +0 -1
  217. package/bundles/breeze-client-mixin-save-queuing.umd.min.js +0 -16
  218. package/bundles/breeze-client-mixin-save-queuing.umd.min.js.map +0 -1
  219. package/bundles/breeze-client.umd.js +0 -14094
  220. package/bundles/breeze-client.umd.js.map +0 -1
  221. package/bundles/breeze-client.umd.min.js +0 -16
  222. package/bundles/breeze-client.umd.min.js.map +0 -1
  223. package/esm2015/adapter-ajax-angularjs/adapter-ajax-angularjs.js +0 -130
  224. package/esm2015/adapter-ajax-angularjs/adapter-core.js +0 -49
  225. package/esm2015/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +0 -5
  226. package/esm2015/adapter-ajax-fetch/adapter-ajax-fetch.js +0 -130
  227. package/esm2015/adapter-ajax-fetch/adapter-core.js +0 -49
  228. package/esm2015/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +0 -5
  229. package/esm2015/adapter-ajax-httpclient/adapter-ajax-httpclient.js +0 -137
  230. package/esm2015/adapter-ajax-httpclient/adapter-core.js +0 -49
  231. package/esm2015/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +0 -5
  232. package/esm2015/adapter-ajax-jquery/adapter-ajax-jquery.js +0 -103
  233. package/esm2015/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +0 -5
  234. package/esm2015/adapter-ajax-post/adapter-ajax-post.js +0 -77
  235. package/esm2015/adapter-ajax-post/breeze-client-adapter-ajax-post.js +0 -5
  236. package/esm2015/adapter-data-service-odata/adapter-core.js +0 -49
  237. package/esm2015/adapter-data-service-odata/adapter-data-service-odata.js +0 -459
  238. package/esm2015/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +0 -5
  239. package/esm2015/adapter-data-service-webapi/adapter-data-service-webapi.js +0 -93
  240. package/esm2015/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +0 -5
  241. package/esm2015/adapter-model-library-backing-store/adapter-model-library-backing-store.js +0 -268
  242. package/esm2015/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +0 -5
  243. package/esm2015/adapter-model-library-ko/adapter-model-library-ko.js +0 -240
  244. package/esm2015/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +0 -5
  245. package/esm2015/adapter-uri-builder-json/adapter-core.js +0 -49
  246. package/esm2015/adapter-uri-builder-json/adapter-uri-builder-json.js +0 -36
  247. package/esm2015/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +0 -5
  248. package/esm2015/adapter-uri-builder-odata/adapter-core.js +0 -49
  249. package/esm2015/adapter-uri-builder-odata/adapter-uri-builder-odata.js +0 -192
  250. package/esm2015/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +0 -5
  251. package/esm2015/breeze-client.js +0 -9
  252. package/esm2015/index.js +0 -2
  253. package/esm2015/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +0 -5
  254. package/esm2015/mixin-get-entity-graph/mixin-get-entity-graph.js +0 -269
  255. package/esm2015/mixin-save-queuing/breeze-client-mixin-save-queuing.js +0 -5
  256. package/esm2015/mixin-save-queuing/mixin-save-queuing.js +0 -400
  257. package/esm2015/public_api.js +0 -2
  258. package/esm2015/src/abstract-data-service-adapter.js +0 -296
  259. package/esm2015/src/array.js +0 -4
  260. package/esm2015/src/assert-param.js +0 -312
  261. package/esm2015/src/breeze.js +0 -85
  262. package/esm2015/src/complex-array.js +0 -119
  263. package/esm2015/src/config.js +0 -223
  264. package/esm2015/src/core.js +0 -706
  265. package/esm2015/src/csdl-metadata-parser.js +0 -385
  266. package/esm2015/src/data-service.js +0 -203
  267. package/esm2015/src/data-type.js +0 -444
  268. package/esm2015/src/default-property-interceptor.js +0 -459
  269. package/esm2015/src/entity-action.js +0 -45
  270. package/esm2015/src/entity-aspect.js +0 -806
  271. package/esm2015/src/entity-group.js +0 -187
  272. package/esm2015/src/entity-key.js +0 -116
  273. package/esm2015/src/entity-manager.js +0 -2094
  274. package/esm2015/src/entity-metadata.js +0 -2109
  275. package/esm2015/src/entity-query.js +0 -996
  276. package/esm2015/src/entity-state.js +0 -99
  277. package/esm2015/src/enum.js +0 -141
  278. package/esm2015/src/event.js +0 -256
  279. package/esm2015/src/interface-registry.js +0 -41
  280. package/esm2015/src/key-generator.js +0 -108
  281. package/esm2015/src/local-query-comparison-options.js +0 -65
  282. package/esm2015/src/mapping-context.js +0 -405
  283. package/esm2015/src/naming-convention.js +0 -88
  284. package/esm2015/src/observable-array.js +0 -185
  285. package/esm2015/src/predicate.js +0 -1235
  286. package/esm2015/src/primitive-array.js +0 -87
  287. package/esm2015/src/query-options.js +0 -152
  288. package/esm2015/src/relation-array.js +0 -175
  289. package/esm2015/src/save-options.js +0 -41
  290. package/esm2015/src/unattached-children-map.js +0 -58
  291. package/esm2015/src/validate.js +0 -991
  292. package/esm2015/src/validation-options.js +0 -64
  293. package/esm5/adapter-ajax-angularjs/adapter-ajax-angularjs.js +0 -132
  294. package/esm5/adapter-ajax-angularjs/adapter-core.js +0 -49
  295. package/esm5/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +0 -5
  296. package/esm5/adapter-ajax-fetch/adapter-ajax-fetch.js +0 -132
  297. package/esm5/adapter-ajax-fetch/adapter-core.js +0 -49
  298. package/esm5/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +0 -5
  299. package/esm5/adapter-ajax-httpclient/adapter-ajax-httpclient.js +0 -139
  300. package/esm5/adapter-ajax-httpclient/adapter-core.js +0 -49
  301. package/esm5/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +0 -5
  302. package/esm5/adapter-ajax-jquery/adapter-ajax-jquery.js +0 -105
  303. package/esm5/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +0 -5
  304. package/esm5/adapter-ajax-post/adapter-ajax-post.js +0 -81
  305. package/esm5/adapter-ajax-post/breeze-client-adapter-ajax-post.js +0 -5
  306. package/esm5/adapter-data-service-odata/adapter-core.js +0 -49
  307. package/esm5/adapter-data-service-odata/adapter-data-service-odata.js +0 -466
  308. package/esm5/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +0 -5
  309. package/esm5/adapter-data-service-webapi/adapter-data-service-webapi.js +0 -98
  310. package/esm5/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +0 -5
  311. package/esm5/adapter-model-library-backing-store/adapter-model-library-backing-store.js +0 -270
  312. package/esm5/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +0 -5
  313. package/esm5/adapter-model-library-ko/adapter-model-library-ko.js +0 -242
  314. package/esm5/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +0 -5
  315. package/esm5/adapter-uri-builder-json/adapter-core.js +0 -49
  316. package/esm5/adapter-uri-builder-json/adapter-uri-builder-json.js +0 -38
  317. package/esm5/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +0 -5
  318. package/esm5/adapter-uri-builder-odata/adapter-core.js +0 -49
  319. package/esm5/adapter-uri-builder-odata/adapter-uri-builder-odata.js +0 -197
  320. package/esm5/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +0 -5
  321. package/esm5/breeze-client.js +0 -9
  322. package/esm5/index.js +0 -2
  323. package/esm5/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +0 -5
  324. package/esm5/mixin-get-entity-graph/mixin-get-entity-graph.js +0 -269
  325. package/esm5/mixin-save-queuing/breeze-client-mixin-save-queuing.js +0 -5
  326. package/esm5/mixin-save-queuing/mixin-save-queuing.js +0 -412
  327. package/esm5/public_api.js +0 -2
  328. package/esm5/src/abstract-data-service-adapter.js +0 -302
  329. package/esm5/src/array.js +0 -4
  330. package/esm5/src/assert-param.js +0 -317
  331. package/esm5/src/breeze.js +0 -85
  332. package/esm5/src/complex-array.js +0 -119
  333. package/esm5/src/config.js +0 -228
  334. package/esm5/src/core.js +0 -714
  335. package/esm5/src/csdl-metadata-parser.js +0 -385
  336. package/esm5/src/data-service.js +0 -207
  337. package/esm5/src/data-type.js +0 -451
  338. package/esm5/src/default-property-interceptor.js +0 -459
  339. package/esm5/src/entity-action.js +0 -52
  340. package/esm5/src/entity-aspect.js +0 -812
  341. package/esm5/src/entity-group.js +0 -189
  342. package/esm5/src/entity-key.js +0 -118
  343. package/esm5/src/entity-manager.js +0 -2112
  344. package/esm5/src/entity-metadata.js +0 -2144
  345. package/esm5/src/entity-query.js +0 -1023
  346. package/esm5/src/entity-state.js +0 -106
  347. package/esm5/src/enum.js +0 -144
  348. package/esm5/src/event.js +0 -259
  349. package/esm5/src/interface-registry.js +0 -43
  350. package/esm5/src/key-generator.js +0 -111
  351. package/esm5/src/local-query-comparison-options.js +0 -67
  352. package/esm5/src/mapping-context.js +0 -407
  353. package/esm5/src/naming-convention.js +0 -90
  354. package/esm5/src/observable-array.js +0 -201
  355. package/esm5/src/predicate.js +0 -1300
  356. package/esm5/src/primitive-array.js +0 -87
  357. package/esm5/src/query-options.js +0 -167
  358. package/esm5/src/relation-array.js +0 -175
  359. package/esm5/src/save-options.js +0 -43
  360. package/esm5/src/unattached-children-map.js +0 -60
  361. package/esm5/src/validate.js +0 -996
  362. package/esm5/src/validation-options.js +0 -66
  363. package/fesm2015/breeze-client-adapter-ajax-angularjs.js.map +0 -1
  364. package/fesm2015/breeze-client-adapter-ajax-fetch.js.map +0 -1
  365. package/fesm2015/breeze-client-adapter-ajax-httpclient.js.map +0 -1
  366. package/fesm2015/breeze-client-adapter-ajax-jquery.js.map +0 -1
  367. package/fesm2015/breeze-client-adapter-ajax-post.js.map +0 -1
  368. package/fesm2015/breeze-client-adapter-data-service-odata.js.map +0 -1
  369. package/fesm2015/breeze-client-adapter-data-service-webapi.js.map +0 -1
  370. package/fesm2015/breeze-client-adapter-model-library-backing-store.js.map +0 -1
  371. package/fesm2015/breeze-client-adapter-model-library-ko.js.map +0 -1
  372. package/fesm2015/breeze-client-adapter-uri-builder-json.js.map +0 -1
  373. package/fesm2015/breeze-client-adapter-uri-builder-odata.js.map +0 -1
  374. package/fesm2015/breeze-client-mixin-get-entity-graph.js.map +0 -1
  375. package/fesm2015/breeze-client-mixin-save-queuing.js.map +0 -1
  376. package/fesm2015/breeze-client.js.map +0 -1
  377. package/fesm5/breeze-client-adapter-ajax-angularjs.js.map +0 -1
  378. package/fesm5/breeze-client-adapter-ajax-fetch.js.map +0 -1
  379. package/fesm5/breeze-client-adapter-ajax-httpclient.js.map +0 -1
  380. package/fesm5/breeze-client-adapter-ajax-jquery.js.map +0 -1
  381. package/fesm5/breeze-client-adapter-ajax-post.js.map +0 -1
  382. package/fesm5/breeze-client-adapter-data-service-odata.js.map +0 -1
  383. package/fesm5/breeze-client-adapter-data-service-webapi.js.map +0 -1
  384. package/fesm5/breeze-client-adapter-model-library-backing-store.js.map +0 -1
  385. package/fesm5/breeze-client-adapter-model-library-ko.js.map +0 -1
  386. package/fesm5/breeze-client-adapter-uri-builder-json.js +0 -92
  387. package/fesm5/breeze-client-adapter-uri-builder-json.js.map +0 -1
  388. package/fesm5/breeze-client-adapter-uri-builder-odata.js +0 -250
  389. package/fesm5/breeze-client-adapter-uri-builder-odata.js.map +0 -1
  390. package/fesm5/breeze-client-mixin-get-entity-graph.js.map +0 -1
  391. package/fesm5/breeze-client-mixin-save-queuing.js.map +0 -1
  392. package/fesm5/breeze-client.js.map +0 -1
  393. package/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.metadata.json +0 -1
  394. package/mixin-get-entity-graph/package.json +0 -13
  395. package/mixin-save-queuing/breeze-client-mixin-save-queuing.metadata.json +0 -1
  396. package/mixin-save-queuing/package.json +0 -13
  397. package/public_api.d.ts +0 -1
@@ -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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TyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7QUFDdkQsQ0FBQztBQUVELFNBQVMsbUJBQW1CLENBQUMsRUFBaUI7SUFDNUMseURBQXlEO0lBQ3pELElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDaEUsZ0RBQWdEO0lBQ2hELE9BQU8sRUFBRSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFO1FBQ3ZELE9BQU8sbUJBQW1CLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLEtBQStCO0lBQ3RELE9BQU8sS0FBSyxDQUFDLFlBQVksSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLElBQUksS0FBSyxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUN6RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGF0YVNlcnZpY2VBZGFwdGVyIH0gZnJvbSAnLi9pbnRlcmZhY2UtcmVnaXN0cnknO1xyXG5pbXBvcnQgeyBjb3JlLCBDYWxsYmFjaywgRXJyb3JDYWxsYmFjayB9IGZyb20gJy4vY29yZSc7XHJcbmltcG9ydCB7IGFzc2VydFBhcmFtLCBhc3NlcnRDb25maWcgfSBmcm9tICcuL2Fzc2VydC1wYXJhbSc7XHJcbmltcG9ydCB7IGNvbmZpZyB9IGZyb20gJy4vY29uZmlnJztcclxuaW1wb3J0IHsgQnJlZXplRXZlbnQgfSBmcm9tICcuL2V2ZW50JztcclxuaW1wb3J0IHsgRW50aXR5QXNwZWN0LCBFbnRpdHksIENvbXBsZXhPYmplY3QsIFN0cnVjdHVyYWxPYmplY3QsIFByb3BlcnR5Q2hhbmdlZEV2ZW50QXJncyB9IGZyb20gJy4vZW50aXR5LWFzcGVjdCc7XHJcbmltcG9ydCB7IE1ldGFkYXRhU3RvcmUsIEVudGl0eVR5cGUsIENvbXBsZXhUeXBlLCBEYXRhUHJvcGVydHksIE5hdmlnYXRpb25Qcm9wZXJ0eSwgQXV0b0dlbmVyYXRlZEtleVR5cGUgfSBmcm9tICcuL2VudGl0eS1tZXRhZGF0YSc7XHJcbmltcG9ydCB7IEVudGl0eUtleSB9IGZyb20gJy4vZW50aXR5LWtleSc7XHJcbmltcG9ydCB7IEVudGl0eUFjdGlvbiAgfSBmcm9tICcuL2VudGl0eS1hY3Rpb24nO1xyXG5pbXBvcnQgeyBFbnRpdHlTdGF0ZSB9IGZyb20gJy4vZW50aXR5LXN0YXRlJztcclxuaW1wb3J0IHsgRGF0YVNlcnZpY2UgfSBmcm9tICcuL2RhdGEtc2VydmljZSc7XHJcbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi9kYXRhLXR5cGUnO1xyXG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICcuL3ZhbGlkYXRlJztcclxuaW1wb3J0IHsgVmFsaWRhdGlvbk9wdGlvbnMgfSBmcm9tICcuL3ZhbGlkYXRpb24tb3B0aW9ucyc7XHJcbmltcG9ydCB7IFF1ZXJ5T3B0aW9ucywgTWVyZ2VTdHJhdGVneSwgRmV0Y2hTdHJhdGVneSB9IGZyb20gJy4vcXVlcnktb3B0aW9ucyc7XHJcbmltcG9ydCB7IFNhdmVPcHRpb25zIH0gZnJvbSAnLi9zYXZlLW9wdGlvbnMnO1xyXG5pbXBvcnQgeyBLZXlHZW5lcmF0b3IgfSBmcm9tICcuL2tleS1nZW5lcmF0b3InO1xyXG5pbXBvcnQgeyBFbnRpdHlHcm91cCB9IGZyb20gJy4vZW50aXR5LWdyb3VwJztcclxuaW1wb3J0IHsgTWFwcGluZ0NvbnRleHQgfSBmcm9tICcuL21hcHBpbmctY29udGV4dCc7XHJcbmltcG9ydCB7IEVudGl0eVF1ZXJ5IH0gZnJvbSAnLi9lbnRpdHktcXVlcnknO1xyXG5pbXBvcnQgeyBVbmF0dGFjaGVkQ2hpbGRyZW5NYXAgfSBmcm9tICcuL3VuYXR0YWNoZWQtY2hpbGRyZW4tbWFwJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSHR0cFJlc3BvbnNlIHtcclxuICBjb25maWc6IGFueTtcclxuICBkYXRhOiBhbnk7XHJcbiAgZXJyb3I/OiBhbnk7XHJcbiAgc2F2ZUNvbnRleHQ/OiBhbnk7XHJcbiAgc3RhdHVzOiBudW1iZXI7XHJcbiAgZ2V0SGVhZGVycyhoZWFkZXJOYW1lOiBzdHJpbmcpOiBzdHJpbmc7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSW1wb3J0UmVzdWx0IHtcclxuICBlbnRpdGllczogRW50aXR5W107XHJcbiAgdGVtcEtleU1hcHBpbmc6IElUZW1wS2V5TWFwO1xyXG59XHJcblxyXG4vLyBzdWJjbGFzc2VzIG9mIEVycm9yXHJcblxyXG4vKiogQmFzZSBzaGFwZSBvZiBhbnkgZXJyb3JzIHJldHVybmVkIGZyb20gdGhlIHNlcnZlci4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJFcnJvciBleHRlbmRzIEVycm9yIHtcclxuICBodHRwUmVzcG9uc2U6IEh0dHBSZXNwb25zZTtcclxuICBzdGF0dXM6IG51bWJlcjtcclxuICBtZXNzYWdlOiBzdHJpbmc7XHJcbiAgc3RhdHVzVGV4dD86IHN0cmluZztcclxuICBib2R5PzogYW55O1xyXG4gIHVybD86IHN0cmluZztcclxufVxyXG5cclxuLyoqIFNoYXBlIG9mIGEgc2F2ZSBlcnJvciByZXR1cm5lZCBmcm9tIHRoZSBzZXJ2ZXIuIFxyXG5Gb3IgdXNlIGJ5IGJyZWV6ZSBwbHVnaW4gYXV0aG9ycyBvbmx5LiBUaGUgY2xhc3MgaXMgZm9yIHVzZSBpbiBidWlsZGluZyBhIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dIGltcGxlbWVudGF0aW9uLiBcclxuQGFkYXB0ZXIgKHNlZSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSkgICAgXHJcbkBoaWRkZW4gQGludGVybmFsIFxyXG4qL1xyXG5leHBvcnQgaW50ZXJmYWNlIFNhdmVFcnJvckZyb21TZXJ2ZXIgZXh0ZW5kcyBTZXJ2ZXJFcnJvciB7XHJcbiAgZW50aXR5RXJyb3JzOiBFbnRpdHlFcnJvckZyb21TZXJ2ZXJbXTtcclxufVxyXG5cclxuLyoqIFNoYXBlIG9mIGEgc2F2ZSBlcnJvciB3aGVuIHJldHVybmVkIHRvIHRoZSBjbGllbnQuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZUVycm9yIGV4dGVuZHMgU2VydmVyRXJyb3Ige1xyXG4gIGVudGl0eUVycm9yczogRW50aXR5RXJyb3JbXTtcclxufVxyXG5cclxuLy8gbm90IHN1YmNsYXNzZXMgb2YgRXJyb3JcclxuLyoqIFxyXG5Gb3IgdXNlIGJ5IGJyZWV6ZSBwbHVnaW4gYXV0aG9ycyBvbmx5LiBUaGUgY2xhc3MgaXMgZm9yIHVzZSBpbiBidWlsZGluZyBhIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dIGltcGxlbWVudGF0aW9uLiBcclxuQGFkYXB0ZXIgKHNlZSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSkgICAgXHJcbkBoaWRkZW4gQGludGVybmFsIFxyXG4qL1xyXG5leHBvcnQgaW50ZXJmYWNlIEVudGl0eUVycm9yRnJvbVNlcnZlciB7XHJcbiAgZW50aXR5VHlwZU5hbWU6IHN0cmluZztcclxuICBrZXlWYWx1ZXM6IGFueVtdO1xyXG5cclxuICBlcnJvck5hbWU6IHN0cmluZztcclxuICBlcnJvck1lc3NhZ2U6IHN0cmluZztcclxuICBwcm9wZXJ0eU5hbWU6IHN0cmluZztcclxuICBjdXN0b20/OiBhbnk7XHJcbn1cclxuXHJcbi8qKiBTaGFwZSBvZiBhbiBlcnJvciBvbiBhIHNwZWNpZmljIGVudGl0eS4gIFBhcnQgb2YgYSBbW0lTYXZlRXJyb3JdXSAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEVudGl0eUVycm9yIHtcclxuICBlbnRpdHk6IEVudGl0eTtcclxuICBlcnJvck5hbWU6IHN0cmluZztcclxuICBlcnJvck1lc3NhZ2U6IHN0cmluZztcclxuICBwcm9wZXJ0eU5hbWU6IHN0cmluZztcclxuICBpc1NlcnZlckVycm9yOiBib29sZWFuO1xyXG4gIGN1c3RvbT86IGFueTtcclxufVxyXG5cclxuLyoqIFRoZSBzaGFwZSBvZiB0aGUgUHJvbWlzZSByZXR1cm5lZCBieSBhbiBbW0VudGl0eU1hbmFnZXIuZXhlY3V0ZVF1ZXJ5XV0gY2FsbC4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBRdWVyeVJlc3VsdCB7XHJcbiAgLyoqIFRvcCBsZXZlbCBlbnRpdGllcyByZXR1cm5lZCAqL1xyXG4gIHJlc3VsdHM6IGFueVtdO1xyXG4gIC8qKiBRdWVyeSB0aGF0IHdhcyBleGVjdXRlZCAqL1xyXG4gIHF1ZXJ5OiBFbnRpdHlRdWVyeSB8IHN0cmluZztcclxuICAvKiogRW50aXR5TWFuYWdlciB0aGF0IGV4ZWN1dGVkIHRoZSBxdWVyeSAqL1xyXG4gIGVudGl0eU1hbmFnZXI/OiBFbnRpdHlNYW5hZ2VyO1xyXG4gIC8qKiBUb3RhbCBudW1iZXIgb2YgcmVzdWx0cyBhdmFpbGFibGUgb24gdGhlIHNlcnZlciAqL1xyXG4gIGlubGluZUNvdW50PzogbnVtYmVyO1xyXG4gIC8qKiBBbGwgZW50aXRpZXMgcmV0dXJuZWQgYnkgdGhlIHF1ZXJ5LiAgRGlmZmVycyBmcm9tIHJlc3VsdHMgd2hlbiBhbiBleHBhbmQgaXMgdXNlZC4gKi9cclxuICByZXRyaWV2ZWRFbnRpdGllcz86IEVudGl0eVtdO1xyXG4gICAgLyoqIFJhdyByZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIgKi9cclxuICBodHRwUmVzcG9uc2U/OiBIdHRwUmVzcG9uc2U7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUXVlcnlTdWNjZXNzQ2FsbGJhY2sge1xyXG4gIChkYXRhOiBRdWVyeVJlc3VsdCk6IHZvaWQ7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUXVlcnlFcnJvckNhbGxiYWNrIHtcclxuICAoZXJyb3I6IHsgcXVlcnk6IEVudGl0eVF1ZXJ5OyBodHRwUmVzcG9uc2U6IEh0dHBSZXNwb25zZTsgZW50aXR5TWFuYWdlcjogRW50aXR5TWFuYWdlcjsgbWVzc2FnZT86IHN0cmluZzsgc3RhY2s/OiBzdHJpbmcgfSk6IHZvaWQ7XHJcbn1cclxuXHJcbi8qKiBLZXkgbWFwcGluZyBpbmZvcm1hdGlvbiByZXR1cm5lZCBhcyBwYXJ0IG9mIGFuIFtbSVNhdmVSZXN1bHRdXS4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBLZXlNYXBwaW5nIHtcclxuICBlbnRpdHlUeXBlTmFtZTogc3RyaW5nO1xyXG4gIHRlbXBWYWx1ZTogYW55O1xyXG4gIHJlYWxWYWx1ZTogYW55O1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSVRlbXBLZXlNYXAge1xyXG4gIFtpbmRleDogc3RyaW5nXTogRW50aXR5S2V5O1xyXG59XHJcblxyXG4vKiogQ29uZmlndXJhdGlvbiBpbmZvIHRvIGJlIHBhc3NlZCB0byB0aGUgW1tFbnRpdHlNYW5hZ2VyLmltcG9ydEVudGl0aWVzXV0gbWV0aG9kICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSW1wb3J0Q29uZmlnIHtcclxuICAvKiogSWYgdHJ1ZSwgbWVyZ2UgQWRkZWQgZW50aXRpZXMgKHdpdGggdGVtcCBrZXlzKSBhcyB3ZWxsLiAgVGhpcyBjYW4gYmUgZGFuZ2Vyb3VzLiAqL1xyXG4gIG1lcmdlQWRkcz86IGJvb2xlYW47XHJcbiAgbWVyZ2VTdHJhdGVneT86IE1lcmdlU3RyYXRlZ3k7ICBcclxuICBtZXRhZGF0YVZlcnNpb25Gbj86IChhcmc6IHsgbWV0YWRhdGFWZXJzaW9uOiBhbnksIG1ldGFkYXRhU3RvcmVOYW1lOiBhbnkgfSkgPT4gdm9pZDtcclxufVxyXG5cclxuaW50ZXJmYWNlIEltcG9ydENvbmZpZ0V4dCBleHRlbmRzIEltcG9ydENvbmZpZyB7XHJcbiAgdGVtcEtleU1hcD86IElUZW1wS2V5TWFwO1xyXG59XHJcblxyXG4vKiogVGhlIHNoYXBlIG9mIHRoZSBQcm9taXNlIHJldHVybmVkIGJ5IGFuIFtbRW50aXR5TWFuYWdlci5zYXZlQ2hhbmdlc11dIGNhbGwuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZVJlc3VsdCB7XHJcbiAgZW50aXRpZXM6IEVudGl0eVtdO1xyXG4gIGtleU1hcHBpbmdzOiBLZXlNYXBwaW5nW107XHJcbiAgZGVsZXRlZEtleXM/OiB7IGVudGl0eVR5cGVOYW1lOiBzdHJpbmcsIGtleVZhbHVlczogYW55W119W107XHJcbiAgaHR0cFJlc3BvbnNlPzogSHR0cFJlc3BvbnNlO1xyXG59XHJcblxyXG4vKiogRm9yIHVzZSBieSBicmVlemUgcGx1Z2luIGF1dGhvcnMgb25seS4gVGhlIGNsYXNzIGlzIGZvciB1c2UgaW4gYnVpbGRpbmcgYSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSBpbXBsZW1lbnRhdGlvbi4gXHJcbkBhZGFwdGVyIChzZWUgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0pICAgIFxyXG5AaGlkZGVuIFxyXG4qL1xyXG5leHBvcnQgaW50ZXJmYWNlIFNhdmVDb250ZXh0IHtcclxuICBlbnRpdHlNYW5hZ2VyOiBFbnRpdHlNYW5hZ2VyO1xyXG4gIGRhdGFTZXJ2aWNlOiBEYXRhU2VydmljZTtcclxuICBwcm9jZXNzU2F2ZWRFbnRpdGllczogKHNhdmVSZXN1bHQ6IFNhdmVSZXN1bHQpID0+IEVudGl0eVtdO1xyXG4gIHJlc291cmNlTmFtZTogc3RyaW5nO1xyXG4gIGFkYXB0ZXI/OiBEYXRhU2VydmljZUFkYXB0ZXI7XHJcbiAgcm91dGVQcmVmaXg/OiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKiBGb3IgdXNlIGJ5IGJyZWV6ZSBwbHVnaW4gYXV0aG9ycyBvbmx5LiBUaGUgY2xhc3MgaXMgZm9yIHVzZSBpbiBidWlsZGluZyBhIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dIGltcGxlbWVudGF0aW9uLiBcclxuQGFkYXB0ZXIgKHNlZSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSkgICAgXHJcbkBoaWRkZW4gXHJcbiovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZUJ1bmRsZSB7XHJcbiAgZW50aXRpZXM6IEVudGl0eVtdO1xyXG4gIHNhdmVPcHRpb25zOiBTYXZlT3B0aW9ucztcclxufVxyXG5cclxuLyoqIENvbmZpZ3VyYXRpb24gaW5mbyB0byBiZSBwYXNzZWQgdG8gdGhlIFtbRW50aXR5TWFuYWdlcl1dIGNvbnN0cnVjdG9yICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5TWFuYWdlckNvbmZpZyB7XHJcbiAgLyoqIFRoZSBzZXJ2aWNlIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gICoqL1xyXG4gIHNlcnZpY2VOYW1lPzogc3RyaW5nO1xyXG4gIC8qKiBUaGUgRGF0YVNlcnZpY2UgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gKiovXHJcbiAgZGF0YVNlcnZpY2U/OiBEYXRhU2VydmljZTtcclxuICAvKiogVGhlIFtbUXVlcnlPcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gICoqL1xyXG4gIHF1ZXJ5T3B0aW9ucz86IFF1ZXJ5T3B0aW9ucztcclxuICAvKiogVGhlIFtbU2F2ZU9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAqKi9cclxuICBzYXZlT3B0aW9ucz86IFNhdmVPcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tWYWxpZGF0aW9uT3B0aW9uc11dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICAqKi9cclxuICB2YWxpZGF0aW9uT3B0aW9ucz86IFZhbGlkYXRpb25PcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tLZXlHZW5lcmF0b3JdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAqKi9cclxuICBrZXlHZW5lcmF0b3I/OiBLZXlHZW5lcmF0b3I7XHJcbiAgLyoqIFRoZSBbW0tleUdlbmVyYXRvcl1dIGNvbnN0cnVjdG9yIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICoqL1xyXG4gIGtleUdlbmVyYXRvckN0b3I/OiB7IG5ldyAoKTogS2V5R2VuZXJhdG9yIH07IC8vIFRPRE86IHJldmlldyB0aGlzXHJcbiAgLyoqIFRoZSBbW01ldGFkYXRhU3RvcmVdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAqKi9cclxuICBtZXRhZGF0YVN0b3JlPzogTWV0YWRhdGFTdG9yZTtcclxufVxyXG5cclxuLyoqIFRoZSBzaGFwZSByZXR1cm5lZCBieSBjYWxsYmFja3MgcmVnaXN0ZXJlZCB3aXRoIFtbRW50aXR5TWFuYWdlci5lbnRpdHlDaGFuZ2VkXV0gZXZlbnQgKi9cclxuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlDaGFuZ2VkRXZlbnRBcmdzIHtcclxuICBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbjtcclxuICBlbnRpdHk/OiBFbnRpdHk7XHJcbiAgYXJncz86IFByb3BlcnR5Q2hhbmdlZEV2ZW50QXJncztcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0aW9uRXJyb3JzQ2hhbmdlZEV2ZW50QXJncyB7XHJcbiAgZW50aXR5OiBFbnRpdHk7IFxyXG4gIGFkZGVkOiBWYWxpZGF0aW9uRXJyb3JbXTsgXHJcbiAgcmVtb3ZlZDogVmFsaWRhdGlvbkVycm9yW107XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSGFzQ2hhbmdlc0NoYW5nZWRFdmVudEFyZ3Mge1xyXG4gIGVudGl0eU1hbmFnZXI6IEVudGl0eU1hbmFnZXI7IFxyXG4gIGhhc0NoYW5nZXM6IGJvb2xlYW47XHJcbn1cclxuXHJcbi8qKlxyXG5JbnN0YW5jZXMgb2YgdGhlIEVudGl0eU1hbmFnZXIgY29udGFpbiBhbmQgbWFuYWdlIGNvbGxlY3Rpb25zIG9mIGVudGl0aWVzLCBlaXRoZXIgcmV0cmlldmVkIGZyb20gYSBiYWNrZW5kIGRhdGFzdG9yZSBvciBjcmVhdGVkIG9uIHRoZSBjbGllbnQuXHJcbioqL1xyXG5leHBvcnQgY2xhc3MgRW50aXR5TWFuYWdlciB7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgXyR0eXBlTmFtZTogc3RyaW5nOyAvLyBhY3R1YWxseSBkZWZpbmVkIG9uIHByb3RvdHlwZVxyXG5cclxuICAvKiogVGhlIHNlcnZpY2UgbmFtZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIHNlcnZpY2VOYW1lOiBzdHJpbmc7XHJcbiAgLyoqIFRoZSBEYXRhU2VydmljZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGRhdGFTZXJ2aWNlOiBEYXRhU2VydmljZTtcclxuICAvKiogVGhlIFtbUXVlcnlPcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBxdWVyeU9wdGlvbnM6IFF1ZXJ5T3B0aW9ucztcclxuICAvKiogVGhlIFtbU2F2ZU9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIHNhdmVPcHRpb25zOiBTYXZlT3B0aW9ucztcclxuICAvKiogVGhlIFtbVmFsaWRhdGlvbk9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIHZhbGlkYXRpb25PcHRpb25zOiBWYWxpZGF0aW9uT3B0aW9ucztcclxuICAvKiogVGhlIFtbS2V5R2VuZXJhdG9yXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBrZXlHZW5lcmF0b3I6IEtleUdlbmVyYXRvcjtcclxuICAvKiogVGhlIFtbS2V5R2VuZXJhdG9yXV0gY29uc3RydWN0b3IgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBrZXlHZW5lcmF0b3JDdG9yOiB7IG5ldyAoKTogS2V5R2VuZXJhdG9yIH07IC8vIFRPRE86IHJldmlldyB0aGlzXHJcbiAgLyoqIFRoZSBbW01ldGFkYXRhU3RvcmVdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIG1ldGFkYXRhU3RvcmU6IE1ldGFkYXRhU3RvcmU7XHJcbiAgaXNMb2FkaW5nOiBib29sZWFuO1xyXG4gIGlzUmVqZWN0aW5nQ2hhbmdlczogYm9vbGVhbjtcclxuXHJcbiAgLy8gZXZlbnRzXHJcbiAgLyoqXHJcbiAgQSBbW0JyZWV6ZUV2ZW50XV0gdGhhdCBmaXJlcyB3aGVuZXZlciBhIGNoYW5nZSB0byBhbnkgZW50aXR5IGluIHRoaXMgRW50aXR5TWFuYWdlciBvY2N1cnMuIF9fUmVhZCBPbmx5X19cclxuXHJcbiAgQGV2ZW50QXJncyAtIFxyXG4gIC0gZW50aXR5QWN0aW9uIC0gVGhlIFtbRW50aXR5QWN0aW9uXV0gdGhhdCBvY2N1cmVkLlxyXG4gIC0gZW50aXR5IC0gVGhlIGVudGl0eSB0aGF0IGNoYW5nZWQuICBJZiB0aGlzIGlzIG51bGwsIHRoZW4gYWxsIGVudGl0aWVzIGluIHRoZSBlbnRpdHlNYW5hZ2VyIHdlcmUgYWZmZWN0ZWQuXHJcbiAgLSBhcmdzIC0gQWRkaXRpb25hbCBpbmZvcm1hdGlvbiBhYm91dCB0aGlzIGV2ZW50LiBUaGlzIHdpbGwgZGlmZmVyIGJhc2VkIG9uIHRoZSBlbnRpdHlBY3Rpb24uXHJcblxyXG4gID4gICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcigge3NlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIgfSk7XHJcbiAgPiAgICAgIGVtLmVudGl0eUNoYW5nZWQuc3Vic2NyaWJlKGZ1bmN0aW9uKGNoYW5nZUFyZ3MpIHtcclxuICA+ICAgICAgICAgIC8vIFRoaXMgY29kZSB3aWxsIGJlIGV4ZWN1dGVkIGFueSB0aW1lIGFueSBlbnRpdHkgd2l0aGluIHRoZSBlbnRpdHlNYW5hZ2VyIFxyXG4gID4gICAgICAgICAgLy8gaXMgYWRkZWQsIG1vZGlmaWVkLCBkZWxldGVkIG9yIGRldGFjaGVkIGZvciBhbnkgcmVhc29uLlxyXG4gID4gICAgICAgICAgbGV0IGFjdGlvbiA9IGNoYW5nZUFyZ3MuZW50aXR5QWN0aW9uO1xyXG4gID4gICAgICAgICAgbGV0IGVudGl0eSA9IGNoYW5nZUFyZ3MuZW50aXR5O1xyXG4gID4gICAgICAgICAgLy8gLi4gZG8gc29tZXRoaW5nIHRvIHRoaXMgZW50aXR5IHdoZW4gaXQgaXMgY2hhbmdlZC5cclxuICA+ICAgICAgfSk7XHJcbiAgPiAgfSk7XHJcbiAgQGV2ZW50XHJcbiAgKiovXHJcbiAgZW50aXR5Q2hhbmdlZDogQnJlZXplRXZlbnQ8RW50aXR5Q2hhbmdlZEV2ZW50QXJncz47XHJcblxyXG4gIC8qKlxyXG4gIEFuIFtbQnJlZXplRXZlbnRdXSB0aGF0IGZpcmVzIHdoZW5ldmVyIHZhbGlkYXRpb25FcnJvcnMgY2hhbmdlIGZvciBhbnkgZW50aXR5IGluIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfX1xyXG4gIEBldmVudEFyZ3MgLVxyXG4gICAgLSBlbnRpdHkgLSBUaGUgZW50aXR5IG9uIHdoaWNoIHRoZSB2YWxpZGF0aW9uIGVycm9ycyBoYXZlIGJlZW4gYWRkZWQgb3IgcmVtb3ZlZC5cclxuICAgIC0gYWRkZWQgLSBBbiBhcnJheSBjb250YWluaW5nIGFueSBuZXdseSBhZGRlZCBbW1ZhbGlkYXRpb25FcnJvcl1dc1xyXG4gICAgLSByZW1vdmVkIC0gQW4gYXJyYXkgY29udGFpbmluZyBhbnkgbmV3bHkgcmVtb3ZlZCBbW1ZhbGlkYXRpb25FcnJvcl1dcy4gVGhpcyBpcyB0aG9zZSBlcnJvcnMgdGhhdCBoYXZlIGJlZW4gJ2ZpeGVkJyAgXHJcblxyXG4gID4gICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcigge3NlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIgfSk7XHJcbiAgPiAgICAgIGVtLnZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkLnN1YnNjcmliZShmdW5jdGlvbihjaGFuZ2VBcmdzKSB7XHJcbiAgPiAgICAgICAgICAgICAgLy8gVGhpcyBjb2RlIHdpbGwgYmUgZXhlY3V0ZWQgYW55IHRpbWUgYW55IGVudGl0eSB3aXRoaW4gdGhlIGVudGl0eU1hbmFnZXIgZXhwZXJpZW5jZXMgYSBjaGFuZ2UgdG8gaXRzIHZhbGlkYXRpb25FcnJvcnMgY29sbGVjdGlvbi5cclxuICA+ICAgICAgICAgICAgICBmdW5jdGlvbiAodmFsaWRhdGlvbkNoYW5nZUFyZ3MpIHtcclxuICA+ICAgICAgICAgICAgICAgICAgbGV0IGVudGl0eSA9PSB2YWxpZGF0aW9uQ2hhbmdlQXJncy5lbnRpdHk7XHJcbiAgPiAgICAgICAgICAgICAgICAgIGxldCBlcnJvcnNBZGRlZCA9IHZhbGlkYXRpb25DaGFuZ2VBcmdzLmFkZGVkO1xyXG4gID4gICAgICAgICAgICAgICAgICBsZXQgZXJyb3JzQ2xlYXJlZCA9IHZhbGlkYXRpb25DaGFuZ2VBcmdzLnJlbW92ZWQ7XHJcbiAgPiAgICAgICAgICAgICAgICAgIC8vIC4uLiBkbyBzb21ldGhpbmcgaW50ZXJlc3Rpbmcgd2l0aCB0aGUgb3JkZXIuXHJcbiAgPiAgICAgICAgICAgICAgfSk7XHJcbiAgPiAgICAgICAgICB9KTtcclxuICA+ICAgICAgfSk7XHJcbiAgQGV2ZW50XHJcbiAgKiovXHJcbiAgdmFsaWRhdGlvbkVycm9yc0NoYW5nZWQ6IEJyZWV6ZUV2ZW50PFZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkRXZlbnRBcmdzPjtcclxuXHJcbiAgLyoqXHJcbiAgQSBbW0JyZWV6ZUV2ZW50XV0gdGhhdCBmaXJlcyB3aGVuZXZlciBhbiBFbnRpdHlNYW5hZ2VyIHRyYW5zaXRpb25zIHRvIG9yIGZyb20gaGF2aW5nIGNoYW5nZXMuIF9fUmVhZCBPbmx5X19cclxuICBAZXZlbnRBcmdzIC1cclxuICAgIC0gZW50aXR5TWFuYWdlciAtIFRoZSBFbnRpdHlNYW5hZ2VyIHdob3NlICdoYXNDaGFuZ2VzJyBzdGF0dXMgaGFzIGNoYW5nZWQuXHJcbiAgICAtIGhhc0NoYW5nZXMgLSBXaGV0aGVyIG9yIG5vdCB0aGlzIEVudGl0eU1hbmFnZXIgaGFzIGNoYW5nZXMuXHJcblxyXG4gID4gICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcigge3NlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIgfSk7XHJcbiAgPiAgICAgIGVtLmhhc0NoYW5nZXNDaGFuZ2VkLnN1YnNjcmliZShmdW5jdGlvbihhcmdzKSB7XHJcbiAgPiAgICAgICAgICAgICAgbGV0IGhhc0NoYW5nZXNDaGFuZ2VkID0gYXJncy5oYXNDaGFuZ2VzO1xyXG4gID4gICAgICAgICAgICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gYXJncy5lbnRpdHlNYW5hZ2VyO1xyXG4gID4gICAgICAgICAgfSk7XHJcbiAgPiAgICAgIH0pO1xyXG4gIEBldmVudCBcclxuICAqKi9cclxuICBoYXNDaGFuZ2VzQ2hhbmdlZDogQnJlZXplRXZlbnQ8SGFzQ2hhbmdlc0NoYW5nZWRFdmVudEFyZ3M+O1xyXG5cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3BlbmRpbmdQdWJzPzogYW55W107IC8vIFRPRE86IHJlZmluZSBsYXRlclxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9oYXNDaGFuZ2VzQWN0aW9uPzogKCgpID0+IGJvb2xlYW4pOyAvLyBUT0RPIHJlZmluZSBsYXRlclxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9oYXNDaGFuZ2VzOiBib29sZWFuO1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9lbnRpdHlHcm91cE1hcDogeyBbaW5kZXg6IHN0cmluZ106IEVudGl0eUdyb3VwIH07XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VuYXR0YWNoZWRDaGlsZHJlbk1hcDogVW5hdHRhY2hlZENoaWxkcmVuTWFwO1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9pbktleUZpeHVwOiBib29sZWFuO1xyXG5cclxuICBoZWxwZXIgPSB7XHJcbiAgICB1bndyYXBJbnN0YW5jZTogdW53cmFwSW5zdGFuY2UsXHJcbiAgICB1bndyYXBPcmlnaW5hbFZhbHVlczogdW53cmFwT3JpZ2luYWxWYWx1ZXMsXHJcbiAgICB1bndyYXBDaGFuZ2VkVmFsdWVzOiB1bndyYXBDaGFuZ2VkVmFsdWVzXHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgRW50aXR5TWFuYWdlciBjb25zdHJ1Y3Rvci5cclxuXHJcbiAgQXQgaXRzIG1vc3QgYmFzaWMgYW4gRW50aXR5TWFuYWdlciBjYW4gYmUgY29uc3RydWN0ZWQgd2l0aCBqdXN0IGEgc2VydmljZSBuYW1lXHJcbiAgPiAgICAgbGV0IGVudGl0eU1hbmFnZXIgPSBuZXcgRW50aXR5TWFuYWdlciggXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiKTtcclxuXHJcbiAgVGhpcyBpcyB0aGUgc2FtZSBhcyBjYWxsaW5nIGl0IHdpdGggdGhlIGZvbGxvd2luZyBjb25maWd1cmF0aW9uIG9iamVjdFxyXG4gID4gICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gbmV3IEVudGl0eU1hbmFnZXIoIHtzZXJ2aWNlTmFtZTogXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiIH0pO1xyXG5cclxuICBVc3VhbGx5IGhvd2V2ZXIsIGNvbmZpZ3VyYXRpb24gb2JqZWN0cyB3aWxsIGNvbnRhaW4gbW9yZSB0aGFuIGp1c3QgdGhlICdzZXJ2aWNlTmFtZSc7XHJcbiAgPiAgICAgbGV0IG1ldGFkYXRhU3RvcmUgPSBuZXcgTWV0YWRhdGFTdG9yZSgpO1xyXG4gID4gICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gbmV3IEVudGl0eU1hbmFnZXIoIHtcclxuICA+ICAgICAgIHNlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIsXHJcbiAgPiAgICAgICBtZXRhZGF0YVN0b3JlOiBtZXRhZGF0YVN0b3JlXHJcbiAgPiAgICAgfSk7XHJcblxyXG4gIG9yXHJcbiAgPiAgICAgcmV0dXJuIG5ldyBRdWVyeU9wdGlvbnMoe1xyXG4gID4gICAgICAgICBtZXJnZVN0cmF0ZWd5OiBvYmosXHJcbiAgPiAgICAgICAgIGZldGNoU3RyYXRlZ3k6IHRoaXMuZmV0Y2hTdHJhdGVneVxyXG4gID4gICAgIH0pO1xyXG4gID4gICAgIGxldCBxdWVyeU9wdGlvbnMgPSBuZXcgUXVlcnlPcHRpb25zKHtcclxuICA+ICAgICAgICAgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneS5PdmVyd3JpdGVDaGFuZ2VzLFxyXG4gID4gICAgICAgICBmZXRjaFN0cmF0ZWd5OiBGZXRjaFN0cmF0ZWd5LkZyb21TZXJ2ZXJcclxuICA+ICAgICB9KTtcclxuICA+ICAgICBsZXQgdmFsaWRhdGlvbk9wdGlvbnMgPSBuZXcgVmFsaWRhdGlvbk9wdGlvbnMoe1xyXG4gID4gICAgICAgICB2YWxpZGF0ZU9uQXR0YWNoOiB0cnVlLFxyXG4gID4gICAgICAgICB2YWxpZGF0ZU9uU2F2ZTogdHJ1ZSxcclxuICA+ICAgICAgICAgdmFsaWRhdGVPblF1ZXJ5OiBmYWxzZVxyXG4gID4gICAgIH0pO1xyXG4gID4gICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gbmV3IEVudGl0eU1hbmFnZXIoe1xyXG4gID4gICAgICAgICBzZXJ2aWNlTmFtZTogXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiLFxyXG4gID4gICAgICAgICBxdWVyeU9wdGlvbnM6IHF1ZXJ5T3B0aW9ucyxcclxuICA+ICAgICAgICAgdmFsaWRhdGlvbk9wdGlvbnM6IHZhbGlkYXRpb25PcHRpb25zXHJcbiAgPiAgICAgfSk7XHJcbiAgQHBhcmFtIGVtQ29uZmlnIC0gQ29uZmlndXJhdGlvbiBzZXR0aW5ncyBvciBhIHNlcnZpY2UgbmFtZS4gIFxyXG4gICoqL1xyXG4gIGNvbnN0cnVjdG9yKGVtQ29uZmlnPzogRW50aXR5TWFuYWdlckNvbmZpZyB8IHN0cmluZykge1xyXG5cclxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgRW50aXR5TWFuYWdlciBjdG9yIGhhcyBhIHNpbmdsZSBvcHRpb25hbCBhcmd1bWVudCB0aGF0IGlzIGVpdGhlciBhICdzZXJ2aWNlTmFtZScgb3IgYSBjb25maWd1cmF0aW9uIG9iamVjdC5cIik7XHJcbiAgICB9XHJcbiAgICBsZXQgY29uZmlnOiBFbnRpdHlNYW5hZ2VyQ29uZmlnO1xyXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgY29uZmlnID0geyBzZXJ2aWNlTmFtZTogXCJcIiB9O1xyXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZW1Db25maWcgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIGNvbmZpZyA9IHsgc2VydmljZU5hbWU6IGVtQ29uZmlnIH07XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25maWcgPSBlbUNvbmZpZyB8fCB7fTtcclxuICAgIH1cclxuXHJcbiAgICBFbnRpdHlNYW5hZ2VyLl91cGRhdGVXaXRoQ29uZmlnKHRoaXMsIGNvbmZpZywgdHJ1ZSk7XHJcblxyXG4gICAgdGhpcy5lbnRpdHlDaGFuZ2VkID0gbmV3IEJyZWV6ZUV2ZW50KFwiZW50aXR5Q2hhbmdlZFwiLCB0aGlzKTtcclxuICAgIHRoaXMudmFsaWRhdGlvbkVycm9yc0NoYW5nZWQgPSBuZXcgQnJlZXplRXZlbnQoXCJ2YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZFwiLCB0aGlzKTtcclxuICAgIHRoaXMuaGFzQ2hhbmdlc0NoYW5nZWQgPSBuZXcgQnJlZXplRXZlbnQoXCJoYXNDaGFuZ2VzQ2hhbmdlZFwiLCB0aGlzKTtcclxuXHJcbiAgICB0aGlzLmNsZWFyKCk7XHJcblxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgR2VuZXJhbCBwdXJwb3NlIHByb3BlcnR5IHNldCBtZXRob2QuICBBbnkgb2YgdGhlIHByb3BlcnRpZXMgaW4gdGhlIFtbRW50aXR5TWFuYWdlckNvbmZpZ11dXHJcbiAgbWF5IGJlIHNldC5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhIHByZXZpb3VzbHkgY3JlYXRlZCBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIC8vIHdoZXJlIHdlIHdhbnQgdG8gY2hhbmdlIHNvbWUgb2YgaXRzIHNldHRpbmdzLlxyXG4gID4gICAgICBlbTEuc2V0UHJvcGVydGllcygge1xyXG4gID4gICAgICAgICAgc2VydmljZU5hbWU6IFwiYnJlZXplL2Zvb1wiXHJcbiAgPiAgICAgIH0pO1xyXG4gIEBwYXJhbSBjb25maWcgLSBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgc2VsZWN0ZWQgcHJvcGVydGllcyBhbmQgdmFsdWVzIHRvIHNldC5cclxuICAqKi9cclxuICBzZXRQcm9wZXJ0aWVzKGNvbmZpZzogRW50aXR5TWFuYWdlckNvbmZpZykge1xyXG4gICAgRW50aXR5TWFuYWdlci5fdXBkYXRlV2l0aENvbmZpZyh0aGlzLCBjb25maWcsIGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIHN0YXRpYyBfdXBkYXRlV2l0aENvbmZpZyhlbTogRW50aXR5TWFuYWdlciwgY29uZmlnOiBFbnRpdHlNYW5hZ2VyQ29uZmlnLCBpc0N0b3I6IGJvb2xlYW4pIHtcclxuICAgIGxldCBkZWZhdWx0UXVlcnlPcHRpb25zID0gaXNDdG9yID8gUXVlcnlPcHRpb25zLmRlZmF1bHRJbnN0YW5jZSA6IGVtLnF1ZXJ5T3B0aW9ucztcclxuICAgIGxldCBkZWZhdWx0U2F2ZU9wdGlvbnMgPSBpc0N0b3IgPyBTYXZlT3B0aW9ucy5kZWZhdWx0SW5zdGFuY2UgOiBlbS5zYXZlT3B0aW9ucztcclxuICAgIGxldCBkZWZhdWx0VmFsaWRhdGlvbk9wdGlvbnMgPSBpc0N0b3IgPyBWYWxpZGF0aW9uT3B0aW9ucy5kZWZhdWx0SW5zdGFuY2UgOiBlbS52YWxpZGF0aW9uT3B0aW9ucztcclxuXHJcbiAgICBsZXQgY29uZmlnUGFyYW0gPSBhc3NlcnRDb25maWcoY29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcInNlcnZpY2VOYW1lXCIpLmlzT3B0aW9uYWwoKS5pc1N0cmluZygpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiZGF0YVNlcnZpY2VcIikuaXNPcHRpb25hbCgpLmlzSW5zdGFuY2VPZihEYXRhU2VydmljZSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJxdWVyeU9wdGlvbnNcIikuaXNJbnN0YW5jZU9mKFF1ZXJ5T3B0aW9ucykuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KGRlZmF1bHRRdWVyeU9wdGlvbnMpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwic2F2ZU9wdGlvbnNcIikuaXNJbnN0YW5jZU9mKFNhdmVPcHRpb25zKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoZGVmYXVsdFNhdmVPcHRpb25zKVxyXG4gICAgICAud2hlcmVQYXJhbShcInZhbGlkYXRpb25PcHRpb25zXCIpLmlzSW5zdGFuY2VPZihWYWxpZGF0aW9uT3B0aW9ucykuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KGRlZmF1bHRWYWxpZGF0aW9uT3B0aW9ucylcclxuICAgICAgLndoZXJlUGFyYW0oXCJrZXlHZW5lcmF0b3JDdG9yXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCk7XHJcbiAgICBpZiAoaXNDdG9yKSB7XHJcbiAgICAgIGNvbmZpZ1BhcmFtID0gY29uZmlnUGFyYW1cclxuICAgICAgICAud2hlcmVQYXJhbShcIm1ldGFkYXRhU3RvcmVcIikuaXNJbnN0YW5jZU9mKE1ldGFkYXRhU3RvcmUpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChuZXcgTWV0YWRhdGFTdG9yZSgpKTtcclxuICAgIH1cclxuICAgIGNvbmZpZ1BhcmFtLmFwcGx5QWxsKGVtKTtcclxuXHJcbiAgICAvLyBpbnN1cmUgdGhhdCBlbnRpdHlNYW5hZ2VyJ3Mgb3B0aW9ucyB2ZXJzaW9ucyBhcmUgY29tcGxldGVseSBwb3B1bGF0ZWRcclxuICAgIGNvcmUudXBkYXRlV2l0aERlZmF1bHRzKGVtLnF1ZXJ5T3B0aW9ucywgZGVmYXVsdFF1ZXJ5T3B0aW9ucyk7XHJcbiAgICBjb3JlLnVwZGF0ZVdpdGhEZWZhdWx0cyhlbS5zYXZlT3B0aW9ucywgZGVmYXVsdFNhdmVPcHRpb25zKTtcclxuICAgIGNvcmUudXBkYXRlV2l0aERlZmF1bHRzKGVtLnZhbGlkYXRpb25PcHRpb25zLCBkZWZhdWx0VmFsaWRhdGlvbk9wdGlvbnMpO1xyXG5cclxuICAgIGlmIChjb25maWcuc2VydmljZU5hbWUpIHtcclxuICAgICAgZW0uZGF0YVNlcnZpY2UgPSBuZXcgRGF0YVNlcnZpY2Uoe1xyXG4gICAgICAgIHNlcnZpY2VOYW1lOiBlbS5zZXJ2aWNlTmFtZVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIGVtLnNlcnZpY2VOYW1lID0gZW0uZGF0YVNlcnZpY2UgJiYgZW0uZGF0YVNlcnZpY2Uuc2VydmljZU5hbWU7XHJcblxyXG4gICAgZW0ua2V5R2VuZXJhdG9yQ3RvciA9IGVtLmtleUdlbmVyYXRvckN0b3IgfHwgS2V5R2VuZXJhdG9yO1xyXG4gICAgaWYgKGlzQ3RvciB8fCBjb25maWcua2V5R2VuZXJhdG9yQ3Rvcikge1xyXG4gICAgICBlbS5rZXlHZW5lcmF0b3IgPSBuZXcgZW0ua2V5R2VuZXJhdG9yQ3RvcigpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgY3JlYXRlRW50aXR5KHR5cGVOYW1lOiBzdHJpbmcsIGluaXRpYWxWYWx1ZXM/OiBPYmplY3QsIGVudGl0eVN0YXRlPzogRW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3k/OiBNZXJnZVN0cmF0ZWd5KTogRW50aXR5O1xyXG4gIGNyZWF0ZUVudGl0eShlbnRpdHlUeXBlOiBFbnRpdHlUeXBlLCBpbml0aWFsVmFsdWVzPzogT2JqZWN0LCBlbnRpdHlTdGF0ZT86IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5PzogTWVyZ2VTdHJhdGVneSk6IEVudGl0eTtcclxuICAvKipcclxuICBDcmVhdGVzIGEgbmV3IGVudGl0eSBvZiBhIHNwZWNpZmllZCB0eXBlIGFuZCBvcHRpb25hbGx5IGluaXRpYWxpemVzIGl0LiBCeSBkZWZhdWx0IHRoZSBuZXcgZW50aXR5IGlzIGNyZWF0ZWQgd2l0aCBhbiBFbnRpdHlTdGF0ZSBvZiBBZGRlZFxyXG4gIGJ1dCB5b3UgY2FuIGFsc28gb3B0aW9uYWxseSBzcGVjaWZ5IGFuIEVudGl0eVN0YXRlLiAgQW4gRW50aXR5U3RhdGUgb2YgJ0RldGFjaGVkJyB3aWxsIGluc3VyZSB0aGF0IHRoZSBlbnRpdHkgaXMgY3JlYXRlZCBidXQgbm90IHlldCBhZGRlZFxyXG4gIHRvIHRoZSBFbnRpdHlNYW5hZ2VyLiBcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIC8vIGNyZWF0ZSBhbmQgYWRkIGFuIGVudGl0eTtcclxuICA+ICAgICAgbGV0IGVtcDEgPSBlbTEuY3JlYXRlRW50aXR5KFwiRW1wbG95ZWVcIik7XHJcbiAgPiAgICAgIC8vIGNyZWF0ZSBhbmQgYWRkIGFuIGluaXRpYWxpemVkIGVudGl0eTtcclxuICA+ICAgICAgbGV0IGVtcDIgPSBlbTEuY3JlYXRlRW50aXR5KFwiRW1wbG95ZWVcIiwgeyBsYXN0TmFtZTogXCJTbWl0aFwiLCBmaXJzdE5hbWU6IFwiSm9oblwiIH0pO1xyXG4gID4gICAgICAvLyBjcmVhdGUgYW5kIGF0dGFjaCAobm90IGFkZCkgYW4gaW5pdGlhbGl6ZWQgZW50aXR5XHJcbiAgPiAgICAgIGxldCBlbXAzID0gZW0xLmNyZWF0ZUVudGl0eShcIkVtcGxveWVlXCIsIHsgaWQ6IDQzNSwgbGFzdE5hbWU6IFwiU21pdGhcIiwgZmlyc3ROYW1lOiBcIkpvaG5cIiB9LCBFbnRpdHlTdGF0ZS5VbmNoYW5nZWQpO1xyXG4gID4gICAgICAvLyBjcmVhdGUgYnV0IGRvbid0IGF0dGFjaCBhbiBlbnRpdHk7XHJcbiAgPiAgICAgIGxldCBlbXA0ID0gZW0xLmNyZWF0ZUVudGl0eShcIkVtcGxveWVlXCIsIHsgaWQ6IDQzNSwgbGFzdE5hbWU6IFwiU21pdGhcIiwgZmlyc3ROYW1lOiBcIkpvaG5cIiB9LCBFbnRpdHlTdGF0ZS5EZXRhY2hlZCk7XHJcbiAgQHBhcmFtIHR5cGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIEVudGl0eVR5cGUgZm9yIHdoaWNoIGFuIGluc3RhbmNlIHNob3VsZCBiZSBjcmVhdGVkLlxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlIC0gVGhlIEVudGl0eVR5cGUgb2YgdGhlIHR5cGUgZm9yIHdoaWNoIGFuIGluc3RhbmNlIHNob3VsZCBiZSBjcmVhdGVkLlxyXG4gIEBwYXJhbSBpbml0aWFsVmFsdWVzIC0gKGRlZmF1bHQ9bnVsbCkgQ29uZmlndXJhdGlvbiBvYmplY3Qgb2YgdGhlIHByb3BlcnRpZXMgdG8gc2V0IGltbWVkaWF0ZWx5IGFmdGVyIGNyZWF0aW9uLlxyXG4gIEBwYXJhbSBlbnRpdHlTdGF0ZSAtIChkZWZhdWx0ID0gW1tFbnRpdHlTdGF0ZS5BZGRlZF1dKSBUaGUgRW50aXR5U3RhdGUgb2YgdGhlIGVudGl0eSBhZnRlciBiZWluZyBjcmVhdGVkIGFuZCBhZGRlZCB0byB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgQHBhcmFtIG1lcmdlU3RyYXRlZ3kgLSAoZGVmYXVsdCA9IFtbTWVyZ2VTdHJhdGVneS5EaXNhbGxvd2VkXV0pIC0gSG93IHRvIGhhbmRsZSBjb25mbGljdHMgaWYgYW4gZW50aXR5IHdpdGggdGhlIHNhbWUga2V5IGFscmVhZHkgZXhpc3RzIHdpdGhpbiB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgQHJldHVybiB7RW50aXR5fSBBIG5ldyBFbnRpdHkgb2YgdGhlIHNwZWNpZmllZCB0eXBlLiBcclxuICAqL1xyXG4gIGNyZWF0ZUVudGl0eShlbnRpdHlUeXBlOiBFbnRpdHlUeXBlIHwgc3RyaW5nLCBpbml0aWFsVmFsdWVzOiBPYmplY3QsIGVudGl0eVN0YXRlOiBFbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5VHlwZSwgXCJlbnRpdHlUeXBlXCIpLmlzU3RyaW5nKCkub3IoKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eVN0YXRlLCBcImVudGl0eVN0YXRlXCIpLmlzRW51bU9mKEVudGl0eVN0YXRlKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKG1lcmdlU3RyYXRlZ3ksIFwibWVyZ2VTdHJhdGVneVwiKS5pc0VudW1PZihNZXJnZVN0cmF0ZWd5KS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuXHJcbiAgICBsZXQgZXQgPSAodHlwZW9mIGVudGl0eVR5cGUgPT09IFwic3RyaW5nXCIpID8gdGhpcy5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShlbnRpdHlUeXBlKSBhcyBFbnRpdHlUeXBlIDogZW50aXR5VHlwZTtcclxuICAgIGVudGl0eVN0YXRlID0gZW50aXR5U3RhdGUgfHwgRW50aXR5U3RhdGUuQWRkZWQ7XHJcbiAgICBsZXQgZW50aXR5ID0ge30gYXMgRW50aXR5O1xyXG4gICAgY29yZS51c2luZyh0aGlzLCBcImlzTG9hZGluZ1wiLCB0cnVlLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIGVudGl0eSA9IGV0LmNyZWF0ZUVudGl0eShpbml0aWFsVmFsdWVzKTtcclxuICAgIH0pO1xyXG4gICAgaWYgKGVudGl0eVN0YXRlICE9PSBFbnRpdHlTdGF0ZS5EZXRhY2hlZCkge1xyXG4gICAgICBlbnRpdHkgPSB0aGlzLmF0dGFjaEVudGl0eShlbnRpdHksIGVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5KTtcclxuICAgIH1cclxuICAgIHJldHVybiBlbnRpdHk7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWRTdHJpbmc6IHN0cmluZywgY29uZmlnPzogSW1wb3J0Q29uZmlnKTogRW50aXR5TWFuYWdlcjtcclxuICBzdGF0aWMgaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWREYXRhOiBPYmplY3QsIGNvbmZpZz86IEltcG9ydENvbmZpZyk6IEVudGl0eU1hbmFnZXI7XHJcbiAgLyoqXHJcbiAgQ3JlYXRlcyBhIG5ldyBFbnRpdHlNYW5hZ2VyIGFuZCBpbXBvcnRzIGEgcHJldmlvdXNseSBleHBvcnRlZCByZXN1bHQgaW50byBpdC5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoKTtcclxuICA+ICAgICAgLy8gY2FuIGJlIHN0b3JlZCB2aWEgdGhlIHdlYiBzdG9yYWdlIGFwaVxyXG4gID4gICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJteUVudGl0eU1hbmFnZXJcIiwgYnVuZGxlKTtcclxuICA+ICAgICAgLy8gYXNzdW1lIHRoZSBjb2RlIGJlbG93IG9jY3VycyBpbiBhIGRpZmZlcmVudCBzZXNzaW9uLlxyXG4gID4gICAgICBsZXQgYnVuZGxlRnJvbVN0b3JhZ2UgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJteUVudGl0eU1hbmFnZXJcIik7XHJcbiAgPiAgICAgIC8vIGFuZCBpbXBvcnRlZFxyXG4gID4gICAgICBsZXQgZW0yID0gRW50aXR5TWFuYWdlci5pbXBvcnRFbnRpdGllcyhidW5kbGVGcm9tU3RvcmFnZSk7XHJcbiAgPiAgICAgIC8vIGVtMiB3aWxsIG5vdyBoYXZlIGEgY29tcGxldGUgY29weSBvZiB3aGF0IHdhcyBpbiBlbTFcclxuICBAcGFyYW0gZXhwb3J0ZWRTdHJpbmcgLSBUaGUgcmVzdWx0IG9mIGEgcHJldmlvdXMgJ2V4cG9ydEVudGl0aWVzJyBjYWxsIGFzIGEgc3RyaW5nXHJcbiAgQHBhcmFtIGV4cG9ydGVkRGF0YSAtIFRoZSByZXN1bHQgb2YgYSBwcmV2aW91cyAnZXhwb3J0RW50aXRpZXMnIGNhbGwgYXMgYW4gT2JqZWN0LlxyXG4gIEBwYXJhbSBjb25maWcgLSBBIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxyXG4gIEBwYXJhbSBjb25maWcubWVyZ2VTdHJhdGVneSAtIEEgIFtbTWVyZ2VTdHJhdGVneV1dIHRvIHVzZSB3aGVuIFxyXG4gIG1lcmdpbmcgaW50byBhbiBleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gIEBwYXJhbSBjb25maWcubWV0YWRhdGFWZXJzaW9uRm4gLSBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgdHdvIGFyZ3VtZW50cyAodGhlIGN1cnJlbnQgbWV0YWRhdGFWZXJzaW9uIGFuZCB0aGUgaW1wb3J0ZWQgc3RvcmUncyAnbmFtZScpXHJcbiAgYW5kIG1heSBiZSB1c2VkIHRvIHBlcmZvcm0gdmVyc2lvbiBjaGVja2luZy5cclxuICBAcmV0dXJuIEEgbmV3IEVudGl0eU1hbmFnZXIuICBOb3RlIHRoYXQgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGlzIG1ldGhvZCBjYWxsIGlzIGRpZmZlcmVudCBmcm9tIHRoYXRcclxuICBwcm92aWRlZCBieSB0aGUgc2FtZSBuYW1lZCBtZXRob2Qgb24gYW4gRW50aXR5TWFuYWdlciBpbnN0YW5jZS4gVXNlIHRoYXQgbWV0aG9kIGlmIHlvdSBuZWVkIGFkZGl0aW9uYWwgaW5mb3JtYXRpb25cclxuICByZWdhcmRpbmcgdGhlIGltcG9ydGVkIGVudGl0aWVzLlxyXG4gICoqL1xyXG4gIHN0YXRpYyBpbXBvcnRFbnRpdGllcyhleHBvcnRlZDogc3RyaW5nIHwgT2JqZWN0LCBjb25maWc/OiBJbXBvcnRDb25maWcpIHtcclxuICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKCk7XHJcbiAgICBlbS5pbXBvcnRFbnRpdGllcyhleHBvcnRlZCwgY29uZmlnKTtcclxuICAgIHJldHVybiBlbTtcclxuICB9XHJcblxyXG4gIC8vIGluc3RhbmNlIG1ldGhvZHNcclxuXHJcbiAgLyoqXHJcbiAgQ2FsbHMgW1tFbnRpdHlBc3BlY3QuYWNjZXB0Q2hhbmdlc11dIG9uIGV2ZXJ5IGNoYW5nZWQgZW50aXR5IGluIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICAqKi9cclxuICBhY2NlcHRDaGFuZ2VzKCkge1xyXG4gICAgdGhpcy5nZXRDaGFuZ2VzKCkubWFwKGZ1bmN0aW9uIChlbnRpdHkpIHtcclxuICAgICAgcmV0dXJuIGVudGl0eS5lbnRpdHlBc3BlY3QuX2NoZWNrT3BlcmF0aW9uKFwiYWNjZXB0Q2hhbmdlc1wiKTtcclxuICAgIH0pLmZvckVhY2goZnVuY3Rpb24gKGFzcGVjdCkge1xyXG4gICAgICBhc3BlY3QuYWNjZXB0Q2hhbmdlcygpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBFeHBvcnRzIHNlbGVjdGVkIGVudGl0aWVzLCBhbGwgZW50aXRpZXMgb2Ygc2VsZWN0ZWQgdHlwZXMsIG9yIGFuIGVudGlyZSBFbnRpdHlNYW5hZ2VyIGNhY2hlLlxyXG5cclxuICBUaGlzIG1ldGhvZCB0YWtlcyBhIHNuYXBzaG90IG9mIGFuIEVudGl0eU1hbmFnZXIgdGhhdCBjYW4gYmUgc3RvcmVkIG9mZmxpbmUgb3IgaGVsZCBpbiBtZW1vcnkuXHJcbiAgVXNlIHRoZSBbW0VudGl0eU1hbmFnZXIuaW1wb3J0RW50aXRpZXNdXSBtZXRob2QgdG8gcmVzdG9yZSBvciBtZXJnZSB0aGUgc25hcHNob3RcclxuICBpbnRvIGFub3RoZXIgRW50aXR5TWFuYWdlciBhdCBzb21lIGxhdGVyIHRpbWUuXHJcbiAgPiAgICAgIC8vIGxldCBlbTEgYmUgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIC8vIGV4cG9ydCBldmVyeSBlbnRpdHkgaW4gZW0xLlxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoKTtcclxuICA+ICAgICAvLyBzYXZlIHRvIHRoZSBicm93c2VyJ3MgbG9jYWwgc3RvcmFnZVxyXG4gID4gICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm15RW50aXR5TWFuYWdlclwiLCBidW5kbGUpO1xyXG4gID4gICAgIC8vIGxhdGVyIHJldHJpZXZlIHRoZSBleHBvcnRcclxuICA+ICAgICBsZXQgYnVuZGxlRnJvbVN0b3JhZ2UgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJteUVudGl0eU1hbmFnZXJcIik7XHJcbiAgPiAgICAgLy8gaW1wb3J0IHRoZSByZXRyaWV2ZWQgZXhwb3J0IGJ1bmRsZSBpbnRvIGFub3RoZXIgbWFuYWdlclxyXG4gID4gICAgIGxldCBlbTIgPSBlbTEuY3JlYXRlRW1wdHlDb3B5KCk7XHJcbiAgPiAgICAgZW0yLmltcG9ydEVudGl0aWVzKGJ1bmRsZUZyb21TdG9yYWdlKTtcclxuICA+ICAgICAvLyBlbTIgbm93IGhhcyBhIGNvbXBsZXRlLCBmYWl0aGZ1bCBjb3B5IG9mIHRoZSBlbnRpdGllcyB0aGF0IHdlcmUgaW4gZW0xXHJcblxyXG4gIFlvdSBjYW4gYWxzbyBjb250cm9sIGV4YWN0bHkgd2hpY2ggZW50aXRpZXMgYXJlIGV4cG9ydGVkLlxyXG4gID4gICAgIC8vIGdldCBlbTEncyB1bnNhdmVkIGNoYW5nZXMgKGFuIGFycmF5KSBhbmQgZXhwb3J0IHRoZW0uXHJcbiAgPiAgICAgbGV0IGNoYW5nZXMgPSBlbTEuZ2V0Q2hhbmdlcygpO1xyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoY2hhbmdlcyk7XHJcbiAgPiAgICAgLy8gbWVyZ2UgdGhlc2UgZW50aXRpZXMgaW50byBlbTIgd2hpY2ggbWF5IGNvbnRhaW5zIHNvbWUgb2YgdGhlIHNhbWUgZW50aXRpZXMuXHJcbiAgPiAgICAgLy8gZG8gTk9UIG92ZXJ3cml0ZSB0aGUgZW50aXRpZXMgaW4gZW0yIGlmIHRoZXkgdGhlbXNlbHZlcyBoYXZlIHVuc2F2ZWQgY2hhbmdlcy5cclxuICA+ICAgICBlbTIuaW1wb3J0RW50aXRpZXMoYnVuZGxlLCB7IG1lcmdlU3RyYXRlZ3k6IE1lcmdlU3RyYXRlZ3kuUHJlc2VydmVDaGFuZ2VzfSApO1xyXG5cclxuICBNZXRhZGF0YSBhcmUgaW5jbHVkZWQgaW4gYW4gZXhwb3J0IGJ5IGRlZmF1bHQuIFlvdSBtYXkgd2FudCB0byBleGNsdWRlIHRoZSBtZXRhZGF0YVxyXG4gIGVzcGVjaWFsbHkgaWYgeW91J3JlIGV4cG9ydGluZyBqdXN0IGEgZmV3IGVudGl0aWVzIGZvciBsb2NhbCBzdG9yYWdlLlxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoYXJyYXlPZlNlbGVjdGVkRW50aXRpZXMsIHtpbmNsdWRlTWV0YWRhdGE6IGZhbHNlfSk7XHJcbiAgPiAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKFwiZ29vZFN0dWZmXCIsIGJ1bmRsZSk7XHJcblxyXG4gIFlvdSBtYXkgc3RpbGwgZXhwcmVzcyB0aGlzIG9wdGlvbiBhcyBhIGJvb2xlYW4gdmFsdWUgYWx0aG91Z2ggdGhpcyBvbGRlciBzeW50YXggaXMgZGVwcmVjYXRlZC5cclxuICA+ICAgICAvLyBFeGNsdWRlIHRoZSBtZXRhZGF0YSAoZGVwcmVjYXRlZCBzeW50YXgpXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcyhhcnJheU9mU2VsZWN0ZWRFbnRpdGllcywgZmFsc2UpO1xyXG5cclxuICBZb3UgY2FuIGV4cG9ydCBhbGwgZW50aXRpZXMgb2Ygb25lIG9yIG1vcmUgc3BlY2lmaWVkIEVudGl0eVR5cGVzLlxyXG4gID4gICAgIC8vIEV4cG9ydCBhbGwgQ3VzdG9tZXIgYW5kIEVtcGxveWVlIGVudGl0aWVzIChhbmQgYWxzbyBleGNsdWRlIG1ldGFkYXRhKVxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoWydDdXN0b21lcicsICdFbXBsb3llZSddLCB7aW5jbHVkZU1ldGFkYXRhOiBmYWxzZX0pO1xyXG5cclxuICBBbGwgb2YgdGhlIGFib3ZlIGV4YW1wbGVzIHJldHVybiBhbiBleHBvcnQgYnVuZGxlIGFzIGEgc3RyaW5nIHdoaWNoIGlzIHRoZSBkZWZhdWx0IGZvcm1hdC5cclxuICBZb3UgY2FuIGV4cG9ydCB0aGUgYnVuZGxlIGFzIEpTT04gaWYgeW91IHByZWZlciBieSBzZXR0aW5nIHRoZSBgYXNTdHJpbmdgIG9wdGlvbiB0byBmYWxzZS5cclxuICA+ICAgICAvLyBFeHBvcnQgYWxsIEN1c3RvbWVyIGFuZCBFbXBsb3llZSBlbnRpdGllcyBhcyBKU09OIGFuZCBleGNsdWRlIHRoZSBtZXRhZGF0YVxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoWydDdXN0b21lcicsICdFbXBsb3llZSddLFxyXG4gID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge2FzU3RyaW5nOiBmYWxzZSwgaW5jbHVkZU1ldGFkYXRhOiBmYWxzZX0pO1xyXG4gID4gICAgIC8vIHN0b3JlIEpTT04gYnVuZGxlIHNvbWV3aGVyZSAuLi4gcGVyaGFwcyBpbmRleERiIC4uLiBhbmQgbGF0ZXIgaW1wb3J0IGFzIHdlIGRvIGhlcmUuXHJcbiAgPiAgICAgZW0yLmltcG9ydEVudGl0aWVzKGJ1bmRsZSk7XHJcbiAgQHBhcmFtIGVudGl0aWVzIC0gVGhlIGVudGl0aWVzIHRvIGV4cG9ydCBvciB0aGUgRW50aXR5VHlwZShzKSBvZiB0aGUgZW50aXRpZXMgdG8gZXhwb3J0O1xyXG4gICAgYWxsIGVudGl0aWVzIGFyZSBleHBvcnRlZCBpZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkIG9yIG51bGwuXHJcbiAgQHBhcmFtIGV4cG9ydENvbmZpZyAtIEV4cG9ydCBjb25maWd1cmF0aW9uIG9wdGlvbnMgb3IgYSBib29sZWFuXHJcbiAgICAtIGFzU3RyaW5nIC0gKGJvb2xlYW4pIC0gSWYgdHJ1ZSAoZGVmYXVsdCksIHJldHVybiBleHBvcnQgYnVuZGxlIGFzIGEgc3RyaW5nLlxyXG4gICAgLSBpbmNsdWRlTWV0YWRhdGEgLSAoYm9vbGVhbikgLSBJZiB0cnVlIChkZWZhdWx0KSwgaW5jbHVkZSBtZXRhZGF0YSBpbiB0aGUgZXhwb3J0IGJ1bmRsZS5cclxuICBAcmV0dXJuIFRoZSBleHBvcnQgYnVuZGxlIGVpdGhlciBzZXJpYWxpemVkIGFzIGEgc3RyaW5nIChkZWZhdWx0KSBvciBhcyBhIEpTT04gb2JqZWN0LlxyXG4gIFRoZSBidW5kbGUgY29udGFpbnMgdGhlIG1ldGFkYXRhICh1bmxlc3MgZXhjbHVkZWQpIGFuZCB0aGUgZW50aXR5IGRhdGEgZ3JvdXBlZCBieSB0eXBlLlxyXG4gIFRoZSBlbnRpdHkgZGF0YSBpbmNsdWRlIHByb3BlcnR5IHZhbHVlcywgY2hhbmdlLXN0YXRlLCBhbmQgdGVtcG9yYXJ5IGtleSBtYXBwaW5ncyAoaWYgYW55KS5cclxuXHJcbiAgVGhlIGV4cG9ydCBidW5kbGUgaW50ZXJuYWxzIGFyZSBkZWxpYmVyYXRlbHkgdW5kb2N1bWVudGVkLiAgVGhpcyBCcmVlemUtaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gb2YgZW50aXR5IGRhdGEgaXNcclxuICBzdWl0YWJsZSBmb3IgZXhwb3J0LCBzdG9yYWdlLCBhbmQgaW1wb3J0LiBUaGUgc2NoZW1hIGFuZCBjb250ZW50cyBvZiB0aGUgYnVuZGxlIG1heSBjaGFuZ2UgaW4gZnV0dXJlIHZlcnNpb25zIG9mIEJyZWV6ZS5cclxuICBNYW5pcHVsYXRlIGl0IGF0IHlvdXIgb3duIHJpc2sgd2l0aCBhcHByb3ByaWF0ZSBjYXV0aW9uLlxyXG4gICoqL1xyXG4gIGV4cG9ydEVudGl0aWVzKGVudGl0aWVzPzogRW50aXR5W10gfCBFbnRpdHlUeXBlW10gfCBzdHJpbmdbXSwgZXhwb3J0Q29uZmlnPzogeyBhc1N0cmluZz86IGJvb2xlYW4sIGluY2x1ZGVNZXRhZGF0YT86IGJvb2xlYW4gfSB8IGJvb2xlYW4pOiBzdHJpbmcgfCBPYmplY3Qge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXRpZXMsIFwiZW50aXRpZXNcIikuaXNBcnJheSgpLmlzRW50aXR5KClcclxuICAgICAgLm9yKCkuaXNOb25FbXB0eUFycmF5KCkuaXNJbnN0YW5jZU9mKEVudGl0eVR5cGUpXHJcbiAgICAgIC5vcigpLmlzTm9uRW1wdHlBcnJheSgpLmlzU3RyaW5nKClcclxuICAgICAgLm9yKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcblxyXG4gICAgLy8gYXNzZXJ0UGFyYW0oZXhwb3J0Q29uZmlnLCBcImV4cG9ydENvbmZpZ1wiKS5pc09iamVjdCgpXHJcbiAgICAvLyAgIC5vcigpLmlzQm9vbGVhbigpXHJcbiAgICAvLyAgIC5vcigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG5cclxuICAgIGlmIChleHBvcnRDb25maWcgPT0gbnVsbCkge1xyXG4gICAgICBleHBvcnRDb25maWcgPSB7IGluY2x1ZGVNZXRhZGF0YTogdHJ1ZSwgYXNTdHJpbmc6IHRydWUgfTtcclxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGV4cG9ydENvbmZpZyA9PT0gJ2Jvb2xlYW4nKSB7IC8vIGRlcHJlY2F0ZWRcclxuICAgICAgZXhwb3J0Q29uZmlnID0geyBpbmNsdWRlTWV0YWRhdGE6IGV4cG9ydENvbmZpZywgYXNTdHJpbmc6IHRydWUgfTtcclxuICAgIH1cclxuXHJcbiAgICBhc3NlcnRDb25maWcoZXhwb3J0Q29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcImFzU3RyaW5nXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdCh0cnVlKVxyXG4gICAgICAud2hlcmVQYXJhbShcImluY2x1ZGVNZXRhZGF0YVwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQodHJ1ZSlcclxuICAgICAgLmFwcGx5QWxsKGV4cG9ydENvbmZpZyk7XHJcblxyXG4gICAgbGV0IGV4cG9ydEJ1bmRsZSA9IGV4cG9ydEVudGl0eUdyb3Vwcyh0aGlzLCBlbnRpdGllcyk7XHJcbiAgICBsZXQganNvbiA9IGNvcmUuZXh0ZW5kKHt9LCBleHBvcnRCdW5kbGUsIFtcInRlbXBLZXlzXCIsIFwiZW50aXR5R3JvdXBNYXBcIl0pO1xyXG5cclxuICAgIGlmIChleHBvcnRDb25maWcuaW5jbHVkZU1ldGFkYXRhKSB7XHJcbiAgICAgIGpzb24gPSBjb3JlLmV4dGVuZChqc29uLCB0aGlzLCBbXCJkYXRhU2VydmljZVwiLCBcInNhdmVPcHRpb25zXCIsIFwicXVlcnlPcHRpb25zXCIsIFwidmFsaWRhdGlvbk9wdGlvbnNcIl0pO1xyXG4gICAgICAoanNvbiBhcyBhbnkpLm1ldGFkYXRhU3RvcmUgPSB0aGlzLm1ldGFkYXRhU3RvcmUuZXhwb3J0TWV0YWRhdGEoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIChqc29uIGFzIGFueSkubWV0YWRhdGFWZXJzaW9uID0gTWV0YWRhdGFTdG9yZS5tZXRhZGF0YVZlcnNpb247XHJcbiAgICAgIChqc29uIGFzIGFueSkubWV0YWRhdGFTdG9yZU5hbWUgPSB0aGlzLm1ldGFkYXRhU3RvcmUubmFtZTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgcmVzdWx0ID0gZXhwb3J0Q29uZmlnLmFzU3RyaW5nID8gSlNPTi5zdHJpbmdpZnkoanNvbiwgbnVsbCwgY29uZmlnLnN0cmluZ2lmeVBhZCkgOiBqc29uO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIC8vIFRPRE86IHR5cGUgdGhlIHJldHVybiB2YWx1ZSB7IGVudGl0aWVzOiBlbnRpdGllc1RvTGluaywgdGVtcEtleU1hcHBpbmc6IHRlbXBLZXlNYXAgfVxyXG4gIGltcG9ydEVudGl0aWVzKGV4cG9ydGVkU3RyaW5nOiBzdHJpbmcsIGNvbmZpZz86IEltcG9ydENvbmZpZyk6IEltcG9ydFJlc3VsdDtcclxuICBpbXBvcnRFbnRpdGllcyhleHBvcnRlZERhdGE6IE9iamVjdCwgY29uZmlnPzogSW1wb3J0Q29uZmlnKTogSW1wb3J0UmVzdWx0O1xyXG4gIC8qKlxyXG4gIEltcG9ydHMgYSBwcmV2aW91c2x5IGV4cG9ydGVkIHJlc3VsdCBpbnRvIHRoaXMgRW50aXR5TWFuYWdlci5cclxuXHJcbiAgVGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gbWFrZSBhIGNvbXBsZXRlIGNvcHkgb2YgYW55IHByZXZpb3VzbHkgY3JlYXRlZCBlbnRpdHlNYW5hZ2VyLCBldmVuIGlmIGNyZWF0ZWRcclxuICBpbiBhIHByZXZpb3VzIHNlc3Npb24gYW5kIHN0b3JlZCBpbiBsb2NhbFN0b3JhZ2UuIFRoZSBzdGF0aWMgdmVyc2lvbiBvZiB0aGlzIG1ldGhvZCBwZXJmb3JtcyBhXHJcbiAgdmVyeSBzaW1pbGFyIHByb2Nlc3MuXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcygpO1xyXG4gID4gICAgIC8vIGJ1bmRsZSBjYW4gYmUgc3RvcmVkIGluIHdpbmRvdy5sb2NhbFN0b3JhZ2Ugb3IganVzdCBoZWxkIGluIG1lbW9yeS5cclxuICA+ICAgICBsZXQgZW0yID0gbmV3IEVudGl0eU1hbmFnZXIoe1xyXG4gID4gICAgICAgICBzZXJ2aWNlTmFtZTogZW0xLnNlcnZpY2VOYW1lLFxyXG4gID4gICAgICAgICBtZXRhZGF0YVN0b3JlOiBlbTEubWV0YWRhdGFTdG9yZVxyXG4gID4gICAgIH0pO1xyXG4gID4gICAgIGVtMi5pbXBvcnRFbnRpdGllcyhidW5kbGUpO1xyXG4gID4gICAgIC8vIGVtMiB3aWxsIG5vdyBoYXZlIGEgY29tcGxldGUgY29weSBvZiB3aGF0IHdhcyBpbiBlbTFcclxuXHJcbiAgSXQgY2FuIGFsc28gYmUgdXNlZCB0byBtZXJnZSB0aGUgY29udGVudHMgb2YgYSBwcmV2aW91c2x5IGNyZWF0ZWQgRW50aXR5TWFuYWdlciB3aXRoIGFuXHJcbiAgZXhpc3RpbmcgRW50aXR5TWFuYWdlciB3aXRoIGNvbnRyb2wgb3ZlciBob3cgdGhlIHR3byBhcmUgbWVyZ2VkLlxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoKTtcclxuICA+ICAgICAvLyBhc3N1bWUgZW0yIGlzIGFub3RoZXIgZW50aXR5TWFuYWdlciBjb250YWluaW5nIHNvbWUgb2YgdGhlIHNhbWUgZW50aXRpZXMgcG9zc2libHkgd2l0aCBtb2RpZmljYXRpb25zLlxyXG4gID4gICAgIGVtMi5pbXBvcnRFbnRpdGllcyhidW5kbGUsIHsgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneS5QcmVzZXJ2ZUNoYW5nZXN9ICk7XHJcbiAgPiAgICAgLy8gZW0yIHdpbGwgbm93IGNvbnRhaW4gYWxsIG9mIHRoZSBlbnRpdGllcyBmcm9tIGJvdGggZW0xIGFuZCBlbTIuICBBbnkgZW0yIGVudGl0aWVzIHdpdGggcHJldmlvdXNseVxyXG4gID4gICAgIC8vIG1hZGUgbW9kaWZpY2F0aW9ucyB3aWxsIG5vdCBoYXZlIGJlZW4gdG91Y2hlZCwgYnV0IGFsbCBvdGhlciBlbnRpdGllcyBmcm9tIGVtMSB3aWxsIGhhdmUgYmVlbiBpbXBvcnRlZC5cclxuICBAcGFyYW0gZXhwb3J0ZWRTdHJpbmcgLSBUaGUgcmVzdWx0IG9mIGEgcHJldmlvdXMgJ2V4cG9ydCcgY2FsbC5cclxuICBAcGFyYW0gaW1wb3J0Q29uZmlnIC0gQSBjb25maWd1cmF0aW9uIG9iamVjdC5cclxuICBAcGFyYW0gaW1wb3J0Q29uZmlnLm1lcmdlU3RyYXRlZ3kgLSAgQSBbW01lcmdlU3RyYXRlZ3ldXSB0byB1c2Ugd2hlblxyXG4gIG1lcmdpbmcgaW50byBhbiBleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gIEBwYXJhbSBpbXBvcnRDb25maWcubWV0YWRhdGFWZXJzaW9uRm4gLSBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgdHdvIGFyZ3VtZW50cyAodGhlIGN1cnJlbnQgbWV0YWRhdGFWZXJzaW9uIGFuZCB0aGUgaW1wb3J0ZWQgc3RvcmUncyAnbmFtZScpXHJcbiAgYW5kIG1heSBiZSB1c2VkIHRvIHBlcmZvcm0gdmVyc2lvbiBjaGVja2luZy5cclxuICBAcmV0dXJuIHJlc3VsdCBcclxuICAgIC0gcmVzdWx0LmVudGl0aWVzIHtBcnJheSBvZiBFbnRpdGllc30gVGhlIGVudGl0aWVzIHRoYXQgd2VyZSBpbXBvcnRlZC5cclxuICAgIC0gcmVzdWx0LnRlbXBLZXlNYXAge09iamVjdH0gTWFwcGluZyBmcm9tIG9yaWdpbmFsIEVudGl0eUtleSBpbiB0aGUgaW1wb3J0IGJ1bmRsZSB0byBpdHMgY29ycmVzcG9uZGluZyBFbnRpdHlLZXkgaW4gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gICoqL1xyXG4gIGltcG9ydEVudGl0aWVzKGV4cG9ydGVkOiBzdHJpbmcgfCBPYmplY3QsIGltcG9ydENvbmZpZz86IEltcG9ydENvbmZpZykge1xyXG4gICAgaW1wb3J0Q29uZmlnID0gaW1wb3J0Q29uZmlnIHx8IHt9O1xyXG4gICAgYXNzZXJ0Q29uZmlnKGltcG9ydENvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJtZXJnZVN0cmF0ZWd5XCIpLmlzRW51bU9mKE1lcmdlU3RyYXRlZ3kpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdCh0aGlzLnF1ZXJ5T3B0aW9ucy5tZXJnZVN0cmF0ZWd5KVxyXG4gICAgICAud2hlcmVQYXJhbShcIm1ldGFkYXRhVmVyc2lvbkZuXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJtZXJnZUFkZHNcIikuaXNCb29sZWFuKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC5hcHBseUFsbChpbXBvcnRDb25maWcpO1xyXG5cclxuICAgIGxldCBqc29uID0gKHR5cGVvZiBleHBvcnRlZCA9PT0gXCJzdHJpbmdcIikgPyBKU09OLnBhcnNlKGV4cG9ydGVkKSA6IGV4cG9ydGVkO1xyXG4gICAgaWYgKGpzb24ubWV0YWRhdGFTdG9yZSkge1xyXG4gICAgICB0aGlzLm1ldGFkYXRhU3RvcmUuaW1wb3J0TWV0YWRhdGEoanNvbi5tZXRhZGF0YVN0b3JlKTtcclxuICAgICAgLy8gdGhlIHx8IGNsYXVzZSBpcyBmb3IgYmFja3dhcmRzIGNvbXBhdCB3aXRoIGFuIGVhcmxpZXIgc2VyaWFsaXphdGlvbiBmb3JtYXQuXHJcbiAgICAgIHRoaXMuZGF0YVNlcnZpY2UgPSAoanNvbi5kYXRhU2VydmljZSAmJiBEYXRhU2VydmljZS5mcm9tSlNPTihqc29uLmRhdGFTZXJ2aWNlKSkgfHwgbmV3IERhdGFTZXJ2aWNlKHsgc2VydmljZU5hbWU6IGpzb24uc2VydmljZU5hbWUgfSk7XHJcblxyXG4gICAgICB0aGlzLnNhdmVPcHRpb25zID0gbmV3IFNhdmVPcHRpb25zKGpzb24uc2F2ZU9wdGlvbnMpO1xyXG4gICAgICB0aGlzLnF1ZXJ5T3B0aW9ucyA9IFF1ZXJ5T3B0aW9ucy5mcm9tSlNPTihqc29uLnF1ZXJ5T3B0aW9ucyk7XHJcbiAgICAgIHRoaXMudmFsaWRhdGlvbk9wdGlvbnMgPSBuZXcgVmFsaWRhdGlvbk9wdGlvbnMoanNvbi52YWxpZGF0aW9uT3B0aW9ucyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpbXBvcnRDb25maWcubWV0YWRhdGFWZXJzaW9uRm4gJiYgaW1wb3J0Q29uZmlnLm1ldGFkYXRhVmVyc2lvbkZuKHtcclxuICAgICAgICBtZXRhZGF0YVZlcnNpb246IGpzb24ubWV0YWRhdGFWZXJzaW9uLFxyXG4gICAgICAgIG1ldGFkYXRhU3RvcmVOYW1lOiBqc29uLm1ldGFkYXRhU3RvcmVOYW1lXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCB0ZW1wS2V5TWFwOiBJVGVtcEtleU1hcCA9IHt9O1xyXG4gICAganNvbi50ZW1wS2V5cy5mb3JFYWNoKChrOiBhbnkpID0+IHtcclxuICAgICAgbGV0IG9sZEtleSA9IEVudGl0eUtleS5mcm9tSlNPTihrLCB0aGlzLm1ldGFkYXRhU3RvcmUpO1xyXG4gICAgICAvLyB0cnkgdG8gdXNlIG9sZEtleSBpZiBub3QgYWxyZWFkeSB1c2VkIGluIHRoaXMga2V5R2VuZXJhdG9yLlxyXG4gICAgICB0ZW1wS2V5TWFwW29sZEtleS50b1N0cmluZygpXSA9IG5ldyBFbnRpdHlLZXkob2xkS2V5LmVudGl0eVR5cGUsIHRoaXMua2V5R2VuZXJhdG9yLmdlbmVyYXRlVGVtcEtleVZhbHVlKG9sZEtleS5lbnRpdHlUeXBlLCBvbGRLZXkudmFsdWVzWzBdKSk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBsZXQgZW50aXRpZXNUb0xpbms6IEVudGl0eVtdID0gW107XHJcbiAgICBsZXQgaW1wQ29uZmlnID0gaW1wb3J0Q29uZmlnIGFzIEltcG9ydENvbmZpZ0V4dDtcclxuXHJcbiAgICBpbXBDb25maWcudGVtcEtleU1hcCA9IHRlbXBLZXlNYXA7XHJcbiAgICBjb3JlLndyYXBFeGVjdXRpb24oKCkgPT4ge1xyXG4gICAgICB0aGlzLl9wZW5kaW5nUHVicyA9IFtdO1xyXG4gICAgfSwgKHN0YXRlKSA9PiB7XHJcbiAgICAgIHRoaXMuX3BlbmRpbmdQdWJzIS5mb3JFYWNoKChmbikgPT4gZm4oKSk7XHJcbiAgICAgIHRoaXMuX3BlbmRpbmdQdWJzID0gdW5kZWZpbmVkO1xyXG4gICAgICB0aGlzLl9oYXNDaGFuZ2VzQWN0aW9uICYmIHRoaXMuX2hhc0NoYW5nZXNBY3Rpb24oKTtcclxuICAgIH0sICgpID0+IHtcclxuICAgICAgY29yZS5vYmplY3RGb3JFYWNoKGpzb24uZW50aXR5R3JvdXBNYXAsIChlbnRpdHlUeXBlTmFtZSwganNvbkdyb3VwKSA9PiB7XHJcbiAgICAgICAgbGV0IGVudGl0eVR5cGUgPSB0aGlzLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGVudGl0eVR5cGVOYW1lLCBmYWxzZSkgYXMgRW50aXR5VHlwZTtcclxuICAgICAgICBsZXQgdGFyZ2V0RW50aXR5R3JvdXAgPSBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cCh0aGlzLCBlbnRpdHlUeXBlKTtcclxuICAgICAgICBsZXQgZW50aXRpZXMgPSBpbXBvcnRFbnRpdHlHcm91cCh0YXJnZXRFbnRpdHlHcm91cCwganNvbkdyb3VwLCBpbXBDb25maWcpO1xyXG4gICAgICAgIGlmIChlbnRpdGllcyAmJiBlbnRpdGllcy5sZW5ndGgpIHtcclxuICAgICAgICAgIGVudGl0aWVzVG9MaW5rID0gZW50aXRpZXNUb0xpbmsuY29uY2F0KGVudGl0aWVzKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICBlbnRpdGllc1RvTGluay5mb3JFYWNoKChlbnRpdHkpID0+IHtcclxuICAgICAgICBpZiAoIWVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUuaXNEZWxldGVkKCkpIHtcclxuICAgICAgICAgIHRoaXMuX2xpbmtSZWxhdGVkRW50aXRpZXMoZW50aXR5KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBlbnRpdGllczogZW50aXRpZXNUb0xpbmssXHJcbiAgICAgIHRlbXBLZXlNYXBwaW5nOiB0ZW1wS2V5TWFwXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQ2xlYXJzIHRoaXMgRW50aXR5TWFuYWdlcidzIGNhY2hlIGJ1dCBrZWVwcyBhbGwgb3RoZXIgc2V0dGluZ3MuIE5vdGUgdGhhdCB0aGlzXHJcbiAgbWV0aG9kIGlzIG5vdCBhcyBmYXN0IGFzIGNyZWF0aW5nIGEgbmV3IEVudGl0eU1hbmFnZXIgdmlhICduZXcgRW50aXR5TWFuYWdlcicuXHJcbiAgVGhpcyBpcyBiZWNhdXNlIGNsZWFyIGFjdHVhbGx5IGRldGFjaGVzIGFsbCBvZiB0aGUgZW50aXRpZXMgZnJvbSB0aGUgRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBlbTEuY2xlYXIoKTtcclxuICA+ICAgICAvLyBlbTEgaXMgd2lsbCBub3cgY29udGFpbiBubyBlbnRpdGllcywgYnV0IGFsbCBvdGhlciBzZXR0aW5nIHdpbGwgYmUgbWFpbnRhaW5lZC5cclxuICAqKi9cclxuICBjbGVhcigpIHtcclxuICAgIGNvcmUub2JqZWN0TWFwKHRoaXMuX2VudGl0eUdyb3VwTWFwLCBmdW5jdGlvbiAoa2V5OiBzdHJpbmcsIGVudGl0eUdyb3VwOiBFbnRpdHlHcm91cCkge1xyXG4gICAgICByZXR1cm4gZW50aXR5R3JvdXAuX2NoZWNrT3BlcmF0aW9uKCdjbGVhcicpO1xyXG4gICAgfSkuZm9yRWFjaCgoZW50aXR5R3JvdXA6IEVudGl0eUdyb3VwKSA9PiB7XHJcbiAgICAgIGVudGl0eUdyb3VwLl9jbGVhcigpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5fZW50aXR5R3JvdXBNYXAgPSB7fTtcclxuICAgIHRoaXMuX3VuYXR0YWNoZWRDaGlsZHJlbk1hcCA9IG5ldyBVbmF0dGFjaGVkQ2hpbGRyZW5NYXAoKTtcclxuICAgIHRoaXMua2V5R2VuZXJhdG9yID0gbmV3IHRoaXMua2V5R2VuZXJhdG9yQ3RvcigpO1xyXG4gICAgdGhpcy5lbnRpdHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5DbGVhciB9KTtcclxuICAgIHRoaXMuX3NldEhhc0NoYW5nZXMoZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQ3JlYXRlcyBhbiBlbXB0eSBjb3B5IG9mIHRoaXMgRW50aXR5TWFuYWdlciBidXQgd2l0aCB0aGUgc2FtZSBEYXRhU2VydmljZSwgTWV0YWRhdGFTdG9yZSwgUXVlcnlPcHRpb25zLCBTYXZlT3B0aW9ucywgVmFsaWRhdGlvbk9wdGlvbnMsIGV0Yy4gXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGVtMiA9IGVtMS5jcmVhdGVFbXB0eUNvcHkoKTtcclxuICA+ICAgICAvLyBlbTIgaXMgYSBuZXcgRW50aXR5TWFuYWdlciB3aXRoIGFsbCBvZiBlbTEncyBzZXR0aW5nc1xyXG4gID4gICAgIC8vIGJ1dCBubyBlbnRpdGllcy5cclxuICBAcmV0dXJuIEEgbmV3IEVudGl0eU1hbmFnZXIuXHJcbiAgKiovXHJcbiAgY3JlYXRlRW1wdHlDb3B5KCkge1xyXG4gICAgbGV0IGNvcHkgPSBuZXcgRW50aXR5TWFuYWdlcihjb3JlLmV4dGVuZCh7fSwgdGhpcyxcclxuICAgICAgW1wiZGF0YVNlcnZpY2VcIiwgXCJtZXRhZGF0YVN0b3JlXCIsIFwicXVlcnlPcHRpb25zXCIsIFwic2F2ZU9wdGlvbnNcIiwgXCJ2YWxpZGF0aW9uT3B0aW9uc1wiLCBcImtleUdlbmVyYXRvckN0b3JcIl0pKTtcclxuICAgIHJldHVybiBjb3B5O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQXR0YWNoZXMgYW4gZW50aXR5IHRvIHRoaXMgRW50aXR5TWFuYWdlciB3aXRoIGFuICBbW0VudGl0eVN0YXRlXV0gb2YgJ0FkZGVkJy5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgbGV0IGN1c3QxID0gY3VzdFR5cGUuY3JlYXRlRW50aXR5KCk7XHJcbiAgPiAgICAgZW0xLmFkZEVudGl0eShjdXN0MSk7XHJcblxyXG4gIE5vdGUgdGhhdCB0aGlzIGlzIHRoZSBzYW1lIGFzIHVzaW5nICdhdHRhY2hFbnRpdHknIHdpdGggYW4gW1tFbnRpdHlTdGF0ZV1dIG9mICdBZGRlZCcuXHJcblxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICBsZXQgY3VzdDEgPSBjdXN0VHlwZS5jcmVhdGVFbnRpdHkoKTtcclxuICA+ICAgICBlbTEuYXR0YWNoRW50aXR5KGN1c3QxLCBFbnRpdHlTdGF0ZS5BZGRlZCk7XHJcbiAgQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gYWRkLlxyXG4gIEByZXR1cm4gVGhlIGFkZGVkIGVudGl0eS5cclxuICAqKi9cclxuICBhZGRFbnRpdHkoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIHJldHVybiB0aGlzLmF0dGFjaEVudGl0eShlbnRpdHksIEVudGl0eVN0YXRlLkFkZGVkKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEF0dGFjaGVzIGFuIGVudGl0eSB0byB0aGlzIEVudGl0eU1hbmFnZXIgd2l0aCBhIHNwZWNpZmllZCBbW0VudGl0eVN0YXRlXV0uXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgIGxldCBjdXN0MSA9IGN1c3RUeXBlLmNyZWF0ZUVudGl0eSgpO1xyXG4gID4gICAgIGVtMS5hdHRhY2hFbnRpdHkoY3VzdDEsIEVudGl0eVN0YXRlLkFkZGVkKTtcclxuICBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBhZGQuXHJcbiAgQHBhcmFtIGVudGl0eVN0YXRlIC0gKGRlZmF1bHQ9RW50aXR5U3RhdGUuVW5jaGFuZ2VkKSBUaGUgRW50aXR5U3RhdGUgb2YgdGhlIG5ld2x5IGF0dGFjaGVkIGVudGl0eS4gSWYgb21pdHRlZCB0aGlzIGRlZmF1bHRzIHRvIEVudGl0eVN0YXRlLlVuY2hhbmdlZC5cclxuICBAcGFyYW0gbWVyZ2VTdHJhdGVneSAtIChkZWZhdWx0ID0gTWVyZ2VTdHJhdGVneS5EaXNhbGxvd2VkKSBIb3cgdGhlIHNwZWNpZmllZCBlbnRpdHkgc2hvdWxkIGJlIG1lcmdlZCBpbnRvIHRoZSBFbnRpdHlNYW5hZ2VyIGlmIHRoaXMgRW50aXR5TWFuYWdlciBhbHJlYWR5IGNvbnRhaW5zIGFuIGVudGl0eSB3aXRoIHRoZSBzYW1lIGtleS5cclxuICBAcmV0dXJuIFRoZSBhdHRhY2hlZCBlbnRpdHkuXHJcbiAgKiovXHJcbiAgYXR0YWNoRW50aXR5KGVudGl0eTogRW50aXR5LCBlbnRpdHlTdGF0ZT86IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5PzogTWVyZ2VTdHJhdGVneSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5LCBcImVudGl0eVwiKS5pc1JlcXVpcmVkKCkuY2hlY2soKTtcclxuICAgIHRoaXMubWV0YWRhdGFTdG9yZS5fY2hlY2tFbnRpdHlUeXBlKGVudGl0eSk7XHJcbiAgICBsZXQgZXNTeW1ib2wgPSBhc3NlcnRQYXJhbShlbnRpdHlTdGF0ZSwgXCJlbnRpdHlTdGF0ZVwiKS5pc0VudW1PZihFbnRpdHlTdGF0ZSkuaXNPcHRpb25hbCgpLmNoZWNrKEVudGl0eVN0YXRlLlVuY2hhbmdlZCkgYXMgRW50aXR5U3RhdGU7XHJcbiAgICBsZXQgbXNTeW1ib2wgPSBhc3NlcnRQYXJhbShtZXJnZVN0cmF0ZWd5LCBcIm1lcmdlU3RyYXRlZ3lcIikuaXNFbnVtT2YoTWVyZ2VTdHJhdGVneSkuaXNPcHRpb25hbCgpLmNoZWNrKE1lcmdlU3RyYXRlZ3kuRGlzYWxsb3dlZCkgYXMgTWVyZ2VTdHJhdGVneTtcclxuXHJcbiAgICBpZiAoZW50aXR5LmVudGl0eVR5cGUubWV0YWRhdGFTdG9yZSAhPT0gdGhpcy5tZXRhZGF0YVN0b3JlKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBhdHRhY2ggdGhpcyBlbnRpdHkgYmVjYXVzZSB0aGUgRW50aXR5VHlwZSAoXCIgKyBlbnRpdHkuZW50aXR5VHlwZS5uYW1lICtcclxuICAgICAgICBcIikgYW5kIE1ldGFkYXRhU3RvcmUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgZW50aXR5IGRvZXMgbm90IG1hdGNoIHRoaXMgRW50aXR5TWFuYWdlcidzIE1ldGFkYXRhU3RvcmUuXCIpO1xyXG4gICAgfVxyXG4gICAgbGV0IGFzcGVjdCA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICBpZiAoYXNwZWN0KSB7XHJcbiAgICAgIC8vIHRvIGF2b2lkIHJlYXR0YWNoaW5nIGFuIGVudGl0eSBpbiBwcm9ncmVzc1xyXG4gICAgICBpZiAoYXNwZWN0Ll9pblByb2Nlc3NFbnRpdHkpIHJldHVybiBhc3BlY3QuX2luUHJvY2Vzc0VudGl0eTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIHRoaXMgb2NjdXIncyB3aGVuIGF0dGFjaGluZyBhbiBlbnRpdHkgY3JlYXRlZCB2aWEgbmV3IGluc3RlYWQgb2YgdmlhIGNyZWF0ZUVudGl0eS5cclxuICAgICAgYXNwZWN0ID0gbmV3IEVudGl0eUFzcGVjdChlbnRpdHkpO1xyXG4gICAgfVxyXG4gICAgbGV0IG1hbmFnZXIgPSBhc3BlY3QuZW50aXR5TWFuYWdlcjtcclxuICAgIGlmIChtYW5hZ2VyKSB7XHJcbiAgICAgIGlmIChtYW5hZ2VyID09PSB0aGlzKSB7XHJcbiAgICAgICAgcmV0dXJuIGVudGl0eTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGVudGl0eSBhbHJlYWR5IGJlbG9uZ3MgdG8gYW5vdGhlciBFbnRpdHlNYW5hZ2VyXCIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGF0dGFjaGVkRW50aXR5ID0ge30gYXMgRW50aXR5O1xyXG4gICAgY29yZS51c2luZyh0aGlzLCBcImlzTG9hZGluZ1wiLCB0cnVlLCAoKSA9PiB7XHJcbiAgICAgIGlmIChlc1N5bWJvbC5pc0FkZGVkKCkpIHtcclxuICAgICAgICBjaGVja0VudGl0eUtleSh0aGlzLCBlbnRpdHkpO1xyXG4gICAgICB9XHJcbiAgICAgIC8vIGF0dGFjaGVkRW50aXR5ID09PSBlbnRpdHkgRVhDRVBUIGluIHRoZSBjYXNlIG9mIGEgbWVyZ2UuXHJcbiAgICAgIGF0dGFjaGVkRW50aXR5ID0gdGhpcy5fYXR0YWNoRW50aXR5Q29yZShlbnRpdHksIGVzU3ltYm9sLCBtc1N5bWJvbCk7XHJcbiAgICAgIGFzcGVjdC5faW5Qcm9jZXNzRW50aXR5ID0gYXR0YWNoZWRFbnRpdHk7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgLy8gZW50aXR5ICggbm90IGF0dGFjaGVkRW50aXR5KSBpcyBkZWxpYmVyYXRlIGhlcmUuXHJcbiAgICAgICAgYXR0YWNoUmVsYXRlZEVudGl0aWVzKHRoaXMsIGVudGl0eSwgZXNTeW1ib2wsIG1zU3ltYm9sKTtcclxuICAgICAgfSBmaW5hbGx5IHtcclxuICAgICAgICAvLyBpbnN1cmUgdGhhdCBfaW5Qcm9jZXNzRW50aXR5IGlzIGNsZWFyZWQuXHJcbiAgICAgICAgYXNwZWN0Ll9pblByb2Nlc3NFbnRpdHkgPSB1bmRlZmluZWQ7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgaWYgKHRoaXMudmFsaWRhdGlvbk9wdGlvbnMudmFsaWRhdGVPbkF0dGFjaCkge1xyXG4gICAgICBhdHRhY2hlZEVudGl0eS5lbnRpdHlBc3BlY3QudmFsaWRhdGVFbnRpdHkoKTtcclxuICAgIH1cclxuICAgIGlmICghZXNTeW1ib2wuaXNVbmNoYW5nZWQoKSkge1xyXG4gICAgICB0aGlzLl9ub3RpZnlTdGF0ZUNoYW5nZShhdHRhY2hlZEVudGl0eSwgdHJ1ZSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmVudGl0eUNoYW5nZWQucHVibGlzaCh7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLkF0dGFjaCwgZW50aXR5OiBhdHRhY2hlZEVudGl0eSB9KTtcclxuXHJcbiAgICByZXR1cm4gYXR0YWNoZWRFbnRpdHk7XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgRGV0YWNoZXMgYW4gZW50aXR5IGZyb20gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIC8vIGFzc3VtZSBjdXN0MSBpcyBhIGN1c3RvbWVyIEVudGl0eSBwcmV2aW91c2x5IGF0dGFjaGVkIHRvIGVtMVxyXG4gID4gICAgIGVtMS5kZXRhY2hFbnRpdHkoY3VzdDEpO1xyXG4gID4gICAgIC8vIGVtMSB3aWxsIG5vdyBubyBsb25nZXIgY29udGFpbiBjdXN0MSBhbmQgY3VzdDEgd2lsbCBoYXZlIGFuXHJcbiAgPiAgICAgLy8gZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlIG9mIEVudGl0eVN0YXRlLkRldGFjaGVkXHJcbiAgQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gZGV0YWNoLlxyXG4gIEByZXR1cm4gV2hldGhlciB0aGUgZW50aXR5IGNvdWxkIGJlIGRldGFjaGVkLiBUaGlzIHdpbGwgcmV0dXJuIGZhbHNlIGlmIHRoZSBlbnRpdHkgaXMgYWxyZWFkeSBkZXRhY2hlZCBvciB3YXMgbmV2ZXIgYXR0YWNoZWQuXHJcbiAgKiovXHJcbiAgZGV0YWNoRW50aXR5KGVudGl0eTogRW50aXR5KSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHksIFwiZW50aXR5XCIpLmlzRW50aXR5KCkuY2hlY2soKTtcclxuICAgIGxldCBhc3BlY3QgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgaWYgKCFhc3BlY3QpIHtcclxuICAgICAgLy8gbm8gYXNwZWN0IG1lYW5zIGluIGNvdWxkbid0IGFwcGVhciBpbiBhbnkgZ3JvdXBcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChhc3BlY3QuZW50aXR5TWFuYWdlciAhPT0gdGhpcykge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGVudGl0eSBkb2VzIG5vdCBiZWxvbmcgdG8gdGhpcyBFbnRpdHlNYW5hZ2VyLlwiKTtcclxuICAgIH1cclxuICAgIHJldHVybiBhc3BlY3Quc2V0RGV0YWNoZWQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEZldGNoZXMgdGhlIG1ldGFkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGUgRW50aXR5TWFuYWdlcidzIGN1cnJlbnQgJ3NlcnZpY2VOYW1lJy4gIFRoaXMgY2FsbFxyXG4gIG9jY3VycyBpbnRlcm5hbGx5IGJlZm9yZSB0aGUgZmlyc3QgcXVlcnkgdG8gYW55IHNlcnZpY2UgaWYgdGhlIG1ldGFkYXRhIGhhc24ndCBhbHJlYWR5IGJlZW5cclxuICBsb2FkZWQuIF9fQXN5bmNfX1xyXG5cclxuICBVc3VhbGx5IHlvdSB3aWxsIG5vdCBhY3R1YWxseSBwcm9jZXNzIHRoZSByZXN1bHRzIG9mIGEgZmV0Y2hNZXRhZGF0YSBjYWxsIGRpcmVjdGx5LCBidXQgd2lsbCBpbnN0ZWFkXHJcbiAgYXNrIGZvciB0aGUgbWV0YWRhdGEgZnJvbSB0aGUgRW50aXR5TWFuYWdlciBhZnRlciB0aGUgZmV0Y2hNZXRhZGF0YSBjYWxsIHJldHVybnMuXHJcbiAgPiAgICAgbGV0IGVtMSA9IG5ldyBFbnRpdHlNYW5hZ2VyKCBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIpO1xyXG4gID4gICAgIGVtMS5mZXRjaE1ldGFkYXRhKClcclxuICA+ICAgICAgIC50aGVuKGZ1bmN0aW9uKCkge1xyXG4gID4gICAgICAgICAgIGxldCBtZXRhZGF0YVN0b3JlID0gZW0xLm1ldGFkYXRhU3RvcmU7XHJcbiAgPiAgICAgICAgICAgLy8gZG8gc29tZXRoaW5nIHdpdGggdGhlIG1ldGFkYXRhXHJcbiAgPiAgICAgICB9KS5jYXRjaChmdW5jdGlvbihleGNlcHRpb24pIHtcclxuICA+ICAgICAgICAgICAvLyBoYW5kbGUgZXhjZXB0aW9uIGhlcmVcclxuICA+ICAgICAgIH0pO1xyXG4gIFxyXG4gIEBwYXJhbSBjYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBzdWNjZXNzLlxyXG4gIEBwYXJhbSBlcnJvckNhbGxiYWNrIC0gRnVuY3Rpb24gY2FsbGVkIG9uIGZhaWx1cmUuXHJcbiAgQHJldHVybiB7UHJvbWlzZX1cclxuICAgIC0gc2NoZW1hIHtPYmplY3R9IFRoZSByYXcgU2NoZW1hIG9iamVjdCBmcm9tIG1ldGFkYXRhIHByb3ZpZGVyIC0gQmVjYXVzZSB0aGlzIHNjaGVtYSB3aWxsIGRpZmZlciBkZXBlbmRpbmcgb24gdGhlIG1ldGFkYXRhIHByb3ZpZGVyXHJcbiAgICAgICAgaXQgaXMgdXN1YWxseSBiZXR0ZXIgdG8gYWNjZXNzIG1ldGFkYXRhIHZpYSB0aGUgJ21ldGFkYXRhU3RvcmUnIHByb3BlcnR5IG9mIHRoZSBFbnRpdHlNYW5hZ2VyIGluc3RlYWQgb2YgdXNpbmcgdGhpcyAncmF3JyBkYXRhLlxyXG4gICoqL1xyXG4gIGZldGNoTWV0YWRhdGEoZGF0YVNlcnZpY2U/OiBEYXRhU2VydmljZSwgY2FsbGJhY2s/OiBDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IEVycm9yQ2FsbGJhY2spIHtcclxuICAgIGlmICh0eXBlb2YgKGRhdGFTZXJ2aWNlKSA9PT0gXCJmdW5jdGlvblwiKSB7XHJcbiAgICAgIC8vIGxlZ2FjeSBzdXBwb3J0IGZvciB3aGVuIGRhdGFTZXJ2aWNlIHdhcyBub3QgYW4gYXJnLiBpLmUuIGZpcnN0IGFyZyB3YXMgY2FsbGJhY2tcclxuICAgICAgZXJyb3JDYWxsYmFjayA9IGNhbGxiYWNrO1xyXG4gICAgICBjYWxsYmFjayA9IGRhdGFTZXJ2aWNlO1xyXG4gICAgICBkYXRhU2VydmljZSA9IHVuZGVmaW5lZDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGFzc2VydFBhcmFtKGRhdGFTZXJ2aWNlLCBcImRhdGFTZXJ2aWNlXCIpLmlzSW5zdGFuY2VPZihEYXRhU2VydmljZSkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICAgIGFzc2VydFBhcmFtKGNhbGxiYWNrLCBcImNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgICAgYXNzZXJ0UGFyYW0oZXJyb3JDYWxsYmFjaywgXCJlcnJvckNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgcHJvbWlzZSA9IHRoaXMubWV0YWRhdGFTdG9yZS5mZXRjaE1ldGFkYXRhKGRhdGFTZXJ2aWNlIHx8IHRoaXMuZGF0YVNlcnZpY2UpO1xyXG4gICAgcmV0dXJuIHByb21pc2VXaXRoQ2FsbGJhY2tzKHByb21pc2UsIGNhbGxiYWNrLCBlcnJvckNhbGxiYWNrKTtcclxuICB9XHJcblxyXG5cclxuICBleGVjdXRlUXVlcnkocXVlcnk6IHN0cmluZywgY2FsbGJhY2s/OiBRdWVyeVN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IFF1ZXJ5RXJyb3JDYWxsYmFjayk6IFByb21pc2U8UXVlcnlSZXN1bHQ+O1xyXG4gIGV4ZWN1dGVRdWVyeShxdWVyeTogRW50aXR5UXVlcnksIGNhbGxiYWNrPzogUXVlcnlTdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s/OiBRdWVyeUVycm9yQ2FsbGJhY2spOiBQcm9taXNlPFF1ZXJ5UmVzdWx0PjtcclxuICAvKipcclxuICBFeGVjdXRlcyB0aGUgc3BlY2lmaWVkIHF1ZXJ5LiBfX0FzeW5jX18gXHJcbiAgXHJcbiAgPiAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKTtcclxuICA+ICAgICBlbS5leGVjdXRlUXVlcnkocXVlcnkpLnRoZW4oIGZ1bmN0aW9uKGRhdGEpIHtcclxuICA+ICAgICAgICAgbGV0IG9yZGVycyA9IGRhdGEucmVzdWx0cztcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IHJlc3VsdHMgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KS5jYXRjaCggZnVuY3Rpb24oZXJyKSB7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSBmYWlsdXJlIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgfSk7XHJcblxyXG4gIG9yIHdpdGggY2FsbGJhY2tzXHJcbiAgPiAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKTtcclxuICA+ICAgICBlbS5leGVjdXRlUXVlcnkocXVlcnksXHJcbiAgPiAgICAgICAgIGZ1bmN0aW9uKGRhdGEpIHtcclxuICA+ICAgICAgICAgICAgIGxldCBvcmRlcnMgPSBkYXRhLnJlc3VsdHM7XHJcbiAgPiAgICAgICAgICAgICAuLi4gcXVlcnkgcmVzdWx0cyBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgICAgICB9LFxyXG4gID4gICAgICAgICBmdW5jdGlvbihlcnIpIHtcclxuICA+ICAgICAgICAgICAgIC4uLiBxdWVyeSBmYWlsdXJlIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgICAgIH0pO1xyXG5cclxuICBFaXRoZXIgd2F5IHRoaXMgbWV0aG9kIGlzIHRoZSBzYW1lIGFzIGNhbGxpbmcgdGhlIFRoZSBbW0VudGl0eVF1ZXJ5XV0gJ2V4ZWN1dGUnIG1ldGhvZC5cclxuICA+ICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcihzZXJ2aWNlTmFtZSk7XHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiT3JkZXJzXCIpLnVzaW5nKGVtKTtcclxuICA+ICAgICBxdWVyeS5leGVjdXRlKCkudGhlbiggZnVuY3Rpb24oZGF0YSkge1xyXG4gID4gICAgICAgICBsZXQgb3JkZXJzID0gZGF0YS5yZXN1bHRzO1xyXG4gID4gICAgICAgICAuLi4gcXVlcnkgcmVzdWx0cyBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgIH0pLmNhdGNoKCBmdW5jdGlvbihlcnIpIHtcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IGZhaWx1cmUgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KTtcclxuICBAcGFyYW0gcXVlcnkgLSBUaGUgW1tFbnRpdHlRdWVyeV1dIG9yIE9EYXRhIHF1ZXJ5IHN0cmluZyB0byBleGVjdXRlLlxyXG4gIEBwYXJhbSBjYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBzdWNjZXNzLlxyXG4gIEBwYXJhbSBlcnJvckNhbGxiYWNrIC0ge0Z1bmN0aW9ufSBGdW5jdGlvbiBjYWxsZWQgb24gZmFpbHVyZS5cclxuICBAcmV0dXJuIFByb21pc2Ugb2YgXHJcbiAgICAtIHJlc3VsdHMgLSBBbiBhcnJheSBvZiBlbnRpdGllc1xyXG4gICAgLSByZXRyaWV2ZWRFbnRpdGllcyAtIEEgYXJyYXkgb2YgYWxsIG9mIHRoZSBlbnRpdGllcyByZXR1cm5lZCBieSB0aGUgcXVlcnkuICBEaWZmZXJzIGZyb20gcmVzdWx0cyAoYWJvdmUpIHdoZW4gLmV4cGFuZCgpIGlzIHVzZWQuXHJcbiAgICAtIHF1ZXJ5IC0gVGhlIG9yaWdpbmFsIFtbRW50aXR5UXVlcnldXSBvciBxdWVyeSBzdHJpbmdcclxuICAgIC0gZW50aXR5TWFuYWdlciAtICBUaGUgRW50aXR5TWFuYWdlci5cclxuICAgIC0gaHR0cFJlc3BvbnNlIC0gVGhlIFtbSUh0dHBSZXNwb25zZV1dIHJldHVybmVkIGZyb20gdGhlIHNlcnZlci5cclxuICAgIC0gaW5saW5lQ291bnQgLSAgT25seSBhdmFpbGFibGUgaWYgJ2lubGluZUNvdW50KHRydWUpJyB3YXMgYXBwbGllZCB0byB0aGUgcXVlcnkuICBSZXR1cm5zIHRoZSBjb3VudCBvZlxyXG4gICAgaXRlbXMgdGhhdCB3b3VsZCBoYXZlIGJlZW4gcmV0dXJuZWQgYnkgdGhlIHF1ZXJ5IGJlZm9yZSBhcHBseWluZyBhbnkgc2tpcCBvciB0YWtlIG9wZXJhdG9ycywgYnV0IGFmdGVyIGFueSBmaWx0ZXIvd2hlcmUgcHJlZGljYXRlc1xyXG4gICAgd291bGQgaGF2ZSBiZWVuIGFwcGxpZWQuXHJcbiAgKiovXHJcbiAgZXhlY3V0ZVF1ZXJ5KHF1ZXJ5OiBFbnRpdHlRdWVyeSB8IHN0cmluZywgY2FsbGJhY2s/OiBRdWVyeVN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IFF1ZXJ5RXJyb3JDYWxsYmFjaykge1xyXG4gICAgYXNzZXJ0UGFyYW0ocXVlcnksIFwicXVlcnlcIikuaXNJbnN0YW5jZU9mKEVudGl0eVF1ZXJ5KS5vcigpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGNhbGxiYWNrLCBcImNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGVycm9yQ2FsbGJhY2ssIFwiZXJyb3JDYWxsYmFja1wiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICBsZXQgcHJvbWlzZTogUHJvbWlzZTxhbnk+O1xyXG4gICAgLy8gJ3Jlc29sdmUnIG1ldGhvZHMgY3JlYXRlIGEgbmV3IHR5cGVkIG9iamVjdCB3aXRoIGFsbCBvZiBpdHMgcHJvcGVydGllcyBmdWxseSByZXNvbHZlZCBhZ2FpbnN0IGEgbGlzdCBvZiBzb3VyY2VzLlxyXG4gICAgLy8gVGhvdWdodCBhYm91dCBjcmVhdGluZyBhICdub3JtYWxpemVkJyBxdWVyeSB3aXRoIHRoZXNlICdyZXNvbHZlZCcgb2JqZWN0c1xyXG4gICAgLy8gYnV0IGRlY2lkZWQgbm90IHRvIGJlY2F1c2UgdGhlICdxdWVyeScgbWF5IG5vdCBiZSBhbiBFbnRpdHlRdWVyeSAoaXQgY2FuIGJlIGEgc3RyaW5nKSBhbmQgaGVuY2UgbWlnaHQgbm90IGhhdmUgYSBxdWVyeU9wdGlvbnMgb3IgZGF0YVNlcnZpY2VzIHByb3BlcnR5IG9uIGl0LlxyXG4gICAgbGV0IHF1ZXJ5T3B0aW9ucyA9IFF1ZXJ5T3B0aW9ucy5yZXNvbHZlKFsocXVlcnkgYXMgYW55KS5xdWVyeU9wdGlvbnMsIHRoaXMucXVlcnlPcHRpb25zLCBRdWVyeU9wdGlvbnMuZGVmYXVsdEluc3RhbmNlXSk7XHJcbiAgICBsZXQgZGF0YVNlcnZpY2UgPSBEYXRhU2VydmljZS5yZXNvbHZlKFsocXVlcnkgYXMgYW55KS5kYXRhU2VydmljZSEsIHRoaXMuZGF0YVNlcnZpY2VdKTtcclxuXHJcbiAgICBpZiAoKCFkYXRhU2VydmljZS5oYXNTZXJ2ZXJNZXRhZGF0YSkgfHwgdGhpcy5tZXRhZGF0YVN0b3JlLmhhc01ldGFkYXRhRm9yKGRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lKSkge1xyXG4gICAgICBwcm9taXNlID0gZXhlY3V0ZVF1ZXJ5Q29yZSh0aGlzLCBxdWVyeSwgcXVlcnlPcHRpb25zLCBkYXRhU2VydmljZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBwcm9taXNlID0gdGhpcy5mZXRjaE1ldGFkYXRhKGRhdGFTZXJ2aWNlKS50aGVuKCgpID0+IHtcclxuICAgICAgICByZXR1cm4gZXhlY3V0ZVF1ZXJ5Q29yZSh0aGlzLCBxdWVyeSwgcXVlcnlPcHRpb25zLCBkYXRhU2VydmljZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBwcm9taXNlV2l0aENhbGxiYWNrcyhwcm9taXNlLCBjYWxsYmFjaywgZXJyb3JDYWxsYmFjayBhcyBFcnJvckNhbGxiYWNrKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEV4ZWN1dGVzIHRoZSBzcGVjaWZpZWQgcXVlcnkgYWdhaW5zdCB0aGlzIEVudGl0eU1hbmFnZXIncyBsb2NhbCBjYWNoZS5cclxuXHJcbiAgQmVjYXVzZSB0aGlzIG1ldGhvZCBpcyBleGVjdXRlZCBpbW1lZGlhdGVseSB0aGVyZSBpcyBubyBuZWVkIGZvciBhIHByb21pc2Ugb3IgYSBjYWxsYmFja1xyXG4gID4gICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKHNlcnZpY2VOYW1lKTtcclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJPcmRlcnNcIik7XHJcbiAgPiAgICAgbGV0IG9yZGVycyA9IGVtLmV4ZWN1dGVRdWVyeUxvY2FsbHkocXVlcnkpO1xyXG5cclxuICBOb3RlIHRoYXQgdGhpcyBjYW4gYWxzbyBiZSBhY2NvbXBsaXNoZWQgdXNpbmcgdGhlICdleGVjdXRlUXVlcnknIG1ldGhvZCB3aXRoXHJcbiAgYSBGZXRjaFN0cmF0ZWd5IG9mIEZyb21Mb2NhbENhY2hlIGFuZCBtYWtpbmcgdXNlIG9mIHRoZSBQcm9taXNlIG9yIGNhbGxiYWNrXHJcbiAgPiAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKS51c2luZyhGZXRjaFN0cmF0ZWd5LkZyb21Mb2NhbENhY2hlKTtcclxuICA+ICAgICBlbS5leGVjdXRlUXVlcnkocXVlcnkpLnRoZW4oIGZ1bmN0aW9uKGRhdGEpIHtcclxuICA+ICAgICAgICAgbGV0IG9yZGVycyA9IGRhdGEucmVzdWx0cztcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IHJlc3VsdHMgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KS5jYXRjaCggZnVuY3Rpb24oZXJyKSB7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSBmYWlsdXJlIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgfSk7XHJcbiAgQHBhcmFtIHF1ZXJ5IC0gVGhlIFtbRW50aXR5UXVlcnldXSB0byBleGVjdXRlLlxyXG4gIEByZXR1cm4gIHtBcnJheSBvZiBFbnRpdHl9ICBBcnJheSBvZiBlbnRpdGllcyBmcm9tIGNhY2hlIHRoYXQgc2F0aXNmeSB0aGUgcXVlcnlcclxuICAqKi9cclxuICBleGVjdXRlUXVlcnlMb2NhbGx5KHF1ZXJ5OiBFbnRpdHlRdWVyeSkge1xyXG4gICAgcmV0dXJuIGV4ZWN1dGVRdWVyeUxvY2FsbHlDb3JlKHRoaXMsIHF1ZXJ5KS5yZXN1bHRzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgU2F2ZXMgZWl0aGVyIGEgbGlzdCBvZiBzcGVjaWZpZWQgZW50aXRpZXMgb3IgYWxsIGNoYW5nZWQgZW50aXRpZXMgd2l0aGluIHRoaXMgRW50aXR5TWFuYWdlci4gSWYgdGhlcmUgYXJlIG5vIGNoYW5nZXMgdG8gYW55IG9mIHRoZSBlbnRpdGllc1xyXG4gIHNwZWNpZmllZCB0aGVuIHRoZXJlIHdpbGwgYmUgbm8gc2VydmVyIHNpZGUgY2FsbCBtYWRlIGJ1dCBhIHZhbGlkICdlbXB0eScgc2F2ZVJlc3VsdCB3aWxsIHN0aWxsIGJlIHJldHVybmVkLiBfX0FzeW5jX19cclxuXHJcbiAgT2Z0ZW4gd2Ugd2lsbCBiZSBzYXZpbmcgYWxsIG9mIHRoZSBlbnRpdGllcyB3aXRoaW4gYW4gRW50aXR5TWFuYWdlciB0aGF0IGFyZSBlaXRoZXIgYWRkZWQsIG1vZGlmaWVkIG9yIGRlbGV0ZWRcclxuICBhbmQgd2Ugd2lsbCBsZXQgdGhlICdzYXZlQ2hhbmdlcycgY2FsbCBkZXRlcm1pbmUgd2hpY2ggZW50aXRpZXMgdGhlc2UgYXJlLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgLy8gVGhpcyBjb3VsZCBpbmNsdWRlIGFkZGVkLCBtb2RpZmllZCBhbmQgZGVsZXRlZCBlbnRpdGllcy5cclxuICA+ICAgICAgZW0uc2F2ZUNoYW5nZXMoKS50aGVuKGZ1bmN0aW9uKHNhdmVSZXN1bHQpIHtcclxuICA+ICAgICAgICAgIGxldCBzYXZlZEVudGl0aWVzID0gc2F2ZVJlc3VsdC5lbnRpdGllcztcclxuICA+ICAgICAgICAgIGxldCBrZXlNYXBwaW5ncyA9IHNhdmVSZXN1bHQua2V5TWFwcGluZ3M7XHJcbiAgPiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlKSB7XHJcbiAgPiAgICAgICAgICAvLyBlIGlzIGFueSBleGNlcHRpb24gdGhhdCB3YXMgdGhyb3duLlxyXG4gID4gICAgICB9KTtcclxuXHJcbiAgQnV0IHdlIGNhbiBhbHNvIGNvbnRyb2wgZXhhY3RseSB3aGljaCBlbnRpdGllcyB0byBzYXZlIGFuZCBjYW4gc3BlY2lmeSBzcGVjaWZpYyBTYXZlT3B0aW9uc1xyXG5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVudGl0aWVzVG9TYXZlIGlzIGFuIGFycmF5IG9mIGVudGl0aWVzIHRvIHNhdmUuXHJcbiAgPiAgICAgIGxldCBzYXZlT3B0aW9ucyA9IG5ldyBTYXZlT3B0aW9ucyh7IGFsbG93Q29uY3VycmVudFNhdmVzOiB0cnVlIH0pO1xyXG4gID4gICAgICBlbS5zYXZlQ2hhbmdlcyhlbnRpdGllc1RvU2F2ZSwgc2F2ZU9wdGlvbnMpLnRoZW4oZnVuY3Rpb24oc2F2ZVJlc3VsdCkge1xyXG4gID4gICAgICAgICAgbGV0IHNhdmVkRW50aXRpZXMgPSBzYXZlUmVzdWx0LmVudGl0aWVzO1xyXG4gID4gICAgICAgICAgbGV0IGtleU1hcHBpbmdzID0gc2F2ZVJlc3VsdC5rZXlNYXBwaW5ncztcclxuICA+ICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGUpIHtcclxuICA+ICAgICAgICAgIC8vIGUgaXMgYW55IGV4Y2VwdGlvbiB0aGF0IHdhcyB0aHJvd24uXHJcbiAgPiAgICAgIH0pO1xyXG5cclxuICBDYWxsYmFjayBtZXRob2RzIGNhbiBhbHNvIGJlIHVzZWRcclxuICA+ICAgICAgZW0uc2F2ZUNoYW5nZXMoZW50aXRpZXNUb1NhdmUsIG51bGwsXHJcbiAgPiAgICAgICAgICBmdW5jdGlvbihzYXZlUmVzdWx0KSB7XHJcbiAgPiAgICAgICAgICAgICAgbGV0IHNhdmVkRW50aXRpZXMgPSBzYXZlUmVzdWx0LmVudGl0aWVzO1xyXG4gID4gICAgICAgICAgICAgIGxldCBrZXlNYXBwaW5ncyA9IHNhdmVSZXN1bHQua2V5TWFwcGluZ3M7XHJcbiAgPiAgICAgICAgICB9LCBmdW5jdGlvbiAoZSkge1xyXG4gID4gICAgICAgICAgICAgIC8vIGUgaXMgYW55IGV4Y2VwdGlvbiB0aGF0IHdhcyB0aHJvd24uXHJcbiAgPiAgICAgICAgICB9XHJcbiAgPiAgICAgICk7XHJcblxyXG4gIEBwYXJhbSBlbnRpdGllcyAtIFRoZSBsaXN0IG9mIGVudGl0aWVzIHRvIHNhdmUuXHJcbiAgRXZlcnkgZW50aXR5IGluIHRoYXQgbGlzdCB3aWxsIGJlIHNlbnQgdG8gdGhlIHNlcnZlciwgd2hldGhlciBjaGFuZ2VkIG9yIHVuY2hhbmdlZCxcclxuICBhcyBsb25nIGFzIGl0IGlzIGF0dGFjaGVkIHRvIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICBJZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkLCBudWxsIG9yIGVtcHR5ICh0aGUgdXN1YWwgY2FzZSksXHJcbiAgZXZlcnkgZW50aXR5IHdpdGggcGVuZGluZyBjaGFuZ2VzIGluIHRoaXMgRW50aXR5TWFuYWdlciB3aWxsIGJlIHNhdmVkLlxyXG4gIEBwYXJhbSBzYXZlT3B0aW9ucyAtIFtbU2F2ZU9wdGlvbnNdXSBmb3IgdGhlIHNhdmUgLSB3aWxsIGRlZmF1bHQgdG9cclxuICBbW0VudGl0eU1hbmFnZXIuc2F2ZU9wdGlvbnNdXSBpZiBudWxsLlxyXG4gIEBwYXJhbSBjYWxsYmFjayAtICBGdW5jdGlvbiBjYWxsZWQgb24gc3VjY2Vzcy5cclxuICBAcGFyYW0gZXJyb3JDYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBmYWlsdXJlLlxyXG4gIEByZXR1cm4ge1Byb21pc2V9IFByb21pc2VcclxuICAqKi9cclxuICBzYXZlQ2hhbmdlcyhlbnRpdGllcz86IEVudGl0eVtdIHwgbnVsbCwgc2F2ZU9wdGlvbnM/OiBTYXZlT3B0aW9ucywgY2FsbGJhY2s/OiBGdW5jdGlvbiwgZXJyb3JDYWxsYmFjaz86IEZ1bmN0aW9uKSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdGllcywgXCJlbnRpdGllc1wiKS5pc09wdGlvbmFsKCkuaXNBcnJheSgpLmlzRW50aXR5KCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKHNhdmVPcHRpb25zLCBcInNhdmVPcHRpb25zXCIpLmlzSW5zdGFuY2VPZihTYXZlT3B0aW9ucykuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShjYWxsYmFjaywgXCJjYWxsYmFja1wiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShlcnJvckNhbGxiYWNrLCBcImVycm9yQ2FsbGJhY2tcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG5cclxuICAgIHNhdmVPcHRpb25zID0gc2F2ZU9wdGlvbnMgfHwgdGhpcy5zYXZlT3B0aW9ucyB8fCBTYXZlT3B0aW9ucy5kZWZhdWx0SW5zdGFuY2U7XHJcblxyXG4gICAgbGV0IGVudGl0aWVzVG9TYXZlID0gZ2V0RW50aXRpZXNUb1NhdmUodGhpcywgZW50aXRpZXMgPyBlbnRpdGllcyA6IHVuZGVmaW5lZCk7XHJcblxyXG4gICAgaWYgKGVudGl0aWVzVG9TYXZlLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICBsZXQgcmVzdWx0ID0geyBlbnRpdGllczogW10sIGtleU1hcHBpbmdzOiBbXSB9IGFzIFNhdmVSZXN1bHQ7XHJcbiAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2socmVzdWx0KTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghc2F2ZU9wdGlvbnMuYWxsb3dDb25jdXJyZW50U2F2ZXMpIHtcclxuICAgICAgbGV0IGFueVBlbmRpbmdTYXZlcyA9IGVudGl0aWVzVG9TYXZlLnNvbWUoZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgICAgIHJldHVybiBlbnRpdHkuZW50aXR5QXNwZWN0LmlzQmVpbmdTYXZlZDtcclxuICAgICAgfSk7XHJcbiAgICAgIGlmIChhbnlQZW5kaW5nU2F2ZXMpIHtcclxuICAgICAgICBsZXQgZXJyID0gbmV3IEVycm9yKFwiQ29uY3VycmVudCBzYXZlcyBub3QgYWxsb3dlZCAtIFNhdmVPcHRpb25zLmFsbG93Q29uY3VycmVudFNhdmVzIGlzIGZhbHNlXCIpO1xyXG4gICAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGVycik7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjbGVhclNlcnZlckVycm9ycyhlbnRpdGllc1RvU2F2ZSk7XHJcblxyXG4gICAgbGV0IHZhbEVycm9yID0gdGhpcy5zYXZlQ2hhbmdlc1ZhbGlkYXRlT25DbGllbnQoZW50aXRpZXNUb1NhdmUpO1xyXG4gICAgaWYgKHZhbEVycm9yKSB7XHJcbiAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKHZhbEVycm9yKTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHZhbEVycm9yKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgZGF0YVNlcnZpY2UgPSBEYXRhU2VydmljZS5yZXNvbHZlKFtzYXZlT3B0aW9ucy5kYXRhU2VydmljZSwgdGhpcy5kYXRhU2VydmljZV0pO1xyXG4gICAgbGV0IHNhdmVDb250ZXh0OiBTYXZlQ29udGV4dCA9IHtcclxuICAgICAgZW50aXR5TWFuYWdlcjogdGhpcyxcclxuICAgICAgZGF0YVNlcnZpY2U6IGRhdGFTZXJ2aWNlLFxyXG4gICAgICBwcm9jZXNzU2F2ZWRFbnRpdGllczogcHJvY2Vzc1NhdmVkRW50aXRpZXMsXHJcbiAgICAgIHJlc291cmNlTmFtZTogc2F2ZU9wdGlvbnMucmVzb3VyY2VOYW1lIHx8IHRoaXMuc2F2ZU9wdGlvbnMucmVzb3VyY2VOYW1lIHx8IFwiU2F2ZUNoYW5nZXNcIlxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBUT0RPOiBuZWVkIHRvIGNoZWNrIHRoYXQgaWYgd2UgYXJlIGRvaW5nIGEgcGFydGlhbCBzYXZlIHRoYXQgYWxsIGVudGl0aWVzIHdob3NlIHRlbXAga2V5c1xyXG4gICAgLy8gYXJlIHJlZmVyZW5jZWQgYXJlIGFsc28gaW4gdGhlIHBhcnRpYWwgc2F2ZSBncm91cFxyXG5cclxuICAgIGxldCBzYXZlQnVuZGxlID0geyBlbnRpdGllczogZW50aXRpZXNUb1NhdmUsIHNhdmVPcHRpb25zOiBzYXZlT3B0aW9ucyB9O1xyXG5cclxuXHJcbiAgICB0cnkgeyAvLyBHdWFyZCBhZ2FpbnN0IGV4Y2VwdGlvbiB0aHJvd24gaW4gZGF0YXNlcnZpY2UgYWRhcHRlciBiZWZvcmUgaXQgZ29lcyBhc3luY1xyXG4gICAgICB1cGRhdGVDb25jdXJyZW5jeVByb3BlcnRpZXMoZW50aXRpZXNUb1NhdmUpO1xyXG4gICAgICByZXR1cm4gZGF0YVNlcnZpY2UuYWRhcHRlckluc3RhbmNlIS5zYXZlQ2hhbmdlcyhzYXZlQ29udGV4dCwgc2F2ZUJ1bmRsZSlcclxuICAgICAgICAudGhlbihzYXZlU3VjY2VzcykudGhlbigocikgPT4gciwgc2F2ZUZhaWwpO1xyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIC8vIHVuZG8gdGhlIG1hcmtpbmcgYnkgdXBkYXRlQ29uY3VycmVuY3lQcm9wZXJ0aWVzXHJcbiAgICAgIG1hcmtJc0JlaW5nU2F2ZWQoZW50aXRpZXNUb1NhdmUsIGZhbHNlKTtcclxuICAgICAgaWYgKGVycm9yQ2FsbGJhY2spIGVycm9yQ2FsbGJhY2soZXJyKTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycik7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gc2F2ZVN1Y2Nlc3Moc2F2ZVJlc3VsdDogU2F2ZVJlc3VsdCkge1xyXG4gICAgICBsZXQgZW0gPSBzYXZlQ29udGV4dC5lbnRpdHlNYW5hZ2VyO1xyXG4gICAgICBtYXJrSXNCZWluZ1NhdmVkKGVudGl0aWVzVG9TYXZlLCBmYWxzZSk7XHJcbiAgICAgIGxldCBzYXZlZEVudGl0aWVzID0gc2F2ZUNvbnRleHQucHJvY2Vzc1NhdmVkRW50aXRpZXMoc2F2ZVJlc3VsdCk7XHJcbiAgICAgIHNhdmVSZXN1bHQuZW50aXRpZXMgPSBzYXZlZEVudGl0aWVzO1xyXG5cclxuICAgICAgLy8gdXBkYXRlIF9oYXNDaGFuZ2VzIGFmdGVyIHNhdmUuXHJcbiAgICAgIGVtLl9zZXRIYXNDaGFuZ2VzKCk7XHJcblxyXG4gICAgICAvLyBjYW4ndCBkbyB0aGlzIGFueW1vcmUgYmVjYXVzZSBvdGhlciBjaGFuZ2VzIG1pZ2h0IGhhdmUgYmVlbiBtYWRlIHdoaWxlIHNhdmVkIGVudGl0aWVzIGluIGZsaWdodC5cclxuICAgICAgLy8gICAgICBsZXQgaGFzQ2hhbmdlcyA9IChpc0Z1bGxTYXZlICYmIGhhdmVTYW1lQ29udGVudHMoZW50aXRpZXNUb1NhdmUsIHNhdmVkRW50aXRpZXMpKSA/IGZhbHNlIDogbnVsbDtcclxuICAgICAgLy8gICAgICBlbS5fc2V0SGFzQ2hhbmdlcyhoYXNDaGFuZ2VzKTtcclxuXHJcbiAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soc2F2ZVJlc3VsdCk7XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc2F2ZVJlc3VsdCk7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1NhdmVkRW50aXRpZXMoc2F2ZVJlc3VsdDogU2F2ZVJlc3VsdCkge1xyXG4gICAgICBsZXQgc2F2ZWRFbnRpdGllcyA9IHNhdmVSZXN1bHQuZW50aXRpZXM7XHJcbiAgICAgIGxldCBkZWxldGVkS2V5cyA9IHNhdmVSZXN1bHQuZGVsZXRlZEtleXMgfHwgW107XHJcbiAgICAgIGlmIChzYXZlZEVudGl0aWVzLmxlbmd0aCA9PT0gMCAmJiBkZWxldGVkS2V5cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICByZXR1cm4gW107XHJcbiAgICAgIH1cclxuICAgICAgbGV0IGtleU1hcHBpbmdzID0gc2F2ZVJlc3VsdC5rZXlNYXBwaW5ncztcclxuICAgICAgbGV0IGVtID0gc2F2ZUNvbnRleHQuZW50aXR5TWFuYWdlcjtcclxuXHJcbiAgICAgIC8vIG11c3Qgb2NjdXIgb3V0c2lkZSBvZiBpc0xvYWRpbmcgYmxvY2tcclxuICAgICAgZml4dXBLZXlzKGVtLCBrZXlNYXBwaW5ncyk7XHJcblxyXG4gICAgICBjb3JlLnVzaW5nKGVtLCBcImlzTG9hZGluZ1wiLCB0cnVlLCAoKSA9PiB7XHJcblxyXG4gICAgICAgIGxldCBtYXBwaW5nQ29udGV4dCA9IG5ldyBNYXBwaW5nQ29udGV4dCh7XHJcbiAgICAgICAgICBxdWVyeTogdW5kZWZpbmVkLCAvLyB0ZWxscyB2aXNpdEFuZE1lcmdlIHRoaXMgaXMgYSBzYXZlIGluc3RlYWQgb2YgYSBxdWVyeVxyXG4gICAgICAgICAgZW50aXR5TWFuYWdlcjogZW0sXHJcbiAgICAgICAgICBtZXJnZU9wdGlvbnM6IHsgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneS5PdmVyd3JpdGVDaGFuZ2VzIH0sXHJcbiAgICAgICAgICBkYXRhU2VydmljZTogZGF0YVNlcnZpY2VcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgLy8gVGhlIHZpc2l0QW5kTWVyZ2Ugb3BlcmF0aW9uIGhhcyBiZWVuIG9wdGltaXplZCBzbyB0aGF0IHdlIGRvIG5vdCBhY3R1YWxseSBwZXJmb3JtIGEgbWVyZ2UgaWYgdGhlXHJcbiAgICAgICAgLy8gdGhlIHNhdmUgb3BlcmF0aW9uIGRpZCBub3QgYWN0dWFsbHkgcmV0dXJuIHRoZSBlbnRpdHkgLSBpLmUuIGR1cmluZyBPRGF0YSBhbmQgTW9uZ28gdXBkYXRlcyBhbmQgZGVsZXRlcy5cclxuICAgICAgICBzYXZlZEVudGl0aWVzID0gbWFwcGluZ0NvbnRleHQudmlzaXRBbmRNZXJnZShzYXZlZEVudGl0aWVzLCB7IG5vZGVUeXBlOiBcInJvb3RcIiB9KTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyBkZXRhY2ggYW55IGVudGl0aWVzIGZvdW5kIGluIHRoZSBlbSB0aGF0IGFwcGVhciBpbiB0aGUgZGVsZXRlZEtleXMgbGlzdC4gXHJcbiAgICAgIGRlbGV0ZWRLZXlzLmZvckVhY2goa2V5ID0+IHtcclxuICAgICAgICBsZXQgZW50aXR5VHlwZSA9IGVtLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGtleS5lbnRpdHlUeXBlTmFtZSkgYXMgRW50aXR5VHlwZTtcclxuICAgICAgICBsZXQgZWtleSA9IG5ldyBFbnRpdHlLZXkoZW50aXR5VHlwZSwga2V5LmtleVZhbHVlcyk7XHJcbiAgICAgICAgbGV0IGVudGl0eSA9IGVtLmdldEVudGl0eUJ5S2V5KGVrZXkpO1xyXG4gICAgICAgIGlmIChlbnRpdHkpIHtcclxuICAgICAgICAgIGVudGl0eS5lbnRpdHlBc3BlY3Quc2V0RGV0YWNoZWQoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgcmV0dXJuIHNhdmVkRW50aXRpZXM7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gc2F2ZUZhaWwoc2VydmVyRXJyb3I6IFNhdmVFcnJvckZyb21TZXJ2ZXIpIHtcclxuICAgICAgbWFya0lzQmVpbmdTYXZlZChlbnRpdGllc1RvU2F2ZSwgZmFsc2UpO1xyXG4gICAgICBsZXQgY2xpZW50RXJyb3IgPSBwcm9jZXNzU2VydmVyRXJyb3JzKHNhdmVDb250ZXh0LCBzZXJ2ZXJFcnJvcik7XHJcbiAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGNsaWVudEVycm9yKTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGNsaWVudEVycm9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJ1biB0aGUgXCJzYXZlQ2hhbmdlc1wiIHByZS1zYXZlIGNsaWVudCB2YWxpZGF0aW9uIGxvZ2ljLlxyXG4gIFxyXG4gIFRoaXMgaXMgTk9UIGEgZ2VuZXJhbCBwdXJwb3NlIHZhbGlkYXRpb24gbWV0aG9kLlxyXG4gIEl0IGlzIGludGVuZGVkIGZvciB1dGlsaXRpZXMgdGhhdCBtdXN0IGtub3cgaWYgc2F2ZUNoYW5nZXNcclxuICB3b3VsZCByZWplY3QgdGhlIHNhdmUgZHVlIHRvIGNsaWVudCB2YWxpZGF0aW9uIGVycm9ycy5cclxuICBcclxuICBJdCBvbmx5IHZhbGlkYXRlcyBlbnRpdGllcyBpZiB0aGUgRW50aXR5TWFuYWdlcidzXHJcbiAgW1tWYWxpZGF0aW9uT3B0aW9uc11dLnZhbGlkYXRlT25TYXZlIGlzIHRydWUuXHJcbiAgXHJcbiAgQHBhcmFtIGVudGl0aWVzVG9TYXZlIHtBcnJheSBvZiBFbnRpdHl9IFRoZSBsaXN0IG9mIGVudGl0aWVzIHRvIHNhdmUgKHRvIHZhbGlkYXRlKS5cclxuICBAcmV0dXJuIHtFcnJvcn0gVmFsaWRhdGlvbiBlcnJvciBvciBudWxsIGlmIG5vIGVycm9yXHJcbiAgKiovXHJcbiAgc2F2ZUNoYW5nZXNWYWxpZGF0ZU9uQ2xpZW50KGVudGl0aWVzVG9TYXZlOiBFbnRpdHlbXSkge1xyXG5cclxuICAgIGlmICh0aGlzLnZhbGlkYXRpb25PcHRpb25zLnZhbGlkYXRlT25TYXZlKSB7XHJcbiAgICAgIGxldCBmYWlsZWRFbnRpdGllcyA9IGVudGl0aWVzVG9TYXZlLmZpbHRlcihmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICAgICAgbGV0IGFzcGVjdCA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICAgICAgbGV0IGlzVmFsaWQgPSBhc3BlY3QuZW50aXR5U3RhdGUuaXNEZWxldGVkKCkgfHwgYXNwZWN0LnZhbGlkYXRlRW50aXR5KCk7XHJcbiAgICAgICAgcmV0dXJuICFpc1ZhbGlkO1xyXG4gICAgICB9KTtcclxuICAgICAgaWYgKGZhaWxlZEVudGl0aWVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBsZXQgdmFsRXJyb3IgPSBuZXcgRXJyb3IoXCJDbGllbnQgc2lkZSB2YWxpZGF0aW9uIGVycm9ycyBlbmNvdW50ZXJlZCAtIHNlZSB0aGUgZW50aXR5RXJyb3JzIGNvbGxlY3Rpb24gb24gdGhpcyBvYmplY3QgZm9yIG1vcmUgZGV0YWlsXCIpO1xyXG4gICAgICAgICh2YWxFcnJvciBhcyBhbnkpLmVudGl0eUVycm9ycyA9IGNyZWF0ZUVudGl0eUVycm9ycyhmYWlsZWRFbnRpdGllcyk7XHJcbiAgICAgICAgcmV0dXJuIHZhbEVycm9yOyAvLyBUT0RPOiB0eXBlIHRoaXMuXHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2ZpbmRFbnRpdHlHcm91cChlbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fZW50aXR5R3JvdXBNYXBbZW50aXR5VHlwZS5uYW1lXTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGVtcGxveWVlVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJFbXBsb3llZVwiKTtcclxuICA+ICAgICAgbGV0IGVtcGxveWVlS2V5ID0gbmV3IEVudGl0eUtleShlbXBsb3llZVR5cGUsIDEpO1xyXG4gID4gICAgICBsZXQgZW1wbG95ZWUgPSBlbTEuZ2V0RW50aXR5QnlLZXkoZW1wbG95ZWVLZXkpO1xyXG4gID4gICAgICAvLyBlbXBsb3llZSB3aWxsIGVpdGhlciBiZSBhbiBlbnRpdHkgb3IgbnVsbC5cclxuICAqKi9cclxuICBnZXRFbnRpdHlCeUtleShlbnRpdHlLZXk6IEVudGl0eUtleSk6IEVudGl0eSB8IG51bGw7XHJcblxyXG4gIC8qKiAgXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgZW1wbG95ZWUgPSBlbTEuZ2V0RW50aXR5QnlLZXkoXCJFbXBsb3llZVwiLCAxKTtcclxuICA+ICAgICAgLy8gZW1wbG95ZWUgd2lsbCBlaXRoZXIgYmUgYW4gZW50aXR5IG9yIG51bGwuXHJcbiAgKiovXHJcbiAgZ2V0RW50aXR5QnlLZXkodHlwZU5hbWU6IHN0cmluZywga2V5VmFsdWVzOiBhbnkgfCBhbnlbXSk6IEVudGl0eSB8IG51bGw7XHJcblxyXG4gIC8qKiAgXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgZW1wbG95ZWVUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkVtcGxveWVlXCIpO1xyXG4gID4gICAgICBsZXQgZW1wbG95ZWUgPSBlbTEuZ2V0RW50aXR5QnlLZXkoZW1wbG95ZWVUeXBlLCAxKTtcclxuICA+ICAgICAgLy8gZW1wbG95ZWUgd2lsbCBlaXRoZXIgYmUgYW4gZW50aXR5IG9yIG51bGwuXHJcbiAgKiovXHJcbiAgZ2V0RW50aXR5QnlLZXkodHlwZTogRW50aXR5VHlwZSwga2V5VmFsdWVzOiBhbnkgfCBhbnlbXSk6IEVudGl0eSB8IG51bGw7XHJcblxyXG4gIC8qKiAgXHJcbiAgQXR0ZW1wdHMgdG8gbG9jYXRlIGFuIGVudGl0eSB3aXRoaW4gdGhpcyBFbnRpdHlNYW5hZ2VyIGJ5IGl0cyBbRW50aXR5S2V5XS5cclxuICBAcGFyYW0gZW50aXR5S2V5IC0gVGhlIFtbRW50aXR5S2V5XV0gb2YgdGhlIEVudGl0eSB0byBiZSBsb2NhdGVkLlxyXG4gIEBwYXJhbSB0eXBlIC0gVGhlIFtbRW50aXR5VHlwZV1dIGZvciB0aGlzIGtleS5cclxuICBAcGFyYW0gdHlwZU5hbWUgLSBUaGUgRW50aXR5VHlwZSBuYW1lIGZvciB0aGlzIGtleS5cclxuICBAcGFyYW0ga2V5VmFsdWVzIC0gVGhlIHZhbHVlcyBmb3IgdGhpcyBrZXkgLSB3aWxsIHVzdWFsbHkganVzdCBiZSBhIHNpbmdsZSB2YWx1ZTsgYW4gYXJyYXkgaXMgb25seSBuZWVkZWQgZm9yIG11bHRpcGFydCBrZXlzLiAgXHJcbiAgQHJldHVybiBBbiBFbnRpdHkgb3IgbnVsbDtcclxuICAqKi9cclxuICBnZXRFbnRpdHlCeUtleSguLi5hcmdzOiBhbnlbXSkge1xyXG4gICAgbGV0IGVudGl0eUtleSA9IGNyZWF0ZUVudGl0eUtleSh0aGlzLCBhcmdzKS5lbnRpdHlLZXk7XHJcbiAgICBsZXQgZW50aXR5VHlwZXMgPSBlbnRpdHlLZXkuX3N1YnR5cGVzIHx8IFtlbnRpdHlLZXkuZW50aXR5VHlwZV07XHJcbiAgICBsZXQgZTogRW50aXR5IHwgdW5kZWZpbmVkO1xyXG4gICAgLy8gaGFjayB1c2Ugb2Ygc29tZSB0byBzaW11bGF0ZSBtYXBGaXJzdCBsb2dpYy5cclxuICAgIGVudGl0eVR5cGVzLnNvbWUoKGV0KSA9PiB7XHJcbiAgICAgIGxldCBncm91cCA9IHRoaXMuX2ZpbmRFbnRpdHlHcm91cChldCk7XHJcbiAgICAgIC8vIGdyb3VwIHZlcnNpb24gb2YgZmluZEVudGl0eUJ5S2V5IGRvZXNuJ3QgY2FyZSBhYm91dCBlbnRpdHlUeXBlXHJcbiAgICAgIGUgPSBncm91cCAmJiBncm91cC5maW5kRW50aXR5QnlLZXkoZW50aXR5S2V5KTtcclxuICAgICAgcmV0dXJuIGUgIT0gbnVsbDtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGUgfHwgbnVsbDtcclxuICB9XHJcblxyXG4gIGZldGNoRW50aXR5QnlLZXkodHlwZU5hbWU6IHN0cmluZywga2V5VmFsdWVzOiBhbnkgfCBhbnlbXSwgY2hlY2tMb2NhbENhY2hlRmlyc3Q/OiBib29sZWFuKTogUHJvbWlzZTxJRW50aXR5QnlLZXlSZXN1bHQ+O1xyXG4gIGZldGNoRW50aXR5QnlLZXkoZW50aXR5VHlwZTogRW50aXR5VHlwZSwga2V5VmFsdWVzOiBhbnkgfCBhbnlbXSwgY2hlY2tMb2NhbENhY2hlRmlyc3Q/OiBib29sZWFuKTogUHJvbWlzZTxJRW50aXR5QnlLZXlSZXN1bHQ+O1xyXG4gIGZldGNoRW50aXR5QnlLZXkoZW50aXR5S2V5OiBFbnRpdHlLZXksIGNoZWNrTG9jYWxDYWNoZUZpcnN0PzogYm9vbGVhbik6IFByb21pc2U8SUVudGl0eUJ5S2V5UmVzdWx0PjtcclxuICAvKipcclxuICBBdHRlbXB0cyB0byBmZXRjaCBhbiBlbnRpdHkgZnJvbSB0aGUgc2VydmVyIGJ5IGl0cyBbW0VudGl0eUtleV1dIHdpdGhcclxuICBhbiBvcHRpb24gdG8gY2hlY2sgdGhlIGxvY2FsIGNhY2hlIGZpcnN0LiBOb3RlIHRoZSB0aGlzIEVudGl0eU1hbmFnZXIncyBxdWVyeU9wdGlvbnMubWVyZ2VTdHJhdGVneVxyXG4gIHdpbGwgYmUgdXNlZCB0byBtZXJnZSBhbnkgc2VydmVyIHNpZGUgZW50aXR5IHJldHVybmVkIGJ5IHRoaXMgbWV0aG9kLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBlbXBsb3llZVR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiRW1wbG95ZWVcIik7XHJcbiAgPiAgICAgbGV0IGVtcGxveWVlS2V5ID0gbmV3IEVudGl0eUtleShlbXBsb3llZVR5cGUsIDEpO1xyXG4gID4gICAgIGVtMS5mZXRjaEVudGl0eUJ5S2V5KGVtcGxveWVlS2V5KS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkge1xyXG4gID4gICAgICAgbGV0IGVtcGxveWVlID0gcmVzdWx0LmVudGl0eTtcclxuICA+ICAgICAgIGxldCBlbnRpdHlLZXkgPSByZXN1bHQuZW50aXR5S2V5O1xyXG4gID4gICAgICAgbGV0IGZyb21DYWNoZSA9IHJlc3VsdC5mcm9tQ2FjaGU7XHJcbiAgPiAgICAgfSk7XHJcbiAgQHBhcmFtIHR5cGVOYW1lICAtIFRoZSBFbnRpdHlUeXBlIG5hbWUgZm9yIHRoaXMga2V5LlxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlICAtIFRoZSBFbnRpdHlUeXBlIGZvciB0aGlzIGtleS5cclxuICBAcGFyYW0ga2V5VmFsdWVzIC0gVGhlIHZhbHVlcyBmb3IgdGhpcyBrZXkgLSB3aWxsIHVzdWFsbHkganVzdCBiZSBhIHNpbmdsZSB2YWx1ZTsgYW4gYXJyYXkgaXMgb25seSBuZWVkZWQgZm9yIG11bHRpcGFydCBrZXlzLlxyXG4gIEBwYXJhbSBlbnRpdHlLZXkgLSBUaGUgW1tFbnRpdHlLZXldXSBvZiB0aGUgRW50aXR5IHRvIGJlIGxvY2F0ZWQuXHJcbiAgQHBhcmFtIGNoZWNrTG9jYWxDYWNoZUZpcnN0IC0gKGRlZmF1bHQgPSBmYWxzZSkgLSBXaGV0aGVyIHRvIGNoZWNrIHRoaXMgRW50aXR5TWFuYWdlciBmaXJzdCBiZWZvcmUgZ29pbmcgdG8gdGhlIHNlcnZlci4gQnkgZGVmYXVsdCwgdGhlIHF1ZXJ5IHdpbGwgTk9UIGRvIHRoaXMuXHJcbiAgQHJldHVybiB7UHJvbWlzZX1cclxuICAgIC0gUHJvcGVydGllcyBvbiB0aGUgcHJvbWlzZSBzdWNjZXNzIHJlc3VsdFxyXG4gICAgICAtIGVudGl0eSB7T2JqZWN0fSBUaGUgZW50aXR5IHJldHVybmVkIG9yIG51bGxcclxuICAgICAgLSBlbnRpdHlLZXkge0VudGl0eUtleX0gVGhlIGVudGl0eUtleSBvZiB0aGUgZW50aXR5IHRvIGZldGNoLlxyXG4gICAgICAtIGZyb21DYWNoZSB7Qm9vbGVhbn0gV2hldGhlciB0aGlzIGVudGl0eSB3YXMgZmV0Y2hlZCBmcm9tIHRoZSBzZXJ2ZXIgb3Igd2FzIGZvdW5kIGluIHRoZSBsb2NhbCBjYWNoZS5cclxuICAqKi9cclxuICBmZXRjaEVudGl0eUJ5S2V5KC4uLmFyZ3M6IGFueVtdKSB7XHJcbiAgICBsZXQgZGF0YVNlcnZpY2UgPSBEYXRhU2VydmljZS5yZXNvbHZlKFt0aGlzLmRhdGFTZXJ2aWNlXSk7XHJcbiAgICBpZiAoKCFkYXRhU2VydmljZS5oYXNTZXJ2ZXJNZXRhZGF0YSkgfHwgdGhpcy5tZXRhZGF0YVN0b3JlLmhhc01ldGFkYXRhRm9yKGRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lKSkge1xyXG4gICAgICByZXR1cm4gZmV0Y2hFbnRpdHlCeUtleUNvcmUodGhpcywgYXJncyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gdGhpcy5mZXRjaE1ldGFkYXRhKGRhdGFTZXJ2aWNlKS50aGVuKCgpID0+IHtcclxuICAgICAgICByZXR1cm4gZmV0Y2hFbnRpdHlCeUtleUNvcmUodGhpcywgYXJncyk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgW0RlcHJlY2F0ZWRdIC0gQXR0ZW1wdHMgdG8gbG9jYXRlIGFuIGVudGl0eSB3aXRoaW4gdGhpcyBFbnRpdHlNYW5hZ2VyIGJ5IGl0cyAgW1tFbnRpdHlLZXldXS5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgZW1wbG95ZWVUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkVtcGxveWVlXCIpO1xyXG4gID4gICAgIGxldCBlbXBsb3llZUtleSA9IG5ldyBFbnRpdHlLZXkoZW1wbG95ZWVUeXBlLCAxKTtcclxuICA+ICAgICBsZXQgZW1wbG95ZWUgPSBlbTEuZmluZEVudGl0eUJ5S2V5KGVtcGxveWVlS2V5KTtcclxuICA+ICAgICAvLyBlbXBsb3llZSB3aWxsIGVpdGhlciBiZSBhbiBlbnRpdHkgb3IgbnVsbC5cclxuICBAZGVwcmVjYXRlZCAgICBVc2UgZ2V0RW50aXR5QnlLZXkgaW5zdGVhZFxyXG4gIEBwYXJhbSBlbnRpdHlLZXkgLSBUaGUgIFtbRW50aXR5S2V5XV0gb2YgdGhlIEVudGl0eSB0byBiZSBsb2NhdGVkLlxyXG4gIEByZXR1cm4gQW4gRW50aXR5IG9yIG51bGw7XHJcbiAgKiovXHJcbiAgZmluZEVudGl0eUJ5S2V5KGVudGl0eUtleTogRW50aXR5S2V5KSB7XHJcbiAgICByZXR1cm4gdGhpcy5nZXRFbnRpdHlCeUtleShlbnRpdHlLZXkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgR2VuZXJhdGVzIGEgdGVtcG9yYXJ5IGtleSBmb3IgdGhlIHNwZWNpZmllZCBlbnRpdHkuICBUaGlzIGlzIHVzZWQgdG8gaW5zdXJlIHRoYXQgbmV3bHlcclxuICBjcmVhdGVkIGVudGl0aWVzIGhhdmUgdW5pcXVlIGtleXMgYW5kIHRvIHJlZ2lzdGVyIHRoYXQgdGhlc2Uga2V5cyBhcmUgdGVtcG9yYXJ5IGFuZFxyXG4gIG5lZWQgdG8gYmUgYXV0b21hdGljYWxseSByZXBsYWNlZCB3aXRoICdyZWFsJyBrZXkgdmFsdWVzIG9uY2UgdGhlc2UgZW50aXRpZXMgYXJlIHNhdmVkLlxyXG4gIFxyXG4gIFRoZSBbW0VudGl0eU1hbmFnZXIua2V5R2VuZXJhdG9yQ3Rvcl1dIHByb3BlcnR5IGlzIHVzZWQgaW50ZXJuYWxseSBieSB0aGlzIG1ldGhvZCB0byBhY3R1YWxseSBnZW5lcmF0ZVxyXG4gIHRoZSBrZXlzIC0gU2VlIHRoZSAgS2V5R2VuZXJhdG9yIGludGVyZmFjZSBpbnRlcmZhY2UgZGVzY3JpcHRpb24gdG8gc2VlXHJcbiAgaG93IGEgY3VzdG9tIGtleSBnZW5lcmF0b3IgY2FuIGJlIHBsdWdnZWQgaW4uXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBjdXN0b21lciA9IGN1c3RUeXBlLmNyZWF0ZUVudGl0eSgpO1xyXG4gID4gICAgICBsZXQgY3VzdG9tZXJJZCA9IGVtLmdlbmVyYXRlVGVtcEtleVZhbHVlKGN1c3RvbWVyKTtcclxuICA+ICAgICAgLy8gVGhlICdjdXN0b21lcicgZW50aXR5ICdDdXN0b21lcklEJyBwcm9wZXJ0eSBpcyBub3cgc2V0IHRvIGEgbmV3bHkgZ2VuZXJhdGVkIHVuaXF1ZSBpZCB2YWx1ZVxyXG4gID4gICAgICAvLyBUaGlzIHByb3BlcnR5IHdpbGwgY2hhbmdlIGFnYWluIGFmdGVyIGEgc3VjY2Vzc2Z1bCBzYXZlIG9mIHRoZSAnY3VzdG9tZXInIGVudGl0eS5cclxuICA+ICBcclxuICA+ICAgICAgZW0xLnNhdmVDaGFuZ2VzKCkudGhlbiggZnVuY3Rpb24oIGRhdGEpIHtcclxuICA+ICAgICAgICAgIGxldCBzYW1lQ3VzdDEgPSBkYXRhLnJlc3VsdHNbMF07XHJcbiAgPiAgICAgICAgICAvLyBjdXN0MSA9PT0gc2FtZUN1c3QxO1xyXG4gID4gICAgICAgICAgLy8gYnV0IGN1c3QxLmdldFByb3BlcnR5KFwiQ3VzdG9tZXJJZFwiKSAhPSBjdXN0b21lcklkXHJcbiAgPiAgICAgICAgICAvLyBiZWNhdXNlIHRoZSBzZXJ2ZXIgd2lsbCBoYXZlIGdlbmVyYXRlZCBhIG5ldyBpZFxyXG4gID4gICAgICAgICAgLy8gYW5kIHRoZSBjbGllbnQgd2lsbCBoYXZlIGJlZW4gdXBkYXRlZCB3aXRoIHRoaXNcclxuICA+ICAgICAgICAgIC8vIG5ldyBpZC5cclxuICA+ICAgICAgfSlcclxuICBAcGFyYW0gZW50aXR5IC0gVGhlIEVudGl0eSB0byBnZW5lcmF0ZSBhIGtleSBmb3IuXHJcbiAgQHJldHVybiBUaGUgbmV3IGtleSB2YWx1ZVxyXG4gICoqL1xyXG4gIGdlbmVyYXRlVGVtcEtleVZhbHVlKGVudGl0eTogRW50aXR5KSB7XHJcbiAgICAvLyBUT0RPIC0gY2hlY2sgaWYgdGhpcyBlbnRpdHkgaXMgYXR0YWNoZWQgdG8gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5LCBcImVudGl0eVwiKS5pc0VudGl0eSgpLmNoZWNrKCk7XHJcbiAgICBsZXQgZW50aXR5VHlwZSA9IGVudGl0eS5lbnRpdHlUeXBlO1xyXG4gICAgbGV0IG5leHRLZXlWYWx1ZSA9IHRoaXMua2V5R2VuZXJhdG9yLmdlbmVyYXRlVGVtcEtleVZhbHVlKGVudGl0eVR5cGUpO1xyXG4gICAgbGV0IGtleVByb3AgPSBlbnRpdHlUeXBlLmtleVByb3BlcnRpZXNbMF07XHJcbiAgICBlbnRpdHkuc2V0UHJvcGVydHkoa2V5UHJvcC5uYW1lLCBuZXh0S2V5VmFsdWUpO1xyXG4gICAgZW50aXR5LmVudGl0eUFzcGVjdC5oYXNUZW1wS2V5ID0gdHJ1ZTtcclxuICAgIHJldHVybiBuZXh0S2V5VmFsdWU7XHJcbiAgfVxyXG5cclxuICBoYXNDaGFuZ2VzKCk6IGJvb2xlYW47XHJcbiAgaGFzQ2hhbmdlcyhlbnRpdHlUeXBlTmFtZXM6IHN0cmluZyB8IHN0cmluZ1tdKTogYm9vbGVhbjtcclxuICBoYXNDaGFuZ2VzKGVudGl0eVR5cGVzOiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdKTogYm9vbGVhbjtcclxuICAvKipcclxuICBSZXR1cm5zIHdoZXRoZXIgdGhlcmUgYXJlIGFueSBjaGFuZ2VkIGVudGl0aWVzIG9mIHRoZSBzcGVjaWZpZWQgW1tFbnRpdHlUeXBlXV1zLiBBICdjaGFuZ2VkJyBFbnRpdHkgaGFzXHJcbiAgaGFzIGFuIFtbRW50aXR5U3RhdGVdXSBvZiBlaXRoZXIgQWRkZWQsIE1vZGlmaWVkIG9yIERlbGV0ZWQuXHJcblxyXG4gIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGRldGVybWluZSBpZiBhbiBFbnRpdHlNYW5hZ2VyIGhhcyBhbnkgY2hhbmdlc1xyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgaWYgKCBlbTEuaGFzQ2hhbmdlcygpIHtcclxuICA+ICAgICAgICAgIC8vIGRvIHNvbWV0aGluZyBpbnRlcmVzdGluZ1xyXG4gID4gICAgICB9XHJcblxyXG4gIG9yIGlmIGl0IGhhcyBhbnkgY2hhbmdlcyBvbiB0byBhIHNwZWNpZmljIFtbRW50aXR5VHlwZV1dLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBpZiAoIGVtMS5oYXNDaGFuZ2VzKGN1c3RUeXBlKSB7XHJcbiAgPiAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgaW50ZXJlc3RpbmdcclxuICA+ICAgICAgfVxyXG5cclxuICBvciB0byBhIGNvbGxlY3Rpb24gb2YgW1tFbnRpdHlUeXBlXV1zXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBvcmRlclR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiT3JkZXJcIik7XHJcbiAgPiAgICAgIGlmICggZW0xLmhhc0NoYW5nZXMoIFtjdXN0VHlwZSwgb3JkZXJUeXBlXSkge1xyXG4gID4gICAgICAgICAgLy8gZG8gc29tZXRoaW5nIGludGVyZXN0aW5nXHJcbiAgPiAgICAgIH1cclxuICBAcGFyYW0gZW50aXR5VHlwZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gb3IgRW50aXR5VHlwZXMgZm9yIHdoaWNoICdjaGFuZ2VkJyBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlTmFtZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gbmFtZSBvciBuYW1lcyBmb3Igd2hpY2ggJ2NoYW5nZWQnIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgQHJldHVybiBXaGV0aGVyIHRoZXJlIGFyZSBhbnkgY2hhbmdlZCBlbnRpdGllcyB0aGF0IG1hdGNoIHRoZSB0eXBlcyBzcGVjaWZpZWQuLlxyXG4gICoqL1xyXG4gIGhhc0NoYW5nZXMoZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICAgIGlmICghdGhpcy5faGFzQ2hhbmdlcykgcmV0dXJuIGZhbHNlO1xyXG4gICAgaWYgKGVudGl0eVR5cGVzID09PSB1bmRlZmluZWQpIHJldHVybiB0aGlzLl9oYXNDaGFuZ2VzO1xyXG4gICAgcmV0dXJuIHRoaXMuX2hhc0NoYW5nZXNDb3JlKGVudGl0eVR5cGVzKTtcclxuICB9XHJcblxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICAvLyBiYWNrZG9vciB0byBcInJlYWxseVwiIGNoZWNrIGZvciBjaGFuZ2VzLlxyXG4gIF9oYXNDaGFuZ2VzQ29yZShlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCBzdHJpbmcgfCBzdHJpbmdbXSkge1xyXG4gICAgbGV0IGV0cyA9IGNoZWNrRW50aXR5VHlwZXModGhpcywgZW50aXR5VHlwZXMpO1xyXG4gICAgbGV0IGVudGl0eUdyb3VwcyA9IGdldEVudGl0eUdyb3Vwcyh0aGlzLCBldHMpO1xyXG4gICAgcmV0dXJuIGVudGl0eUdyb3Vwcy5zb21lKGZ1bmN0aW9uIChlZykge1xyXG4gICAgICByZXR1cm4gZWcgJiYgZWcuaGFzQ2hhbmdlcygpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBnZXRDaGFuZ2VzKCk6IEVudGl0eVtdO1xyXG4gIGdldENoYW5nZXMoZW50aXR5VHlwZU5hbWVzOiBzdHJpbmcgfCBzdHJpbmdbXSk6IEVudGl0eVtdO1xyXG4gIGdldENoYW5nZXMoZW50aXR5VHlwZXM6IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10pOiBFbnRpdHlbXTtcclxuICAvKipcclxuICBSZXR1cm5zIGEgYXJyYXkgb2YgYWxsIGNoYW5nZWQgZW50aXRpZXMgb2YgdGhlIHNwZWNpZmllZCBbW0VudGl0eVR5cGVdXXMuIEEgJ2NoYW5nZWQnIEVudGl0eSBoYXNcclxuICBoYXMgYW4gW1tFbnRpdHlTdGF0ZV1dIG9mIGVpdGhlciBBZGRlZCwgTW9kaWZpZWQgb3IgRGVsZXRlZC5cclxuICBcclxuICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBnZXQgYWxsIG9mIHRoZSBjaGFuZ2VkIGVudGl0aWVzIHdpdGhpbiBhbiBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY2hhbmdlZEVudGl0aWVzID0gZW0xLmdldENoYW5nZXMoKTtcclxuXHJcbiAgb3IgeW91IGNhbiBzcGVjaWZ5IHRoYXQgeW91IG9ubHkgd2FudCB0aGUgY2hhbmdlcyBvbiBhIHNwZWNpZmljIFtbRW50aXR5VHlwZV1dXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBjaGFuZ2VkQ3VzdG9tZXJzID0gZW0xLmdldENoYW5nZXMoY3VzdFR5cGUpO1xyXG5cclxuICBvciB0byBhIGNvbGxlY3Rpb24gb2YgW1tFbnRpdHlUeXBlXV1zXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBvcmRlclR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiT3JkZXJcIik7XHJcbiAgPiAgICAgIGxldCBjaGFuZ2VkQ3VzdG9tZXJzQW5kT3JkZXJzID0gZW0xLmdldENoYW5nZXMoW2N1c3RUeXBlLCBvcmRlclR5cGVdKTtcclxuICBAcGFyYW0gZW50aXR5VHlwZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gb3IgRW50aXR5VHlwZXMgZm9yIHdoaWNoICdjaGFuZ2VkJyBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlTmFtZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gbmFtZSBvciBuYW1lcyBmb3Igd2hpY2ggJ2NoYW5nZWQnIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgQHJldHVybiBBbiBhcnJheSBvZiBFbnRpdGllc1xyXG4gICoqL1xyXG4gIGdldENoYW5nZXMoZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICAgIGxldCBldHMgPSBjaGVja0VudGl0eVR5cGVzKHRoaXMsIGVudGl0eVR5cGVzKTtcclxuICAgIHJldHVybiBnZXRDaGFuZ2VzQ29yZSh0aGlzLCBldHMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmVqZWN0cyAocmV2ZXJzZXMgdGhlIGVmZmVjdHMpIGFsbCBvZiB0aGUgYWRkaXRpb25zLCBtb2RpZmljYXRpb25zIGFuZCBkZWxldGVzIGZyb20gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gIENhbGxzIFtbRW50aXR5QXNwZWN0LnJlamVjdENoYW5nZXNdXSBvbiBldmVyeSBjaGFuZ2VkIGVudGl0eSBpbiB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgZW50aXRpZXMgPSBlbTEucmVqZWN0Q2hhbmdlcygpO1xyXG4gIEByZXR1cm4gVGhlIGVudGl0aWVzIHdob3NlIGNoYW5nZXMgd2VyZSByZWplY3RlZC4gVGhlc2UgZW50aXRpZXMgd2lsbCBhbGwgaGF2ZSBFbnRpdHlTdGF0ZXMgb2ZcclxuICBlaXRoZXIgJ1VuY2hhbmdlZCcgb3IgJ0RldGFjaGVkJ1xyXG4gICoqL1xyXG4gIHJlamVjdENoYW5nZXMoKSB7XHJcbiAgICBpZiAoIXRoaXMuX2hhc0NoYW5nZXMpIHJldHVybiBbXTtcclxuICAgIGxldCBjaGFuZ2VzID0gZ2V0Q2hhbmdlc0NvcmUodGhpcyk7XHJcbiAgICAvLyBuZXh0IGxpbmUgc3RvcHMgaW5kaXZpZHVhbCByZWplY3QgY2hhbmdlcyBmcm9tIGVhY2ggY2FsbGluZyBfaGFzQ2hhbmdlc0NvcmVcclxuICAgIGxldCBhc3BlY3RzID0gY2hhbmdlcy5tYXAoZnVuY3Rpb24gKGUpIHtcclxuICAgICAgcmV0dXJuIGUuZW50aXR5QXNwZWN0Ll9jaGVja09wZXJhdGlvbihcInJlamVjdENoYW5nZXNcIik7XHJcbiAgICB9KTtcclxuICAgIHRoaXMuX2hhc0NoYW5nZXMgPSBmYWxzZTtcclxuICAgIGFzcGVjdHMuZm9yRWFjaChmdW5jdGlvbiAoYXNwZWN0KSB7XHJcbiAgICAgIGFzcGVjdC5yZWplY3RDaGFuZ2VzKCk7XHJcbiAgICB9KTtcclxuICAgIHRoaXMuaGFzQ2hhbmdlc0NoYW5nZWQucHVibGlzaCh7IGVudGl0eU1hbmFnZXI6IHRoaXMsIGhhc0NoYW5nZXM6IGZhbHNlIH0pO1xyXG4gICAgcmV0dXJuIGNoYW5nZXM7XHJcbiAgfVxyXG5cclxuICBnZXRFbnRpdGllcyhlbnRpdHlUeXBlTmFtZXM/OiBzdHJpbmcgfCBzdHJpbmdbXSwgZW50aXR5U3RhdGVzPzogRW50aXR5U3RhdGUgfCBFbnRpdHlTdGF0ZVtdKTogRW50aXR5W107XHJcbiAgZ2V0RW50aXRpZXMoZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdLCBlbnRpdHlTdGF0ZXM/OiBFbnRpdHlTdGF0ZSB8IEVudGl0eVN0YXRlW10pOiBFbnRpdHlbXTtcclxuICAvKipcclxuICBSZXR1cm5zIGEgYXJyYXkgb2YgYWxsIGVudGl0aWVzIG9mIHRoZSBzcGVjaWZpZWQgW1tFbnRpdHlUeXBlXV1zIHdpdGggdGhlIHNwZWNpZmllZCBbW0VudGl0eVN0YXRlXV1zLlxyXG5cclxuICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBnZXQgYWxsIG9mIHRoZSBlbnRpdGllcyB3aXRoaW4gYW4gRW50aXR5TWFuYWdlclxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGVudGl0aWVzID0gZW0xLmdldEVudGl0aWVzKCk7XHJcblxyXG4gIG9yIHlvdSBjYW4gc3BlY2lmeSB0aGF0IHlvdSBvbmx5IHdhbnQgdGhlIGNoYW5nZXMgb24gYSBzcGVjaWZpYyBbW0VudGl0eVR5cGVdXVxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgY3VzdG9tZXJzID0gZW0xLmdldEVudGl0aWVzKGN1c3RUeXBlKTtcclxuXHJcbiAgb3IgdG8gYSBjb2xsZWN0aW9uIG9mIFtbRW50aXR5VHlwZV1dc1xyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gID4gICAgICBsZXQgY3VzdG9tZXJzQW5kT3JkZXJzID0gZW0xLmdldENoYW5nZXMoW2N1c3RUeXBlLCBvcmRlclR5cGVdKTtcclxuXHJcbiAgWW91IGNhbiBhbHNvIGFzayBmb3IgZW50aXRpZXMgd2l0aCBhIHBhcnRpY3VsYXIgW1tFbnRpdHlTdGF0ZV1dIG9yIEVudGl0eVN0YXRlcy5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IG9yZGVyVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJPcmRlclwiKTtcclxuICA+ICAgICAgbGV0IGFkZGVkQ3VzdG9tZXJzQW5kT3JkZXJzID0gZW0xLmdldEVudGl0aWVzKFtjdXN0VHlwZSwgb3JkZXJUeXBlXSwgRW50aXR5U3RhdGUuQWRkZWQpO1xyXG4gXHJcbiAgQHBhcmFtIGVudGl0eVR5cGVOYW1lIC0gVGhlIFtbRW50aXR5VHlwZV1dIG5hbWUgb3IgbmFtZXMgZm9yIHdoaWNoIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgSWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCwgYWxsIEVudGl0eVR5cGVzIGFyZSBzZWFyY2hlZC4gIFxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlcyAtIFRoZSBbW0VudGl0eVR5cGVdXSBvciBFbnRpdHlUeXBlcyBmb3Igd2hpY2ggZW50aXRpZXMgd2lsbCBiZSBmb3VuZC5cclxuICBJZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkLCBhbGwgRW50aXR5VHlwZXMgYXJlIHNlYXJjaGVkLiBcclxuICBAcGFyYW0gZW50aXR5U3RhdGVzIC0gVGhlIFtbRW50aXR5U3RhdGVdXXMgZm9yIHdoaWNoIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgSWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCwgZW50aXRpZXMgb2YgYWxsIEVudGl0eVN0YXRlcyBhcmUgcmV0dXJuZWQuXHJcbiAgQHJldHVybiBBbiBhcnJheSBvZiBFbnRpdGllc1xyXG4gICoqL1xyXG4gIGdldEVudGl0aWVzKGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZyB8IHN0cmluZ1tdLCBlbnRpdHlTdGF0ZXM/OiBFbnRpdHlTdGF0ZSB8IEVudGl0eVN0YXRlW10pIHtcclxuICAgIGxldCBlbnRUeXBlcyA9IGNoZWNrRW50aXR5VHlwZXModGhpcywgZW50aXR5VHlwZXMpO1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5U3RhdGVzLCBcImVudGl0eVN0YXRlc1wiKS5pc09wdGlvbmFsKCkuaXNFbnVtT2YoRW50aXR5U3RhdGUpLm9yKCkuaXNOb25FbXB0eUFycmF5KCkuaXNFbnVtT2YoRW50aXR5U3RhdGUpLmNoZWNrKCk7XHJcblxyXG4gICAgbGV0IHN0YXRlcyA9IHZhbGlkYXRlRW50aXR5U3RhdGVzKHRoaXMsIGVudGl0eVN0YXRlcyk7XHJcbiAgICByZXR1cm4gZ2V0RW50aXRpZXNDb3JlKHRoaXMsIGVudFR5cGVzLCBzdGF0ZXMpO1xyXG4gIH1cclxuXHJcblxyXG4gIC8vIHByb3RlY3RlZCBtZXRob2RzXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX25vdGlmeVN0YXRlQ2hhbmdlKGVudGl0eTogRW50aXR5LCBuZWVkc1NhdmU6IGJvb2xlYW4pIHtcclxuICAgIGxldCBlY0FyZ3MgPSB7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLkVudGl0eVN0YXRlQ2hhbmdlLCBlbnRpdHk6IGVudGl0eSB9O1xyXG5cclxuICAgIGlmIChuZWVkc1NhdmUpIHtcclxuICAgICAgaWYgKCF0aGlzLl9oYXNDaGFuZ2VzKSB0aGlzLl9zZXRIYXNDaGFuZ2VzKHRydWUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gY2FsbGVkIHdoZW4gcmVqZWN0aW5nIGEgY2hhbmdlIG9yIG1lcmdpbmcgYW4gdW5jaGFuZ2VkIHJlY29yZC5cclxuICAgICAgLy8gTk9URTogdGhpcyBjYW4gYmUgc2xvdyB3aXRoIGxvdHMgb2YgZW50aXRpZXMgaW4gdGhlIGNhY2hlLlxyXG4gICAgICAvLyBzbyBkZWZlciBpdCBkdXJpbmcgYSBxdWVyeS9pbXBvcnQgb3Igc2F2ZSBhbmQgY2FsbCBpdCBvbmNlIHdoZW4gY29tcGxldGUgKCBpZiBuZWVkZWQpLlxyXG4gICAgICBpZiAodGhpcy5faGFzQ2hhbmdlcykge1xyXG4gICAgICAgIGlmICh0aGlzLmlzTG9hZGluZykge1xyXG4gICAgICAgICAgdGhpcy5faGFzQ2hhbmdlc0FjdGlvbiA9IHRoaXMuX2hhc0NoYW5nZXNBY3Rpb24gfHwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB0aGlzLl9zZXRIYXNDaGFuZ2VzKG51bGwpO1xyXG4gICAgICAgICAgICB0aGlzLmVudGl0eUNoYW5nZWQucHVibGlzaChlY0FyZ3MpO1xyXG4gICAgICAgICAgfS5iaW5kKHRoaXMpO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLl9zZXRIYXNDaGFuZ2VzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICB0aGlzLmVudGl0eUNoYW5nZWQucHVibGlzaChlY0FyZ3MpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3NldEhhc0NoYW5nZXMoaGFzQ2hhbmdlcz86IGJvb2xlYW4pIHtcclxuICAgIGlmIChoYXNDaGFuZ2VzID09IG51bGwpIGhhc0NoYW5nZXMgPSB0aGlzLl9oYXNDaGFuZ2VzQ29yZSgpO1xyXG4gICAgbGV0IGhhZENoYW5nZXMgPSB0aGlzLl9oYXNDaGFuZ2VzO1xyXG4gICAgdGhpcy5faGFzQ2hhbmdlcyA9IGhhc0NoYW5nZXM7XHJcbiAgICBpZiAoaGFzQ2hhbmdlcyAhPT0gaGFkQ2hhbmdlcykge1xyXG4gICAgICB0aGlzLmhhc0NoYW5nZXNDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlNYW5hZ2VyOiB0aGlzLCBoYXNDaGFuZ2VzOiBoYXNDaGFuZ2VzIH0pO1xyXG4gICAgfVxyXG4gICAgdGhpcy5faGFzQ2hhbmdlc0FjdGlvbiA9IHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9saW5rUmVsYXRlZEVudGl0aWVzKGVudGl0eTogRW50aXR5KSB7XHJcbiAgICBsZXQgZW0gPSB0aGlzO1xyXG4gICAgbGV0IGVudGl0eUFzcGVjdCA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICAvLyB3ZSBkbyBub3Qgd2FudCBlbnRpdHlTdGF0ZSB0byBjaGFuZ2UgYXMgYSByZXN1bHQgb2YgbGlua2FnZS5cclxuICAgIGNvcmUudXNpbmcoZW0sIFwiaXNMb2FkaW5nXCIsIHRydWUsIGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgICAgIGxldCB1bmF0dGFjaGVkTWFwID0gZW0uX3VuYXR0YWNoZWRDaGlsZHJlbk1hcDtcclxuICAgICAgbGV0IGVudGl0eUtleSA9IGVudGl0eUFzcGVjdC5nZXRLZXkoKTtcclxuICAgICAgbGV0IGVudGl0eVR5cGUgPSBlbnRpdHlLZXkuZW50aXR5VHlwZTtcclxuXHJcbiAgICAgIHdoaWxlIChlbnRpdHlUeXBlKSB7XHJcbiAgICAgICAgbGV0IGtleXN0cmluZyA9IGVudGl0eUtleS50b1N0cmluZyhlbnRpdHlUeXBlKTtcclxuXHJcbiAgICAgICAgLy8gYXR0YWNoIGFueSB1bmF0dGFjaGVkQ2hpbGRyZW5cclxuICAgICAgICBsZXQgdHVwbGVzID0gdW5hdHRhY2hlZE1hcC5nZXRUdXBsZXNCeVN0cmluZyhrZXlzdHJpbmcpO1xyXG4gICAgICAgIGlmICh0dXBsZXMpIHtcclxuICAgICAgICAgIHR1cGxlcy5zbGljZSgwKS5mb3JFYWNoKGZ1bmN0aW9uICh0cGwpIHtcclxuXHJcbiAgICAgICAgICAgIGxldCB1bmF0dGFjaGVkQ2hpbGRyZW4gPSB0cGwuY2hpbGRyZW4uZmlsdGVyKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIGUuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlICE9PSBFbnRpdHlTdGF0ZS5EZXRhY2hlZDtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICBsZXQgY2hpbGRUb1BhcmVudE5wOiBOYXZpZ2F0aW9uUHJvcGVydHk7XHJcbiAgICAgICAgICAgIGxldCBwYXJlbnRUb0NoaWxkTnA6IE5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuXHJcbiAgICAgICAgICAgIC8vIG5wIGlzIHVzdWFsbHkgY2hpbGRUb1BhcmVudE5wXHJcbiAgICAgICAgICAgIC8vIGV4Y2VwdCB3aXRoIHVuaWRpcmVjdGlvbmFsIDEtbiB3aGVyZSBpdCBpcyBwYXJlbnRUb0NoaWxkTnA7XHJcbiAgICAgICAgICAgIGxldCBucCA9IHRwbC5uYXZpZ2F0aW9uUHJvcGVydHk7XHJcblxyXG4gICAgICAgICAgICBsZXQgaW52ZXJzZU5wID0gbnAuaW52ZXJzZTtcclxuICAgICAgICAgICAgaWYgKGludmVyc2VOcCkge1xyXG4gICAgICAgICAgICAgIC8vIGJpZGlyZWN0aW9uYWxcclxuICAgICAgICAgICAgICBjaGlsZFRvUGFyZW50TnAgPSBucDtcclxuICAgICAgICAgICAgICBwYXJlbnRUb0NoaWxkTnAgPSBpbnZlcnNlTnA7XHJcblxyXG4gICAgICAgICAgICAgIGlmIChwYXJlbnRUb0NoaWxkTnAuaXNTY2FsYXIpIHtcclxuICAgICAgICAgICAgICAgIGxldCBvbmx5Q2hpbGQgPSB1bmF0dGFjaGVkQ2hpbGRyZW5bMF07XHJcbiAgICAgICAgICAgICAgICBlbnRpdHkuc2V0UHJvcGVydHkocGFyZW50VG9DaGlsZE5wLm5hbWUsIG9ubHlDaGlsZCk7XHJcbiAgICAgICAgICAgICAgICBvbmx5Q2hpbGQuc2V0UHJvcGVydHkoY2hpbGRUb1BhcmVudE5wLm5hbWUsIGVudGl0eSk7XHJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50Q2hpbGRyZW4gPSBlbnRpdHkuZ2V0UHJvcGVydHkocGFyZW50VG9DaGlsZE5wLm5hbWUpO1xyXG4gICAgICAgICAgICAgICAgdW5hdHRhY2hlZENoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICAgIGN1cnJlbnRDaGlsZHJlbi5wdXNoKGNoaWxkKTtcclxuICAgICAgICAgICAgICAgICAgY2hpbGQuc2V0UHJvcGVydHkoY2hpbGRUb1BhcmVudE5wLm5hbWUsIGVudGl0eSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgdW5hdHRhY2hlZE1hcC5yZW1vdmVDaGlsZHJlbihrZXlzdHJpbmcsIGNoaWxkVG9QYXJlbnROcCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gdW5pZGlyZWN0aW9uYWxcclxuICAgICAgICAgICAgICAvLyBpZiAobnAuaXNTY2FsYXIgfHwgbnAucGFyZW50VHlwZSAhPT0gZW50aXR5LmVudGl0eVR5cGUpIHtcclxuICAgICAgICAgICAgICBpZiAobnAuaXNTY2FsYXIpIHtcclxuICAgICAgICAgICAgICAgIC8vIG4gLT4gMSAgZWc6IGNoaWxkOiBPcmRlckRldGFpbCBwYXJlbnQ6IFByb2R1Y3RcclxuICAgICAgICAgICAgICAgIC8vIDEgLT4gMSBlZyBjaGlsZDogRW1wbG95ZWUgcGFyZW50OiBFbXBsb3llZSAoIG9ubHkgTWFuYWdlciwgbm8gRGlyZWN0UmVwb3J0cyBwcm9wZXJ0eSlcclxuICAgICAgICAgICAgICAgIGNoaWxkVG9QYXJlbnROcCA9IG5wO1xyXG4gICAgICAgICAgICAgICAgdW5hdHRhY2hlZENoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICAgIGNoaWxkLnNldFByb3BlcnR5KGNoaWxkVG9QYXJlbnROcC5uYW1lLCBlbnRpdHkpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB1bmF0dGFjaGVkTWFwLnJlbW92ZUNoaWxkcmVuKGtleXN0cmluZywgY2hpbGRUb1BhcmVudE5wKTtcclxuICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gMSAtPiBuICBlZzogcGFyZW50OiBSZWdpb24gY2hpbGQ6IFRlcnJcclxuICAgICAgICAgICAgICAgIC8vIFRPRE86IG5lZWQgdG8gcmVtb3ZlIHVuYXR0YWNoZWQgY2hpbGRyZW4gZnJvbSB0aGUgbWFwIGFmdGVyIHRoaXM7IG9ubHkgYSBwZXJmIGlzc3VlLlxyXG4gICAgICAgICAgICAgICAgcGFyZW50VG9DaGlsZE5wID0gbnA7XHJcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudENoaWxkcmVuID0gZW50aXR5LmdldFByb3BlcnR5KHBhcmVudFRvQ2hpbGROcC5uYW1lKTtcclxuICAgICAgICAgICAgICAgIHVuYXR0YWNoZWRDaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICAgICAgICAvLyB3ZSBrbm93IGlmIGNhbid0IGFscmVhZHkgYmUgdGhlcmUuXHJcbiAgICAgICAgICAgICAgICAgIGN1cnJlbnRDaGlsZHJlbi5fcHVzaChjaGlsZCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbnRpdHlUeXBlID0gZW50aXR5VHlwZS5iYXNlRW50aXR5VHlwZTsgLy8gbG9vayBmb3IgcmVsYXRpb25zaGlwcyB1cCB0aGUgaGllcmFyY2h5XHJcbiAgICAgIH1cclxuXHJcblxyXG4gICAgICAvLyBub3cgYWRkIHRvIHVuYXR0YWNoZWRNYXAgaWYgbmVlZGVkLlxyXG4gICAgICBlbnRpdHkuZW50aXR5VHlwZS5uYXZpZ2F0aW9uUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChucCkge1xyXG4gICAgICAgIGlmIChucC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgbGV0IHZhbHVlID0gZW50aXR5LmdldFByb3BlcnR5KG5wLm5hbWUpO1xyXG4gICAgICAgICAgLy8gcHJvcGVydHkgaXMgYWxyZWFkeSBsaW5rZWQgdXBcclxuICAgICAgICAgIGlmICh2YWx1ZSkgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gZmlyc3QgZGV0ZXJtaW5lIGlmIG5wIGNvbnRhaW5zIGEgcGFyZW50IG9yIGNoaWxkXHJcbiAgICAgICAgLy8gaGF2aW5nIGEgcGFyZW50S2V5IG1lYW5zIHRoYXQgdGhpcyBpcyBhIGNoaWxkXHJcbiAgICAgICAgLy8gaWYgYSBwYXJlbnQgdGhlbiBubyBuZWVkIGZvciBtb3JlIHdvcmsgYmVjYXVzZSBjaGlsZHJlbiB3aWxsIGF0dGFjaCB0byBpdC5cclxuICAgICAgICBsZXQgcGFyZW50S2V5ID0gZW50aXR5QXNwZWN0LmdldFBhcmVudEtleShucCk7XHJcbiAgICAgICAgaWYgKHBhcmVudEtleSkge1xyXG4gICAgICAgICAgLy8gY2hlY2sgZm9yIGVtcHR5IGtleXMgLSBtZWFuaW5nIHRoYXQgcGFyZW50IGlkJ3MgYXJlIG5vdCB5ZXQgc2V0LlxyXG4gICAgICAgICAgaWYgKHBhcmVudEtleS5faXNFbXB0eSgpKSByZXR1cm47XHJcbiAgICAgICAgICAvLyBpZiBhIGNoaWxkIC0gbG9vayBmb3IgcGFyZW50IGluIHRoZSBlbSBjYWNoZVxyXG4gICAgICAgICAgaWYgKG5wLmludkZvcmVpZ25LZXlOYW1lcy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgLy8gbnAgcmVsYXRlcyB0byBub24tUEsgcHJvcGVydHkgb2YgcGFyZW50IGVudGl0eVxyXG4gICAgICAgICAgICBjb25zdCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShwYXJlbnRLZXkuZW50aXR5VHlwZS5kZWZhdWx0UmVzb3VyY2VOYW1lKS53aGVyZShucC5pbnZGb3JlaWduS2V5TmFtZXNbMF0sICdlcScsIHBhcmVudEtleS52YWx1ZXNbMF0pO1xyXG4gICAgICAgICAgICBjb25zdCBxcmVzdWx0ID0gZW0uZXhlY3V0ZVF1ZXJ5TG9jYWxseShxdWVyeSk7XHJcbiAgICAgICAgICAgIGlmIChxcmVzdWx0Lmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICAgIGxldCBwYXJlbnQgPSBxcmVzdWx0WzBdO1xyXG4gICAgICAgICAgICAgIGVudGl0eS5zZXRQcm9wZXJ0eShucC5uYW1lLCBwYXJlbnQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBucCByZWxhdGVzIHRvIFBLIG9mIHBhcmVudCBlbnRpdHlcclxuICAgICAgICAgICAgbGV0IHBhcmVudCA9IGVtLmdldEVudGl0eUJ5S2V5KHBhcmVudEtleSk7XHJcbiAgICAgICAgICAgIGlmIChwYXJlbnQpIHtcclxuICAgICAgICAgICAgICAvLyBpZiBmb3VuZCBob29rIGl0IHVwXHJcbiAgICAgICAgICAgICAgZW50aXR5LnNldFByb3BlcnR5KG5wLm5hbWUsIHBhcmVudCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gZWxzZSBhZGQgcGFyZW50IHRvIHVucmVzb2x2ZWRQYXJlbnRNYXA7XHJcbiAgICAgICAgICAgICAgdW5hdHRhY2hlZE1hcC5hZGRDaGlsZChwYXJlbnRLZXksIG5wLCBlbnRpdHkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmIChucC5pbnZlcnNlICYmIG5wLmludmVyc2UuaW52Rm9yZWlnbktleU5hbWVzLmxlbmd0aCkge1xyXG4gICAgICAgICAgLy8gbnAgcmVsYXRlcyB0byBub24tUEsgcHJvcGVydHkgb2YgcGFyZW50IGVudGl0eTsgcXVlcnkgZW50aXRpZXMgYnkgRktcclxuICAgICAgICAgIGNvbnN0IGFrVmFsdWUgPSBlbnRpdHkuZ2V0UHJvcGVydHkobnAuaW52ZXJzZS5pbnZGb3JlaWduS2V5TmFtZXNbMF0pO1xyXG4gICAgICAgICAgY29uc3QgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkobnAuZW50aXR5VHlwZS5kZWZhdWx0UmVzb3VyY2VOYW1lKS53aGVyZShucC5pbnZGb3JlaWduS2V5TmFtZXNbMF0sICdlcScsIGFrVmFsdWUpO1xyXG4gICAgICAgICAgY29uc3QgcXJlc3VsdCA9IGVtLmV4ZWN1dGVRdWVyeUxvY2FsbHkocXVlcnkpO1xyXG4gICAgICAgICAgcXJlc3VsdC5mb3JFYWNoKChjaGlsZDogRW50aXR5KSA9PiB7XHJcbiAgICAgICAgICAgIGNoaWxkLnNldFByb3BlcnR5KG5wLmludmVyc2UubmFtZSwgZW50aXR5KTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyBoYW5kbGUgdW5pZGlyZWN0aW9uYWwgMS14IHdoZXJlIHdlIHNldCB4LmZrXHJcbiAgICAgIGVudGl0eS5lbnRpdHlUeXBlLmZvcmVpZ25LZXlQcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKGZrUHJvcCkge1xyXG4gICAgICAgIGxldCBpbnZOcCA9IGZrUHJvcC5pbnZlcnNlTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gICAgICAgIGlmICghaW52TnApIHJldHVybjtcclxuICAgICAgICAvLyB1bmlkaXJlY3Rpb25hbCBmayBwcm9wcyBvbmx5XHJcbiAgICAgICAgbGV0IGZrVmFsdWUgPSBlbnRpdHkuZ2V0UHJvcGVydHkoZmtQcm9wLm5hbWUpO1xyXG4gICAgICAgIGxldCBwYXJlbnRLZXkgPSBuZXcgRW50aXR5S2V5KGludk5wLnBhcmVudFR5cGUsIFtma1ZhbHVlXSk7XHJcbiAgICAgICAgbGV0IHBhcmVudCA9IGVtLmdldEVudGl0eUJ5S2V5KHBhcmVudEtleSk7XHJcblxyXG4gICAgICAgIGlmIChwYXJlbnQpIHtcclxuICAgICAgICAgIGlmIChpbnZOcC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgICBwYXJlbnQuc2V0UHJvcGVydHkoaW52TnAubmFtZSwgZW50aXR5KTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGlmIChlbS5pc0xvYWRpbmcpIHtcclxuICAgICAgICAgICAgICBwYXJlbnQuZ2V0UHJvcGVydHkoaW52TnAubmFtZSkuX3B1c2goZW50aXR5KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICBwYXJlbnQuZ2V0UHJvcGVydHkoaW52TnAubmFtZSkucHVzaChlbnRpdHkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vIGVsc2UgYWRkIHBhcmVudCB0byB1bnJlc29sdmVkUGFyZW50TWFwO1xyXG4gICAgICAgICAgdW5hdHRhY2hlZE1hcC5hZGRDaGlsZChwYXJlbnRLZXksIGludk5wLCBlbnRpdHkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9KTtcclxuXHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfYXR0YWNoRW50aXR5Q29yZShlbnRpdHk6IEVudGl0eSwgZW50aXR5U3RhdGU6IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5KSB7XHJcbiAgICBsZXQgZ3JvdXAgPSBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cCh0aGlzLCBlbnRpdHkuZW50aXR5VHlwZSk7XHJcbiAgICBsZXQgYXR0YWNoZWRFbnRpdHkgPSBncm91cC5hdHRhY2hFbnRpdHkoZW50aXR5LCBlbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneSk7XHJcbiAgICB0aGlzLl9saW5rUmVsYXRlZEVudGl0aWVzKGF0dGFjaGVkRW50aXR5KTtcclxuICAgIHJldHVybiBhdHRhY2hlZEVudGl0eTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF91cGRhdGVGa1ZhbChma1Byb3A6IERhdGFQcm9wZXJ0eSwgb2xkVmFsdWU6IGFueSwgbmV3VmFsdWU6IGFueSkge1xyXG4gICAgbGV0IGdyb3VwID0gdGhpcy5fZW50aXR5R3JvdXBNYXBbZmtQcm9wLnBhcmVudFR5cGUubmFtZV07XHJcbiAgICBpZiAoIWdyb3VwKSByZXR1cm47XHJcbiAgICBncm91cC5fdXBkYXRlRmtWYWwoZmtQcm9wLCBvbGRWYWx1ZSwgbmV3VmFsdWUpO1xyXG4gIH1cclxufVxyXG5cclxuRW50aXR5TWFuYWdlci5wcm90b3R5cGUuXyR0eXBlTmFtZSA9IFwiRW50aXR5TWFuYWdlclwiO1xyXG5cclxuQnJlZXplRXZlbnQuYnViYmxlRXZlbnQoRW50aXR5TWFuYWdlci5wcm90b3R5cGUpO1xyXG5cclxuZnVuY3Rpb24gY2xlYXJTZXJ2ZXJFcnJvcnMoZW50aXRpZXM6IEVudGl0eVtdKSB7XHJcbiAgZW50aXRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICBsZXQgc2VydmVyS2V5czogc3RyaW5nW10gPSBbXTtcclxuICAgIGxldCBhc3BlY3QgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgY29yZS5vYmplY3RGb3JFYWNoKGFzcGVjdC5fdmFsaWRhdGlvbkVycm9ycywgZnVuY3Rpb24gKGtleSwgdmUpIHtcclxuICAgICAgaWYgKHZlLmlzU2VydmVyRXJyb3IpIHNlcnZlcktleXMucHVzaChrZXkpO1xyXG4gICAgfSk7XHJcbiAgICBpZiAoc2VydmVyS2V5cy5sZW5ndGggPT09IDApIHJldHVybjtcclxuICAgIGFzcGVjdC5fcHJvY2Vzc1ZhbGlkYXRpb25PcEFuZFB1Ymxpc2goZnVuY3Rpb24gKCkge1xyXG4gICAgICBzZXJ2ZXJLZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xyXG4gICAgICAgIGFzcGVjdC5fcmVtb3ZlVmFsaWRhdGlvbkVycm9yKGtleSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUVudGl0eUVycm9ycyhlbnRpdGllczogRW50aXR5W10pIHtcclxuICBsZXQgZW50aXR5RXJyb3JzOiBFbnRpdHlFcnJvcltdID0gW107XHJcbiAgZW50aXRpZXMuZm9yRWFjaCgoZW50aXR5KSA9PiB7XHJcbiAgICBjb3JlLm9iamVjdEZvckVhY2goZW50aXR5LmVudGl0eUFzcGVjdC5fdmFsaWRhdGlvbkVycm9ycywgZnVuY3Rpb24gKGtleSwgdmUpIHtcclxuICAgICAgbGV0IGNmZyA9IGNvcmUuZXh0ZW5kKHtcclxuICAgICAgICBlbnRpdHk6IGVudGl0eSxcclxuICAgICAgICBlcnJvck5hbWU6IHZlLnZhbGlkYXRvci5uYW1lXHJcbiAgICAgIH0sIHZlLCBbXCJlcnJvck1lc3NhZ2VcIiwgXCJwcm9wZXJ0eU5hbWVcIiwgXCJpc1NlcnZlckVycm9yXCIsIFwiY3VzdG9tXCJdKSBhcyBFbnRpdHlFcnJvcjtcclxuICAgICAgZW50aXR5RXJyb3JzLnB1c2goY2ZnKTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG4gIHJldHVybiBlbnRpdHlFcnJvcnM7XHJcbn1cclxuXHJcblxyXG5mdW5jdGlvbiBwcm9jZXNzU2VydmVyRXJyb3JzKHNhdmVDb250ZXh0OiBTYXZlQ29udGV4dCwgc2F2ZUVycm9yOiBTYXZlRXJyb3JGcm9tU2VydmVyKSB7XHJcbiAgLy8gY29udmVydGluZyBJU2F2ZUVycm9yRnJvbVNlcnZlciAtPiBJU2F2ZUVycm9yXHJcbiAgbGV0IHNlcnZlckVycm9ycyA9IHNhdmVFcnJvci5lbnRpdHlFcnJvcnM7XHJcbiAgaWYgKCFzZXJ2ZXJFcnJvcnMpIHJldHVybiA8U2F2ZUVycm9yPiA8YW55PiBzYXZlRXJyb3I7XHJcbiAgbGV0IGVudGl0eU1hbmFnZXIgPSBzYXZlQ29udGV4dC5lbnRpdHlNYW5hZ2VyO1xyXG4gIGxldCBtZXRhZGF0YVN0b3JlID0gZW50aXR5TWFuYWdlci5tZXRhZGF0YVN0b3JlO1xyXG4gIGxldCBlbnRpdHlFcnJvcnMgPSBzZXJ2ZXJFcnJvcnMubWFwKChzZXJyKSA9PiB7XHJcbiAgICBsZXQgZW50aXR5OiBFbnRpdHkgfCBudWxsID0gbnVsbDtcclxuICAgIGxldCBlbnRpdHlUeXBlOiBFbnRpdHlUeXBlIHwgdW5kZWZpbmVkO1xyXG4gICAgaWYgKHNlcnIua2V5VmFsdWVzKSB7XHJcbiAgICAgIGVudGl0eVR5cGUgPSBtZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShzZXJyLmVudGl0eVR5cGVOYW1lKSBhcyBFbnRpdHlUeXBlO1xyXG4gICAgICBsZXQgZWtleSA9IG5ldyBFbnRpdHlLZXkoZW50aXR5VHlwZSwgc2Vyci5rZXlWYWx1ZXMpO1xyXG4gICAgICBlbnRpdHkgPSBlbnRpdHlNYW5hZ2VyLmdldEVudGl0eUJ5S2V5KGVrZXkpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlbnRpdHlUeXBlICYmIGVudGl0eSkge1xyXG4gICAgICBsZXQgY29udGV4dCA9IHNlcnIucHJvcGVydHlOYW1lID9cclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm9wZXJ0eU5hbWU6IHNlcnIucHJvcGVydHlOYW1lLFxyXG4gICAgICAgICAgcHJvcGVydHk6IGVudGl0eVR5cGUuZ2V0UHJvcGVydHkoc2Vyci5wcm9wZXJ0eU5hbWUpXHJcbiAgICAgICAgfSA6IHtcclxuICAgICAgICB9O1xyXG4gICAgICBsZXQga2V5ID0gVmFsaWRhdGlvbkVycm9yLmdldEtleShzZXJyLmVycm9yTmFtZSB8fCBzZXJyLmVycm9yTWVzc2FnZSwgc2Vyci5wcm9wZXJ0eU5hbWUpO1xyXG5cclxuICAgICAgbGV0IHZlID0gbmV3IFZhbGlkYXRpb25FcnJvcihudWxsLCBjb250ZXh0LCBzZXJyLmVycm9yTWVzc2FnZSwga2V5KTtcclxuICAgICAgdmUuaXNTZXJ2ZXJFcnJvciA9IHRydWU7XHJcbiAgICAgIGVudGl0eS5lbnRpdHlBc3BlY3QuYWRkVmFsaWRhdGlvbkVycm9yKHZlKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgZW50aXR5RXJyb3IgPSBjb3JlLmV4dGVuZCh7XHJcbiAgICAgIGVudGl0eTogZW50aXR5LFxyXG4gICAgICBpc1NlcnZlckVycm9yOiB0cnVlXHJcbiAgICB9LCBzZXJyLCBbXCJlcnJvck5hbWVcIiwgXCJlcnJvck1lc3NhZ2VcIiwgXCJwcm9wZXJ0eU5hbWVcIiwgXCJjdXN0b21cIl0pIGFzIEVudGl0eUVycm9yO1xyXG4gICAgcmV0dXJuIGVudGl0eUVycm9yO1xyXG4gIH0pO1xyXG4gIC8vIGNvbnZlcnRpbmcgSVNhdmVFcnJvckZyb21TZXJ2ZXIgLT4gSVNhdmVFcnJvciBcclxuICBzYXZlRXJyb3IuZW50aXR5RXJyb3JzID0gZW50aXR5RXJyb3JzIGFzIGFueTtcclxuICByZXR1cm4gPFNhdmVFcnJvcj4gPGFueT4gc2F2ZUVycm9yO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIElFbnRpdHlCeUtleVJlc3VsdCB7XHJcbiAgZW50aXR5PzogRW50aXR5O1xyXG4gIGVudGl0eUtleTogRW50aXR5S2V5O1xyXG4gIGZyb21DYWNoZTogYm9vbGVhbjtcclxufVxyXG5cclxuZnVuY3Rpb24gZmV0Y2hFbnRpdHlCeUtleUNvcmUoZW06IEVudGl0eU1hbmFnZXIsIGFyZ3M6IGFueVtdKTogUHJvbWlzZTxJRW50aXR5QnlLZXlSZXN1bHQ+IHtcclxuICBsZXQgdHBsID0gY3JlYXRlRW50aXR5S2V5KGVtLCBhcmdzKTtcclxuICBsZXQgZW50aXR5S2V5ID0gdHBsLmVudGl0eUtleTtcclxuXHJcbiAgbGV0IGNoZWNrTG9jYWxDYWNoZUZpcnN0ID0gdHBsLnJlbWFpbmluZ0FyZ3MubGVuZ3RoID09PSAwID8gZmFsc2UgOiAhIXRwbC5yZW1haW5pbmdBcmdzWzBdO1xyXG4gIGxldCBlbnRpdHk6IEVudGl0eSB8IG51bGwgPSBudWxsO1xyXG4gIGxldCBmb3VuZEl0ID0gZmFsc2U7XHJcbiAgaWYgKGNoZWNrTG9jYWxDYWNoZUZpcnN0KSB7XHJcbiAgICBlbnRpdHkgPSBlbS5nZXRFbnRpdHlCeUtleShlbnRpdHlLZXkpO1xyXG4gICAgZm91bmRJdCA9IGVudGl0eSAhPSBudWxsO1xyXG4gICAgaWYgKGVudGl0eSAhPSBudWxsICYmXHJcbiAgICAgIC8vIG51bGwgdGhlIGVudGl0eSBpZiBpdCBpcyBkZWxldGVkIGFuZCB3ZSBzaG91bGQgZXhjbHVkZSBkZWxldGVkIGVudGl0aWVzXHJcbiAgICAgICFlbS5xdWVyeU9wdGlvbnMuaW5jbHVkZURlbGV0ZWQgJiYgZW50aXR5LmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZS5pc0RlbGV0ZWQoKSkge1xyXG4gICAgICBlbnRpdHkgPSBudWxsO1xyXG4gICAgICAvLyBidXQgcmVzdW1lIGxvb2tpbmcgaWYgd2UnZCBvdmVyd3JpdGUgZGVsZXRlZCBlbnRpdHkgd2l0aCBhIHJlbW90ZSBlbnRpdHlcclxuICAgICAgLy8gbm90ZTogZW0ucXVlcnlPcHRpb25zIGlzIGFsd2F5cyBmdWxseSByZXNvbHZlZCBieSBub3dcclxuICAgICAgZm91bmRJdCA9IGVtLnF1ZXJ5T3B0aW9ucy5tZXJnZVN0cmF0ZWd5ICE9PSBNZXJnZVN0cmF0ZWd5Lk92ZXJ3cml0ZUNoYW5nZXM7XHJcbiAgICB9XHJcbiAgfVxyXG4gIGlmIChmb3VuZEl0KSB7XHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgZW50aXR5OiBlbnRpdHkgfHwgdW5kZWZpbmVkLCBlbnRpdHlLZXk6IGVudGl0eUtleSwgZnJvbUNhY2hlOiB0cnVlIH0pO1xyXG4gIH0gZWxzZSB7XHJcbiAgICByZXR1cm4gRW50aXR5UXVlcnkuZnJvbUVudGl0eUtleShlbnRpdHlLZXkpLnVzaW5nKGVtKS5leGVjdXRlKCkudGhlbihmdW5jdGlvbiAoZGF0YTogYW55KSB7XHJcbiAgICAgIGVudGl0eSA9IChkYXRhLnJlc3VsdHMubGVuZ3RoID09PSAwKSA/IG51bGwgOiBkYXRhLnJlc3VsdHNbMF07XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBlbnRpdHk6IGVudGl0eSB8fCB1bmRlZmluZWQsIGVudGl0eUtleTogZW50aXR5S2V5LCBmcm9tQ2FjaGU6IGZhbHNlIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcblxyXG5cclxuLy8gcHJpdmF0ZSBmbnNcclxuXHJcbi8vIHRha2VzIGluIGVudGl0eVR5cGVzIGFzIGVpdGhlciBzdHJpbmdzIG9yIGVudGl0eVR5cGVzIG9yIGFycmF5cyBvZiBlaXRoZXJcclxuLy8gYW5kIHJldHVybnMgZWl0aGVyIGFuIGVudGl0eVR5cGUgb3IgYW4gYXJyYXkgb2YgZW50aXR5VHlwZXMgb3IgdGhyb3dzIGFuIGVycm9yXHJcbmZ1bmN0aW9uIGNoZWNrRW50aXR5VHlwZXMoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZyB8IHN0cmluZ1tdKSB7XHJcbiAgYXNzZXJ0UGFyYW0oZW50aXR5VHlwZXMsIFwiZW50aXR5VHlwZXNcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKCkub3IoKS5pc05vbkVtcHR5QXJyYXkoKS5pc1N0cmluZygpXHJcbiAgICAub3IoKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkub3IoKS5pc05vbkVtcHR5QXJyYXkoKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkuY2hlY2soKTtcclxuICBsZXQgcmVzdWx0VHlwZXM6IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCB1bmRlZmluZWQ7XHJcbiAgaWYgKHR5cGVvZiBlbnRpdHlUeXBlcyA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgcmVzdWx0VHlwZXMgPSBlbS5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShlbnRpdHlUeXBlcywgZmFsc2UpIGFzIChFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdKTtcclxuICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZW50aXR5VHlwZXMpICYmIHR5cGVvZiBlbnRpdHlUeXBlc1swXSA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgcmVzdWx0VHlwZXMgPSAoZW50aXR5VHlwZXMgYXMgc3RyaW5nW10pLm1hcChmdW5jdGlvbiAoZXROYW1lKSB7XHJcbiAgICAgIHJldHVybiBlbS5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShldE5hbWUsIGZhbHNlKSBhcyBFbnRpdHlUeXBlO1xyXG4gICAgfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIHJlc3VsdFR5cGVzID0gZW50aXR5VHlwZXMgYXMgKEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCB1bmRlZmluZWQpO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc3VsdFR5cGVzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRDaGFuZ2VzQ29yZShlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdKSB7XHJcbiAgbGV0IGVudGl0eUdyb3VwcyA9IGdldEVudGl0eUdyb3VwcyhlbSwgZW50aXR5VHlwZXMpO1xyXG5cclxuICAvLyBUT0RPOiB0aGluayBhYm91dCB3cml0aW5nIGEgY29yZS5tYXBNYW55IG1ldGhvZCBpZiB3ZSBzZWUgbW9yZSBvZiB0aGVzZS5cclxuICBsZXQgc2VsZWN0ZWQ6IEVudGl0eVtdID0gW107XHJcbiAgZW50aXR5R3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGVnKSB7XHJcbiAgICAvLyBlZyBtYXkgYmUgdW5kZWZpbmVkIG9yIG51bGxcclxuICAgIGlmICghZWcpIHJldHVybjtcclxuICAgIGxldCBlbnRpdGllcyA9IGVnLmdldENoYW5nZXMoKTtcclxuICAgIGlmIChzZWxlY3RlZCAmJiBzZWxlY3RlZC5sZW5ndGgpIHtcclxuICAgICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZW50aXRpZXMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgc2VsZWN0ZWQgPSBlbnRpdGllcztcclxuICAgIH1cclxuICB9KTtcclxuICByZXR1cm4gc2VsZWN0ZWQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEVudGl0aWVzQ29yZShlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZXM6IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCB1bmRlZmluZWQsIGVudGl0eVN0YXRlczogRW50aXR5U3RhdGVbXSkge1xyXG4gIGxldCBlbnRpdHlHcm91cHMgPSBnZXRFbnRpdHlHcm91cHMoZW0sIGVudGl0eVR5cGVzKTtcclxuXHJcbiAgLy8gVE9ETzogdGhpbmsgYWJvdXQgd3JpdGluZyBhIGNvcmUubWFwTWFueSBtZXRob2QgaWYgd2Ugc2VlIG1vcmUgb2YgdGhlc2UuXHJcbiAgbGV0IHNlbGVjdGVkOiBFbnRpdHlbXSA9IFtdO1xyXG4gIGVudGl0eUdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChlZykge1xyXG4gICAgLy8gZWcgbWF5IGJlIHVuZGVmaW5lZCBvciBudWxsXHJcbiAgICBpZiAoIWVnKSByZXR1cm47XHJcbiAgICBsZXQgZW50aXRpZXMgPSBlZy5nZXRFbnRpdGllcyhlbnRpdHlTdGF0ZXMpO1xyXG4gICAgaWYgKHNlbGVjdGVkICYmIHNlbGVjdGVkLmxlbmd0aCkge1xyXG4gICAgICBzZWxlY3RlZCA9IHNlbGVjdGVkLmNvbmNhdChlbnRpdGllcyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBzZWxlY3RlZCA9IGVudGl0aWVzO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiBzZWxlY3RlZDtcclxufVxyXG5cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUVudGl0eUtleShlbTogRW50aXR5TWFuYWdlciwgYXJnczogYW55W10pIHtcclxuICB0cnkge1xyXG4gICAgaWYgKGFyZ3NbMF0gaW5zdGFuY2VvZiBFbnRpdHlLZXkpIHtcclxuICAgICAgcmV0dXJuIHsgZW50aXR5S2V5OiBhcmdzWzBdIGFzIEVudGl0eUtleSwgcmVtYWluaW5nQXJnczogY29yZS5hcnJheVNsaWNlKGFyZ3MsIDEpIH07XHJcbiAgICB9IGVsc2UgaWYgKGFyZ3MubGVuZ3RoID49IDIpIHtcclxuICAgICAgbGV0IGVudGl0eVR5cGUgPSAodHlwZW9mIGFyZ3NbMF0gPT09ICdzdHJpbmcnKSA/IGVtLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGFyZ3NbMF0sIGZhbHNlKSA6IGFyZ3NbMF07XHJcbiAgICAgIHJldHVybiB7IGVudGl0eUtleTogbmV3IEVudGl0eUtleShlbnRpdHlUeXBlLCBhcmdzWzFdKSwgcmVtYWluaW5nQXJnczogY29yZS5hcnJheVNsaWNlKGFyZ3MsIDIpIH07XHJcbiAgICB9XHJcbiAgfSBjYXRjaCAoZSkgey8qIHRocm93IGJlbG93ICovXHJcbiAgICAvLyB0aHJvdyBuZXcgRXJyb3IoXCJNdXN0IHN1cHBseSBhbiBFbnRpdHlLZXkgT1IgYW4gRW50aXR5VHlwZSBuYW1lIG9yIEVudGl0eVR5cGUgZm9sbG93ZWQgYnkgYSBrZXkgdmFsdWUgb3IgYW4gYXJyYXkgb2Yga2V5IHZhbHVlcy5cIik7XHJcbiAgfVxyXG4gIHRocm93IG5ldyBFcnJvcihcIk11c3Qgc3VwcGx5IGFuIEVudGl0eUtleSBPUiBhbiBFbnRpdHlUeXBlIG5hbWUgb3IgRW50aXR5VHlwZSBmb2xsb3dlZCBieSBhIGtleSB2YWx1ZSBvciBhbiBhcnJheSBvZiBrZXkgdmFsdWVzLlwiKTtcclxufVxyXG5cclxuZnVuY3Rpb24gbWFya0lzQmVpbmdTYXZlZChlbnRpdGllczogRW50aXR5W10sIGZsYWc6IGJvb2xlYW4pIHtcclxuICBlbnRpdGllcy5mb3JFYWNoKGZ1bmN0aW9uIChlbnRpdHkpIHtcclxuICAgIGVudGl0eS5lbnRpdHlBc3BlY3QuaXNCZWluZ1NhdmVkID0gZmxhZztcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gZXhwb3J0RW50aXR5R3JvdXBzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdGllc09yRW50aXR5VHlwZXM6IEVudGl0eVtdIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nW10pIHtcclxuICBsZXQgZW50aXR5R3JvdXBNYXA6IHsgW2luZGV4OiBzdHJpbmddOiBFbnRpdHlHcm91cCB9O1xyXG4gIGxldCBmaXJzdCA9IGVudGl0aWVzT3JFbnRpdHlUeXBlcyAmJiBlbnRpdGllc09yRW50aXR5VHlwZXNbMF07XHJcbiAgLy8gY2hlY2sgaWYgYXJyYXlcclxuICBpZiAoZmlyc3QpIHtcclxuICAgIC8vIGdyb3VwIGVudGl0aWVzIGJ5IGVudGl0eVR5cGUgYW5kXHJcbiAgICAvLyBjcmVhdGUgJ2dyb3VwcycgdGhhdCBsb29rIGxpa2UgZW50aXR5R3JvdXBzLlxyXG4gICAgZW50aXR5R3JvdXBNYXAgPSB7fTtcclxuICAgIGlmICgoZmlyc3QgYXMgYW55KS5lbnRpdHlUeXBlKSB7XHJcbiAgICAgIGxldCBlbnRpdGllcyA9IGVudGl0aWVzT3JFbnRpdHlUeXBlcyBhcyBFbnRpdHlbXTtcclxuICAgICAgLy8gYXNzdW1lIFwiZW50aXRpZXNcIiBpcyBhbiBhcnJheSBvZiBlbnRpdGllcztcclxuICAgICAgZW50aXRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGlmIChlLmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZSA9PT0gRW50aXR5U3RhdGUuRGV0YWNoZWQpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBleHBvcnQgYW4gZW50aXR5IHdpdGggYW4gRW50aXR5U3RhdGUgb2YgJ0RldGFjaGVkJ1wiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbGV0IGdyb3VwID0gZW50aXR5R3JvdXBNYXBbZS5lbnRpdHlUeXBlLm5hbWVdO1xyXG4gICAgICAgIGlmICghZ3JvdXApIHtcclxuICAgICAgICAgIGdyb3VwID0ge30gYXMgRW50aXR5R3JvdXA7XHJcbiAgICAgICAgICBncm91cC5lbnRpdHlUeXBlID0gZS5lbnRpdHlUeXBlO1xyXG4gICAgICAgICAgZ3JvdXAuX2VudGl0aWVzID0gW107XHJcbiAgICAgICAgICBlbnRpdHlHcm91cE1hcFtlLmVudGl0eVR5cGUubmFtZV0gPSBncm91cDtcclxuICAgICAgICB9XHJcbiAgICAgICAgZ3JvdXAuX2VudGl0aWVzLnB1c2goZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gYXNzdW1lIFwiZW50aXRpZXNcIiBpcyBhbiBhcnJheSBvZiBFbnRpdHlUeXBlcyAob3IgbmFtZXMpXHJcbiAgICAgIGxldCBlbnRpdHlUeXBlcyA9IGNoZWNrRW50aXR5VHlwZXMoZW0sIGVudGl0aWVzT3JFbnRpdHlUeXBlcyBhcyBFbnRpdHlUeXBlW10gfCBzdHJpbmdbXSkgYXMgRW50aXR5VHlwZVtdO1xyXG4gICAgICBpZiAoZW50aXR5VHlwZXMgIT0gbnVsbCkge1xyXG4gICAgICAgIGVudGl0eVR5cGVzLmZvckVhY2goKGV0KSA9PiB7XHJcbiAgICAgICAgICBsZXQgZ3JvdXAgPSBlbS5fZW50aXR5R3JvdXBNYXBbZXQubmFtZV07XHJcbiAgICAgICAgICBpZiAoZ3JvdXAgJiYgZ3JvdXAuX2VudGl0aWVzLmxlbmd0aCkge1xyXG4gICAgICAgICAgICBlbnRpdHlHcm91cE1hcFtldC5uYW1lXSA9IGdyb3VwO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSBlbHNlIGlmIChlbnRpdGllc09yRW50aXR5VHlwZXMgJiYgZW50aXRpZXNPckVudGl0eVR5cGVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgLy8gZW1wdHkgYXJyYXkgPSBleHBvcnQgbm90aGluZ1xyXG4gICAgZW50aXR5R3JvdXBNYXAgPSB7fTtcclxuICB9IGVsc2Uge1xyXG4gICAgZW50aXR5R3JvdXBNYXAgPSBlbS5fZW50aXR5R3JvdXBNYXA7XHJcbiAgfVxyXG5cclxuICBsZXQgdGVtcEtleXM6IElUZW1wS2V5W10gPSBbXTtcclxuICBsZXQgbmV3R3JvdXBNYXAgPSB7fTtcclxuICBjb3JlLm9iamVjdEZvckVhY2goZW50aXR5R3JvdXBNYXAsIChlbnRpdHlUeXBlTmFtZSwgZW50aXR5R3JvdXApID0+IHtcclxuICAgIG5ld0dyb3VwTWFwW2VudGl0eVR5cGVOYW1lXSA9IGV4cG9ydEVudGl0eUdyb3VwKGVudGl0eUdyb3VwLCB0ZW1wS2V5cyk7XHJcbiAgfSk7XHJcblxyXG4gIHJldHVybiB7IGVudGl0eUdyb3VwTWFwOiBuZXdHcm91cE1hcCwgdGVtcEtleXM6IHRlbXBLZXlzIH07XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGV4cG9ydEVudGl0eUdyb3VwKGVudGl0eUdyb3VwOiBFbnRpdHlHcm91cCwgdGVtcEtleXM6IElUZW1wS2V5W10pIHtcclxuICBsZXQgcmVzdWx0R3JvdXAgPSB7fSBhcyB7IGVudGl0aWVzOiBhbnlbXSB9O1xyXG4gIGxldCBlbnRpdHlUeXBlID0gZW50aXR5R3JvdXAuZW50aXR5VHlwZTtcclxuICBsZXQgZHBzID0gZW50aXR5VHlwZS5kYXRhUHJvcGVydGllcztcclxuICBsZXQgc2VyaWFsaXplckZuID0gZ2V0U2VyaWFsaXplckZuKGVudGl0eVR5cGUpO1xyXG4gIGxldCByYXdFbnRpdGllczogYW55W10gPSBbXTtcclxuICBlbnRpdHlHcm91cC5fZW50aXRpZXMuZm9yRWFjaCgoZW50aXR5KSA9PiB7XHJcbiAgICBpZiAoZW50aXR5KSB7XHJcbiAgICAgIGxldCByYXdFbnRpdHkgPSBzdHJ1Y3R1cmFsT2JqZWN0VG9Kc29uKGVudGl0eSwgZHBzLCBzZXJpYWxpemVyRm4sIHRlbXBLZXlzKTtcclxuICAgICAgcmF3RW50aXRpZXMucHVzaChyYXdFbnRpdHkpO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJlc3VsdEdyb3VwLmVudGl0aWVzID0gcmF3RW50aXRpZXM7XHJcbiAgcmV0dXJuIHJlc3VsdEdyb3VwO1xyXG59XHJcblxyXG5mdW5jdGlvbiBzdHJ1Y3R1cmFsT2JqZWN0VG9Kc29uKHNvOiBTdHJ1Y3R1cmFsT2JqZWN0LCBkcHM6IERhdGFQcm9wZXJ0eVtdLCBzZXJpYWxpemVyRm4/OiAoZHA6IERhdGFQcm9wZXJ0eSwgdmFsdWU6IGFueSkgPT4gYW55LCB0ZW1wS2V5cz86IElUZW1wS2V5W10pIHtcclxuXHJcbiAgbGV0IHJlc3VsdCA9IHt9O1xyXG4gIGRwcy5mb3JFYWNoKGZ1bmN0aW9uIChkcCkge1xyXG4gICAgbGV0IGRwTmFtZSA9IGRwLm5hbWU7XHJcbiAgICBsZXQgdmFsdWUgPSBzby5nZXRQcm9wZXJ0eShkcE5hbWUpO1xyXG4gICAgaWYgKHZhbHVlID09IG51bGwgJiYgZHAuZGVmYXVsdFZhbHVlID09IG51bGwpIHJldHVybjtcclxuXHJcbiAgICBpZiAodmFsdWUgJiYgZHAuaXNDb21wbGV4UHJvcGVydHkpIHtcclxuICAgICAgbGV0IGNvRHBzID0gKGRwLmRhdGFUeXBlIGFzIENvbXBsZXhUeXBlKS5kYXRhUHJvcGVydGllcztcclxuICAgICAgdmFsdWUgPSBjb3JlLm1hcCh2YWx1ZSwgZnVuY3Rpb24gKHY6IENvbXBsZXhPYmplY3QpIHtcclxuICAgICAgICByZXR1cm4gc3RydWN0dXJhbE9iamVjdFRvSnNvbih2LCBjb0Rwcywgc2VyaWFsaXplckZuKTtcclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB2YWx1ZSA9IHNlcmlhbGl6ZXJGbiA/IHNlcmlhbGl6ZXJGbihkcCwgdmFsdWUpIDogdmFsdWU7XHJcbiAgICAgIGlmIChkcC5pc1VubWFwcGVkKSB7XHJcbiAgICAgICAgdmFsdWUgPSBjb3JlLnRvSlNPTlNhZmUodmFsdWUsIGNvcmUudG9KU09OU2FmZVJlcGxhY2VyKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybjtcclxuICAgIHJlc3VsdFtkcE5hbWVdID0gdmFsdWU7XHJcbiAgfSk7XHJcblxyXG4gIC8vIGlmIChzby5lbnRpdHlBc3BlY3QpIHtcclxuICBpZiAoRW50aXR5QXNwZWN0LmlzRW50aXR5KHNvKSkge1xyXG4gICAgbGV0IGFzcGVjdCA9IHNvLmVudGl0eUFzcGVjdDtcclxuICAgIGxldCBlbnRpdHlTdGF0ZSA9IGFzcGVjdC5lbnRpdHlTdGF0ZTtcclxuICAgIGxldCBuZXdBc3BlY3QgPSB7XHJcbiAgICAgIHRlbXBOYXZQcm9wTmFtZXM6IGV4cG9ydFRlbXBLZXlJbmZvKGFzcGVjdCwgdGVtcEtleXMgfHwgW10pLFxyXG4gICAgICBlbnRpdHlTdGF0ZTogZW50aXR5U3RhdGUubmFtZVxyXG4gICAgfSBhcyBhbnk7XHJcbiAgICBpZiAoYXNwZWN0LmV4dHJhTWV0YWRhdGEpIHtcclxuICAgICAgbmV3QXNwZWN0LmV4dHJhTWV0YWRhdGEgPSBhc3BlY3QuZXh0cmFNZXRhZGF0YTtcclxuICAgIH1cclxuICAgIGlmIChlbnRpdHlTdGF0ZS5pc01vZGlmaWVkKCkgfHwgZW50aXR5U3RhdGUuaXNEZWxldGVkKCkpIHtcclxuICAgICAgbmV3QXNwZWN0Lm9yaWdpbmFsVmFsdWVzTWFwID0gYXNwZWN0Lm9yaWdpbmFsVmFsdWVzO1xyXG4gICAgfVxyXG4gICAgKHJlc3VsdCBhcyBhbnkpLmVudGl0eUFzcGVjdCA9IG5ld0FzcGVjdDtcclxuICB9IGVsc2Uge1xyXG4gICAgbGV0IGFzcGVjdCA9IHNvLmNvbXBsZXhBc3BlY3Q7XHJcbiAgICBsZXQgbmV3QXNwZWN0ID0ge30gYXMgYW55O1xyXG4gICAgaWYgKGFzcGVjdC5vcmlnaW5hbFZhbHVlcyAmJiAhY29yZS5pc0VtcHR5KGFzcGVjdC5vcmlnaW5hbFZhbHVlcykpIHtcclxuICAgICAgbmV3QXNwZWN0Lm9yaWdpbmFsVmFsdWVzTWFwID0gYXNwZWN0Lm9yaWdpbmFsVmFsdWVzO1xyXG4gICAgfVxyXG5cclxuICAgIChyZXN1bHQgYXMgYW55KS5jb21wbGV4QXNwZWN0ID0gbmV3QXNwZWN0O1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuaW50ZXJmYWNlIElUZW1wS2V5IHtcclxuICBlbnRpdHlUeXBlOiBzdHJpbmc7XHJcbiAgdmFsdWVzOiBhbnlbXTtcclxufVxyXG5cclxuZnVuY3Rpb24gZXhwb3J0VGVtcEtleUluZm8oZW50aXR5QXNwZWN0OiBFbnRpdHlBc3BlY3QsIHRlbXBLZXlzOiBJVGVtcEtleVtdKSB7XHJcbiAgbGV0IGVudGl0eSA9IGVudGl0eUFzcGVjdC5lbnRpdHkgYXMgRW50aXR5O1xyXG4gIGlmIChlbnRpdHlBc3BlY3QuaGFzVGVtcEtleSkge1xyXG4gICAgdGVtcEtleXMucHVzaChlbnRpdHlBc3BlY3QuZ2V0S2V5KCkudG9KU09OKCkpO1xyXG4gIH1cclxuICAvLyBjcmVhdGUgbWFwIGZvciB0aGlzIGVudGl0eSB3aXRoIGZvcmVpZ25LZXlzIHRoYXQgYXJlICd0ZW1wb3JhcnknXHJcbiAgLy8gbWFwIC0+IGtleTogdGVtcEtleSwgdmFsdWU6IGZrUHJvcE5hbWVcclxuICBsZXQgdGVtcE5hdlByb3BOYW1lczogc3RyaW5nW10gPSBbXTtcclxuICBlbnRpdHkuZW50aXR5VHlwZS5uYXZpZ2F0aW9uUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChucCkge1xyXG4gICAgaWYgKG5wLnJlbGF0ZWREYXRhUHJvcGVydGllcykge1xyXG4gICAgICBsZXQgcmVsYXRlZFZhbHVlID0gZW50aXR5LmdldFByb3BlcnR5KG5wLm5hbWUpO1xyXG4gICAgICBpZiAocmVsYXRlZFZhbHVlICYmIHJlbGF0ZWRWYWx1ZS5lbnRpdHlBc3BlY3QuaGFzVGVtcEtleSkge1xyXG4gICAgICAgIHRlbXBOYXZQcm9wTmFtZXMucHVzaChucC5uYW1lKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiB0ZW1wTmF2UHJvcE5hbWVzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBpbXBvcnRFbnRpdHlHcm91cChlbnRpdHlHcm91cDogRW50aXR5R3JvdXAsIGpzb25Hcm91cDogeyBlbnRpdGllczogYW55W10gfSwgaW1wb3J0Q29uZmlnOiBJbXBvcnRDb25maWdFeHQpIHtcclxuXHJcbiAgbGV0IHRlbXBLZXlNYXAgPSBpbXBvcnRDb25maWcudGVtcEtleU1hcDtcclxuICBsZXQgbWVyZ2VBZGRzID0gISFpbXBvcnRDb25maWcubWVyZ2VBZGRzO1xyXG5cclxuICBsZXQgZW50aXR5VHlwZSA9IGVudGl0eUdyb3VwLmVudGl0eVR5cGU7XHJcbiAgbGV0IG1lcmdlU3RyYXRlZ3kgPSBpbXBvcnRDb25maWcubWVyZ2VTdHJhdGVneTtcclxuXHJcbiAgbGV0IHRhcmdldEVudGl0eTogRW50aXR5IHwgdW5kZWZpbmVkO1xyXG5cclxuICBsZXQgZW0gPSBlbnRpdHlHcm91cC5lbnRpdHlNYW5hZ2VyO1xyXG4gIGxldCBlbnRpdHlDaGFuZ2VkID0gZW0uZW50aXR5Q2hhbmdlZDtcclxuICBsZXQgZW50aXRpZXNUb0xpbms6IEVudGl0eVtdID0gW107XHJcbiAgbGV0IHJhd1ZhbHVlRm4gPSBEYXRhUHJvcGVydHkuZ2V0UmF3VmFsdWVGcm9tQ2xpZW50O1xyXG4gIGpzb25Hcm91cC5lbnRpdGllcy5mb3JFYWNoKGZ1bmN0aW9uIChyYXdFbnRpdHk6IGFueSkge1xyXG4gICAgbGV0IG5ld0FzcGVjdCA9IHJhd0VudGl0eS5lbnRpdHlBc3BlY3Q7XHJcblxyXG4gICAgbGV0IGVudGl0eUtleSA9IGVudGl0eVR5cGUuZ2V0RW50aXR5S2V5RnJvbVJhd0VudGl0eShyYXdFbnRpdHksIHJhd1ZhbHVlRm4pO1xyXG4gICAgbGV0IGVudGl0eVN0YXRlID0gRW50aXR5U3RhdGUuZnJvbU5hbWUobmV3QXNwZWN0LmVudGl0eVN0YXRlKSBhcyBFbnRpdHlTdGF0ZTtcclxuICAgIGlmICghZW50aXR5U3RhdGUgfHwgZW50aXR5U3RhdGUgPT09IEVudGl0eVN0YXRlLkRldGFjaGVkKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgZW50aXRpZXMgd2l0aCBhIG5vbiBkZXRhY2hlZCBlbnRpdHkgc3RhdGUgbWF5IGJlIGltcG9ydGVkLlwiKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBNZXJnZSBpZiByYXcgZW50aXR5IGlzIGluIGNhY2hlIFVOTEVTUyB0aGlzIGlzIGEgbmV3IGVudGl0eSB3LyBhIHRlbXAga2V5XHJcbiAgICAvLyBDYW5ub3Qgc2FmZWx5IG1lcmdlIHN1Y2ggZW50aXRpZXMgZXZlbiBpZiBjb3VsZCBtYXRjaCB0ZW1wIGtleSB0byBhbiBlbnRpdHkgaW4gY2FjaGUuXHJcbiAgICAvLyBDYW4gZW5hYmxlIG1lcmdlIG9mIGVudGl0aWVzIHcvdGVtcCBrZXkgdXNpbmcgXCJtZXJnZUFkZHNcIiAtIHVzZSBhdCB5b3VyIG93biByaXNrIVxyXG4gICAgbGV0IG5ld1RlbXBLZXkgPSAhbWVyZ2VBZGRzICYmIGVudGl0eVN0YXRlLmlzQWRkZWQoKSAmJiBnZXRNYXBwZWRLZXkodGVtcEtleU1hcCEsIGVudGl0eUtleSk7XHJcbiAgICB0YXJnZXRFbnRpdHkgPSBuZXdUZW1wS2V5ID8gdW5kZWZpbmVkIDogZW50aXR5R3JvdXAuZmluZEVudGl0eUJ5S2V5KGVudGl0eUtleSk7XHJcblxyXG4gICAgaWYgKHRhcmdldEVudGl0eSkge1xyXG4gICAgICBpZiAobWVyZ2VTdHJhdGVneSA9PT0gTWVyZ2VTdHJhdGVneS5Ta2lwTWVyZ2UpIHtcclxuICAgICAgICAvLyBkZWxpYmVyYXRlIGZhbGwgdGhydVxyXG4gICAgICB9IGVsc2UgaWYgKG1lcmdlU3RyYXRlZ3kgPT09IE1lcmdlU3RyYXRlZ3kuRGlzYWxsb3dlZCkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkEgTWVyZ2VTdHJhdGVneSBvZiAnRGlzYWxsb3dlZCcgcHJldmVudHMgXCIgKyBlbnRpdHlLZXkudG9TdHJpbmcoKSArIFwiIGZyb20gYmVpbmcgbWVyZ2VkXCIpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGxldCB0YXJnZXRFbnRpdHlTdGF0ZSA9IHRhcmdldEVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGU7XHJcbiAgICAgICAgbGV0IHdhc1VuY2hhbmdlZCA9IHRhcmdldEVudGl0eVN0YXRlLmlzVW5jaGFuZ2VkKCk7XHJcbiAgICAgICAgaWYgKG1lcmdlU3RyYXRlZ3kgPT09IE1lcmdlU3RyYXRlZ3kuT3ZlcndyaXRlQ2hhbmdlcyB8fCB3YXNVbmNoYW5nZWQpIHtcclxuICAgICAgICAgIGVudGl0eVR5cGUuX3VwZGF0ZVRhcmdldEZyb21SYXcodGFyZ2V0RW50aXR5LCByYXdFbnRpdHksIHJhd1ZhbHVlRm4pO1xyXG4gICAgICAgICAgdGFyZ2V0RW50aXR5LmVudGl0eUFzcGVjdC5zZXRFbnRpdHlTdGF0ZShlbnRpdHlTdGF0ZSk7XHJcbiAgICAgICAgICBlbnRpdHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5NZXJnZU9uSW1wb3J0LCBlbnRpdHk6IHRhcmdldEVudGl0eSB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRhcmdldEVudGl0eSA9IGVudGl0eVR5cGUuX2NyZWF0ZUluc3RhbmNlQ29yZSgpIGFzIEVudGl0eTtcclxuICAgICAgZW50aXR5VHlwZS5fdXBkYXRlVGFyZ2V0RnJvbVJhdyh0YXJnZXRFbnRpdHksIHJhd0VudGl0eSwgcmF3VmFsdWVGbik7XHJcbiAgICAgIGlmIChuZXdUZW1wS2V5KSB7XHJcbiAgICAgICAgdGFyZ2V0RW50aXR5LmVudGl0eUFzcGVjdC5oYXNUZW1wS2V5ID0gdHJ1ZTtcclxuICAgICAgICAvLyBmaXh1cCBwa1xyXG4gICAgICAgIHRhcmdldEVudGl0eS5zZXRQcm9wZXJ0eShlbnRpdHlUeXBlLmtleVByb3BlcnRpZXNbMF0ubmFtZSwgbmV3VGVtcEtleS52YWx1ZXNbMF0pO1xyXG5cclxuICAgICAgICAvLyBmaXh1cCBmb3JlaWduIGtleXNcclxuICAgICAgICAvLyBUaGlzIGlzIHNhZmUgYmVjYXVzZSB0aGUgZW50aXR5IGlzIGRldGFjaGVkIGhlcmUgYW5kIHRoZXJlZm9yZSBvcmlnaW5hbFZhbHVlcyB3aWxsIG5vdCBiZSB1cGRhdGVkLlxyXG4gICAgICAgIGlmIChuZXdBc3BlY3QudGVtcE5hdlByb3BOYW1lcykge1xyXG4gICAgICAgICAgbmV3QXNwZWN0LnRlbXBOYXZQcm9wTmFtZXMuZm9yRWFjaChmdW5jdGlvbiAobnBOYW1lOiBzdHJpbmcpIHtcclxuICAgICAgICAgICAgbGV0IG5wID0gZW50aXR5VHlwZS5nZXROYXZpZ2F0aW9uUHJvcGVydHkobnBOYW1lKTtcclxuICAgICAgICAgICAgbGV0IGZrUHJvcE5hbWUgPSBucCEucmVsYXRlZERhdGFQcm9wZXJ0aWVzWzBdLm5hbWU7XHJcbiAgICAgICAgICAgIGxldCBvbGRGa1ZhbHVlID0gdGFyZ2V0RW50aXR5IS5nZXRQcm9wZXJ0eShma1Byb3BOYW1lKTtcclxuICAgICAgICAgICAgbGV0IGZrID0gbmV3IEVudGl0eUtleShucCEuZW50aXR5VHlwZSwgW29sZEZrVmFsdWVdKTtcclxuICAgICAgICAgICAgbGV0IG5ld0ZrID0gZ2V0TWFwcGVkS2V5KHRlbXBLZXlNYXAhLCBmayk7XHJcbiAgICAgICAgICAgIHRhcmdldEVudGl0eSEuc2V0UHJvcGVydHkoZmtQcm9wTmFtZSwgbmV3RmshLnZhbHVlc1swXSk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgLy8gTm93IHBlcmZvcm1lZCBpbiBhdHRhY2hFbnRpdHlcclxuICAgICAgdGFyZ2V0RW50aXR5ID0gZW50aXR5R3JvdXAuYXR0YWNoRW50aXR5KHRhcmdldEVudGl0eSwgZW50aXR5U3RhdGUpO1xyXG4gICAgICBlbnRpdHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5BdHRhY2hPbkltcG9ydCwgZW50aXR5OiB0YXJnZXRFbnRpdHkgfSk7XHJcbiAgICAgIGlmICghZW50aXR5U3RhdGUuaXNVbmNoYW5nZWQoKSkge1xyXG4gICAgICAgIGVtLl9ub3RpZnlTdGF0ZUNoYW5nZSh0YXJnZXRFbnRpdHksIHRydWUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgZW50aXRpZXNUb0xpbmsucHVzaCh0YXJnZXRFbnRpdHkpO1xyXG4gIH0pO1xyXG4gIHJldHVybiBlbnRpdGllc1RvTGluaztcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0TWFwcGVkS2V5KHRlbXBLZXlNYXA6IElUZW1wS2V5TWFwLCBlbnRpdHlLZXk6IEVudGl0eUtleSkge1xyXG4gIGxldCBuZXdLZXkgPSB0ZW1wS2V5TWFwW2VudGl0eUtleS50b1N0cmluZygpXTtcclxuICBpZiAobmV3S2V5KSByZXR1cm4gbmV3S2V5O1xyXG4gIGxldCBzdWJ0eXBlcyA9IGVudGl0eUtleS5fc3VidHlwZXM7XHJcbiAgaWYgKCFzdWJ0eXBlcykgcmV0dXJuIG51bGw7XHJcbiAgZm9yIChsZXQgaSA9IDAsIGogPSBzdWJ0eXBlcy5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuICAgIG5ld0tleSA9IHRlbXBLZXlNYXBbZW50aXR5S2V5LnRvU3RyaW5nKHN1YnR5cGVzW2ldKV07XHJcbiAgICBpZiAobmV3S2V5KSByZXR1cm4gbmV3S2V5O1xyXG4gIH1cclxuICByZXR1cm4gbnVsbDtcclxufVxyXG5cclxuZnVuY3Rpb24gcHJvbWlzZVdpdGhDYWxsYmFja3M8VD4ocHJvbWlzZTogUHJvbWlzZTxUPiwgY2FsbGJhY2s/OiBDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IEVycm9yQ2FsbGJhY2spIHtcclxuICBwcm9taXNlID0gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XHJcbiAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKGRhdGEpO1xyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKTtcclxuICB9LCBmdW5jdGlvbiAoZXJyb3IpIHtcclxuICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGVycm9yKTtcclxuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XHJcbiAgfSk7XHJcbiAgcmV0dXJuIHByb21pc2U7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEVudGl0aWVzVG9TYXZlKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdGllcz86IEVudGl0eVtdKSB7XHJcbiAgbGV0IGVudGl0aWVzVG9TYXZlOiBFbnRpdHlbXTtcclxuICBpZiAoZW50aXRpZXMpIHtcclxuICAgIGVudGl0aWVzVG9TYXZlID0gZW50aXRpZXMuZmlsdGVyKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIGlmIChlLmVudGl0eUFzcGVjdC5lbnRpdHlNYW5hZ2VyICE9PSBlbSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgZW50aXRpZXMgaW4gdGhpcyBlbnRpdHlNYW5hZ2VyIG1heSBiZSBzYXZlZFwiKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gIWUuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlLmlzRGV0YWNoZWQoKTtcclxuICAgIH0pO1xyXG4gIH0gZWxzZSB7XHJcbiAgICBlbnRpdGllc1RvU2F2ZSA9IGVtLmdldENoYW5nZXMoKTtcclxuICB9XHJcbiAgcmV0dXJuIGVudGl0aWVzVG9TYXZlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBmaXh1cEtleXMoZW06IEVudGl0eU1hbmFnZXIsIGtleU1hcHBpbmdzOiBLZXlNYXBwaW5nW10pIHtcclxuICBlbS5faW5LZXlGaXh1cCA9IHRydWU7XHJcbiAga2V5TWFwcGluZ3MuZm9yRWFjaChmdW5jdGlvbiAoa20pIHtcclxuICAgIGxldCBncm91cCA9IGVtLl9lbnRpdHlHcm91cE1hcFtrbS5lbnRpdHlUeXBlTmFtZV07XHJcbiAgICBpZiAoIWdyb3VwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBsb2NhdGUgdGhlIGZvbGxvd2luZyBmdWxseSBxdWFsaWZpZWQgRW50aXR5VHlwZSBuYW1lOiBcIiArIGttLmVudGl0eVR5cGVOYW1lKTtcclxuICAgIH1cclxuICAgIGdyb3VwLl9maXh1cEtleShrbS50ZW1wVmFsdWUsIGttLnJlYWxWYWx1ZSk7XHJcbiAgfSk7XHJcbiAgZW0uX2luS2V5Rml4dXAgPSBmYWxzZTtcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0RW50aXR5R3JvdXBzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10pIHtcclxuICBsZXQgZ3JvdXBNYXAgPSBlbS5fZW50aXR5R3JvdXBNYXA7XHJcbiAgaWYgKGVudGl0eVR5cGVzKSB7XHJcbiAgICByZXR1cm4gY29yZS50b0FycmF5KGVudGl0eVR5cGVzKS5tYXAoZnVuY3Rpb24gKGV0OiBFbnRpdHlUeXBlKSB7XHJcbiAgICAgIGlmIChldCBpbnN0YW5jZW9mIEVudGl0eVR5cGUpIHtcclxuICAgICAgICByZXR1cm4gZ3JvdXBNYXBbZXQubmFtZV07XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIEVudGl0eU1hbmFnZXIuZ2V0Q2hhbmdlcygpICdlbnRpdHlUeXBlcycgcGFyYW1ldGVyIG11c3QgYmUgZWl0aGVyIGFuIGVudGl0eVR5cGUgb3IgYW4gYXJyYXkgb2YgZW50aXR5VHlwZXMgb3IgbnVsbFwiKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIHJldHVybiBjb3JlLmdldE93blByb3BlcnR5VmFsdWVzKGdyb3VwTWFwKSBhcyBFbnRpdHlHcm91cFtdO1xyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gY2hlY2tFbnRpdHlLZXkoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eTogRW50aXR5KSB7XHJcbiAgbGV0IGVrID0gZW50aXR5LmVudGl0eUFzcGVjdC5nZXRLZXkoKTtcclxuICAvLyByZXR1cm4gcHJvcGVydGllcyB0aGF0IGFyZSA9IHRvIGRlZmF1bHRWYWx1ZXNcclxuICBsZXQga2V5UHJvcHNXaXRoRGVmYXVsdFZhbHVlcyA9IGNvcmUuYXJyYXlaaXAoZW50aXR5LmVudGl0eVR5cGUua2V5UHJvcGVydGllcywgZWsudmFsdWVzLCBmdW5jdGlvbiAoa3AsIGt2KSB7XHJcbiAgICByZXR1cm4gKGtwLmRlZmF1bHRWYWx1ZSA9PT0ga3YpID8ga3AgOiBudWxsO1xyXG4gIH0pLmZpbHRlcihmdW5jdGlvbiAoa3ApIHtcclxuICAgIHJldHVybiBrcCAhPT0gbnVsbDtcclxuICB9KTtcclxuICBpZiAoa2V5UHJvcHNXaXRoRGVmYXVsdFZhbHVlcy5sZW5ndGgpIHtcclxuICAgIGlmIChlbnRpdHkuZW50aXR5VHlwZS5hdXRvR2VuZXJhdGVkS2V5VHlwZSAhPT0gQXV0b0dlbmVyYXRlZEtleVR5cGUuTm9uZSkge1xyXG4gICAgICBlbS5nZW5lcmF0ZVRlbXBLZXlWYWx1ZShlbnRpdHkpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gd2Ugd2lsbCBhbGxvdyBhdHRhY2hlcyBvZiBlbnRpdGllcyB3aGVyZSBvbmx5IHBhcnQgb2YgdGhlIGtleSBpcyBzZXQuXHJcbiAgICAgIGlmIChrZXlQcm9wc1dpdGhEZWZhdWx0VmFsdWVzLmxlbmd0aCA9PT0gZWsudmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBhdHRhY2ggYW4gb2JqZWN0IG9mIHR5cGUgIChcIiArIGVudGl0eS5lbnRpdHlUeXBlLm5hbWUgKyBcIikgdG8gYW4gRW50aXR5TWFuYWdlciB3aXRob3V0IGZpcnN0IHNldHRpbmcgaXRzIGtleSBvciBzZXR0aW5nIGl0cyBlbnRpdHlUeXBlICdBdXRvR2VuZXJhdGVkS2V5VHlwZScgcHJvcGVydHkgdG8gc29tZXRoaW5nIG90aGVyIHRoYW4gJ05vbmUnXCIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiB2YWxpZGF0ZUVudGl0eVN0YXRlcyhlbTogRW50aXR5TWFuYWdlciwgZW50aXR5U3RhdGVzPzogRW50aXR5U3RhdGUgfCBFbnRpdHlTdGF0ZVtdKSB7XHJcbiAgaWYgKCFlbnRpdHlTdGF0ZXMpIHJldHVybiBbXSBhcyBFbnRpdHlTdGF0ZVtdO1xyXG4gIGxldCBlbnRTdGF0ZXMgPSBjb3JlLnRvQXJyYXkoZW50aXR5U3RhdGVzKSBhcyBFbnRpdHlTdGF0ZVtdO1xyXG4gIGVudFN0YXRlcy5mb3JFYWNoKChlcykgPT4ge1xyXG4gICAgaWYgKCEoZXMgaW5zdGFuY2VvZiBFbnRpdHlTdGF0ZSkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIEVudGl0eU1hbmFnZXIuZ2V0Q2hhbmdlcygpICdlbnRpdHlTdGF0ZXMnIHBhcmFtZXRlciBtdXN0IGVpdGhlciBiZSBudWxsLCBhbiBlbnRpdHlTdGF0ZSBvciBhbiBhcnJheSBvZiBlbnRpdHlTdGF0ZXNcIik7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIGVudFN0YXRlcztcclxufVxyXG5cclxuZnVuY3Rpb24gYXR0YWNoUmVsYXRlZEVudGl0aWVzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHk6IEVudGl0eSwgZW50aXR5U3RhdGU6IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5KSB7XHJcbiAgbGV0IG5hdlByb3BzID0gZW50aXR5LmVudGl0eVR5cGUubmF2aWdhdGlvblByb3BlcnRpZXM7XHJcbiAgbmF2UHJvcHMuZm9yRWFjaChmdW5jdGlvbiAobnApIHtcclxuICAgIGxldCByZWxhdGVkID0gZW50aXR5LmdldFByb3BlcnR5KG5wLm5hbWUpO1xyXG4gICAgaWYgKG5wLmlzU2NhbGFyKSB7XHJcbiAgICAgIGlmICghcmVsYXRlZCkgcmV0dXJuO1xyXG4gICAgICBlbS5hdHRhY2hFbnRpdHkocmVsYXRlZCwgZW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3kpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmVsYXRlZC5mb3JFYWNoKGZ1bmN0aW9uIChlOiBFbnRpdHkpIHtcclxuICAgICAgICBlbS5hdHRhY2hFbnRpdHkoZSwgZW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3kpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9KTtcclxufVxyXG5cclxuLy8gcmV0dXJucyBhIHByb21pc2VcclxuZnVuY3Rpb24gZXhlY3V0ZVF1ZXJ5Q29yZShlbTogRW50aXR5TWFuYWdlciwgcXVlcnk6IEVudGl0eVF1ZXJ5IHwgc3RyaW5nLCBxdWVyeU9wdGlvbnM6IFF1ZXJ5T3B0aW9ucywgZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlKTogUHJvbWlzZTxRdWVyeVJlc3VsdD4ge1xyXG4gIHRyeSB7XHJcbiAgICBsZXQgcmVzdWx0czogYW55W107XHJcbiAgICBsZXQgbWV0YWRhdGFTdG9yZSA9IGVtLm1ldGFkYXRhU3RvcmU7XHJcblxyXG4gICAgaWYgKG1ldGFkYXRhU3RvcmUuaXNFbXB0eSgpICYmIGRhdGFTZXJ2aWNlLmhhc1NlcnZlck1ldGFkYXRhKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImNhbm5vdCBleGVjdXRlIF9leGVjdXRlUXVlcnlDb3JlIHVudGlsIG1ldGFkYXRhU3RvcmUgaXMgcG9wdWxhdGVkLlwiKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAocXVlcnlPcHRpb25zLmZldGNoU3RyYXRlZ3kgPT09IEZldGNoU3RyYXRlZ3kuRnJvbUxvY2FsQ2FjaGUpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBpZiAodHlwZW9mIHF1ZXJ5ID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY2Fubm90IGV4ZWN1dGUgJ3N0cmluZycgRW50aXR5UXVlcnkgbG9jYWxseS5cIik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGxldCBxciA9IGV4ZWN1dGVRdWVyeUxvY2FsbHlDb3JlKGVtLCBxdWVyeSk7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IHJlc3VsdHM6IHFyLnJlc3VsdHMsIGVudGl0eU1hbmFnZXI6IGVtLCBpbmxpbmVDb3VudDogcXIuaW5saW5lQ291bnQsIHF1ZXJ5OiBxdWVyeSB9KTtcclxuICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBtYXBwaW5nQ29udGV4dDogTWFwcGluZ0NvbnRleHQgfCB1bmRlZmluZWQgPSBuZXcgTWFwcGluZ0NvbnRleHQoe1xyXG4gICAgICBxdWVyeTogcXVlcnksXHJcbiAgICAgIGVudGl0eU1hbmFnZXI6IGVtLFxyXG4gICAgICBkYXRhU2VydmljZTogZGF0YVNlcnZpY2UsXHJcbiAgICAgIG1lcmdlT3B0aW9uczoge1xyXG4gICAgICAgIG1lcmdlU3RyYXRlZ3k6IHF1ZXJ5T3B0aW9ucy5tZXJnZVN0cmF0ZWd5LFxyXG4gICAgICAgIG5vVHJhY2tpbmc6ICEhKHF1ZXJ5IGFzIGFueSkubm9UcmFja2luZ0VuYWJsZWQsXHJcbiAgICAgICAgaW5jbHVkZURlbGV0ZWQ6IHF1ZXJ5T3B0aW9ucy5pbmNsdWRlRGVsZXRlZFxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBsZXQgdmFsaWRhdGVPblF1ZXJ5ID0gZW0udmFsaWRhdGlvbk9wdGlvbnMudmFsaWRhdGVPblF1ZXJ5O1xyXG5cclxuICAgIHJldHVybiBkYXRhU2VydmljZS5hZGFwdGVySW5zdGFuY2UhLmV4ZWN1dGVRdWVyeShtYXBwaW5nQ29udGV4dCkudGhlbihmdW5jdGlvbiAoZGF0YTogYW55KSB7XHJcbiAgICAgIGxldCByZXN1bHQgPSBjb3JlLndyYXBFeGVjdXRpb24oZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGxldCBzdGF0ZSA9IHsgaXNMb2FkaW5nOiBlbS5pc0xvYWRpbmcgfTtcclxuICAgICAgICBlbS5pc0xvYWRpbmcgPSB0cnVlO1xyXG4gICAgICAgIGVtLl9wZW5kaW5nUHVicyA9IFtdO1xyXG4gICAgICAgIHJldHVybiBzdGF0ZTtcclxuICAgICAgfSwgZnVuY3Rpb24gKHN0YXRlKSB7XHJcbiAgICAgICAgLy8gY2xlYW51cFxyXG4gICAgICAgIGVtLmlzTG9hZGluZyA9IHN0YXRlLmlzTG9hZGluZztcclxuICAgICAgICBlbS5fcGVuZGluZ1B1YnMhLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7XHJcbiAgICAgICAgICBmbigpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGVtLl9wZW5kaW5nUHVicyA9IHVuZGVmaW5lZDtcclxuICAgICAgICBlbS5faGFzQ2hhbmdlc0FjdGlvbiAmJiBlbS5faGFzQ2hhbmdlc0FjdGlvbigpO1xyXG4gICAgICAgIC8vIFRPRE86IHJlbW92ZWQgLSBub3Qgc3VyZSB3aHkgbmVlZGVkIGluIGZpcnN0IHBsYWNlLi4uXHJcbiAgICAgICAgLy8gLy8gSEFDSyBmb3IgR0NcclxuICAgICAgICAvLyBxdWVyeSA9IHVuZGVmaW5lZDtcclxuICAgICAgICBtYXBwaW5nQ29udGV4dCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAvLyBIQUNLOiBzb21lIGVycm9ycyB0aHJvd24gaW4gbmV4dCBmdW5jdGlvbiBkbyBub3QgcHJvcG9nYXRlIHByb3Blcmx5IC0gdGhpcyBjYXRjaGVzIHRoZW0uXHJcblxyXG4gICAgICAgIGlmIChzdGF0ZS5lcnJvcikge1xyXG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHN0YXRlLmVycm9yKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICB9LCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgbGV0IG5vZGVzID0gZGF0YVNlcnZpY2UuanNvblJlc3VsdHNBZGFwdGVyLmV4dHJhY3RSZXN1bHRzKGRhdGEpO1xyXG4gICAgICAgIG5vZGVzID0gY29yZS50b0FycmF5KG5vZGVzKTtcclxuXHJcbiAgICAgICAgcmVzdWx0cyA9IG1hcHBpbmdDb250ZXh0IS52aXNpdEFuZE1lcmdlKG5vZGVzLCB7IG5vZGVUeXBlOiBcInJvb3RcIiB9KTtcclxuICAgICAgICBpZiAodmFsaWRhdGVPblF1ZXJ5KSB7XHJcbiAgICAgICAgICByZXN1bHRzLmZvckVhY2goZnVuY3Rpb24gKHI6IGFueSkge1xyXG4gICAgICAgICAgICAvLyBhbm9uIHR5cGVzIGFuZCBzaW1wbGUgdHlwZXMgd2lsbCBub3QgaGF2ZSBhbiBlbnRpdHlBc3BlY3QuXHJcbiAgICAgICAgICAgIHIuZW50aXR5QXNwZWN0ICYmIHIuZW50aXR5QXNwZWN0LnZhbGlkYXRlRW50aXR5KCk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbWFwcGluZ0NvbnRleHQhLnByb2Nlc3NEZWZlcnJlZCgpO1xyXG4gICAgICAgIC8vIGlmIHF1ZXJ5IGhhcyBleHBhbmQgY2xhdXNlcyB3YWxrIGVhY2ggb2YgdGhlICdyZXN1bHRzJyBhbmQgbWFyayB0aGUgZXhwYW5kZWQgcHJvcHMgYXMgbG9hZGVkLlxyXG4gICAgICAgIGlmIChxdWVyeSBpbnN0YW5jZW9mIEVudGl0eVF1ZXJ5KSB7XHJcbiAgICAgICAgICBtYXJrTG9hZGVkTmF2UHJvcHMocmVzdWx0cywgcXVlcnkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBsZXQgcmV0cmlldmVkRW50aXRpZXMgPSBjb3JlLm9iamVjdE1hcChtYXBwaW5nQ29udGV4dCEucmVmTWFwKTtcclxuICAgICAgICByZXR1cm4geyByZXN1bHRzOiByZXN1bHRzLCBxdWVyeTogcXVlcnksIGVudGl0eU1hbmFnZXI6IGVtLCBodHRwUmVzcG9uc2U6IGRhdGEuaHR0cFJlc3BvbnNlLCBpbmxpbmVDb3VudDogZGF0YS5pbmxpbmVDb3VudCwgcmV0cmlldmVkRW50aXRpZXM6IHJldHJpZXZlZEVudGl0aWVzIH07XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XHJcbiAgICB9LCBmdW5jdGlvbiAoZTogYW55KSB7XHJcbiAgICAgIGlmIChlKSB7XHJcbiAgICAgICAgZS5xdWVyeSA9IHF1ZXJ5O1xyXG4gICAgICAgIGUuZW50aXR5TWFuYWdlciA9IGVtO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcclxuICAgIH0pO1xyXG5cclxuICB9IGNhdGNoIChlKSB7XHJcbiAgICBpZiAoZSkge1xyXG4gICAgICBlLnF1ZXJ5ID0gcXVlcnk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBtYXJrTG9hZGVkTmF2UHJvcHMoZW50aXRpZXM6IEVudGl0eVtdLCBxdWVyeTogRW50aXR5UXVlcnkpIHtcclxuICBpZiAocXVlcnkubm9UcmFja2luZ0VuYWJsZWQpIHJldHVybjtcclxuICBsZXQgZXhwYW5kQ2xhdXNlID0gcXVlcnkuZXhwYW5kQ2xhdXNlO1xyXG4gIGlmIChleHBhbmRDbGF1c2UgPT0gbnVsbCkgcmV0dXJuO1xyXG4gIGV4cGFuZENsYXVzZS5wcm9wZXJ0eVBhdGhzLmZvckVhY2goZnVuY3Rpb24gKHByb3BlcnR5UGF0aCkge1xyXG4gICAgbGV0IHByb3BOYW1lcyA9IHByb3BlcnR5UGF0aC5zcGxpdCgnLicpO1xyXG4gICAgbWFya0xvYWRlZE5hdlBhdGgoZW50aXRpZXMsIHByb3BOYW1lcyk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIG1hcmtMb2FkZWROYXZQYXRoKGVudGl0aWVzOiBFbnRpdHlbXSwgcHJvcE5hbWVzOiBzdHJpbmdbXSkge1xyXG4gIGxldCBwcm9wTmFtZSA9IHByb3BOYW1lc1swXTtcclxuICBlbnRpdGllcy5mb3JFYWNoKChlbnRpdHkpID0+IHtcclxuICAgIGxldCBlYSA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICBpZiAoIWVhKSByZXR1cm47IC8vIGVudGl0eSBtYXkgbm90IGJlIGEgJ3JlYWwnIGVudGl0eSBpbiB0aGUgY2FzZSBvZiBhIHByb2plY3Rpb24uXHJcbiAgICBlYS5fbWFya0FzTG9hZGVkKHByb3BOYW1lKTtcclxuICAgIGlmIChwcm9wTmFtZXMubGVuZ3RoID09PSAxKSByZXR1cm47XHJcbiAgICBsZXQgbmV4dCA9IGVudGl0eS5nZXRQcm9wZXJ0eShwcm9wTmFtZSk7XHJcbiAgICBpZiAoIW5leHQpIHJldHVybjsgLy8gbm8gY2hpbGRyZW4gdG8gcHJvY2Vzcy5cclxuICAgIC8vIHN0cmFuZ2UgbG9naWMgYmVjYXVzZSBub25zY2FsYXIgbmF2IHZhbHVlcyBhcmUgTk9UIHJlYWxseSBhcnJheXNcclxuICAgIC8vIG90aGVyd2lzZSB3ZSBjb3VsZCB1c2UgQXJyYXkuaXNBcnJheVxyXG4gICAgaWYgKCFuZXh0LmFycmF5Q2hhbmdlZCkgbmV4dCA9IFtuZXh0XTtcclxuICAgIG1hcmtMb2FkZWROYXZQYXRoKG5leHQsIHByb3BOYW1lcy5zbGljZSgxKSk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVwZGF0ZUNvbmN1cnJlbmN5UHJvcGVydGllcyhlbnRpdGllczogRW50aXR5W10pIHtcclxuICBsZXQgY2FuZGlkYXRlcyA9IGVudGl0aWVzLmZpbHRlcigoZSkgPT4ge1xyXG4gICAgZS5lbnRpdHlBc3BlY3QuaXNCZWluZ1NhdmVkID0gdHJ1ZTtcclxuICAgIHJldHVybiBlLmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZS5pc01vZGlmaWVkKClcclxuICAgICAgJiYgZS5lbnRpdHlUeXBlLmNvbmN1cnJlbmN5UHJvcGVydGllcy5sZW5ndGggPiAwO1xyXG5cclxuICB9KTtcclxuICBpZiAoY2FuZGlkYXRlcy5sZW5ndGggPT09IDApIHJldHVybjtcclxuICBjYW5kaWRhdGVzLmZvckVhY2goZnVuY3Rpb24gKGMpIHtcclxuICAgIGMuZW50aXR5VHlwZS5jb25jdXJyZW5jeVByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAoY3ApIHtcclxuICAgICAgdXBkYXRlQ29uY3VycmVuY3lQcm9wZXJ0eShjLCBjcCk7XHJcbiAgICB9KTtcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gdXBkYXRlQ29uY3VycmVuY3lQcm9wZXJ0eShlbnRpdHk6IEVudGl0eSwgcHJvcGVydHk6IERhdGFQcm9wZXJ0eSkge1xyXG4gIC8vIGNoZWNrIGlmIHByb3BlcnR5IGhhcyBhbHJlYWR5IGJlZW4gdXBkYXRlZFxyXG4gIGlmIChlbnRpdHkuZW50aXR5QXNwZWN0Lm9yaWdpbmFsVmFsdWVzW3Byb3BlcnR5Lm5hbWVdKSByZXR1cm47XHJcbiAgbGV0IHZhbHVlID0gZW50aXR5LmdldFByb3BlcnR5KHByb3BlcnR5Lm5hbWUpO1xyXG4gIGxldCBkYXRhVHlwZSA9IHByb3BlcnR5LmRhdGFUeXBlIGFzIERhdGFUeXBlO1xyXG4gIGlmICghdmFsdWUpIHZhbHVlID0gZGF0YVR5cGUuZGVmYXVsdFZhbHVlO1xyXG4gIGlmIChkYXRhVHlwZS5pc051bWVyaWMpIHtcclxuICAgIGVudGl0eS5zZXRQcm9wZXJ0eShwcm9wZXJ0eS5uYW1lLCB2YWx1ZSArIDEpO1xyXG4gIH0gZWxzZSBpZiAoZGF0YVR5cGUuZ2V0Q29uY3VycmVuY3lWYWx1ZSkge1xyXG4gICAgLy8gRGF0YVR5cGUgaGFzIGl0cyBvd24gaW1wbGVtZW50YXRpb25cclxuICAgIGxldCBuZXh0VmFsdWUgPSBkYXRhVHlwZS5nZXRDb25jdXJyZW5jeVZhbHVlKHZhbHVlKTtcclxuICAgIGVudGl0eS5zZXRQcm9wZXJ0eShwcm9wZXJ0eS5uYW1lLCBuZXh0VmFsdWUpO1xyXG4gIH0gZWxzZSBpZiAoZGF0YVR5cGUgPT09IERhdGFUeXBlLkJpbmFyeSkge1xyXG4gICAgLy8gYmVzdCBndWVzcyAtIHRoYXQgdGhpcyBpcyBhIHRpbWVzdGFtcCBjb2x1bW4gYW5kIGlzIGNvbXB1dGVkIG9uIHRoZSBzZXJ2ZXIgZHVyaW5nIHNhdmVcclxuICAgIC8vIC0gc28gbm8gbmVlZCB0byBzZXQgaXQgaGVyZS5cclxuICAgIHJldHVybjtcclxuICB9IGVsc2Uge1xyXG4gICAgLy8gdGhpcyBqdXN0IGxlYXZlcyBEYXRhVHlwZXMgb2YgQm9vbGVhbiwgU3RyaW5nIGFuZCBCeXRlIC0gbm9uZSBvZiB3aGljaCBzaG91bGQgYmUgdGhlXHJcbiAgICAvLyB0eXBlIGZvciBhIGNvbmN1cnJlbmN5IGNvbHVtbi5cclxuICAgIC8vIE5PVEU6IHRob3VnaHQgYWJvdXQganVzdCByZXR1cm5pbmcgaGVyZSBidXQgd291bGQgcmF0aGVyIGJlIHNhZmUgZm9yIG5vdy5cclxuICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byB1cGRhdGUgdGhlIHZhbHVlIG9mIGNvbmN1cnJlbmN5IHByb3BlcnR5IGJlZm9yZSBzYXZpbmc6IFwiICsgcHJvcGVydHkubmFtZSk7XHJcbiAgfVxyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gZmluZE9yQ3JlYXRlRW50aXR5R3JvdXAoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVR5cGU6IEVudGl0eVR5cGUpIHtcclxuICBsZXQgZ3JvdXAgPSBlbS5fZW50aXR5R3JvdXBNYXBbZW50aXR5VHlwZS5uYW1lXTtcclxuICBpZiAoIWdyb3VwKSB7XHJcbiAgICBncm91cCA9IG5ldyBFbnRpdHlHcm91cChlbSwgZW50aXR5VHlwZSk7XHJcbiAgICBlbS5fZW50aXR5R3JvdXBNYXBbZW50aXR5VHlwZS5uYW1lXSA9IGdyb3VwO1xyXG4gIH1cclxuICByZXR1cm4gZ3JvdXA7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZpbmRPckNyZWF0ZUVudGl0eUdyb3VwcyhlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZTogRW50aXR5VHlwZSkge1xyXG4gIGxldCBlbnRpdHlUeXBlcyA9IGVudGl0eVR5cGUuZ2V0U2VsZkFuZFN1YnR5cGVzKCk7XHJcbiAgcmV0dXJuIGVudGl0eVR5cGVzLm1hcCgoZXQpID0+IHtcclxuICAgIHJldHVybiBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cChlbSwgZXQpO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiB1bndyYXBJbnN0YW5jZShzdHJ1Y3RPYmo6IFN0cnVjdHVyYWxPYmplY3QsIHRyYW5zZm9ybUZuPzogKGRwOiBEYXRhUHJvcGVydHksIHZhbDogYW55KSA9PiBhbnkpIHtcclxuXHJcbiAgbGV0IHJhd09iamVjdDogYW55ID0ge307XHJcbiAgbGV0IHN0eXBlID0gRW50aXR5QXNwZWN0LmlzRW50aXR5KHN0cnVjdE9iaikgPyBzdHJ1Y3RPYmouZW50aXR5VHlwZSA6IHN0cnVjdE9iai5jb21wbGV4VHlwZTtcclxuICBsZXQgc2VyaWFsaXplckZuID0gZ2V0U2VyaWFsaXplckZuKHN0eXBlKTtcclxuICBsZXQgdW5tYXBwZWQgPSB7fTtcclxuICBzdHlwZS5kYXRhUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChkcCkge1xyXG4gICAgaWYgKGRwLmlzQ29tcGxleFByb3BlcnR5KSB7XHJcbiAgICAgIHJhd09iamVjdFtkcC5uYW1lT25TZXJ2ZXJdID0gY29yZS5tYXAoc3RydWN0T2JqLmdldFByb3BlcnR5KGRwLm5hbWUpLCBmdW5jdGlvbiAoY28pIHtcclxuICAgICAgICByZXR1cm4gdW53cmFwSW5zdGFuY2UoY28sIHRyYW5zZm9ybUZuKTtcclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXQgdmFsID0gc3RydWN0T2JqLmdldFByb3BlcnR5KGRwLm5hbWUpO1xyXG4gICAgICB2YWwgPSB0cmFuc2Zvcm1GbiA/IHRyYW5zZm9ybUZuKGRwLCB2YWwpIDogdmFsO1xyXG4gICAgICBpZiAodmFsID09PSB1bmRlZmluZWQpIHJldHVybjtcclxuICAgICAgdmFsID0gc2VyaWFsaXplckZuID8gc2VyaWFsaXplckZuKGRwLCB2YWwpIDogdmFsO1xyXG4gICAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICBpZiAoZHAuaXNVbm1hcHBlZCkge1xyXG4gICAgICAgICAgdW5tYXBwZWRbZHAubmFtZU9uU2VydmVyXSA9IGNvcmUudG9KU09OU2FmZSh2YWwsIGNvcmUudG9KU09OU2FmZVJlcGxhY2VyKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgcmF3T2JqZWN0W2RwLm5hbWVPblNlcnZlcl0gPSB2YWw7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSk7XHJcblxyXG4gIGlmICghY29yZS5pc0VtcHR5KHVubWFwcGVkKSkge1xyXG4gICAgLy8gVE9ETzogcmV2aWV3IHRoaXMuXHJcbiAgICAocmF3T2JqZWN0IGFzIGFueSkuX191bm1hcHBlZCA9IHVubWFwcGVkO1xyXG4gIH1cclxuICByZXR1cm4gcmF3T2JqZWN0O1xyXG59XHJcblxyXG5mdW5jdGlvbiB1bndyYXBPcmlnaW5hbFZhbHVlcyh0YXJnZXQ6IFN0cnVjdHVyYWxPYmplY3QsIG1ldGFkYXRhU3RvcmU6IE1ldGFkYXRhU3RvcmUsIHRyYW5zZm9ybUZuPzogKGRwOiBEYXRhUHJvcGVydHksIHZhbDogYW55KSA9PiBhbnkpIHtcclxuICBsZXQgc3R5cGUgPSBFbnRpdHlBc3BlY3QuaXNFbnRpdHkodGFyZ2V0KSA/IHRhcmdldC5lbnRpdHlUeXBlIDogdGFyZ2V0LmNvbXBsZXhUeXBlO1xyXG4gIGxldCBhc3BlY3QgPSBFbnRpdHlBc3BlY3QuaXNFbnRpdHkodGFyZ2V0KSA/IHRhcmdldC5lbnRpdHlBc3BlY3QgOiB0YXJnZXQuY29tcGxleEFzcGVjdDtcclxuICBsZXQgZm4gPSBtZXRhZGF0YVN0b3JlLm5hbWluZ0NvbnZlbnRpb24uY2xpZW50UHJvcGVydHlOYW1lVG9TZXJ2ZXI7XHJcbiAgbGV0IHJlc3VsdCA9IHt9O1xyXG4gIGNvcmUub2JqZWN0Rm9yRWFjaChhc3BlY3Qub3JpZ2luYWxWYWx1ZXMsIGZ1bmN0aW9uIChwcm9wTmFtZSwgdmFsKSB7XHJcbiAgICBsZXQgcHJvcCA9IHN0eXBlLmdldFByb3BlcnR5KHByb3BOYW1lKSBhcyBEYXRhUHJvcGVydHk7XHJcbiAgICB2YWwgPSB0cmFuc2Zvcm1GbiA/IHRyYW5zZm9ybUZuKHByb3AsIHZhbCkgOiB2YWw7XHJcbiAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmVzdWx0W2ZuKHByb3BOYW1lLCBwcm9wKV0gPSB2YWw7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgc3R5cGUuY29tcGxleFByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAoY3ApIHtcclxuICAgIGxldCBuZXh0VGFyZ2V0ID0gdGFyZ2V0LmdldFByb3BlcnR5KGNwLm5hbWUpO1xyXG4gICAgaWYgKGNwLmlzU2NhbGFyKSB7XHJcbiAgICAgIGxldCB1bndyYXBwZWRDbyA9IHVud3JhcE9yaWdpbmFsVmFsdWVzKG5leHRUYXJnZXQsIG1ldGFkYXRhU3RvcmUsIHRyYW5zZm9ybUZuKTtcclxuICAgICAgaWYgKCFjb3JlLmlzRW1wdHkodW53cmFwcGVkQ28pKSB7XHJcbiAgICAgICAgcmVzdWx0W2ZuKGNwLm5hbWUsIGNwKV0gPSB1bndyYXBwZWRDbztcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgbGV0IHVud3JhcHBlZENvcyA9IG5leHRUYXJnZXQubWFwKChpdGVtOiBhbnkpID0+IHtcclxuICAgICAgICByZXR1cm4gdW53cmFwT3JpZ2luYWxWYWx1ZXMoaXRlbSwgbWV0YWRhdGFTdG9yZSwgdHJhbnNmb3JtRm4pO1xyXG4gICAgICB9KTtcclxuICAgICAgcmVzdWx0W2ZuKGNwLm5hbWUsIGNwKV0gPSB1bndyYXBwZWRDb3M7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZnVuY3Rpb24gdW53cmFwQ2hhbmdlZFZhbHVlcyhlbnRpdHk6IEVudGl0eSwgbWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSwgdHJhbnNmb3JtRm46IChkcDogRGF0YVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55KSB7XHJcbiAgbGV0IHN0eXBlID0gZW50aXR5LmVudGl0eVR5cGU7XHJcbiAgbGV0IHNlcmlhbGl6ZXJGbiA9IGdldFNlcmlhbGl6ZXJGbihzdHlwZSk7XHJcbiAgbGV0IGZuID0gbWV0YWRhdGFTdG9yZS5uYW1pbmdDb252ZW50aW9uLmNsaWVudFByb3BlcnR5TmFtZVRvU2VydmVyO1xyXG4gIGxldCByZXN1bHQgPSB7fTtcclxuICBjb3JlLm9iamVjdEZvckVhY2goZW50aXR5LmVudGl0eUFzcGVjdC5vcmlnaW5hbFZhbHVlcywgZnVuY3Rpb24gKHByb3BOYW1lLCB2YWx1ZSkge1xyXG4gICAgbGV0IHByb3AgPSBzdHlwZS5nZXRQcm9wZXJ0eShwcm9wTmFtZSkgYXMgRGF0YVByb3BlcnR5O1xyXG4gICAgbGV0IHZhbCA9IGVudGl0eS5nZXRQcm9wZXJ0eShwcm9wTmFtZSk7XHJcbiAgICB2YWwgPSB0cmFuc2Zvcm1GbiA/IHRyYW5zZm9ybUZuKHByb3AsIHZhbCkgOiB2YWw7XHJcbiAgICBpZiAodmFsID09PSB1bmRlZmluZWQpIHJldHVybjtcclxuICAgIHZhbCA9IHNlcmlhbGl6ZXJGbiA/IHNlcmlhbGl6ZXJGbihwcm9wLCB2YWwpIDogdmFsO1xyXG4gICAgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJlc3VsdFtmbihwcm9wTmFtZSwgcHJvcCldID0gdmFsO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIC8vIGFueSBjaGFuZ2UgdG8gYW55IGNvbXBsZXggb2JqZWN0IG9yIGFycmF5IG9mIGNvbXBsZXggb2JqZWN0cyByZXR1cm5zIHRoZSBFTlRJUkVcclxuICAvLyBjdXJyZW50IGNvbXBsZXggb2JqZWN0IG9yIGNvbXBsZXggb2JqZWN0IGFycmF5LiAgVGhpcyBpcyBieSBkZXNpZ24uIENvbXBsZXggT2JqZWN0c1xyXG4gIC8vIGFyZSBhdG9taWMuXHJcbiAgc3R5cGUuY29tcGxleFByb3BlcnRpZXMuZm9yRWFjaCgoY3ApID0+IHtcclxuICAgIGlmIChjcEhhc09yaWdpbmFsVmFsdWVzKGVudGl0eSwgY3ApKSB7XHJcbiAgICAgIGxldCBjb09yQ29zID0gZW50aXR5LmdldFByb3BlcnR5KGNwLm5hbWUpO1xyXG4gICAgICByZXN1bHRbZm4oY3AubmFtZSwgY3ApXSA9IGNvcmUubWFwKGNvT3JDb3MsIGZ1bmN0aW9uIChjbykge1xyXG4gICAgICAgIHJldHVybiB1bndyYXBJbnN0YW5jZShjbywgdHJhbnNmb3JtRm4pO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9KTtcclxuICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5mdW5jdGlvbiBjcEhhc09yaWdpbmFsVmFsdWVzKHN0cnVjdHVyYWxPYmplY3Q6IFN0cnVjdHVyYWxPYmplY3QsIGNwOiBEYXRhUHJvcGVydHkpOiBib29sZWFuIHtcclxuICBsZXQgY29PckNvcyA9IHN0cnVjdHVyYWxPYmplY3QuZ2V0UHJvcGVydHkoY3AubmFtZSk7XHJcbiAgaWYgKGNwLmlzU2NhbGFyKSB7XHJcbiAgICByZXR1cm4gY29IYXNPcmlnaW5hbFZhbHVlcyhjb09yQ29zKTtcclxuICB9IGVsc2Uge1xyXG4gICAgLy8gdGhpcyBvY2N1cnMgd2hlbiBhIG5vbnNjYWxhciBjbyBhcnJheSBoYXMgaGFkIGNvcyBhZGRlZCBvciByZW1vdmVkLlxyXG4gICAgaWYgKGNvT3JDb3MuX29yaWdWYWx1ZXMpIHJldHVybiB0cnVlO1xyXG4gICAgcmV0dXJuIGNvT3JDb3Muc29tZShmdW5jdGlvbiAoY286IENvbXBsZXhPYmplY3QpIHtcclxuICAgICAgcmV0dXJuIGNvSGFzT3JpZ2luYWxWYWx1ZXMoY28pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBleGVjdXRlUXVlcnlMb2NhbGx5Q29yZShlbTogRW50aXR5TWFuYWdlciwgcXVlcnk6IEVudGl0eVF1ZXJ5KSB7XHJcbiAgYXNzZXJ0UGFyYW0ocXVlcnksIFwicXVlcnlcIikuaXNJbnN0YW5jZU9mKEVudGl0eVF1ZXJ5KS5jaGVjaygpO1xyXG5cclxuICBsZXQgbWV0YWRhdGFTdG9yZSA9IGVtLm1ldGFkYXRhU3RvcmU7XHJcbiAgbGV0IGVudGl0eVR5cGUgPSBxdWVyeS5fZ2V0RnJvbUVudGl0eVR5cGUobWV0YWRhdGFTdG9yZSwgdHJ1ZSk7XHJcbiAgLy8gdGhlcmUgbWF5IGJlIG11bHRpcGxlIGdyb3VwcyBpcyB0aGlzIGlzIGEgYmFzZSBlbnRpdHkgdHlwZS5cclxuICBsZXQgZ3JvdXBzID0gZmluZE9yQ3JlYXRlRW50aXR5R3JvdXBzKGVtLCBlbnRpdHlUeXBlISk7XHJcbiAgLy8gZmlsdGVyIHRoZW4gb3JkZXIgdGhlbiBza2lwIHRoZW4gdGFrZVxyXG4gIGxldCBmaWx0ZXJGdW5jID0gcXVlcnkud2hlcmVQcmVkaWNhdGUgJiYgcXVlcnkud2hlcmVQcmVkaWNhdGUudG9GdW5jdGlvbih7IGVudGl0eVR5cGU6IGVudGl0eVR5cGUgfSk7XHJcblxyXG4gIGxldCBxdWVyeU9wdGlvbnMgPSBRdWVyeU9wdGlvbnMucmVzb2x2ZShbcXVlcnkucXVlcnlPcHRpb25zLCBlbS5xdWVyeU9wdGlvbnMsIFF1ZXJ5T3B0aW9ucy5kZWZhdWx0SW5zdGFuY2VdKTtcclxuICBsZXQgaW5jbHVkZURlbGV0ZWQgPSBxdWVyeU9wdGlvbnMuaW5jbHVkZURlbGV0ZWQgPT09IHRydWU7XHJcblxyXG4gIGxldCBuZXdGaWx0ZXJGdW5jID0gZnVuY3Rpb24gKGVudGl0eTogRW50aXR5KSB7XHJcbiAgICByZXR1cm4gZW50aXR5ICYmIChpbmNsdWRlRGVsZXRlZCB8fCAhZW50aXR5LmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZS5pc0RlbGV0ZWQoKSkgJiYgKGZpbHRlckZ1bmMgPyBmaWx0ZXJGdW5jKGVudGl0eSkgOiB0cnVlKTtcclxuICB9O1xyXG5cclxuICBsZXQgcmVzdWx0OiBhbnlbXSA9IFtdO1xyXG4gIC8vIFRPRE86IG1hcE1hbnlcclxuICBncm91cHMuZm9yRWFjaCgoZ3JvdXApID0+IHtcclxuICAgIGxldCBlbnRpdGllcyA9IGdyb3VwLl9lbnRpdGllcy5maWx0ZXIobmV3RmlsdGVyRnVuYykgYXMgRW50aXR5W107XHJcbiAgICBpZiAoZW50aXRpZXMubGVuZ3RoKSB7XHJcbiAgICAgIHJlc3VsdCA9IHJlc3VsdC5sZW5ndGggPyByZXN1bHQuY29uY2F0KGVudGl0aWVzKSA6IGVudGl0aWVzO1xyXG4gICAgfVxyXG4gIH0pO1xyXG5cclxuICBsZXQgb3JkZXJCeUNvbXBhcmVyID0gcXVlcnkub3JkZXJCeUNsYXVzZSAmJiBxdWVyeS5vcmRlckJ5Q2xhdXNlLmdldENvbXBhcmVyKGVudGl0eVR5cGUhKTtcclxuICBpZiAob3JkZXJCeUNvbXBhcmVyKSB7XHJcbiAgICByZXN1bHQuc29ydChvcmRlckJ5Q29tcGFyZXIpO1xyXG4gIH1cclxuXHJcbiAgbGV0IGlubGluZUNvdW50ID0gcXVlcnkuaW5saW5lQ291bnRFbmFibGVkID8gcmVzdWx0Lmxlbmd0aCA6IHVuZGVmaW5lZDtcclxuXHJcbiAgbGV0IHNraXBDb3VudCA9IHF1ZXJ5LnNraXBDb3VudDtcclxuICBpZiAoc2tpcENvdW50KSB7XHJcbiAgICByZXN1bHQgPSByZXN1bHQuc2xpY2Uoc2tpcENvdW50KTtcclxuICB9XHJcbiAgbGV0IHRha2VDb3VudCA9IHF1ZXJ5LnRha2VDb3VudDtcclxuICBpZiAodGFrZUNvdW50KSB7XHJcbiAgICByZXN1bHQgPSByZXN1bHQuc2xpY2UoMCwgdGFrZUNvdW50KTtcclxuICB9XHJcblxyXG4gIGxldCBzZWxlY3RDbGF1c2UgPSBxdWVyeS5zZWxlY3RDbGF1c2U7XHJcbiAgaWYgKHNlbGVjdENsYXVzZSkge1xyXG4gICAgbGV0IHNlbGVjdEZuID0gc2VsZWN0Q2xhdXNlLnRvRnVuY3Rpb24oKTtcclxuICAgIHJlc3VsdCA9IHJlc3VsdC5tYXAoc2VsZWN0Rm4pO1xyXG4gIH1cclxuICByZXR1cm4geyByZXN1bHRzOiByZXN1bHQsIGlubGluZUNvdW50OiBpbmxpbmVDb3VudCB9O1xyXG59XHJcblxyXG5mdW5jdGlvbiBjb0hhc09yaWdpbmFsVmFsdWVzKGNvOiBDb21wbGV4T2JqZWN0KSB7XHJcbiAgLy8gbmV4dCBsaW5lIGNoZWNrcyBhbGwgbm9uIGNvbXBsZXggcHJvcGVydGllcyBvZiB0aGUgY28uXHJcbiAgaWYgKCFjb3JlLmlzRW1wdHkoY28uY29tcGxleEFzcGVjdC5vcmlnaW5hbFZhbHVlcykpIHJldHVybiB0cnVlO1xyXG4gIC8vIG5vdyBuZWVkIHRvIHJlY3Vyc2l2ZWx5IGNoZWNrIGVhY2ggb2YgdGhlIGNwc1xyXG4gIHJldHVybiBjby5jb21wbGV4VHlwZS5jb21wbGV4UHJvcGVydGllcy5zb21lKGZ1bmN0aW9uIChjcCkge1xyXG4gICAgcmV0dXJuIGNwSGFzT3JpZ2luYWxWYWx1ZXMoY28sIGNwKTtcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0U2VyaWFsaXplckZuKHN0eXBlOiBFbnRpdHlUeXBlIHwgQ29tcGxleFR5cGUpIHtcclxuICByZXR1cm4gc3R5cGUuc2VyaWFsaXplckZuIHx8IChzdHlwZS5tZXRhZGF0YVN0b3JlICYmIHN0eXBlLm1ldGFkYXRhU3RvcmUuc2VyaWFsaXplckZuKTtcclxufVxyXG5cclxuIl19