breeze-client 2.2.0 → 2.2.1-cjs

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 (377) hide show
  1. package/adapter-ajax-angularjs/{index.d.ts → breeze-client-adapter-ajax-angularjs.d.ts} +0 -1
  2. package/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.metadata.json +1 -0
  3. package/adapter-ajax-angularjs/package.json +13 -0
  4. package/adapter-ajax-fetch/{index.d.ts → breeze-client-adapter-ajax-fetch.d.ts} +0 -1
  5. package/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.metadata.json +1 -0
  6. package/adapter-ajax-fetch/package.json +13 -0
  7. package/adapter-ajax-httpclient/{index.d.ts → breeze-client-adapter-ajax-httpclient.d.ts} +0 -1
  8. package/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.metadata.json +1 -0
  9. package/adapter-ajax-httpclient/package.json +13 -0
  10. package/adapter-ajax-jquery/{index.d.ts → breeze-client-adapter-ajax-jquery.d.ts} +0 -1
  11. package/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.metadata.json +1 -0
  12. package/adapter-ajax-jquery/package.json +13 -0
  13. package/adapter-ajax-post/{index.d.ts → breeze-client-adapter-ajax-post.d.ts} +0 -1
  14. package/adapter-ajax-post/breeze-client-adapter-ajax-post.metadata.json +1 -0
  15. package/adapter-ajax-post/package.json +13 -0
  16. package/adapter-data-service-odata/{index.d.ts → breeze-client-adapter-data-service-odata.d.ts} +0 -1
  17. package/adapter-data-service-odata/breeze-client-adapter-data-service-odata.metadata.json +1 -0
  18. package/adapter-data-service-odata/package.json +13 -0
  19. package/adapter-data-service-webapi/{index.d.ts → breeze-client-adapter-data-service-webapi.d.ts} +0 -1
  20. package/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.metadata.json +1 -0
  21. package/adapter-data-service-webapi/package.json +13 -0
  22. package/adapter-model-library-backing-store/{index.d.ts → breeze-client-adapter-model-library-backing-store.d.ts} +0 -1
  23. package/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.metadata.json +1 -0
  24. package/adapter-model-library-backing-store/package.json +13 -0
  25. package/adapter-model-library-ko/{index.d.ts → breeze-client-adapter-model-library-ko.d.ts} +0 -1
  26. package/adapter-model-library-ko/breeze-client-adapter-model-library-ko.metadata.json +1 -0
  27. package/adapter-model-library-ko/package.json +13 -0
  28. package/adapter-uri-builder-json/{index.d.ts → breeze-client-adapter-uri-builder-json.d.ts} +0 -1
  29. package/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.metadata.json +1 -0
  30. package/adapter-uri-builder-json/package.json +13 -0
  31. package/adapter-uri-builder-odata/{index.d.ts → breeze-client-adapter-uri-builder-odata.d.ts} +0 -1
  32. package/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.metadata.json +1 -0
  33. package/adapter-uri-builder-odata/package.json +13 -0
  34. package/breeze-client.d.ts +8 -0
  35. package/breeze-client.metadata.json +1 -0
  36. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js +190 -0
  37. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js.map +1 -0
  38. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js +2 -0
  39. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js.map +1 -0
  40. package/bundles/breeze-client-adapter-ajax-fetch.umd.js +190 -0
  41. package/bundles/breeze-client-adapter-ajax-fetch.umd.js.map +1 -0
  42. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js +2 -0
  43. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js.map +1 -0
  44. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js +195 -0
  45. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js.map +1 -0
  46. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js +2 -0
  47. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js.map +1 -0
  48. package/bundles/breeze-client-adapter-ajax-jquery.umd.js +115 -0
  49. package/bundles/breeze-client-adapter-ajax-jquery.umd.js.map +1 -0
  50. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js +2 -0
  51. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js.map +1 -0
  52. package/bundles/breeze-client-adapter-ajax-post.umd.js +92 -0
  53. package/bundles/breeze-client-adapter-ajax-post.umd.js.map +1 -0
  54. package/bundles/breeze-client-adapter-ajax-post.umd.min.js +2 -0
  55. package/bundles/breeze-client-adapter-ajax-post.umd.min.js.map +1 -0
  56. package/bundles/breeze-client-adapter-data-service-odata.umd.js +747 -0
  57. package/bundles/breeze-client-adapter-data-service-odata.umd.js.map +1 -0
  58. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js +16 -0
  59. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js.map +1 -0
  60. package/bundles/breeze-client-adapter-data-service-webapi.umd.js +333 -0
  61. package/bundles/breeze-client-adapter-data-service-webapi.umd.js.map +1 -0
  62. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js +16 -0
  63. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js.map +1 -0
  64. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js +280 -0
  65. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js.map +1 -0
  66. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js +2 -0
  67. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js.map +1 -0
  68. package/bundles/breeze-client-adapter-model-library-ko.umd.js +252 -0
  69. package/bundles/breeze-client-adapter-model-library-ko.umd.js.map +1 -0
  70. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js +2 -0
  71. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js.map +1 -0
  72. package/bundles/breeze-client-adapter-uri-builder-json.umd.js +96 -0
  73. package/bundles/breeze-client-adapter-uri-builder-json.umd.js.map +1 -0
  74. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js +2 -0
  75. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js.map +1 -0
  76. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js +262 -0
  77. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js.map +1 -0
  78. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js +2 -0
  79. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js.map +1 -0
  80. package/bundles/breeze-client-mixin-get-entity-graph.umd.js +258 -0
  81. package/bundles/breeze-client-mixin-get-entity-graph.umd.js.map +1 -0
  82. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js +2 -0
  83. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js.map +1 -0
  84. package/bundles/breeze-client-mixin-save-queuing.umd.js +579 -0
  85. package/bundles/breeze-client-mixin-save-queuing.umd.js.map +1 -0
  86. package/bundles/breeze-client-mixin-save-queuing.umd.min.js +16 -0
  87. package/bundles/breeze-client-mixin-save-queuing.umd.min.js.map +1 -0
  88. package/bundles/breeze-client.umd.js +14234 -0
  89. package/bundles/breeze-client.umd.js.map +1 -0
  90. package/bundles/breeze-client.umd.min.js +16 -0
  91. package/bundles/breeze-client.umd.min.js.map +1 -0
  92. package/esm2015/adapter-ajax-angularjs/adapter-ajax-angularjs.js +130 -0
  93. package/esm2015/adapter-ajax-angularjs/adapter-core.js +49 -0
  94. package/esm2015/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +5 -0
  95. package/esm2015/adapter-ajax-fetch/adapter-ajax-fetch.js +130 -0
  96. package/esm2015/adapter-ajax-fetch/adapter-core.js +49 -0
  97. package/esm2015/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +5 -0
  98. package/esm2015/adapter-ajax-httpclient/adapter-ajax-httpclient.js +137 -0
  99. package/esm2015/adapter-ajax-httpclient/adapter-core.js +49 -0
  100. package/esm2015/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +5 -0
  101. package/esm2015/adapter-ajax-jquery/adapter-ajax-jquery.js +103 -0
  102. package/esm2015/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +5 -0
  103. package/esm2015/adapter-ajax-post/adapter-ajax-post.js +77 -0
  104. package/esm2015/adapter-ajax-post/breeze-client-adapter-ajax-post.js +5 -0
  105. package/esm2015/adapter-data-service-odata/adapter-core.js +49 -0
  106. package/esm2015/adapter-data-service-odata/adapter-data-service-odata.js +463 -0
  107. package/esm2015/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +5 -0
  108. package/esm2015/adapter-data-service-webapi/adapter-data-service-webapi.js +100 -0
  109. package/esm2015/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +5 -0
  110. package/esm2015/adapter-model-library-backing-store/adapter-model-library-backing-store.js +268 -0
  111. package/esm2015/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +5 -0
  112. package/esm2015/adapter-model-library-ko/adapter-model-library-ko.js +240 -0
  113. package/esm2015/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +5 -0
  114. package/esm2015/adapter-uri-builder-json/adapter-core.js +49 -0
  115. package/esm2015/adapter-uri-builder-json/adapter-uri-builder-json.js +36 -0
  116. package/esm2015/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +5 -0
  117. package/esm2015/adapter-uri-builder-odata/adapter-core.js +49 -0
  118. package/esm2015/adapter-uri-builder-odata/adapter-uri-builder-odata.js +192 -0
  119. package/esm2015/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +5 -0
  120. package/esm2015/breeze-client.js +9 -0
  121. package/esm2015/index.js +2 -0
  122. package/esm2015/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +5 -0
  123. package/esm2015/mixin-get-entity-graph/mixin-get-entity-graph.js +269 -0
  124. package/esm2015/mixin-save-queuing/breeze-client-mixin-save-queuing.js +5 -0
  125. package/esm2015/mixin-save-queuing/mixin-save-queuing.js +400 -0
  126. package/esm2015/src/abstract-data-service-adapter.js +327 -0
  127. package/esm2015/src/array.js +4 -0
  128. package/esm2015/src/assert-param.js +312 -0
  129. package/esm2015/src/breeze.js +85 -0
  130. package/esm2015/src/complex-array.js +119 -0
  131. package/esm2015/src/config.js +223 -0
  132. package/esm2015/src/core.js +714 -0
  133. package/esm2015/src/csdl-metadata-parser.js +385 -0
  134. package/esm2015/src/data-service.js +203 -0
  135. package/esm2015/src/data-type.js +506 -0
  136. package/esm2015/src/default-property-interceptor.js +460 -0
  137. package/{esm2022/src/entity-action.mjs → esm2015/src/entity-action.js} +25 -25
  138. package/esm2015/src/entity-aspect.js +804 -0
  139. package/esm2015/src/entity-group.js +187 -0
  140. package/esm2015/src/entity-key.js +116 -0
  141. package/esm2015/src/entity-manager.js +2094 -0
  142. package/esm2015/src/entity-metadata.js +2109 -0
  143. package/esm2015/src/entity-query.js +1015 -0
  144. package/esm2015/src/entity-state.js +107 -0
  145. package/esm2015/src/enum.js +141 -0
  146. package/esm2015/src/event.js +256 -0
  147. package/esm2015/src/interface-registry.js +41 -0
  148. package/esm2015/src/key-generator.js +108 -0
  149. package/esm2015/src/local-query-comparison-options.js +65 -0
  150. package/esm2015/src/mapping-context.js +411 -0
  151. package/esm2015/src/naming-convention.js +88 -0
  152. package/esm2015/src/observable-array.js +185 -0
  153. package/esm2015/src/predicate.js +1242 -0
  154. package/esm2015/src/primitive-array.js +87 -0
  155. package/esm2015/src/query-options.js +152 -0
  156. package/esm2015/src/relation-array.js +175 -0
  157. package/esm2015/src/save-options.js +41 -0
  158. package/esm2015/src/unattached-children-map.js +58 -0
  159. package/esm2015/src/validate.js +991 -0
  160. package/esm2015/src/validation-options.js +64 -0
  161. package/esm5/adapter-ajax-angularjs/adapter-ajax-angularjs.js +132 -0
  162. package/esm5/adapter-ajax-angularjs/adapter-core.js +49 -0
  163. package/esm5/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +5 -0
  164. package/esm5/adapter-ajax-fetch/adapter-ajax-fetch.js +132 -0
  165. package/esm5/adapter-ajax-fetch/adapter-core.js +49 -0
  166. package/esm5/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +5 -0
  167. package/esm5/adapter-ajax-httpclient/adapter-ajax-httpclient.js +139 -0
  168. package/esm5/adapter-ajax-httpclient/adapter-core.js +49 -0
  169. package/esm5/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +5 -0
  170. package/esm5/adapter-ajax-jquery/adapter-ajax-jquery.js +105 -0
  171. package/esm5/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +5 -0
  172. package/esm5/adapter-ajax-post/adapter-ajax-post.js +81 -0
  173. package/esm5/adapter-ajax-post/breeze-client-adapter-ajax-post.js +5 -0
  174. package/esm5/adapter-data-service-odata/adapter-core.js +49 -0
  175. package/{esm2022/adapter-data-service-odata/adapter-data-service-odata.mjs → esm5/adapter-data-service-odata/adapter-data-service-odata.js} +147 -138
  176. package/esm5/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +5 -0
  177. package/esm5/adapter-data-service-webapi/adapter-data-service-webapi.js +105 -0
  178. package/esm5/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +5 -0
  179. package/esm5/adapter-model-library-backing-store/adapter-model-library-backing-store.js +270 -0
  180. package/esm5/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +5 -0
  181. package/esm5/adapter-model-library-ko/adapter-model-library-ko.js +242 -0
  182. package/esm5/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +5 -0
  183. package/esm5/adapter-uri-builder-json/adapter-core.js +49 -0
  184. package/esm5/adapter-uri-builder-json/adapter-uri-builder-json.js +38 -0
  185. package/esm5/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +5 -0
  186. package/esm5/adapter-uri-builder-odata/adapter-core.js +49 -0
  187. package/esm5/adapter-uri-builder-odata/adapter-uri-builder-odata.js +197 -0
  188. package/esm5/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +5 -0
  189. package/esm5/breeze-client.js +9 -0
  190. package/esm5/index.js +2 -0
  191. package/esm5/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +5 -0
  192. package/esm5/mixin-get-entity-graph/mixin-get-entity-graph.js +269 -0
  193. package/esm5/mixin-save-queuing/breeze-client-mixin-save-queuing.js +5 -0
  194. package/esm5/mixin-save-queuing/mixin-save-queuing.js +412 -0
  195. package/esm5/src/abstract-data-service-adapter.js +333 -0
  196. package/esm5/src/array.js +4 -0
  197. package/esm5/src/assert-param.js +317 -0
  198. package/esm5/src/breeze.js +85 -0
  199. package/esm5/src/complex-array.js +119 -0
  200. package/esm5/src/config.js +228 -0
  201. package/esm5/src/core.js +722 -0
  202. package/esm5/src/csdl-metadata-parser.js +385 -0
  203. package/esm5/src/data-service.js +207 -0
  204. package/esm5/src/data-type.js +513 -0
  205. package/esm5/src/default-property-interceptor.js +460 -0
  206. package/esm5/src/entity-action.js +52 -0
  207. package/esm5/src/entity-aspect.js +810 -0
  208. package/esm5/src/entity-group.js +189 -0
  209. package/esm5/src/entity-key.js +118 -0
  210. package/esm5/src/entity-manager.js +2112 -0
  211. package/esm5/src/entity-metadata.js +2144 -0
  212. package/esm5/src/entity-query.js +1042 -0
  213. package/esm5/src/entity-state.js +114 -0
  214. package/esm5/src/enum.js +144 -0
  215. package/esm5/src/event.js +259 -0
  216. package/esm5/src/interface-registry.js +43 -0
  217. package/esm5/src/key-generator.js +111 -0
  218. package/esm5/src/local-query-comparison-options.js +67 -0
  219. package/esm5/src/mapping-context.js +413 -0
  220. package/esm5/src/naming-convention.js +90 -0
  221. package/esm5/src/observable-array.js +201 -0
  222. package/esm5/src/predicate.js +1307 -0
  223. package/esm5/src/primitive-array.js +87 -0
  224. package/esm5/src/query-options.js +167 -0
  225. package/esm5/src/relation-array.js +175 -0
  226. package/esm5/src/save-options.js +43 -0
  227. package/esm5/src/unattached-children-map.js +60 -0
  228. package/{esm2022/src/validate.mjs → esm5/src/validate.js} +110 -116
  229. package/esm5/src/validation-options.js +66 -0
  230. package/{fesm2022/breeze-client-adapter-ajax-angularjs.mjs → fesm2015/breeze-client-adapter-ajax-angularjs.js} +1 -6
  231. package/fesm2015/breeze-client-adapter-ajax-angularjs.js.map +1 -0
  232. package/{fesm2022/breeze-client-adapter-ajax-fetch.mjs → fesm2015/breeze-client-adapter-ajax-fetch.js} +4 -9
  233. package/fesm2015/breeze-client-adapter-ajax-fetch.js.map +1 -0
  234. package/{fesm2022/breeze-client-adapter-ajax-httpclient.mjs → fesm2015/breeze-client-adapter-ajax-httpclient.js} +4 -6
  235. package/fesm2015/breeze-client-adapter-ajax-httpclient.js.map +1 -0
  236. package/{fesm2022/breeze-client-adapter-ajax-jquery.mjs → fesm2015/breeze-client-adapter-ajax-jquery.js} +2 -6
  237. package/fesm2015/breeze-client-adapter-ajax-jquery.js.map +1 -0
  238. package/{fesm2022/breeze-client-adapter-ajax-post.mjs → fesm2015/breeze-client-adapter-ajax-post.js} +1 -1
  239. package/fesm2015/breeze-client-adapter-ajax-post.js.map +1 -0
  240. package/{fesm2022/breeze-client-adapter-data-service-odata.mjs → fesm2015/breeze-client-adapter-data-service-odata.js} +69 -68
  241. package/fesm2015/breeze-client-adapter-data-service-odata.js.map +1 -0
  242. package/{fesm2022/breeze-client-adapter-data-service-webapi.mjs → fesm2015/breeze-client-adapter-data-service-webapi.js} +30 -30
  243. package/fesm2015/breeze-client-adapter-data-service-webapi.js.map +1 -0
  244. package/{fesm2022/breeze-client-adapter-model-library-backing-store.mjs → fesm2015/breeze-client-adapter-model-library-backing-store.js} +13 -14
  245. package/fesm2015/breeze-client-adapter-model-library-backing-store.js.map +1 -0
  246. package/{fesm2022/breeze-client-adapter-model-library-ko.mjs → fesm2015/breeze-client-adapter-model-library-ko.js} +13 -14
  247. package/fesm2015/breeze-client-adapter-model-library-ko.js.map +1 -0
  248. package/{fesm2022/breeze-client-adapter-uri-builder-json.mjs → fesm2015/breeze-client-adapter-uri-builder-json.js} +8 -9
  249. package/fesm2015/breeze-client-adapter-uri-builder-json.js.map +1 -0
  250. package/{fesm2022/breeze-client-adapter-uri-builder-odata.mjs → fesm2015/breeze-client-adapter-uri-builder-odata.js} +86 -86
  251. package/fesm2015/breeze-client-adapter-uri-builder-odata.js.map +1 -0
  252. package/{fesm2022/breeze-client-mixin-get-entity-graph.mjs → fesm2015/breeze-client-mixin-get-entity-graph.js} +1 -1
  253. package/fesm2015/breeze-client-mixin-get-entity-graph.js.map +1 -0
  254. package/{fesm2022/breeze-client-mixin-save-queuing.mjs → fesm2015/breeze-client-mixin-save-queuing.js} +2 -23
  255. package/fesm2015/breeze-client-mixin-save-queuing.js.map +1 -0
  256. package/{fesm2022/breeze-client.mjs → fesm2015/breeze-client.js} +1543 -2042
  257. package/fesm2015/breeze-client.js.map +1 -0
  258. package/fesm5/breeze-client-adapter-ajax-angularjs.js +186 -0
  259. package/fesm5/breeze-client-adapter-ajax-angularjs.js.map +1 -0
  260. package/fesm5/breeze-client-adapter-ajax-fetch.js +186 -0
  261. package/fesm5/breeze-client-adapter-ajax-fetch.js.map +1 -0
  262. package/fesm5/breeze-client-adapter-ajax-httpclient.js +193 -0
  263. package/fesm5/breeze-client-adapter-ajax-httpclient.js.map +1 -0
  264. package/fesm5/breeze-client-adapter-ajax-jquery.js +111 -0
  265. package/fesm5/breeze-client-adapter-ajax-jquery.js.map +1 -0
  266. package/fesm5/breeze-client-adapter-ajax-post.js +86 -0
  267. package/fesm5/breeze-client-adapter-ajax-post.js.map +1 -0
  268. package/fesm5/breeze-client-adapter-data-service-odata.js +523 -0
  269. package/fesm5/breeze-client-adapter-data-service-odata.js.map +1 -0
  270. package/fesm5/breeze-client-adapter-data-service-webapi.js +111 -0
  271. package/fesm5/breeze-client-adapter-data-service-webapi.js.map +1 -0
  272. package/fesm5/breeze-client-adapter-model-library-backing-store.js +276 -0
  273. package/fesm5/breeze-client-adapter-model-library-backing-store.js.map +1 -0
  274. package/fesm5/breeze-client-adapter-model-library-ko.js +248 -0
  275. package/fesm5/breeze-client-adapter-model-library-ko.js.map +1 -0
  276. package/fesm5/breeze-client-adapter-uri-builder-json.js +92 -0
  277. package/fesm5/breeze-client-adapter-uri-builder-json.js.map +1 -0
  278. package/fesm5/breeze-client-adapter-uri-builder-odata.js +250 -0
  279. package/fesm5/breeze-client-adapter-uri-builder-odata.js.map +1 -0
  280. package/fesm5/breeze-client-mixin-get-entity-graph.js +254 -0
  281. package/fesm5/breeze-client-mixin-get-entity-graph.js.map +1 -0
  282. package/fesm5/breeze-client-mixin-save-queuing.js +356 -0
  283. package/fesm5/breeze-client-mixin-save-queuing.js.map +1 -0
  284. package/fesm5/breeze-client.js +13956 -0
  285. package/fesm5/breeze-client.js.map +1 -0
  286. package/mixin-get-entity-graph/{index.d.ts → breeze-client-mixin-get-entity-graph.d.ts} +0 -1
  287. package/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.metadata.json +1 -0
  288. package/mixin-get-entity-graph/package.json +13 -0
  289. package/mixin-save-queuing/{index.d.ts → breeze-client-mixin-save-queuing.d.ts} +0 -1
  290. package/mixin-save-queuing/breeze-client-mixin-save-queuing.metadata.json +1 -0
  291. package/mixin-save-queuing/package.json +13 -0
  292. package/package.json +12 -94
  293. package/src/config.d.ts +1 -1
  294. package/src/core.d.ts +1 -1
  295. package/src/entity-aspect.d.ts +1 -1
  296. package/src/entity-metadata.d.ts +6 -8
  297. package/src/entity-query.d.ts +1 -1
  298. package/esm2022/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +0 -135
  299. package/esm2022/adapter-ajax-angularjs/adapter-core.mjs +0 -49
  300. package/esm2022/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +0 -5
  301. package/esm2022/adapter-ajax-fetch/adapter-ajax-fetch.mjs +0 -135
  302. package/esm2022/adapter-ajax-fetch/adapter-core.mjs +0 -49
  303. package/esm2022/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +0 -5
  304. package/esm2022/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +0 -139
  305. package/esm2022/adapter-ajax-httpclient/adapter-core.mjs +0 -49
  306. package/esm2022/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +0 -5
  307. package/esm2022/adapter-ajax-jquery/adapter-ajax-jquery.mjs +0 -107
  308. package/esm2022/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +0 -5
  309. package/esm2022/adapter-ajax-post/adapter-ajax-post.mjs +0 -77
  310. package/esm2022/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +0 -5
  311. package/esm2022/adapter-data-service-odata/adapter-core.mjs +0 -49
  312. package/esm2022/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +0 -5
  313. package/esm2022/adapter-data-service-webapi/adapter-data-service-webapi.mjs +0 -100
  314. package/esm2022/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +0 -5
  315. package/esm2022/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +0 -269
  316. package/esm2022/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +0 -5
  317. package/esm2022/adapter-model-library-ko/adapter-model-library-ko.mjs +0 -241
  318. package/esm2022/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +0 -5
  319. package/esm2022/adapter-uri-builder-json/adapter-core.mjs +0 -49
  320. package/esm2022/adapter-uri-builder-json/adapter-uri-builder-json.mjs +0 -37
  321. package/esm2022/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +0 -5
  322. package/esm2022/adapter-uri-builder-odata/adapter-core.mjs +0 -49
  323. package/esm2022/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +0 -191
  324. package/esm2022/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +0 -5
  325. package/esm2022/breeze-client.mjs +0 -5
  326. package/esm2022/index.mjs +0 -2
  327. package/esm2022/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +0 -5
  328. package/esm2022/mixin-get-entity-graph/mixin-get-entity-graph.mjs +0 -269
  329. package/esm2022/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +0 -5
  330. package/esm2022/mixin-save-queuing/mixin-save-queuing.mjs +0 -421
  331. package/esm2022/src/abstract-data-service-adapter.mjs +0 -325
  332. package/esm2022/src/array.mjs +0 -4
  333. package/esm2022/src/assert-param.mjs +0 -330
  334. package/esm2022/src/breeze.mjs +0 -85
  335. package/esm2022/src/complex-array.mjs +0 -117
  336. package/esm2022/src/config.mjs +0 -232
  337. package/esm2022/src/core.mjs +0 -712
  338. package/esm2022/src/csdl-metadata-parser.mjs +0 -385
  339. package/esm2022/src/data-service.mjs +0 -239
  340. package/esm2022/src/data-type.mjs +0 -510
  341. package/esm2022/src/default-property-interceptor.mjs +0 -460
  342. package/esm2022/src/entity-aspect.mjs +0 -897
  343. package/esm2022/src/entity-group.mjs +0 -192
  344. package/esm2022/src/entity-key.mjs +0 -127
  345. package/esm2022/src/entity-manager.mjs +0 -2183
  346. package/esm2022/src/entity-metadata.mjs +0 -2242
  347. package/esm2022/src/entity-query.mjs +0 -1024
  348. package/esm2022/src/entity-state.mjs +0 -107
  349. package/esm2022/src/enum.mjs +0 -143
  350. package/esm2022/src/event.mjs +0 -264
  351. package/esm2022/src/interface-registry.mjs +0 -39
  352. package/esm2022/src/key-generator.mjs +0 -110
  353. package/esm2022/src/local-query-comparison-options.mjs +0 -75
  354. package/esm2022/src/mapping-context.mjs +0 -422
  355. package/esm2022/src/naming-convention.mjs +0 -96
  356. package/esm2022/src/observable-array.mjs +0 -183
  357. package/esm2022/src/predicate.mjs +0 -1259
  358. package/esm2022/src/primitive-array.mjs +0 -85
  359. package/esm2022/src/query-options.mjs +0 -160
  360. package/esm2022/src/relation-array.mjs +0 -173
  361. package/esm2022/src/save-options.mjs +0 -51
  362. package/esm2022/src/unattached-children-map.mjs +0 -56
  363. package/esm2022/src/validation-options.mjs +0 -78
  364. package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs.map +0 -1
  365. package/fesm2022/breeze-client-adapter-ajax-fetch.mjs.map +0 -1
  366. package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs.map +0 -1
  367. package/fesm2022/breeze-client-adapter-ajax-jquery.mjs.map +0 -1
  368. package/fesm2022/breeze-client-adapter-ajax-post.mjs.map +0 -1
  369. package/fesm2022/breeze-client-adapter-data-service-odata.mjs.map +0 -1
  370. package/fesm2022/breeze-client-adapter-data-service-webapi.mjs.map +0 -1
  371. package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs.map +0 -1
  372. package/fesm2022/breeze-client-adapter-model-library-ko.mjs.map +0 -1
  373. package/fesm2022/breeze-client-adapter-uri-builder-json.mjs.map +0 -1
  374. package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs.map +0 -1
  375. package/fesm2022/breeze-client-mixin-get-entity-graph.mjs.map +0 -1
  376. package/fesm2022/breeze-client-mixin-save-queuing.mjs.map +0 -1
  377. package/fesm2022/breeze-client.mjs.map +0 -1
@@ -0,0 +1,2109 @@
1
+ import { core } from './core';
2
+ import { config } from './config';
3
+ import { BreezeEvent } from './event';
4
+ import { assertParam, assertConfig, Param } from './assert-param';
5
+ import { DataType } from './data-type';
6
+ import { EntityAspect, ComplexAspect } from './entity-aspect';
7
+ import { EntityKey } from './entity-key';
8
+ import { Validator } from './validate';
9
+ import { BreezeEnum } from './enum';
10
+ import { DataService } from './data-service';
11
+ import { NamingConvention } from './naming-convention';
12
+ import { CsdlMetadataParser } from './csdl-metadata-parser'; // TODO isolate this later;
13
+ import { LocalQueryComparisonOptions } from './local-query-comparison-options';
14
+ import { defaultPropertyInterceptor } from './default-property-interceptor';
15
+ /**
16
+ An instance of the MetadataStore contains all of the metadata about a collection of [[EntityType]]'s.
17
+ MetadataStores may be shared across [[EntityManager]]'s. If an EntityManager is created without an
18
+ explicit MetadataStore, the MetadataStore from the MetadataStore.defaultInstance property will be used.
19
+ @dynamic
20
+ **/
21
+ export class MetadataStore {
22
+ /**
23
+ Constructs a new MetadataStore.
24
+
25
+ > let ms = new MetadataStore();
26
+
27
+ The store can then be associated with an EntityManager
28
+ > let entityManager = new EntityManager( {
29
+ > serviceName: "breeze/NorthwindIBModel",
30
+ > metadataStore: ms
31
+ > });
32
+
33
+ or for an existing EntityManager
34
+ > // Assume em1 is an existing EntityManager
35
+ > em1.setProperties( { metadataStore: ms });
36
+
37
+ @param config - Configuration settings .
38
+ - namingConvention - (default=NamingConvention.defaultInstance) NamingConvention to be used in mapping property names
39
+ between client and server. Uses the NamingConvention.defaultInstance if not specified.
40
+ - localQueryComparisonOptions - (default=LocalQueryComparisonOptions.defaultInstance) The LocalQueryComparisonOptions to be
41
+ used when performing "local queries" in order to match the semantics of queries against a remote service.
42
+ - serializerFn - A function that is used to mediate the serialization of instances of this type.
43
+ **/
44
+ constructor(config) {
45
+ config = config || {};
46
+ assertConfig(config)
47
+ .whereParam("namingConvention").isOptional().isInstanceOf(NamingConvention).withDefault(NamingConvention.defaultInstance)
48
+ .whereParam("localQueryComparisonOptions").isOptional().isInstanceOf(LocalQueryComparisonOptions).withDefault(LocalQueryComparisonOptions.defaultInstance)
49
+ .whereParam("serializerFn").isOptional().isFunction()
50
+ .applyAll(this);
51
+ this.dataServices = []; // array of dataServices;
52
+ this._resourceEntityTypeMap = {}; // key is resource name - value is qualified entityType name
53
+ this._structuralTypeMap = {}; // key is qualified structuraltype name - value is structuralType. ( structural = entityType or complexType).
54
+ this._shortNameMap = {}; // key is shortName, value is qualified name - does not need to be serialized.
55
+ this._ctorRegistry = {}; // key is either short or qual type name - value is ctor;
56
+ this._incompleteTypeMap = {}; // key is entityTypeName; value is array of nav props
57
+ this._incompleteComplexTypeMap = {}; // key is complexTypeName; value is array of complexType props
58
+ this._id = MetadataStore.__id++;
59
+ this.metadataFetched = new BreezeEvent("metadataFetched", this);
60
+ }
61
+ // for debugging use the line below instead.
62
+ //ctor.normalizeTypeName = function (rawTypeName) { return parseTypeName(rawTypeName).typeName; };
63
+ /**
64
+ General purpose property set method
65
+
66
+ > // assume em1 is an EntityManager containing a number of existing entities.
67
+ > em1.metadataStore.setProperties( {
68
+ > version: "6.1.3",
69
+ > serializerFn: function(prop, value) {
70
+ > return (prop.isUnmapped) ? undefined : value;
71
+ > }
72
+ > )};
73
+ @param config - An object containing the selected properties and values to set.
74
+ **/
75
+ setProperties(config) {
76
+ assertConfig(config)
77
+ .whereParam("name").isString().isOptional()
78
+ .whereParam("serializerFn").isFunction().isOptional()
79
+ .applyAll(this);
80
+ }
81
+ /**
82
+ Adds a DataService to this MetadataStore. If a DataService with the same serviceName is already
83
+ in the MetadataStore an exception will be thrown.
84
+ @param dataService - The [[DataService]] to add
85
+ @param shouldOverwrite - (default=false) Permit overwrite of existing DataService rather than throw exception
86
+ **/
87
+ addDataService(dataService, shouldOverwrite) {
88
+ assertParam(dataService, "dataService").isInstanceOf(DataService).check();
89
+ assertParam(shouldOverwrite, "shouldOverwrite").isBoolean().isOptional().check();
90
+ let ix = this._getDataServiceIndex(dataService.serviceName);
91
+ if (ix >= 0) {
92
+ if (!!shouldOverwrite) {
93
+ this.dataServices[ix] = dataService;
94
+ }
95
+ else {
96
+ throw new Error("A dataService with this name '" + dataService.serviceName + "' already exists in this MetadataStore");
97
+ }
98
+ }
99
+ else {
100
+ this.dataServices.push(dataService);
101
+ }
102
+ }
103
+ /** @hidden @internal */
104
+ _getDataServiceIndex(serviceName) {
105
+ return core.arrayIndexOf(this.dataServices, function (ds) {
106
+ return ds.serviceName === serviceName;
107
+ });
108
+ }
109
+ /**
110
+ Adds an EntityType to this MetadataStore. No additional properties may be added to the EntityType after its has
111
+ been added to the MetadataStore.
112
+ @param structuralType - The EntityType or ComplexType to add
113
+ **/
114
+ addEntityType(stype) {
115
+ let structuralType;
116
+ if (stype instanceof EntityType || stype instanceof ComplexType) {
117
+ structuralType = stype;
118
+ }
119
+ else {
120
+ structuralType = stype.isComplexType ? new ComplexType(stype) : new EntityType(stype);
121
+ }
122
+ // if (!structuralType.isComplexType) { // same as below but isn't a 'type guard'
123
+ if (structuralType instanceof EntityType) {
124
+ if (structuralType.baseTypeName && !structuralType.baseEntityType) {
125
+ let baseEntityType = this._getStructuralType(structuralType.baseTypeName, true);
126
+ // safe cast because we know that baseEntityType must be an EntityType if the structuralType is an EntityType
127
+ structuralType._updateFromBase(baseEntityType);
128
+ }
129
+ if (structuralType.keyProperties.length === 0 && !structuralType.isAbstract) {
130
+ throw new Error("Unable to add " + structuralType.name +
131
+ " to this MetadataStore. An EntityType must have at least one property designated as a key property - See the 'DataProperty.isPartOfKey' property.");
132
+ }
133
+ }
134
+ structuralType.metadataStore = this;
135
+ // don't register anon types
136
+ if (!structuralType.isAnonymous) {
137
+ if (this._structuralTypeMap[structuralType.name]) {
138
+ throw new Error("Type " + structuralType.name + " already exists in this MetadataStore.");
139
+ }
140
+ this._structuralTypeMap[structuralType.name] = structuralType;
141
+ this._shortNameMap[structuralType.shortName] = structuralType.name;
142
+ }
143
+ structuralType.getProperties().forEach(p => {
144
+ structuralType._updateNames(p);
145
+ if (!p.isUnmapped) {
146
+ structuralType._mappedPropertiesCount++;
147
+ }
148
+ });
149
+ structuralType._updateCps();
150
+ // 'isEntityType' is a type guard
151
+ if (structuralType instanceof EntityType) {
152
+ structuralType._updateNps();
153
+ // give the type it's base's resource name if it doesn't have its own.
154
+ let defResourceName = structuralType.defaultResourceName || (structuralType.baseEntityType && structuralType.baseEntityType.defaultResourceName);
155
+ if (defResourceName && !this.getEntityTypeNameForResourceName(defResourceName)) {
156
+ this.setEntityTypeForResourceName(defResourceName, structuralType.name);
157
+ }
158
+ structuralType.defaultResourceName = defResourceName;
159
+ // check if this structural type's name, short version or qualified version has a registered ctor.
160
+ structuralType.getEntityCtor();
161
+ }
162
+ }
163
+ /**
164
+ Exports this MetadataStore to a serialized string appropriate for local storage. This operation is also called
165
+ internally when exporting an EntityManager.
166
+ > // assume ms is a previously created MetadataStore
167
+ > let metadataAsString = ms.exportMetadata();
168
+ > window.localStorage.setItem("metadata", metadataAsString);
169
+ > // and later, usually in a different session imported
170
+ > let metadataFromStorage = window.localStorage.getItem("metadata");
171
+ > let newMetadataStore = new MetadataStore();
172
+ > newMetadataStore.importMetadata(metadataFromStorage);
173
+ @return A serialized version of this MetadataStore that may be stored locally and later restored.
174
+ **/
175
+ exportMetadata() {
176
+ let result = JSON.stringify({
177
+ "metadataVersion": MetadataStore.metadataVersion,
178
+ "name": this.name,
179
+ "namingConvention": this.namingConvention.name,
180
+ "localQueryComparisonOptions": this.localQueryComparisonOptions.name,
181
+ "dataServices": this.dataServices,
182
+ "structuralTypes": core.objectMap(this._structuralTypeMap),
183
+ "resourceEntityTypeMap": this._resourceEntityTypeMap
184
+ }, null, config.stringifyPad);
185
+ return result;
186
+ }
187
+ /**
188
+ Imports a previously exported serialized MetadataStore into this MetadataStore.
189
+
190
+ > // assume ms is a previously created MetadataStore
191
+ > let metadataAsString = ms.exportMetadata();
192
+ > window.localStorage.setItem("metadata", metadataAsString);
193
+ > // and later, usually in a different session
194
+ > let metadataFromStorage = window.localStorage.getItem("metadata");
195
+ > let newMetadataStore = new MetadataStore();
196
+ > newMetadataStore.importMetadata(metadataFromStorage);
197
+ @param exportedMetadata - A previously exported MetadataStore.
198
+ @param allowMerge - Allows custom metadata to be merged into existing metadata types.
199
+ @return This MetadataStore.
200
+ @chainable
201
+ **/
202
+ importMetadata(exportedMetadata, allowMerge = false) {
203
+ assertParam(allowMerge, "allowMerge").isOptional().isBoolean().check();
204
+ this._deferredTypes = {};
205
+ // insure that we don't mutate incoming exportedMetadata ( if its an object)
206
+ let metadataAsString = (typeof (exportedMetadata) === "string") ? exportedMetadata : JSON.stringify(exportedMetadata);
207
+ const metadataJson = JSON.parse(metadataAsString);
208
+ if (metadataJson.schema) {
209
+ return CsdlMetadataParser.parse(this, metadataJson.schema, metadataJson.altMetadata);
210
+ }
211
+ let json = metadataJson;
212
+ if (json.metadataVersion && json.metadataVersion !== MetadataStore.metadataVersion) {
213
+ let msg = core.formatString("Cannot import metadata with a different 'metadataVersion' (%1) than the current 'MetadataStore.metadataVersion' (%2) ", json.metadataVersion, MetadataStore.metadataVersion);
214
+ throw new Error(msg);
215
+ }
216
+ let ncName = json.namingConvention;
217
+ let lqcoName = json.localQueryComparisonOptions;
218
+ if (this.isEmpty()) {
219
+ this.namingConvention = config._fetchObject(NamingConvention, ncName) || this.namingConvention;
220
+ this.localQueryComparisonOptions = config._fetchObject(LocalQueryComparisonOptions, lqcoName) || this.localQueryComparisonOptions;
221
+ }
222
+ else {
223
+ if (ncName && this.namingConvention.name !== ncName) {
224
+ throw new Error("Cannot import metadata with a different 'namingConvention' from the current MetadataStore");
225
+ }
226
+ if (lqcoName && this.localQueryComparisonOptions.name !== lqcoName) {
227
+ throw new Error("Cannot import metadata with different 'localQueryComparisonOptions' from the current MetadataStore");
228
+ }
229
+ }
230
+ //noinspection JSHint
231
+ json.dataServices && json.dataServices.forEach((ds) => {
232
+ let realDs = DataService.fromJSON(ds);
233
+ this.addDataService(realDs, true);
234
+ });
235
+ json.structuralTypes && json.structuralTypes.forEach((stype) => {
236
+ structuralTypeFromJson(this, stype, allowMerge);
237
+ });
238
+ core.extend(this._resourceEntityTypeMap, json.resourceEntityTypeMap);
239
+ core.extend(this._incompleteTypeMap, json.incompleteTypeMap);
240
+ return this;
241
+ }
242
+ /**
243
+ Creates a new MetadataStore from a previously exported serialized MetadataStore
244
+ > // assume ms is a previously created MetadataStore
245
+ > let metadataAsString = ms.exportMetadata();
246
+ > window.localStorage.setItem("metadata", metadataAsString);
247
+ > // and later, usually in a different session
248
+ > let metadataFromStorage = window.localStorage.getItem("metadata");
249
+ > let newMetadataStore = MetadataStore.importMetadata(metadataFromStorage);
250
+ @param exportedString - A previously exported MetadataStore.
251
+ @return A new MetadataStore.
252
+ **/
253
+ static importMetadata(exportedString) {
254
+ let ms = new MetadataStore();
255
+ ms.importMetadata(exportedString);
256
+ return ms;
257
+ }
258
+ /**
259
+ Returns whether Metadata has been retrieved for a specified service name.
260
+ > // Assume em1 is an existing EntityManager.
261
+ > if (!em1.metadataStore.hasMetadataFor("breeze/NorthwindIBModel"))) {
262
+ > // do something interesting
263
+ > }
264
+ @param serviceName - The service name.
265
+ @return Whether metadata has already been retrieved for the specified service name.
266
+ **/
267
+ hasMetadataFor(serviceName) {
268
+ return !!this.getDataService(serviceName);
269
+ }
270
+ /**
271
+ Returns the DataService for a specified service name
272
+ > // Assume em1 is an existing EntityManager.
273
+ > let ds = em1.metadataStore.getDataService("breeze/NorthwindIBModel");
274
+ > let adapterName = ds.adapterName; // may be null
275
+ @param serviceName - The service name.
276
+ @return The DataService with the specified name.
277
+ **/
278
+ getDataService(serviceName) {
279
+ assertParam(serviceName, "serviceName").isString().check();
280
+ serviceName = DataService._normalizeServiceName(serviceName);
281
+ return core.arrayFirst(this.dataServices, function (ds) {
282
+ return ds.serviceName === serviceName;
283
+ });
284
+ }
285
+ /**
286
+ Fetches the metadata for a specified 'service'. This method is automatically called
287
+ internally by an EntityManager before its first query against a new service. __Async__
288
+
289
+ Usually you will not actually process the results of a fetchMetadata call directly, but will instead
290
+ ask for the metadata from the EntityManager after the fetchMetadata call returns.
291
+ > let ms = new MetadataStore();
292
+ > // or more commonly
293
+ > // let ms = anEntityManager.metadataStore;
294
+ > ms.fetchMetadata("breeze/NorthwindIBModel").then(function(rawMetadata) {
295
+ > // do something with the metadata
296
+ > }).catch(function(exception) {
297
+ > // handle exception here
298
+ > });
299
+ @param dataService - Either a DataService or just the name of the DataService to fetch metadata for.
300
+ @param callback - Function called on success.
301
+ @param errorCallback - Function called on failure.
302
+ @return Promise
303
+ **/
304
+ fetchMetadata(dataService, callback, errorCallback) {
305
+ try {
306
+ assertParam(dataService, "dataService").isString().or().isInstanceOf(DataService).check();
307
+ assertParam(callback, "callback").isFunction().isOptional().check();
308
+ assertParam(errorCallback, "errorCallback").isFunction().isOptional().check();
309
+ if (typeof dataService === "string") {
310
+ // use the dataService with a matching name or create a new one.
311
+ dataService = this.getDataService(dataService) || new DataService({ serviceName: dataService });
312
+ }
313
+ dataService = DataService.resolve([dataService]);
314
+ if (this.hasMetadataFor(dataService.serviceName)) {
315
+ throw new Error("Metadata for a specific serviceName may only be fetched once per MetadataStore. ServiceName: " + dataService.serviceName);
316
+ }
317
+ return dataService.adapterInstance.fetchMetadata(this, dataService).then((rawMetadata) => {
318
+ this.metadataFetched.publish({ metadataStore: this, dataService: dataService, rawMetadata: rawMetadata });
319
+ if (callback)
320
+ callback(rawMetadata);
321
+ return Promise.resolve(rawMetadata);
322
+ }, function (error) {
323
+ if (errorCallback)
324
+ errorCallback(error);
325
+ return Promise.reject(error);
326
+ });
327
+ }
328
+ catch (e) {
329
+ return Promise.reject(e);
330
+ }
331
+ }
332
+ // TODO: strongly type interceptor below.
333
+ /**
334
+ Used to register a constructor for an EntityType that is not known via standard Metadata discovery;
335
+ i.e. an unmapped type.
336
+ @param entityCtor - The constructor function for the 'unmapped' type.
337
+ @param interceptor - An interceptor function
338
+ **/
339
+ trackUnmappedType(entityCtor, interceptor) {
340
+ assertParam(entityCtor, "entityCtor").isFunction().check();
341
+ assertParam(interceptor, "interceptor").isFunction().isOptional().check();
342
+ // TODO: think about adding this to the MetadataStore.
343
+ let entityType = new EntityType(this);
344
+ entityType._setCtor(entityCtor, interceptor);
345
+ }
346
+ /**
347
+ Provides a mechanism to register a 'custom' constructor to be used when creating new instances
348
+ of the specified entity type. If this call is not made, a default constructor is created for
349
+ the entity as needed.
350
+ This call may be made before or after the corresponding EntityType has been discovered via
351
+ Metadata discovery.
352
+ > let Customer = function () {
353
+ > this.miscData = "asdf";
354
+ > };
355
+ > Customer.prototype.doFoo() {
356
+ > ...
357
+ > }
358
+ > // assume em1 is a preexisting EntityManager;
359
+ > em1.metadataStore.registerEntityTypeCtor("Customer", Customer);
360
+ > // any queries or EntityType.create calls from this point on will call the Customer constructor
361
+ > // registered above.
362
+ @param structuralTypeName - The name of the EntityType or ComplexType.
363
+ @param aCtor - The constructor for this EntityType or ComplexType; may be null if all you want to do is set the next parameter.
364
+ @param initFn - A function or the name of a function on the entity that is to be executed immediately after the entity has been created
365
+ and populated with any initial values. Called with 'initFn(entity)'
366
+ @param noTrackingFn - A function that is executed immediately after a noTracking entity has been created and whose return
367
+ value will be used in place of the noTracking entity.
368
+ **/
369
+ registerEntityTypeCtor(structuralTypeName, aCtor, initFn, noTrackingFn) {
370
+ assertParam(structuralTypeName, "structuralTypeName").isString().check();
371
+ assertParam(aCtor, "aCtor").isFunction().isOptional().check();
372
+ assertParam(initFn, "initFn").isOptional().isFunction().or().isString().check();
373
+ assertParam(noTrackingFn, "noTrackingFn").isOptional().isFunction().check();
374
+ let qualifiedTypeName = getQualifiedTypeName(this, structuralTypeName, false);
375
+ let typeName = qualifiedTypeName || structuralTypeName;
376
+ if (aCtor) {
377
+ if (aCtor._$typeName && aCtor._$typeName !== typeName) {
378
+ // TODO: wrap this - console and especially console.warn does not exist in all browsers.
379
+ console.warn("Registering a constructor for " + typeName + " that is already used for " + aCtor._$typeName + ".");
380
+ }
381
+ aCtor._$typeName = typeName;
382
+ }
383
+ this._ctorRegistry[typeName] = { ctor: aCtor, initFn: initFn, noTrackingFn: noTrackingFn };
384
+ if (qualifiedTypeName) {
385
+ let stype = this._structuralTypeMap[qualifiedTypeName];
386
+ stype && stype.getCtor(true); // this will complete the registration if avail now.
387
+ }
388
+ }
389
+ /**
390
+ Returns whether this MetadataStore contains any metadata yet.
391
+ > // assume em1 is a preexisting EntityManager;
392
+ > if (em1.metadataStore.isEmpty()) {
393
+ > // do something interesting
394
+ > }
395
+ **/
396
+ isEmpty() {
397
+ return core.isEmpty(this._structuralTypeMap);
398
+ }
399
+ /**
400
+ Returns an [[EntityType]] or null given its name.
401
+ > // assume em1 is a preexisting EntityManager
402
+ > let odType = em1.metadataStore.getAsEntityType("OrderDetail");
403
+
404
+ or to throw an error if the type is not found
405
+ > let badType = em1.metadataStore.getAsEntityType("Foo", false);
406
+ > // badType will not get set and an exception will be thrown.
407
+ @param structuralTypeName - Either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
408
+ that same short name an exception will be thrown.
409
+ @param okIfNotFound - (default=false) Whether to throw an error if the specified EntityType is not found.
410
+ @return The EntityType. ComplexType or 'null' if not not found.
411
+ **/
412
+ getAsEntityType(typeName, okIfNotFound = false) {
413
+ const st = this.getStructuralType(typeName, okIfNotFound);
414
+ if (st instanceof EntityType) {
415
+ return st;
416
+ }
417
+ else if (okIfNotFound) {
418
+ return null;
419
+ }
420
+ else {
421
+ let msg = core.formatString("Unable to locate an 'EntityType' by the name: '%1'. Be sure to execute a query or call fetchMetadata first.", typeName);
422
+ throw new Error(msg);
423
+ }
424
+ }
425
+ /**
426
+ Returns an [[EntityType]] or null given its name.
427
+ > // assume em1 is a preexisting EntityManager
428
+ > let locType = em1.metadataStore.getAsComplexType("Location");
429
+
430
+ or to throw an error if the type is not found
431
+ > let badType = em1.metadataStore.getAsComplexType("Foo", false);
432
+ > // badType will not get set and an exception will be thrown.
433
+ @param structuralTypeName - Either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
434
+ that same short name an exception will be thrown.
435
+ @param okIfNotFound - (default=false) Whether to throw an error if the specified EntityType is not found.
436
+ @return The EntityType. ComplexType or 'null' if not not found.
437
+ **/
438
+ getAsComplexType(typeName, okIfNotFound = false) {
439
+ const st = this.getStructuralType(typeName, okIfNotFound);
440
+ if (st instanceof ComplexType) {
441
+ return st;
442
+ }
443
+ else if (okIfNotFound) {
444
+ return null;
445
+ }
446
+ else {
447
+ let msg = core.formatString("Unable to locate an 'ComplexType' by the name: '%1'. Be sure to execute a query or call fetchMetadata first.", typeName);
448
+ throw new Error(msg);
449
+ }
450
+ }
451
+ /**
452
+ Returns an [[EntityType]] or a [[ComplexType]] given its name.
453
+ @deprecated Replaced by getStructuralType but ... it is probably more usefull to call either getAsEntityType or getAsComplexType instead
454
+ @param typeName - Either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
455
+ that same short name an exception will be thrown.
456
+ @param okIfNotFound - (default=false) Whether to throw an error if the specified EntityType is not found.
457
+ @return The EntityType. ComplexType or 'null' if not not found.
458
+ **/
459
+ getEntityType(typeName, okIfNotFound = false) {
460
+ return this.getStructuralType(typeName, okIfNotFound);
461
+ }
462
+ /**
463
+ Returns an [[EntityType]] or a [[ComplexType]] given its name.
464
+ > // assume em1 is a preexisting EntityManager
465
+ > let odType = em1.metadataStore.getStructuralType("OrderDetail");
466
+
467
+ or to throw an error if the type is not found
468
+ > let badType = em1.metadataStore.getStructuralType("Foo", false);
469
+ > // badType will not get set and an exception will be thrown.
470
+ @deprecated Preferably use either getAsEntityType or getAsComplexType. Get
471
+ @param typeName - Either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
472
+ that same short name an exception will be thrown.
473
+ @param okIfNotFound - (default=false) Whether to throw an error if the specified EntityType is not found.
474
+ @return The EntityType. ComplexType or 'null' if not not found.
475
+ **/
476
+ getStructuralType(typeName, okIfNotFound = false) {
477
+ assertParam(typeName, "typeName").isString().check();
478
+ assertParam(okIfNotFound, "okIfNotFound").isBoolean().isOptional().check(false);
479
+ return this._getStructuralType(typeName, okIfNotFound);
480
+ }
481
+ /** @hidden @internal */
482
+ _getStructuralType(typeName, okIfNotFound = false) {
483
+ let qualTypeName = getQualifiedTypeName(this, typeName, false);
484
+ let type = this._structuralTypeMap[qualTypeName];
485
+ if (!type) {
486
+ if (okIfNotFound)
487
+ return null;
488
+ let msg = core.formatString("Unable to locate a 'Type' by the name: '%1'. Be sure to execute a query or call fetchMetadata first.", typeName);
489
+ throw new Error(msg);
490
+ }
491
+ return type;
492
+ }
493
+ /**
494
+ Returns an array containing all of the [[EntityType]]s or [[ComplexType]]s in this MetadataStore.
495
+ > // assume em1 is a preexisting EntityManager
496
+ > let allTypes = em1.metadataStore.getEntityTypes();
497
+ **/
498
+ getEntityTypes() {
499
+ return getTypesFromMap(this._structuralTypeMap);
500
+ }
501
+ getIncompleteNavigationProperties() {
502
+ return core.objectMap(this._incompleteTypeMap, function (key, value) {
503
+ return value;
504
+ });
505
+ }
506
+ /**
507
+ Returns a fully qualified entityTypeName for a specified resource name. The reverse of this operation
508
+ can be obtained via the [[EntityType.defaultResourceName]] property
509
+ **/
510
+ getEntityTypeNameForResourceName(resourceName) {
511
+ assertParam(resourceName, "resourceName").isString().check();
512
+ return this._resourceEntityTypeMap[resourceName];
513
+ }
514
+ /**
515
+ Associates a resourceName with an entityType.
516
+
517
+ This method is only needed in those cases where multiple resources return the same
518
+ entityType. In this case Metadata discovery will only determine a single resource name for
519
+ each entityType.
520
+ @param resourceName - The resource name
521
+ @param entityTypeOrName - If passing a string either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
522
+ that same short name an exception will be thrown. If the entityType has not yet been discovered then a fully qualified name must be used.
523
+ **/
524
+ setEntityTypeForResourceName(resourceName, entityTypeOrName) {
525
+ assertParam(resourceName, "resourceName").isString().check();
526
+ assertParam(entityTypeOrName, "entityTypeOrName").isInstanceOf(EntityType).or().isString().check();
527
+ let entityTypeName;
528
+ if (entityTypeOrName instanceof EntityType) {
529
+ entityTypeName = entityTypeOrName.name;
530
+ }
531
+ else {
532
+ entityTypeName = getQualifiedTypeName(this, entityTypeOrName, true);
533
+ }
534
+ this._resourceEntityTypeMap[resourceName] = entityTypeName;
535
+ let entityType = this._getStructuralType(entityTypeName, true);
536
+ if (entityType && entityType instanceof EntityType && !entityType.defaultResourceName) {
537
+ entityType.defaultResourceName = resourceName;
538
+ }
539
+ }
540
+ /** __Dev Only__ - for use when creating a new MetadataParserAdapter */
541
+ static parseTypeName(entityTypeName) {
542
+ // TODO: removed
543
+ // if (!entityTypeName) {
544
+ // return null;
545
+ // }
546
+ let typeParts = entityTypeName.split(":#");
547
+ if (typeParts.length > 1) {
548
+ return MetadataStore.makeTypeHash(typeParts[0], typeParts[1]);
549
+ }
550
+ if (core.stringStartsWith(entityTypeName, MetadataStore.ANONTYPE_PREFIX)) {
551
+ let typeHash = MetadataStore.makeTypeHash(entityTypeName);
552
+ typeHash.isAnonymous = true;
553
+ return typeHash;
554
+ }
555
+ let entityTypeNameNoAssembly = entityTypeName.split(",")[0];
556
+ typeParts = entityTypeNameNoAssembly.split(".");
557
+ if (typeParts.length > 1) {
558
+ let shortName = typeParts[typeParts.length - 1];
559
+ let namespaceParts = typeParts.slice(0, typeParts.length - 1);
560
+ let ns = namespaceParts.join(".");
561
+ return MetadataStore.makeTypeHash(shortName, ns);
562
+ }
563
+ else {
564
+ return MetadataStore.makeTypeHash(entityTypeName);
565
+ }
566
+ }
567
+ /** __Dev Only__ - for use when creating a new MetadataParserAdapter */
568
+ static makeTypeHash(shortName, ns) {
569
+ return {
570
+ shortTypeName: shortName,
571
+ namespace: ns,
572
+ typeName: qualifyTypeName(shortName, ns)
573
+ };
574
+ }
575
+ // protected methods
576
+ /** @hidden @internal */
577
+ _checkEntityType(entity) {
578
+ if (entity.entityType)
579
+ return;
580
+ let typeName = entity.prototype._$typeName;
581
+ if (!typeName) {
582
+ throw new Error("This entity has not been registered. See the MetadataStore.registerEntityTypeCtor method");
583
+ }
584
+ // we know that it is an EntityType ( as opposed to a ComplexType)
585
+ let entityType = this._getStructuralType(typeName);
586
+ if (entityType) {
587
+ entity.entityType = entityType;
588
+ }
589
+ }
590
+ }
591
+ /** @hidden @internal */
592
+ MetadataStore.__id = 0;
593
+ /** @hidden @internal */
594
+ MetadataStore.ANONTYPE_PREFIX = "_IB_";
595
+ /** The version of any MetadataStores created by this class */
596
+ MetadataStore.metadataVersion = '1.0.5';
597
+ // needs to be made avail to dataService.xxx files
598
+ MetadataStore.normalizeTypeName = core.memoize(function (rawTypeName) {
599
+ return rawTypeName && MetadataStore.parseTypeName(rawTypeName).typeName;
600
+ });
601
+ MetadataStore.prototype._$typeName = "MetadataStore";
602
+ BreezeEvent.bubbleEvent(MetadataStore.prototype);
603
+ function getTypesFromMap(typeMap) {
604
+ let types = [];
605
+ for (let key in typeMap) {
606
+ let value = typeMap[key];
607
+ // skip 'shortName' entries
608
+ if (key === value.name) {
609
+ types.push(typeMap[key]);
610
+ }
611
+ }
612
+ return types;
613
+ }
614
+ function structuralTypeFromJson(metadataStore, json, allowMerge) {
615
+ let typeName = qualifyTypeName(json.shortName, json.namespace);
616
+ let stype = metadataStore._getStructuralType(typeName, true);
617
+ if (stype) {
618
+ if (allowMerge) {
619
+ return mergeStructuralType(stype, json);
620
+ }
621
+ else {
622
+ // allow it but don't replace anything.
623
+ return stype;
624
+ }
625
+ }
626
+ let config = {
627
+ shortName: json.shortName,
628
+ namespace: json.namespace,
629
+ isAbstract: json.isAbstract,
630
+ autoGeneratedKeyType: AutoGeneratedKeyType.fromName(json.autoGeneratedKeyType),
631
+ defaultResourceName: json.defaultResourceName,
632
+ custom: json.custom
633
+ };
634
+ stype = json.isComplexType ? new ComplexType(config) : new EntityType(config);
635
+ // baseType may not have been imported yet so we need to defer handling this type until later.
636
+ if (json.baseTypeName && stype instanceof EntityType) {
637
+ stype.baseTypeName = json.baseTypeName;
638
+ let baseEntityType = metadataStore._getStructuralType(json.baseTypeName, true);
639
+ if (baseEntityType) {
640
+ completeStructuralTypeFromJson(metadataStore, json, stype);
641
+ }
642
+ else {
643
+ core.getArray(metadataStore._deferredTypes, json.baseTypeName).push({ json: json, stype: stype });
644
+ }
645
+ }
646
+ else {
647
+ completeStructuralTypeFromJson(metadataStore, json, stype);
648
+ }
649
+ // stype may or may not have been added to the metadataStore at this point.
650
+ return stype;
651
+ }
652
+ function mergeStructuralType(stype, json) {
653
+ if (json.custom) {
654
+ stype.custom = json.custom;
655
+ }
656
+ mergeProps(stype, json.dataProperties);
657
+ mergeProps(stype, json.navigationProperties);
658
+ return stype;
659
+ }
660
+ function mergeProps(stype, jsonProps) {
661
+ if (!jsonProps)
662
+ return;
663
+ jsonProps.forEach((jsonProp) => {
664
+ let propName = jsonProp.name;
665
+ if (!propName) {
666
+ if (jsonProp.nameOnServer) {
667
+ propName = stype.metadataStore.namingConvention.serverPropertyNameToClient(jsonProp.nameOnServer, {});
668
+ }
669
+ else {
670
+ // backslash-quote works around compiler bug
671
+ const msg = "Unable to complete \'importMetadata\' - cannot locate a \'name\' or \'nameOnServer\' for one of the imported property nodes";
672
+ throw new Error(msg);
673
+ }
674
+ }
675
+ if (jsonProp.custom) {
676
+ let prop = stype.getProperty(propName, true);
677
+ prop.custom = jsonProp.custom;
678
+ }
679
+ });
680
+ }
681
+ function completeStructuralTypeFromJson(metadataStore, json, stype) {
682
+ // validators from baseType work because validation walks thru base types
683
+ // so no need to copy down.
684
+ if (json.validators) {
685
+ stype.validators = json.validators.map(Validator.fromJSON);
686
+ }
687
+ json.dataProperties.forEach(function (dp) {
688
+ stype._addPropertyCore(DataProperty.fromJSON(dp));
689
+ });
690
+ let isEntityType = !json.isComplexType;
691
+ if (isEntityType) {
692
+ //noinspection JSHint
693
+ json.navigationProperties && json.navigationProperties.forEach(function (np) {
694
+ stype._addPropertyCore(NavigationProperty.fromJSON(np));
695
+ });
696
+ }
697
+ metadataStore.addEntityType(stype);
698
+ let deferredTypes = metadataStore._deferredTypes;
699
+ let deferrals = deferredTypes[stype.name];
700
+ if (deferrals) {
701
+ deferrals.forEach(function (d) {
702
+ completeStructuralTypeFromJson(metadataStore, d.json, d.stype);
703
+ });
704
+ delete deferredTypes[stype.name];
705
+ }
706
+ }
707
+ function getQualifiedTypeName(metadataStore, structTypeName, throwIfNotFound) {
708
+ if (isQualifiedTypeName(structTypeName))
709
+ return structTypeName;
710
+ let result = metadataStore._shortNameMap[structTypeName];
711
+ if (!result && throwIfNotFound) {
712
+ throw new Error("Unable to locate 'entityTypeName' of: " + structTypeName);
713
+ }
714
+ return result;
715
+ }
716
+ /** Container for all of the metadata about a specific type of Entity.
717
+ **/
718
+ export class EntityType {
719
+ /** EntityType constructor
720
+ > let entityType = new EntityType( {
721
+ > shortName: "person",
722
+ > namespace: "myAppNamespace"
723
+ > });
724
+ @param config - Configuration settings or a MetadataStore. If this parameter is just a MetadataStore
725
+ then what will be created is an 'anonymous' type that will never be communicated to or from the server. It is purely for
726
+ client side use and will be given an automatically generated name. Normally, however, you will use a configuration object.
727
+ **/
728
+ constructor(config) {
729
+ /** Always false for an EntityType. **/
730
+ this.isComplexType = false;
731
+ /**
732
+ @deprecated Use [[getCtor]] instead.
733
+ */
734
+ this.getEntityCtor = this.getCtor;
735
+ if (arguments.length > 1) {
736
+ throw new Error("The EntityType ctor has a single argument that is either a 'MetadataStore' or a configuration object.");
737
+ }
738
+ // let etConfig = <EntityTypeConfig> <any> undefined;
739
+ let etConfig = undefined;
740
+ if (config._$typeName === "MetadataStore") {
741
+ this.metadataStore = config;
742
+ this.shortName = "Anon_" + (++EntityType.__nextAnonIx);
743
+ this.namespace = "";
744
+ this.isAnonymous = true;
745
+ // etConfig = undefined;
746
+ }
747
+ else {
748
+ etConfig = config;
749
+ assertConfig(config)
750
+ .whereParam("shortName").isNonEmptyString()
751
+ .whereParam("namespace").isString().isOptional().withDefault("")
752
+ .whereParam("baseTypeName").isString().isOptional()
753
+ .whereParam("isAbstract").isBoolean().isOptional().withDefault(false)
754
+ .whereParam("autoGeneratedKeyType").isEnumOf(AutoGeneratedKeyType).isOptional().withDefault(AutoGeneratedKeyType.None)
755
+ .whereParam("defaultResourceName").isNonEmptyString().isOptional().withDefault(null)
756
+ .whereParam("dataProperties").isOptional()
757
+ .whereParam("navigationProperties").isOptional()
758
+ .whereParam("serializerFn").isOptional().isFunction()
759
+ .whereParam("custom").isOptional()
760
+ .applyAll(this);
761
+ }
762
+ this.name = qualifyTypeName(this.shortName, this.namespace);
763
+ // the defaultResourceName may also be set up either via metadata lookup or first query or via the 'setProperties' method
764
+ this.dataProperties = [];
765
+ this.navigationProperties = [];
766
+ this.complexProperties = [];
767
+ this.keyProperties = [];
768
+ this.foreignKeyProperties = [];
769
+ this.inverseForeignKeyProperties = [];
770
+ this.concurrencyProperties = [];
771
+ this.unmappedProperties = []; // will be updated later.
772
+ this.validators = [];
773
+ this.warnings = [];
774
+ this._mappedPropertiesCount = 0;
775
+ this.subtypes = [];
776
+ // now process any data/nav props
777
+ if (etConfig && etConfig.dataProperties) {
778
+ addProperties(this, etConfig.dataProperties, DataProperty);
779
+ }
780
+ if (etConfig && etConfig.navigationProperties) {
781
+ addProperties(this, etConfig.navigationProperties, NavigationProperty);
782
+ }
783
+ }
784
+ /**
785
+ General purpose property set method
786
+ > // assume em1 is an EntityManager containing a number of existing entities.
787
+ > let custType = em1.metadataStore.getEntityType("Customer");
788
+ > custType.setProperties( {
789
+ > autoGeneratedKeyType: AutoGeneratedKeyType.Identity;
790
+ > defaultResourceName: "CustomersAndIncludedOrders"
791
+ > )};
792
+ @param config - a configuration object
793
+ **/
794
+ setProperties(config) {
795
+ assertConfig(config)
796
+ .whereParam("autoGeneratedKeyType").isEnumOf(AutoGeneratedKeyType).isOptional()
797
+ .whereParam("defaultResourceName").isString().isOptional()
798
+ .whereParam("serializerFn").isFunction().isOptional()
799
+ .whereParam("custom").isOptional()
800
+ .applyAll(this);
801
+ if (config.defaultResourceName) {
802
+ this.defaultResourceName = config.defaultResourceName;
803
+ }
804
+ }
805
+ /**
806
+ Returns whether this type is a subtype of a specified type.
807
+ **/
808
+ isSubtypeOf(entityType) {
809
+ assertParam(entityType, "entityType").isInstanceOf(EntityType).check();
810
+ let baseType = this;
811
+ do {
812
+ if (baseType === entityType)
813
+ return true;
814
+ baseType = baseType.baseEntityType;
815
+ } while (baseType);
816
+ return false;
817
+ }
818
+ /**
819
+ Returns an array containing this type and any/all subtypes of this type down thru the hierarchy.
820
+ **/
821
+ getSelfAndSubtypes() {
822
+ let result = [this];
823
+ this.subtypes.forEach(function (st) {
824
+ let subtypes = st.getSelfAndSubtypes();
825
+ result.push.apply(result, subtypes);
826
+ });
827
+ return result;
828
+ }
829
+ getAllValidators() {
830
+ let result = this.validators.slice(0);
831
+ let bt = this.baseEntityType;
832
+ while (bt) {
833
+ result.push.apply(result, bt.validators);
834
+ bt = bt.baseEntityType;
835
+ }
836
+ return result;
837
+ }
838
+ /**
839
+ Adds a [[DataProperty]] or a [[NavigationProperty]] to this EntityType.
840
+ > // assume myEntityType is a newly constructed EntityType.
841
+ > myEntityType.addProperty(dataProperty1);
842
+ > myEntityType.addProperty(dataProperty2);
843
+ > myEntityType.addProperty(navigationProperty1);
844
+ **/
845
+ addProperty(property) {
846
+ assertParam(property, "property").isInstanceOf(DataProperty).or().isInstanceOf(NavigationProperty).check();
847
+ // true is 2nd arg to force resolve of any navigation properties.
848
+ let newprop = this._addPropertyCore(property, true);
849
+ if (this.subtypes && this.subtypes.length) {
850
+ let stype = this;
851
+ stype.getSelfAndSubtypes().forEach(function (st) {
852
+ if (st !== stype) {
853
+ if (property.isNavigationProperty) {
854
+ st._addPropertyCore(new NavigationProperty(property), true);
855
+ }
856
+ else {
857
+ st._addPropertyCore(new DataProperty(property), true);
858
+ }
859
+ }
860
+ });
861
+ }
862
+ return newprop;
863
+ }
864
+ /** @hidden @internal */
865
+ _updateFromBase(baseEntityType) {
866
+ this.baseEntityType = baseEntityType;
867
+ if (this.autoGeneratedKeyType === AutoGeneratedKeyType.None) {
868
+ this.autoGeneratedKeyType = baseEntityType.autoGeneratedKeyType;
869
+ }
870
+ baseEntityType.dataProperties.forEach((dp) => {
871
+ let newDp = new DataProperty(dp);
872
+ // don't need to copy validators becaue we will walk the hierarchy to find them
873
+ newDp.validators = [];
874
+ newDp.baseProperty = dp;
875
+ this._addPropertyCore(newDp);
876
+ }, this);
877
+ baseEntityType.navigationProperties.forEach((np) => {
878
+ let newNp = new NavigationProperty(np);
879
+ // don't need to copy validators becaue we will walk the hierarchy to find them
880
+ newNp.validators = [];
881
+ newNp.baseProperty = np;
882
+ this._addPropertyCore(newNp);
883
+ }, this);
884
+ baseEntityType.subtypes.push(this);
885
+ }
886
+ /** @hidden @internal */
887
+ _addPropertyCore(property, shouldResolve = false) {
888
+ if (this.isFrozen) {
889
+ throw new Error("The '" + this.name + "' EntityType/ComplexType has been frozen. You can only add properties to an EntityType/ComplexType before any instances of that type have been created and attached to an entityManager.");
890
+ }
891
+ let parentType = property.parentType;
892
+ if (parentType) {
893
+ if (parentType !== this) {
894
+ throw new Error("This property: " + property.name + " has already been added to " + property.parentType.name);
895
+ }
896
+ else {
897
+ // adding the same property more than once to the same entityType is just ignored.
898
+ return;
899
+ }
900
+ }
901
+ property.parentType = this;
902
+ let ms = this.metadataStore;
903
+ // if (property.isDataProperty) { // modified because doesn't act as a type guard
904
+ if (property instanceof DataProperty) {
905
+ this._addDataProperty(property);
906
+ }
907
+ else {
908
+ this._addNavigationProperty(property);
909
+ // metadataStore can be undefined if this entityType has not yet been added to a MetadataStore.
910
+ if (shouldResolve && ms) {
911
+ tryResolveNp(property, ms);
912
+ }
913
+ }
914
+ // unmapped properties can be added AFTER entityType has already resolved all property names.
915
+ if (ms && !(property.name && property.nameOnServer)) {
916
+ updateClientServerNames(ms.namingConvention, property, "name");
917
+ }
918
+ // props can be added after entity prototype has already been wrapped.
919
+ if (ms && this._extra) {
920
+ if (this._extra.alreadyWrappedProps) {
921
+ let proto = this._ctor.prototype;
922
+ config.interfaceRegistry.modelLibrary.getDefaultInstance().initializeEntityPrototype(proto);
923
+ }
924
+ }
925
+ }
926
+ /**
927
+ Create a new entity of this type.
928
+ > // assume em1 is an EntityManager containing a number of existing entities.
929
+ > let custType = em1.metadataStore.getAsEntityType("Customer");
930
+ > let cust1 = custType.createEntity();
931
+ > em1.addEntity(cust1);
932
+ @param initialValues- Configuration object of the properties to set immediately after creation.
933
+ @return The new entity.
934
+ **/
935
+ createEntity(initialValues) {
936
+ // ignore the _$eref once the entity is attached to an entityManager.
937
+ if (initialValues && initialValues._$eref && !initialValues._$eref.entityAspect.entityManager)
938
+ return initialValues._$eref;
939
+ let instance = this._createInstanceCore();
940
+ if (initialValues) {
941
+ // only assign an _eref if the object is fully "keyed"
942
+ if (this.keyProperties.every(function (kp) {
943
+ return initialValues[kp.name] != null;
944
+ })) {
945
+ initialValues._$eref = instance;
946
+ }
947
+ this._updateTargetFromRaw(instance, initialValues, getRawValueFromConfig);
948
+ this.navigationProperties.forEach(function (np) {
949
+ let relatedEntity;
950
+ let val = initialValues[np.name];
951
+ if (val != undefined) {
952
+ let navEntityType = np.entityType;
953
+ if (np.isScalar) {
954
+ relatedEntity = val.entityAspect ? val : navEntityType.createEntity(val);
955
+ instance.setProperty(np.name, relatedEntity);
956
+ }
957
+ else {
958
+ let relatedEntities = instance.getProperty(np.name);
959
+ val.forEach((v) => {
960
+ relatedEntity = v.entityAspect ? v : navEntityType.createEntity(v);
961
+ relatedEntities.push(relatedEntity);
962
+ });
963
+ }
964
+ }
965
+ });
966
+ }
967
+ this._initializeInstance(instance);
968
+ return instance;
969
+ }
970
+ /** @hidden @internal */
971
+ _createInstanceCore() {
972
+ let aCtor = this.getCtor();
973
+ let instance = new aCtor();
974
+ new EntityAspect(instance);
975
+ return instance;
976
+ }
977
+ /** @hidden @internal */
978
+ _initializeInstance(instance) {
979
+ if (this.baseEntityType) {
980
+ this.baseEntityType._initializeInstance(instance);
981
+ }
982
+ let initFn = this.initFn;
983
+ if (initFn) {
984
+ let fn = (typeof initFn === "string") ? instance[initFn] : initFn;
985
+ fn(instance);
986
+ }
987
+ this.complexProperties && this.complexProperties.forEach(function (cp) {
988
+ let complexType = cp.dataType;
989
+ let ctInstance = instance.getProperty(cp.name);
990
+ if (Array.isArray(ctInstance)) {
991
+ ctInstance.forEach((ctInst) => {
992
+ complexType._initializeInstance(ctInst);
993
+ });
994
+ }
995
+ else {
996
+ complexType._initializeInstance(ctInstance);
997
+ }
998
+ });
999
+ // not needed for complexObjects
1000
+ if (instance.entityAspect) {
1001
+ instance.entityAspect._initialized = true;
1002
+ }
1003
+ }
1004
+ /**
1005
+ Returns the constructor for this EntityType.
1006
+ @param forceRefresh - Whether to ignore any cached version of this constructor. (default == false)
1007
+ @return The constructor for this EntityType.
1008
+ **/
1009
+ getCtor(forceRefresh = false) {
1010
+ if (this._ctor && !forceRefresh)
1011
+ return this._ctor;
1012
+ let ctorRegistry = this.metadataStore._ctorRegistry;
1013
+ let r = ctorRegistry[this.name] || ctorRegistry[this.shortName] || {};
1014
+ let aCtor = r.ctor || this._ctor;
1015
+ let ctorType = aCtor && aCtor.prototype && (aCtor.prototype.entityType || aCtor.prototype.complexType);
1016
+ if (ctorType && ctorType.metadataStore !== this.metadataStore) {
1017
+ // We can't risk a mismatch between the ctor and the type info in a specific metadatastore
1018
+ // because modelLibraries rely on type info to intercept ctor properties
1019
+ throw new Error("Cannot register the same constructor for " + this.name + " in different metadata stores. Please define a separate constructor for each metadata store.");
1020
+ }
1021
+ if (r.ctor && forceRefresh) {
1022
+ this._extra = undefined;
1023
+ }
1024
+ if (!aCtor) {
1025
+ let createCtor = config.interfaceRegistry.modelLibrary.getDefaultInstance().createCtor;
1026
+ aCtor = createCtor ? createCtor(this) : createEmptyCtor(this);
1027
+ }
1028
+ this.initFn = r.initFn;
1029
+ this.noTrackingFn = r.noTrackingFn;
1030
+ aCtor.prototype._$typeName = this.name;
1031
+ this._setCtor(aCtor);
1032
+ return aCtor;
1033
+ }
1034
+ /** @hidden @internal */
1035
+ // May make public later.
1036
+ _setCtor(aCtor, interceptor) {
1037
+ let instanceProto = aCtor.prototype;
1038
+ // place for extra breeze related data
1039
+ this._extra = this._extra || {};
1040
+ let instance = new aCtor();
1041
+ calcUnmappedProperties(this, instance);
1042
+ if (this._$typeName === "EntityType") {
1043
+ // insure that all of the properties are on the 'template' instance before watching the class.
1044
+ instanceProto.entityType = this;
1045
+ }
1046
+ else {
1047
+ instanceProto.complexType = this;
1048
+ }
1049
+ // defaultPropertyInterceptor is a 'global' (but internal to breeze) function;
1050
+ instanceProto._$interceptor = interceptor || defaultPropertyInterceptor;
1051
+ config.interfaceRegistry.modelLibrary.getDefaultInstance().initializeEntityPrototype(instanceProto);
1052
+ this._ctor = aCtor;
1053
+ }
1054
+ /**
1055
+ Adds either an entity or property level validator to this EntityType.
1056
+ > // assume em1 is an EntityManager containing a number of existing entities.
1057
+ > let custType = em1.metadataStore.getEntityType("Customer");
1058
+ > let countryProp = custType.getProperty("Country");
1059
+ > let valFn = function (v) {
1060
+ > if (v == null) return true;
1061
+ > return (core.stringStartsWith(v, "US"));
1062
+ > };
1063
+ > let countryValidator = new Validator("countryIsUS", valFn,
1064
+ > { displayName: "Country", messageTemplate: "'%displayName%' must start with 'US'" });
1065
+ > custType.addValidator(countryValidator, countryProp);
1066
+
1067
+ This is the same as adding an entity level validator via the 'validators' property of DataProperty or NavigationProperty
1068
+ > countryProp.validators.push(countryValidator);
1069
+
1070
+ Entity level validators can also be added by omitting the 'property' parameter.
1071
+ > custType.addValidator(someEntityLevelValidator);
1072
+
1073
+ or
1074
+ > custType.validators.push(someEntityLevelValidator);
1075
+ @param validator - Validator to add.
1076
+ @param property - Property to add this validator to. If omitted, the validator is assumed to be an
1077
+ entity level validator and is added to the EntityType's 'validators'.
1078
+ **/
1079
+ addValidator(validator, property) {
1080
+ assertParam(validator, "validator").isInstanceOf(Validator).check();
1081
+ assertParam(property, "property").isOptional().isString().or().isEntityProperty().check();
1082
+ if (property != null) {
1083
+ let prop = (typeof property === 'string') ? this.getProperty(property, true) : property;
1084
+ prop.validators.push(validator);
1085
+ }
1086
+ else {
1087
+ this.validators.push(validator);
1088
+ }
1089
+ }
1090
+ /**
1091
+ Returns all of the properties ( dataProperties and navigationProperties) for this EntityType.
1092
+ > // assume em1 is an EntityManager containing a number of existing entities.
1093
+ > let custType = em1.metadataStore.getEntityType("Customer");
1094
+ > let arrayOfProps = custType.getProperties();
1095
+ @return An array of Data and Navigation properties.
1096
+ **/
1097
+ getProperties() {
1098
+ return this.dataProperties.concat(this.navigationProperties);
1099
+ }
1100
+ /**
1101
+ Returns all of the property names ( for both dataProperties and navigationProperties) for this EntityType.
1102
+ > // assume em1 is an EntityManager containing a number of existing entities.
1103
+ > let custType = em1.metadataStore.getEntityType("Customer");
1104
+ > let arrayOfPropNames = custType.getPropertyNames();
1105
+ **/
1106
+ getPropertyNames() {
1107
+ return this.getProperties().map(core.pluck('name'));
1108
+ }
1109
+ /**
1110
+ Returns a data property with the specified name or null.
1111
+ > // assume em1 is an EntityManager containing a number of existing entities.
1112
+ > let custType = em1.metadataStore.getEntityType("Customer");
1113
+ > let customerNameDataProp = custType.getDataProperty("CustomerName");
1114
+ @return A DataProperty or null if not found.
1115
+ **/
1116
+ getDataProperty(propertyName) {
1117
+ return core.arrayFirst(this.dataProperties, core.propEq('name', propertyName));
1118
+ }
1119
+ /**
1120
+ Returns a navigation property with the specified name or null.
1121
+ > // assume em1 is an EntityManager containing a number of existing entities.
1122
+ > let custType = em1.metadataStore.getEntityType("Customer");
1123
+ > let customerOrdersNavProp = custType.getDataProperty("Orders");
1124
+ @return A NavigationProperty or null if not found.
1125
+ **/
1126
+ getNavigationProperty(propertyName) {
1127
+ return core.arrayFirst(this.navigationProperties, core.propEq('name', propertyName));
1128
+ }
1129
+ /**
1130
+ Returns either a DataProperty or a NavigationProperty with the specified name or null.
1131
+
1132
+ This method also accepts a '.' delimited property path and will return the 'property' at the
1133
+ end of the path.
1134
+ > let custType = em1.metadataStore.getEntityType("Customer");
1135
+ > let companyNameProp = custType.getProperty("CompanyName");
1136
+
1137
+ This method can also walk a property path to return a property
1138
+ > let orderDetailType = em1.metadataStore.getEntityType("OrderDetail");
1139
+ > let companyNameProp2 = orderDetailType.getProperty("Order.Customer.CompanyName");
1140
+ > // companyNameProp === companyNameProp2
1141
+ @param [throwIfNotFound=false] {Boolean} Whether to throw an exception if not found.
1142
+ @return A DataProperty or NavigationProperty or null if not found.
1143
+ **/
1144
+ getProperty(propertyPath, throwIfNotFound = false) {
1145
+ let props = this.getPropertiesOnPath(propertyPath, false, throwIfNotFound);
1146
+ return (props && props.length > 0) ? props[props.length - 1] : null;
1147
+ }
1148
+ /** @hidden @internal */
1149
+ // TODO: have this return empty array instead of null and fix consumers.
1150
+ // TODO: think about renaming with '_' prefix.
1151
+ getPropertiesOnPath(propertyPath, useServerName, throwIfNotFound = false) {
1152
+ let propertyNames = (Array.isArray(propertyPath)) ? propertyPath : propertyPath.trim().split('.');
1153
+ let ok = true;
1154
+ let key = useServerName === true ? "nameOnServer" : useServerName === false ? "name" : null;
1155
+ let parentType = this;
1156
+ const getProps = (propName) => {
1157
+ const fn = key === null ? core.propsEq("name", "nameOnServer", propName) : core.propEq(key, propName);
1158
+ let prop = core.arrayFirst(parentType.getProperties(), fn);
1159
+ if (prop) {
1160
+ parentType = (prop instanceof NavigationProperty) ? prop.entityType : prop.dataType;
1161
+ // parentType = prop.isNavigationProperty ? prop.entityType : prop.dataType;
1162
+ }
1163
+ else if (throwIfNotFound) {
1164
+ throw new Error("unable to locate property: " + propName + " on entityType: " + parentType.name);
1165
+ }
1166
+ else {
1167
+ ok = false;
1168
+ }
1169
+ return prop;
1170
+ };
1171
+ let props = propertyNames.map(getProps);
1172
+ return ok ? props : null;
1173
+ }
1174
+ /** For use in pluggable adapters. */
1175
+ // TODO: document use
1176
+ clientPropertyPathToServer(propertyPath, delimiter = '.') {
1177
+ let propNames;
1178
+ if (this.isAnonymous) {
1179
+ let fn = this.metadataStore.namingConvention.clientPropertyNameToServer;
1180
+ propNames = propertyPath.split(".").map(function (propName) {
1181
+ return fn(propName);
1182
+ });
1183
+ }
1184
+ else {
1185
+ let props = this.getPropertiesOnPath(propertyPath, false, true);
1186
+ propNames = props.map((prop) => prop.nameOnServer);
1187
+ }
1188
+ return propNames.join(delimiter);
1189
+ }
1190
+ /** For use in pluggable adapters. */
1191
+ // TODO: document use
1192
+ getEntityKeyFromRawEntity(rawEntity, rawValueFn) {
1193
+ let keyValues = this.keyProperties.map((dp) => {
1194
+ let val = rawValueFn(rawEntity, dp);
1195
+ return DataType.parseRawValue(val, dp.dataType);
1196
+ });
1197
+ return new EntityKey(this, keyValues);
1198
+ }
1199
+ /** @hidden @internal */
1200
+ _updateTargetFromRaw(target, raw, rawValueFn) {
1201
+ // called recursively for complex properties
1202
+ this.dataProperties.forEach((dp) => {
1203
+ if (!dp.isSettable)
1204
+ return;
1205
+ let rawVal = rawValueFn(raw, dp);
1206
+ if (rawVal === undefined)
1207
+ return;
1208
+ let dataType = dp.dataType; // this will be a complexType when dp is a complexProperty
1209
+ let oldVal;
1210
+ if (dp.isComplexProperty) {
1211
+ let complexType = dp.dataType;
1212
+ if (rawVal === null)
1213
+ return; // rawVal may be null in nosql dbs where it was never defined for the given row.
1214
+ oldVal = target.getProperty(dp.name);
1215
+ if (dp.isScalar) {
1216
+ complexType._updateTargetFromRaw(oldVal, rawVal, rawValueFn);
1217
+ }
1218
+ else {
1219
+ if (Array.isArray(rawVal)) {
1220
+ let newVal = rawVal.map(function (rawCo) {
1221
+ let newCo = complexType._createInstanceCore(target, dp);
1222
+ complexType._updateTargetFromRaw(newCo, rawCo, rawValueFn);
1223
+ complexType._initializeInstance(newCo);
1224
+ return newCo;
1225
+ });
1226
+ if (!core.arrayEquals(oldVal, newVal, coEquals)) {
1227
+ // clear the old array and push new objects into it.
1228
+ oldVal.length = 0;
1229
+ newVal.forEach(function (nv) {
1230
+ oldVal.push(nv);
1231
+ });
1232
+ }
1233
+ }
1234
+ else {
1235
+ oldVal.length = 0;
1236
+ }
1237
+ }
1238
+ }
1239
+ else {
1240
+ if (dp.isScalar) {
1241
+ let newVal = DataType.parseRawValue(rawVal, dataType);
1242
+ target.setProperty(dp.name, newVal);
1243
+ }
1244
+ else {
1245
+ oldVal = target.getProperty(dp.name);
1246
+ if (Array.isArray(rawVal)) {
1247
+ // need to compare values
1248
+ let newVal = rawVal.map((rv) => {
1249
+ return DataType.parseRawValue(rv, dataType);
1250
+ });
1251
+ if (!core.arrayEquals(oldVal, newVal)) {
1252
+ // clear the old array and push new objects into it.
1253
+ oldVal.length = 0;
1254
+ newVal.forEach(function (nv) {
1255
+ oldVal.push(nv);
1256
+ });
1257
+ }
1258
+ }
1259
+ else {
1260
+ oldVal.length = 0;
1261
+ }
1262
+ }
1263
+ }
1264
+ });
1265
+ // if merging from an import then raw will have an entityAspect or a complexAspect
1266
+ let rawAspect = raw.entityAspect || raw.complexAspect;
1267
+ if (rawAspect) {
1268
+ let targetAspect = EntityAspect.isEntity(target) ? target.entityAspect : target.complexAspect;
1269
+ if (rawAspect.originalValuesMap) {
1270
+ targetAspect.originalValues = rawAspect.originalValuesMap;
1271
+ }
1272
+ if (rawAspect.extraMetadata) {
1273
+ targetAspect.extraMetadata = rawAspect.extraMetadata;
1274
+ }
1275
+ }
1276
+ }
1277
+ /**
1278
+ Returns a string representation of this EntityType.
1279
+ **/
1280
+ toString() {
1281
+ return this.name;
1282
+ }
1283
+ toJSON() {
1284
+ return core.toJson(this, {
1285
+ shortName: null,
1286
+ namespace: null,
1287
+ baseTypeName: null,
1288
+ isAbstract: false,
1289
+ autoGeneratedKeyType: null,
1290
+ defaultResourceName: null,
1291
+ dataProperties: localPropsOnly,
1292
+ navigationProperties: localPropsOnly,
1293
+ validators: null,
1294
+ custom: null
1295
+ });
1296
+ }
1297
+ /** @hidden @internal */
1298
+ _updateNames(property) {
1299
+ let nc = this.metadataStore.namingConvention;
1300
+ updateClientServerNames(nc, property, "name");
1301
+ if (property.isNavigationProperty) {
1302
+ updateClientServerNames(nc, property, "foreignKeyNames");
1303
+ updateClientServerNames(nc, property, "invForeignKeyNames");
1304
+ // these will get set later via _updateNps
1305
+ // this.inverse
1306
+ // this.entityType
1307
+ // this.relatedDataProperties
1308
+ // dataProperty.relatedNavigationProperty
1309
+ // dataProperty.inverseNavigationProperty
1310
+ }
1311
+ }
1312
+ /** @hidden @internal */
1313
+ _checkNavProperty(navigationProperty) {
1314
+ // if (navigationProperty.isNavigationProperty) {
1315
+ if (navigationProperty instanceof NavigationProperty) {
1316
+ if (navigationProperty.parentType !== this) {
1317
+ throw new Error(core.formatString("The navigationProperty '%1' is not a property of entity type '%2'", navigationProperty.name, this.name));
1318
+ }
1319
+ return navigationProperty;
1320
+ }
1321
+ if (typeof (navigationProperty) === 'string') {
1322
+ let np = this.getProperty(navigationProperty);
1323
+ // if (np && np.isNavigationProperty) return np;
1324
+ if (np && np instanceof NavigationProperty)
1325
+ return np;
1326
+ }
1327
+ throw new Error("The 'navigationProperty' parameter must either be a NavigationProperty or the name of a NavigationProperty");
1328
+ }
1329
+ /** @hidden @internal */
1330
+ _addDataProperty(dp) {
1331
+ this.dataProperties.push(dp);
1332
+ if (dp.isPartOfKey) {
1333
+ this.keyProperties.push(dp);
1334
+ }
1335
+ if (dp.isComplexProperty) {
1336
+ this.complexProperties.push(dp);
1337
+ }
1338
+ if (dp.concurrencyMode && dp.concurrencyMode !== "None") {
1339
+ this.concurrencyProperties.push(dp);
1340
+ }
1341
+ if (dp.isUnmapped) {
1342
+ this.unmappedProperties.push(dp);
1343
+ }
1344
+ }
1345
+ /** @hidden @internal */
1346
+ _addNavigationProperty(np) {
1347
+ this.navigationProperties.push(np);
1348
+ if (!isQualifiedTypeName(np.entityTypeName)) {
1349
+ np.entityTypeName = qualifyTypeName(np.entityTypeName, this.namespace);
1350
+ }
1351
+ }
1352
+ /** @hidden @internal */
1353
+ _updateCps() {
1354
+ let metadataStore = this.metadataStore;
1355
+ let incompleteTypeMap = metadataStore._incompleteComplexTypeMap;
1356
+ this.complexProperties.forEach(function (cp) {
1357
+ if (cp.complexType)
1358
+ return;
1359
+ if (!resolveCp(cp, metadataStore)) {
1360
+ core.getArray(incompleteTypeMap, cp.complexTypeName).push(cp);
1361
+ }
1362
+ });
1363
+ if (this.isComplexType) {
1364
+ (incompleteTypeMap[this.name] || []).forEach(function (cp) {
1365
+ resolveCp(cp, metadataStore);
1366
+ });
1367
+ delete incompleteTypeMap[this.name];
1368
+ }
1369
+ }
1370
+ /** @hidden @internal */
1371
+ _updateNps() {
1372
+ let metadataStore = this.metadataStore;
1373
+ // resolve all navProps for this entityType
1374
+ this.navigationProperties.forEach(function (np) {
1375
+ tryResolveNp(np, metadataStore);
1376
+ });
1377
+ let incompleteTypeMap = metadataStore._incompleteTypeMap;
1378
+ // next resolve all navProp that point to this entityType.
1379
+ (incompleteTypeMap[this.name] || []).forEach(function (np) {
1380
+ tryResolveNp(np, metadataStore);
1381
+ });
1382
+ // every navProp that pointed to this type should now be resolved
1383
+ delete incompleteTypeMap[this.name];
1384
+ }
1385
+ }
1386
+ /** @hidden @internal */
1387
+ EntityType.__nextAnonIx = 0;
1388
+ /** @hidden @internal */
1389
+ EntityType.qualifyTypeName = qualifyTypeName;
1390
+ EntityType.prototype._$typeName = "EntityType";
1391
+ function getRawValueFromConfig(rawEntity, dp) {
1392
+ // 'true' fork can happen if an initializer contains an actaul instance of an already created complex object.
1393
+ return (rawEntity.entityAspect || rawEntity.complexAspect) ? rawEntity.getProperty(dp.name) : rawEntity[dp.name];
1394
+ }
1395
+ function updateClientServerNames(nc, parent, clientPropName) {
1396
+ let serverPropName = clientPropName + "OnServer";
1397
+ let clientName = parent[clientPropName];
1398
+ if (clientName && clientName.length) {
1399
+ // if (parent.isUnmapped) return;
1400
+ let serverNames = core.toArray(clientName).map(function (cName) {
1401
+ let sName = nc.clientPropertyNameToServer(cName, parent);
1402
+ let testName = nc.serverPropertyNameToClient(sName, parent);
1403
+ if (cName !== testName) {
1404
+ throw new Error("NamingConvention for this client property name does not roundtrip properly:" + cName + "-->" + testName);
1405
+ }
1406
+ return sName;
1407
+ });
1408
+ parent[serverPropName] = Array.isArray(clientName) ? serverNames : serverNames[0];
1409
+ }
1410
+ else {
1411
+ let serverName = parent[serverPropName];
1412
+ if ((!serverName) || serverName.length === 0)
1413
+ return;
1414
+ let clientNames = core.toArray(serverName).map(function (sName) {
1415
+ let cName = nc.serverPropertyNameToClient(sName, parent);
1416
+ let testName = nc.clientPropertyNameToServer(cName, parent);
1417
+ if (sName !== testName) {
1418
+ throw new Error("NamingConvention for this server property name does not roundtrip properly:" + sName + "-->" + testName);
1419
+ }
1420
+ return cName;
1421
+ });
1422
+ parent[clientPropName] = Array.isArray(serverName) ? clientNames : clientNames[0];
1423
+ }
1424
+ }
1425
+ function createEmptyCtor(type) {
1426
+ if (config.noEval) {
1427
+ let Entity = function () { };
1428
+ return Entity;
1429
+ }
1430
+ else {
1431
+ let name = type.name.replace(/\W/g, '_');
1432
+ return Function('return function ' + name + '(){}')();
1433
+ }
1434
+ }
1435
+ function coEquals(co1, co2) {
1436
+ let complexType = co1.complexAspect.parentProperty.dataType;
1437
+ let dataProps = complexType.dataProperties;
1438
+ let areEqual = dataProps.every(function (dp) {
1439
+ if (!dp.isSettable)
1440
+ return true;
1441
+ let v1 = co1.getProperty(dp.name);
1442
+ let v2 = co2.getProperty(dp.name);
1443
+ if (dp.isComplexProperty && dp.isScalar) {
1444
+ return coEquals(v1, v2);
1445
+ }
1446
+ else if (dp.isComplexProperty && !dp.isScalar) {
1447
+ return core.arrayEquals(v1, v2, coEquals);
1448
+ }
1449
+ else {
1450
+ let dataType = dp.dataType; // this will be a complexType when dp is a complexProperty
1451
+ return (v1 === v2 || (dataType && dataType.normalize && v1 && v2 && dataType.normalize(v1) === dataType.normalize(v2)));
1452
+ }
1453
+ });
1454
+ return areEqual;
1455
+ }
1456
+ function localPropsOnly(props) {
1457
+ return props.filter(function (prop) {
1458
+ return prop.baseProperty == null;
1459
+ });
1460
+ }
1461
+ function resolveCp(cp, metadataStore) {
1462
+ let complexType = metadataStore._getStructuralType(cp.complexTypeName, true);
1463
+ if (!complexType)
1464
+ return false;
1465
+ if (!(complexType instanceof ComplexType)) {
1466
+ throw new Error("Unable to resolve ComplexType with the name: " + cp.complexTypeName + " for the property: " + cp.name);
1467
+ }
1468
+ cp.dataType = complexType;
1469
+ cp.defaultValue = null;
1470
+ return true;
1471
+ }
1472
+ function tryResolveNp(np, metadataStore) {
1473
+ if (np.entityType)
1474
+ return true;
1475
+ let entityType = metadataStore._getStructuralType(np.entityTypeName, true);
1476
+ if (entityType) {
1477
+ np.entityType = entityType;
1478
+ np._resolveNp();
1479
+ // don't bother removing - _updateNps will do it later.
1480
+ // __arrayRemoveItem(incompleteNps, np, false);
1481
+ }
1482
+ else {
1483
+ let incompleteNps = core.getArray(metadataStore._incompleteTypeMap, np.entityTypeName);
1484
+ core.arrayAddItemUnique(incompleteNps, np);
1485
+ }
1486
+ return !!entityType;
1487
+ }
1488
+ function calcUnmappedProperties(stype, instance) {
1489
+ let metadataPropNames = stype.getPropertyNames();
1490
+ let modelLib = config.interfaceRegistry.modelLibrary.getDefaultInstance();
1491
+ let trackablePropNames = modelLib.getTrackablePropertyNames(instance);
1492
+ trackablePropNames.forEach(function (pn) {
1493
+ if (metadataPropNames.indexOf(pn) === -1) {
1494
+ let val = instance[pn];
1495
+ try {
1496
+ if (typeof val === "function")
1497
+ val = val();
1498
+ }
1499
+ catch (e) {
1500
+ }
1501
+ let dt = DataType.fromValue(val);
1502
+ let newProp = new DataProperty({
1503
+ name: pn,
1504
+ dataType: dt,
1505
+ isNullable: true,
1506
+ isUnmapped: true
1507
+ });
1508
+ newProp.isSettable = core.isSettable(instance, pn);
1509
+ if (stype instanceof EntityType && stype.subtypes != null && stype.subtypes.length) {
1510
+ stype.getSelfAndSubtypes().forEach((st) => {
1511
+ st._addPropertyCore(new DataProperty(newProp));
1512
+ });
1513
+ }
1514
+ else {
1515
+ stype._addPropertyCore(newProp);
1516
+ }
1517
+ }
1518
+ });
1519
+ }
1520
+ /** Container for all of the metadata about a specific type of Complex object.
1521
+ > let complexType = new ComplexType( {
1522
+ > shortName: "address",
1523
+ > namespace: "myAppNamespace"
1524
+ > });
1525
+ @param config - Configuration settings
1526
+ **/
1527
+ export class ComplexType {
1528
+ constructor(config) {
1529
+ /** For polymorphic purpose only - always true here */
1530
+ this.isComplexType = true;
1531
+ // copy entityType methods onto complexType
1532
+ /** See [[EntityType.getCtor]] */
1533
+ this.getCtor = EntityType.prototype.getCtor;
1534
+ // note the name change.
1535
+ this.createInstance = EntityType.prototype.createEntity;
1536
+ /** See [EntityType.addValidator] */
1537
+ this.addValidator = EntityType.prototype.addValidator;
1538
+ this.getProperty = EntityType.prototype.getProperty;
1539
+ this.getPropertiesOnPath = EntityType.prototype.getPropertiesOnPath;
1540
+ this.getPropertyNames = EntityType.prototype.getPropertyNames;
1541
+ /** @hidden @internal */
1542
+ this._addPropertyCore = EntityType.prototype._addPropertyCore;
1543
+ /** @hidden @internal */
1544
+ this._addDataProperty = EntityType.prototype._addDataProperty;
1545
+ /** @hidden @internal */
1546
+ this._updateNames = EntityType.prototype._updateNames;
1547
+ /** @hidden @internal */
1548
+ this._updateCps = EntityType.prototype._updateCps;
1549
+ /** @hidden @internal */
1550
+ this._initializeInstance = EntityType.prototype._initializeInstance;
1551
+ /** @hidden @internal */
1552
+ this._updateTargetFromRaw = EntityType.prototype._updateTargetFromRaw;
1553
+ /** @hidden @internal */
1554
+ this._setCtor = EntityType.prototype._setCtor;
1555
+ if (arguments.length > 1) {
1556
+ throw new Error("The ComplexType ctor has a single argument that is a configuration object.");
1557
+ }
1558
+ assertConfig(config)
1559
+ .whereParam("shortName").isNonEmptyString()
1560
+ .whereParam("namespace").isString().isOptional().withDefault("")
1561
+ .whereParam("dataProperties").isOptional()
1562
+ .whereParam("isComplexType").isOptional().isBoolean() // needed because this ctor can get called from the addEntityType method which needs the isComplexType prop
1563
+ .whereParam("custom").isOptional()
1564
+ .applyAll(this);
1565
+ this.name = qualifyTypeName(this.shortName, this.namespace);
1566
+ this.isComplexType = true;
1567
+ this.dataProperties = [];
1568
+ this.complexProperties = [];
1569
+ this.validators = [];
1570
+ this.concurrencyProperties = [];
1571
+ this.unmappedProperties = [];
1572
+ this._mappedPropertiesCount = 0;
1573
+ // keyProperties and navigationProperties are not used on complexTypes - but here to allow sharing of code between EntityType and ComplexType.
1574
+ this.navigationProperties = [];
1575
+ this.keyProperties = []; // may be used later to enforce uniqueness on arrays of complextypes.
1576
+ if (config.dataProperties) {
1577
+ addProperties(this, config.dataProperties, DataProperty);
1578
+ }
1579
+ }
1580
+ /**
1581
+ General purpose property set method
1582
+ > // assume em1 is an EntityManager
1583
+ > let addresstType = em1.metadataStore.getEntityType("Address");
1584
+ > addressType.setProperties( {
1585
+ > custom: { foo: 7, bar: "test" }
1586
+ > });
1587
+ @param config - Custom config object
1588
+ @param config.custom - {Object}
1589
+ **/
1590
+ setProperties(config) {
1591
+ assertConfig(config)
1592
+ .whereParam("custom").isOptional()
1593
+ .applyAll(this);
1594
+ }
1595
+ getAllValidators() {
1596
+ // ComplexType inheritance is not YET supported.
1597
+ return this.validators;
1598
+ }
1599
+ /** @hidden @internal */
1600
+ _createInstanceCore(parent, parentProperty) {
1601
+ let aCtor = this.getCtor();
1602
+ let instance = new aCtor();
1603
+ new ComplexAspect(instance, parent, parentProperty);
1604
+ // initialization occurs during either attach or in createInstance call.
1605
+ return instance;
1606
+ }
1607
+ addProperty(dataProperty) {
1608
+ assertParam(dataProperty, "dataProperty").isInstanceOf(DataProperty).check();
1609
+ return this._addPropertyCore(dataProperty);
1610
+ }
1611
+ getProperties() {
1612
+ return this.dataProperties;
1613
+ }
1614
+ toJSON() {
1615
+ return core.toJson(this, {
1616
+ shortName: null,
1617
+ namespace: null,
1618
+ isComplexType: null,
1619
+ dataProperties: null,
1620
+ validators: null,
1621
+ custom: null
1622
+ });
1623
+ }
1624
+ }
1625
+ ComplexType.prototype._$typeName = "ComplexType";
1626
+ /** Creates an instance of this complexType */
1627
+ ComplexType.prototype.createInstance = EntityType.prototype.createEntity;
1628
+ /**
1629
+ A DataProperty describes the metadata for a single property of an [[EntityType]] that contains simple data.
1630
+
1631
+ Instances of the DataProperty class are constructed automatically during Metadata retrieval. However it is also possible to construct them
1632
+ directly via the constructor.
1633
+ **/
1634
+ export class DataProperty {
1635
+ /** DataProperty constructor
1636
+ > let lastNameProp = new DataProperty( {
1637
+ > name: "lastName",
1638
+ > dataType: DataType.String,
1639
+ > isNullable: true,
1640
+ > maxLength: 20
1641
+ > });
1642
+ > // assuming personEntityType is a newly constructed EntityType
1643
+ > personEntityType.addProperty(lastNameProperty);
1644
+ @param config - A configuration Object or a DataProperty
1645
+ */
1646
+ constructor(config) {
1647
+ /** Is this a DataProperty? - always true here. Allows polymorphic treatment of DataProperties and NavigationProperties. __Read Only__ */
1648
+ this.isDataProperty = true;
1649
+ /** Is this a NavigationProperty? - always false here. Allows polymorphic treatment of DataProperties and NavigationProperties. __Read Only__ */
1650
+ this.isNavigationProperty = false;
1651
+ assertConfig(config)
1652
+ .whereParam("name").isString().isOptional()
1653
+ .whereParam("nameOnServer").isString().isOptional()
1654
+ .whereParam("dataType").isEnumOf(DataType).isOptional().or().isString().or().isInstanceOf(ComplexType)
1655
+ .whereParam("complexTypeName").isOptional()
1656
+ .whereParam("isNullable").isBoolean().isOptional().withDefault(true)
1657
+ .whereParam("isScalar").isOptional().withDefault(true) // will be false for some NoSQL databases.
1658
+ .whereParam("defaultValue").isOptional()
1659
+ .whereParam("isPartOfKey").isBoolean().isOptional()
1660
+ .whereParam("isUnmapped").isBoolean().isOptional()
1661
+ .whereParam("isSettable").isBoolean().isOptional().withDefault(true)
1662
+ .whereParam("concurrencyMode").isString().isOptional()
1663
+ .whereParam("maxLength").isNumber().isOptional()
1664
+ .whereParam("validators").isInstanceOf(Validator).isArray().isOptional().withDefault([])
1665
+ .whereParam("displayName").isOptional()
1666
+ .whereParam("enumType").isOptional()
1667
+ .whereParam("rawTypeName").isOptional() // occurs with undefined datatypes
1668
+ .whereParam("custom").isOptional()
1669
+ .applyAll(this);
1670
+ let hasName = !!(this.name || this.nameOnServer);
1671
+ if (!hasName) {
1672
+ throw new Error("A DataProperty must be instantiated with either a 'name' or a 'nameOnServer' property");
1673
+ }
1674
+ // name/nameOnServer is resolved later when a metadataStore is available.
1675
+ if (this.complexTypeName) {
1676
+ this.isComplexProperty = true;
1677
+ // this.dataType = null; // TODO: would like to remove this line because dataType will be set later.
1678
+ }
1679
+ else if (typeof (this.dataType) === "string") {
1680
+ let dt = DataType.fromName(this.dataType);
1681
+ if (!dt) {
1682
+ throw new Error("Unable to find a DataType enumeration by the name of: " + this.dataType);
1683
+ }
1684
+ this.dataType = dt;
1685
+ }
1686
+ else if (!this.dataType) {
1687
+ this.dataType = DataType.String;
1688
+ }
1689
+ // == as opposed to === is deliberate here.
1690
+ if (this.defaultValue == null) {
1691
+ if (this.isNullable) {
1692
+ this.defaultValue = null;
1693
+ }
1694
+ else {
1695
+ if (this.isComplexProperty) {
1696
+ // what to do? - shouldn't happen from EF - but otherwise ???
1697
+ }
1698
+ else if (this.dataType === DataType.Binary) {
1699
+ this.defaultValue = "AAAAAAAAJ3U="; // hack for all binary fields but value is specifically valid for timestamp fields - arbitrary valid 8 byte base64 value.
1700
+ }
1701
+ else {
1702
+ this.defaultValue = this.dataType.defaultValue;
1703
+ const msg = "A nonnullable DataProperty cannot have a null defaultValue. Name: " + (this.name || this.nameOnServer);
1704
+ if (this.defaultValue === null) {
1705
+ throw new Error(msg); // if defaultValue is explicity set to null, that's an error
1706
+ }
1707
+ else if (this.defaultValue == null) {
1708
+ console.warn(msg); // if defaultValue is not set, that's a warning
1709
+ }
1710
+ }
1711
+ }
1712
+ }
1713
+ else if (this.dataType.isNumeric) {
1714
+ // in case the defaultValue comes in as a string ( which it does in EF6).
1715
+ if (typeof (this.defaultValue) === "string") {
1716
+ this.defaultValue = parseFloat(this.defaultValue);
1717
+ }
1718
+ }
1719
+ if (this.isComplexProperty) {
1720
+ this.isScalar = this.isScalar == null || this.isScalar === true;
1721
+ }
1722
+ }
1723
+ static getRawValueFromServer(rawEntity, dp) {
1724
+ if (dp.isUnmapped) {
1725
+ return rawEntity[dp.nameOnServer || dp.name];
1726
+ }
1727
+ else {
1728
+ let val = rawEntity[dp.nameOnServer];
1729
+ return val !== undefined ? val : dp.defaultValue;
1730
+ }
1731
+ }
1732
+ static getRawValueFromClient(rawEntity, dp) {
1733
+ let val = rawEntity[dp.name];
1734
+ return val !== undefined ? val : dp.defaultValue;
1735
+ }
1736
+ resolveProperty(propName) {
1737
+ let result = this[propName];
1738
+ let baseProp = this.baseProperty;
1739
+ while (result == undefined && baseProp != null) {
1740
+ result = baseProp[propName];
1741
+ baseProp = baseProp.baseProperty;
1742
+ }
1743
+ return result;
1744
+ }
1745
+ formatName() {
1746
+ return this.parentType.name + "--" + this.name;
1747
+ }
1748
+ /**
1749
+ General purpose property set method
1750
+ > // assume em1 is an EntityManager
1751
+ > let prop = myEntityType.getProperty("myProperty");
1752
+ > prop.setProperties( {
1753
+ > custom: { foo: 7, bar: "test" }
1754
+ > });
1755
+ @param config - A configuration object.
1756
+ **/
1757
+ setProperties(config) {
1758
+ assertConfig(config)
1759
+ .whereParam("displayName").isOptional()
1760
+ .whereParam("custom").isOptional()
1761
+ .applyAll(this);
1762
+ }
1763
+ getAllValidators() {
1764
+ let validators = this.validators.slice(0);
1765
+ let baseProp = this.baseProperty;
1766
+ while (baseProp) {
1767
+ validators.push.apply(validators, baseProp.validators);
1768
+ baseProp = baseProp.baseProperty;
1769
+ }
1770
+ return validators;
1771
+ }
1772
+ toJSON() {
1773
+ // do not serialize dataTypes that are complexTypes
1774
+ return core.toJson(this, {
1775
+ name: null,
1776
+ dataType: function (v) {
1777
+ return (v && v instanceof DataType) ? v.name : undefined;
1778
+ },
1779
+ complexTypeName: null,
1780
+ isNullable: true,
1781
+ defaultValue: null,
1782
+ isPartOfKey: false,
1783
+ isUnmapped: false,
1784
+ isSettable: true,
1785
+ concurrencyMode: null,
1786
+ maxLength: null,
1787
+ validators: null,
1788
+ displayName: null,
1789
+ enumType: null,
1790
+ rawTypeName: null,
1791
+ isScalar: true,
1792
+ custom: null
1793
+ });
1794
+ }
1795
+ static fromJSON(json) {
1796
+ json.dataType = DataType.fromName(json.dataType);
1797
+ // Parse default value into correct data type. (dateTime instances require extra work to deserialize properly.)
1798
+ if (json.defaultValue && json.dataType && json.dataType.parse) {
1799
+ json.defaultValue = json.dataType.parse(json.defaultValue, typeof json.defaultValue);
1800
+ }
1801
+ if (json.validators) {
1802
+ json.validators = json.validators.map(Validator.fromJSON);
1803
+ }
1804
+ return new DataProperty(json);
1805
+ }
1806
+ }
1807
+ DataProperty.prototype._$typeName = "DataProperty";
1808
+ /** A NavigationProperty describes the metadata for a single property of an [[EntityType]] that return instances of other EntityTypes.
1809
+
1810
+ Instances of the NavigationProperty class are constructed automatically during Metadata retrieval. However it is also possible to construct them
1811
+ directly via the constructor.
1812
+ **/
1813
+ export class NavigationProperty {
1814
+ /** NavigationProperty constructor
1815
+ > let homeAddressProp = new NavigationProperty( {
1816
+ > name: "homeAddress",
1817
+ > entityTypeName: "Address:#myNamespace",
1818
+ > isScalar: true,
1819
+ > associationName: "address_person",
1820
+ > foreignKeyNames: ["homeAddressId"]
1821
+ > });
1822
+ > let homeAddressIdProp = new DataProperty( {
1823
+ > name: "homeAddressId"
1824
+ > dataType: DataType.Integer
1825
+ > });
1826
+ > // assuming personEntityType is a newly constructed EntityType
1827
+ > personEntityType.addProperty(homeAddressProp);
1828
+ > personEntityType.addProperty(homeAddressIdProp);
1829
+ @param config - A configuration object.
1830
+ **/
1831
+ constructor(config) {
1832
+ /** Is this a DataProperty? - always false here
1833
+ Allows polymorphic treatment of DataProperties and NavigationProperties. __Read Only__ */
1834
+ this.isDataProperty = false;
1835
+ /** Is this a NavigationProperty? - always true here
1836
+ Allows polymorphic treatment of DataProperties and NavigationProperties. __Read Only__ */
1837
+ this.isNavigationProperty = true;
1838
+ this.formatName = DataProperty.prototype.formatName;
1839
+ this.getAllValidators = DataProperty.prototype.getAllValidators;
1840
+ this.resolveProperty = DataProperty.prototype.resolveProperty;
1841
+ assertConfig(config)
1842
+ .whereParam("name").isString().isOptional()
1843
+ .whereParam("nameOnServer").isString().isOptional()
1844
+ .whereParam("entityTypeName").isString()
1845
+ .whereParam("isScalar").isBoolean().isOptional().withDefault(true)
1846
+ .whereParam("associationName").isString().isOptional()
1847
+ .whereParam("foreignKeyNames").isArray().isString().isOptional().withDefault([])
1848
+ .whereParam("foreignKeyNamesOnServer").isArray().isString().isOptional().withDefault([])
1849
+ .whereParam("invForeignKeyNames").isArray().isString().isOptional().withDefault([])
1850
+ .whereParam("invForeignKeyNamesOnServer").isArray().isString().isOptional().withDefault([])
1851
+ .whereParam("validators").isInstanceOf(Validator).isArray().isOptional().withDefault([])
1852
+ .whereParam("displayName").isOptional()
1853
+ .whereParam("custom").isOptional()
1854
+ .applyAll(this);
1855
+ let hasName = !!(this.name || this.nameOnServer);
1856
+ if (!hasName) {
1857
+ throw new Error("A Navigation property must be instantiated with either a 'name' or a 'nameOnServer' property");
1858
+ }
1859
+ }
1860
+ /**
1861
+ General purpose property set method
1862
+ > // assume myEntityType is an EntityType
1863
+ > let prop = myEntityType.getProperty("myProperty");
1864
+ > prop.setProperties( {
1865
+ > custom: { foo: 7, bar: "test" }
1866
+ > });
1867
+ @param config - A config object
1868
+ **/
1869
+ // TODO: create an interface for this.
1870
+ setProperties(config) {
1871
+ if (!this.parentType) {
1872
+ throw new Error("Cannot call NavigationProperty.setProperties until the parent EntityType of the NavigationProperty has been set.");
1873
+ }
1874
+ let inverse = config.inverse;
1875
+ if (inverse)
1876
+ delete config.inverse;
1877
+ assertConfig(config)
1878
+ .whereParam("displayName").isOptional()
1879
+ .whereParam("foreignKeyNames").isArray().isString().isOptional().withDefault([])
1880
+ .whereParam("invForeignKeyNames").isArray().isString().isOptional().withDefault([])
1881
+ .whereParam("custom").isOptional()
1882
+ .applyAll(this);
1883
+ this.parentType._updateNames(this);
1884
+ this._resolveNp();
1885
+ if (inverse) {
1886
+ this.setInverse(inverse);
1887
+ }
1888
+ }
1889
+ /** The inverse of this NavigationProperty. The NavigationProperty that represents a navigation in the opposite direction
1890
+ to this NavigationProperty. May be undefined for a undirectional NavigationProperty. __Read Only__ */
1891
+ get inverse() {
1892
+ return this.getInverse();
1893
+ }
1894
+ /** @hidden @internal */
1895
+ getInverse() {
1896
+ let np = this;
1897
+ while (!np._inverse && np.baseProperty) {
1898
+ np = np.baseProperty;
1899
+ }
1900
+ return np._inverse;
1901
+ }
1902
+ setInverse(inverseNp) {
1903
+ // let invNp: NavigationProperty;
1904
+ let invNp = (inverseNp instanceof NavigationProperty) ? inverseNp : this.entityType.getNavigationProperty(inverseNp);
1905
+ if (!invNp) {
1906
+ throw throwSetInverseError(this, "Unable to find inverse property: " + inverseNp);
1907
+ }
1908
+ if (this._inverse || invNp._inverse) {
1909
+ throwSetInverseError(this, "It has already been set on one side or the other.");
1910
+ }
1911
+ if (invNp.entityType !== this.parentType) {
1912
+ throwSetInverseError(this, invNp.formatName + " is not a valid inverse property for this.");
1913
+ }
1914
+ if (this.associationName) {
1915
+ invNp.associationName = this.associationName;
1916
+ }
1917
+ else {
1918
+ if (!invNp.associationName) {
1919
+ invNp.associationName = this.formatName() + "_" + invNp.formatName();
1920
+ }
1921
+ this.associationName = invNp.associationName;
1922
+ }
1923
+ this._resolveNp();
1924
+ invNp._resolveNp();
1925
+ }
1926
+ // // In progress - will be used for manual metadata config
1927
+ // createInverse(config: any) {
1928
+ // if (!this.entityType) {
1929
+ // throwCreateInverseError(this, "has not yet been defined.");
1930
+ // }
1931
+ // if (this.entityType.isFrozen) {
1932
+ // throwCreateInverseError(this, "is frozen.");
1933
+ // }
1934
+ // let metadataStore = this.entityType.metadataStore;
1935
+ // if (metadataStore == null) {
1936
+ // throwCreateInverseError(this, "has not yet been added to the metadataStore.");
1937
+ // }
1938
+ // config.entityTypeName = this.parentEntityType.name;
1939
+ // config.associationName = this.associationName;
1940
+ // let invNp = new NavigationProperty(config);
1941
+ // this.parentEntityType.addNavigationProperty(invNp);
1942
+ // return invNp;
1943
+ // };
1944
+ toJSON() {
1945
+ return core.toJson(this, {
1946
+ name: null,
1947
+ entityTypeName: null,
1948
+ isScalar: null,
1949
+ associationName: null,
1950
+ validators: null,
1951
+ displayName: null,
1952
+ foreignKeyNames: null,
1953
+ invForeignKeyNames: null,
1954
+ custom: null
1955
+ });
1956
+ }
1957
+ static fromJSON(json) {
1958
+ if (json.validators) {
1959
+ json.validators = json.validators.map(Validator.fromJSON);
1960
+ }
1961
+ return new NavigationProperty(json);
1962
+ }
1963
+ /** @hidden @internal */
1964
+ _resolveNp() {
1965
+ let np = this;
1966
+ let entityType = np.entityType;
1967
+ let invNp = core.arrayFirst(entityType.navigationProperties, (altNp) => {
1968
+ // Can't do this because of possibility of comparing a base class np with a subclass altNp.
1969
+ // return altNp.associationName === np.associationName
1970
+ // && altNp !== np;
1971
+ // So use this instead.
1972
+ return altNp.associationName === np.associationName &&
1973
+ (altNp.name !== np.name || altNp.entityTypeName !== np.entityTypeName);
1974
+ });
1975
+ np._inverse = invNp || undefined;
1976
+ //if (invNp && invNp.inverse == null) {
1977
+ // invNp._resolveNp();
1978
+ //}
1979
+ if (!invNp) {
1980
+ // unidirectional 1-n relationship
1981
+ np.invForeignKeyNames.forEach(function (invFkName) {
1982
+ let fkProp = entityType.getDataProperty(invFkName);
1983
+ if (fkProp == null) {
1984
+ throw new Error("EntityType '" + np.entityTypeName + "' has no foreign key matching '" + invFkName + "'");
1985
+ }
1986
+ let invEntityType = np.parentType;
1987
+ invNp = core.arrayFirst(invEntityType.navigationProperties, (np2) => {
1988
+ return np2.invForeignKeyNames && np2.invForeignKeyNames.indexOf(fkProp.name) >= 0 && np2.entityType === fkProp.parentType;
1989
+ });
1990
+ fkProp.inverseNavigationProperty = invNp || undefined;
1991
+ core.arrayAddItemUnique(entityType.foreignKeyProperties, fkProp);
1992
+ });
1993
+ }
1994
+ resolveRelated(np);
1995
+ }
1996
+ }
1997
+ NavigationProperty.prototype._$typeName = "NavigationProperty";
1998
+ function throwSetInverseError(np, message) {
1999
+ throw new Error("Cannot set the inverse property for: " + np.formatName() + ". " + message);
2000
+ }
2001
+ // Not current used.
2002
+ // function throwCreateInverseError(np: NavigationProperty, message: string) {
2003
+ // throw new Error("Cannot create inverse for: " + np.formatName() + ". The entityType for this navigation property " + message);
2004
+ // }
2005
+ // sets navigation property: relatedDataProperties and dataProperty: relatedNavigationProperty
2006
+ function resolveRelated(np) {
2007
+ let fkNames = np.foreignKeyNames;
2008
+ if (fkNames.length === 0)
2009
+ return;
2010
+ let parentEntityType = np.parentType;
2011
+ let fkProps = fkNames.map(function (fkName) {
2012
+ return parentEntityType.getDataProperty(fkName);
2013
+ });
2014
+ let fkPropCollection = parentEntityType.foreignKeyProperties;
2015
+ fkProps.forEach((dp) => {
2016
+ core.arrayAddItemUnique(fkPropCollection, dp);
2017
+ dp.relatedNavigationProperty = np;
2018
+ // now update the inverse
2019
+ core.arrayAddItemUnique(np.entityType.inverseForeignKeyProperties, dp);
2020
+ if (np.relatedDataProperties) {
2021
+ core.arrayAddItemUnique(np.relatedDataProperties, dp);
2022
+ }
2023
+ else {
2024
+ np.relatedDataProperties = [dp];
2025
+ }
2026
+ });
2027
+ }
2028
+ /**
2029
+ AutoGeneratedKeyType is an 'Enum' containing all of the valid states for an automatically generated key.
2030
+ **/
2031
+ export class AutoGeneratedKeyType extends BreezeEnum {
2032
+ }
2033
+ /**
2034
+ This entity does not have an autogenerated key.
2035
+ The client must set the key before adding the entity to the EntityManager
2036
+ **/
2037
+ AutoGeneratedKeyType.None = new AutoGeneratedKeyType();
2038
+ /**
2039
+ This entity's key is an Identity column and is set by the backend database.
2040
+ Keys for new entities will be temporary until the entities are saved at which point the keys will
2041
+ be converted to their 'real' versions.
2042
+ **/
2043
+ AutoGeneratedKeyType.Identity = new AutoGeneratedKeyType();
2044
+ /**
2045
+ This entity's key is generated by a KeyGenerator and is set by the backend database.
2046
+ Keys for new entities will be temporary until the entities are saved at which point the keys will
2047
+ be converted to their 'real' versions.
2048
+ **/
2049
+ AutoGeneratedKeyType.KeyGenerator = new AutoGeneratedKeyType();
2050
+ AutoGeneratedKeyType.prototype._$typeName = "AutoGeneratedKeyType";
2051
+ Error['x'] = AutoGeneratedKeyType.resolveSymbols();
2052
+ let proto = Param.prototype;
2053
+ // 'this' below is TS annotation
2054
+ proto.isEntity = function () {
2055
+ return this._addContext({
2056
+ fn: isEntity,
2057
+ msg: " must be an entity"
2058
+ });
2059
+ };
2060
+ function isEntity(context, v) {
2061
+ if (v == null)
2062
+ return false;
2063
+ return (v.entityType !== undefined);
2064
+ }
2065
+ proto.isEntityProperty = function () {
2066
+ return this._addContext({
2067
+ fn: isEntityProperty,
2068
+ msg: " must be either a DataProperty or a NavigationProperty"
2069
+ });
2070
+ };
2071
+ function isEntityProperty(context, v) {
2072
+ if (v == null)
2073
+ return false;
2074
+ return (v.isDataProperty || v.isNavigationProperty);
2075
+ }
2076
+ // functions shared between classes related to Metadata
2077
+ function isQualifiedTypeName(entityTypeName) {
2078
+ return entityTypeName.indexOf(":#") >= 0;
2079
+ }
2080
+ export function qualifyTypeName(shortName, ns) {
2081
+ if (ns && ns.length > 0) {
2082
+ return shortName + ":#" + ns;
2083
+ }
2084
+ else {
2085
+ return shortName;
2086
+ }
2087
+ }
2088
+ // Used by both ComplexType and EntityType
2089
+ function addProperties(entityType, propObj, ctor) {
2090
+ if (propObj == null)
2091
+ return;
2092
+ if (Array.isArray(propObj)) {
2093
+ propObj.forEach(entityType._addPropertyCore.bind(entityType));
2094
+ }
2095
+ else if (typeof (propObj) === 'object') {
2096
+ for (let key in propObj) {
2097
+ if (core.hasOwnProperty(propObj, key)) {
2098
+ let value = propObj[key];
2099
+ value.name = key;
2100
+ let prop = new ctor(value);
2101
+ entityType._addPropertyCore(prop);
2102
+ }
2103
+ }
2104
+ }
2105
+ else {
2106
+ throw new Error("The 'dataProperties' or 'navigationProperties' values must be either an array of data/nav properties or an object where each property defines a data/nav property");
2107
+ }
2108
+ }
2109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LW1ldGFkYXRhLmpzIiwic291cmNlUm9vdCI6Im5nOi8vYnJlZXplLWNsaWVudC8iLCJzb3VyY2VzIjpbInNyYy9lbnRpdHktbWV0YWRhdGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBaUIsTUFBTSxRQUFRLENBQUM7QUFDN0MsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDdkMsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQTJDLE1BQU0saUJBQWlCLENBQUM7QUFDdkcsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDcEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDLENBQUMsMkJBQTJCO0FBQ3hGLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQy9FLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBNkM1RTs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBcUR4Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BcUJHO0lBQ0gsWUFBWSxNQUE0QjtRQUN0QyxNQUFNLEdBQUcsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUN0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QUNMLE1BQU0sSUFBSSxLQUFLLENBQUMsbUtBQW1LLENBQUMsQ0FBQztLQUN0TDtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjb3JlLCBFcnJvckNhbGxiYWNrIH0gZnJvbSAnLi9jb3JlJztcclxuaW1wb3J0IHsgY29uZmlnIH0gZnJvbSAnLi9jb25maWcnO1xyXG5pbXBvcnQgeyBCcmVlemVFdmVudCB9IGZyb20gJy4vZXZlbnQnO1xyXG5pbXBvcnQgeyBhc3NlcnRQYXJhbSwgYXNzZXJ0Q29uZmlnLCBQYXJhbSB9IGZyb20gJy4vYXNzZXJ0LXBhcmFtJztcclxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuL2RhdGEtdHlwZSc7XHJcbmltcG9ydCB7IEVudGl0eUFzcGVjdCwgQ29tcGxleEFzcGVjdCwgRW50aXR5LCBDb21wbGV4T2JqZWN0LCBTdHJ1Y3R1cmFsT2JqZWN0IH0gZnJvbSAnLi9lbnRpdHktYXNwZWN0JztcclxuaW1wb3J0IHsgRW50aXR5S2V5IH0gZnJvbSAnLi9lbnRpdHkta2V5JztcclxuaW1wb3J0IHsgVmFsaWRhdG9yIH0gZnJvbSAnLi92YWxpZGF0ZSc7XHJcbmltcG9ydCB7IEJyZWV6ZUVudW0gfSBmcm9tICcuL2VudW0nO1xyXG5pbXBvcnQgeyBEYXRhU2VydmljZSB9IGZyb20gJy4vZGF0YS1zZXJ2aWNlJztcclxuaW1wb3J0IHsgTmFtaW5nQ29udmVudGlvbiB9IGZyb20gJy4vbmFtaW5nLWNvbnZlbnRpb24nO1xyXG5pbXBvcnQgeyBDc2RsTWV0YWRhdGFQYXJzZXIgfSBmcm9tICcuL2NzZGwtbWV0YWRhdGEtcGFyc2VyJzsgLy8gVE9ETyBpc29sYXRlIHRoaXMgbGF0ZXI7XHJcbmltcG9ydCB7IExvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucyB9IGZyb20gJy4vbG9jYWwtcXVlcnktY29tcGFyaXNvbi1vcHRpb25zJztcclxuaW1wb3J0IHsgZGVmYXVsdFByb3BlcnR5SW50ZXJjZXB0b3IgfSBmcm9tICcuL2RlZmF1bHQtcHJvcGVydHktaW50ZXJjZXB0b3InO1xyXG5cclxuZXhwb3J0IHR5cGUgRW50aXR5UHJvcGVydHkgPSBEYXRhUHJvcGVydHkgfCBOYXZpZ2F0aW9uUHJvcGVydHk7XHJcbmV4cG9ydCB0eXBlIFN0cnVjdHVyYWxUeXBlID0gRW50aXR5VHlwZSB8IENvbXBsZXhUeXBlO1xyXG5cclxuLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSVN0cnVjdHVyYWxUeXBlTWFwIHtcclxuICBbaW5kZXg6IHN0cmluZ106IFN0cnVjdHVyYWxUeXBlO1xyXG59XHJcbi8qKiBLZWVwIHRyYWNrIG9mIGNvbnN0cnVjdG9ycyBhbmQgaW5pdGlhbGl6ZXJzIGZvciBTdHJ1Y3R1cmFsVHlwZXMgKi9cclxuaW50ZXJmYWNlIEN0b3JSZWNvcmQgeyBcclxuICBjdG9yOiB7IG5ldyAoKTogU3RydWN0dXJhbE9iamVjdCB9O1xyXG4gIGluaXRGbj86IEZ1bmN0aW9uIHwgc3RyaW5nOyBcclxuICBub1RyYWNraW5nRm4/OiBGdW5jdGlvbjtcclxufVxyXG5cclxuLy8gVE9ETzogY29uc2lkZXIgZXhwb3NpbmcgbGF0ZXJcclxuLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSU1ldGFkYXRhSnNvbiB7XHJcbiAgbWV0YWRhdGFWZXJzaW9uOiBzdHJpbmc7XHJcbiAgbmFtZTogc3RyaW5nO1xyXG4gIG5hbWluZ0NvbnZlbnRpb246IHN0cmluZztcclxuICBsb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnM6IHN0cmluZztcclxuICBkYXRhU2VydmljZXM6IE9iamVjdFtdOyAvLyBJRGF0YVNlcnZpY2VKc29uW11cclxuICBzdHJ1Y3R1cmFsVHlwZXM6IE9iamVjdFtdOyAvLyBJU3RydWN0dXJhbFR5cGVKc29uW107IFxyXG4gIHJlc291cmNlRW50aXR5VHlwZU1hcDogT2JqZWN0W107IC8vIElSZXNvdXJjZUVudGl0eVR5cGVKc29uW11cclxuICBpbmNvbXBsZXRlVHlwZU1hcDogT2JqZWN0W107XHJcbn1cclxuXHJcbi8qKiBDb25maWd1cmF0aW9uIGluZm8gdG8gYmUgcGFzc2VkIHRvIHRoZSBbW01ldGFkYXRhU3RvcmVdXSBjb25zdHJ1Y3RvciAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIE1ldGFkYXRhU3RvcmVDb25maWcge1xyXG4gIC8qKiBUaGUgIFtbTmFtaW5nQ29udmVudGlvbl1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIE1ldGFkYXRhU3RvcmUuICovXHJcbiAgbmFtaW5nQ29udmVudGlvbj86IE5hbWluZ0NvbnZlbnRpb247XHJcbiAgLyoqIFRoZSAgW1tMb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBNZXRhZGF0YVN0b3JlLiAqL1xyXG4gIGxvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucz86IExvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucztcclxuICBzZXJpYWxpemVyRm4/OiAocHJvcDogRW50aXR5UHJvcGVydHksIHZhbDogYW55KSA9PiBhbnk7XHJcbiAgbmFtZT86IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBNZXRhZGF0YUZldGNoZWRFdmVudEFyZ3Mge1xyXG4gIG1ldGFkYXRhU3RvcmU6IE1ldGFkYXRhU3RvcmU7XHJcbiAgZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlIHwgc3RyaW5nO1xyXG4gIHJhd01ldGFkYXRhOiBhbnk7XHJcbn1cclxuXHJcbi8qKlxyXG5BbiBpbnN0YW5jZSBvZiB0aGUgTWV0YWRhdGFTdG9yZSBjb250YWlucyBhbGwgb2YgdGhlIG1ldGFkYXRhIGFib3V0IGEgY29sbGVjdGlvbiBvZiBbW0VudGl0eVR5cGVdXSdzLlxyXG5NZXRhZGF0YVN0b3JlcyBtYXkgYmUgc2hhcmVkIGFjcm9zcyBbW0VudGl0eU1hbmFnZXJdXSdzLiAgSWYgYW4gRW50aXR5TWFuYWdlciBpcyBjcmVhdGVkIHdpdGhvdXQgYW5cclxuZXhwbGljaXQgTWV0YWRhdGFTdG9yZSwgdGhlIE1ldGFkYXRhU3RvcmUgZnJvbSB0aGUgTWV0YWRhdGFTdG9yZS5kZWZhdWx0SW5zdGFuY2UgcHJvcGVydHkgd2lsbCBiZSB1c2VkLlxyXG5AZHluYW1pY1xyXG4qKi9cclxuZXhwb3J0IGNsYXNzIE1ldGFkYXRhU3RvcmUge1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIGRlY2xhcmUgXyR0eXBlTmFtZTogc3RyaW5nOyAvLyBvbiBwcm90b1xyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBzdGF0aWMgX19pZCA9IDA7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgc3RhdGljIEFOT05UWVBFX1BSRUZJWCA9IFwiX0lCX1wiO1xyXG4gIC8qKiBUaGUgdmVyc2lvbiBvZiBhbnkgTWV0YWRhdGFTdG9yZXMgY3JlYXRlZCBieSB0aGlzIGNsYXNzICovXHJcbiAgc3RhdGljIG1ldGFkYXRhVmVyc2lvbiA9ICcxLjAuNSc7XHJcblxyXG4gIG5hbWU6IHN0cmluZztcclxuICBkYXRhU2VydmljZXM6IERhdGFTZXJ2aWNlW107XHJcblxyXG4gIC8qKiBUaGUgIFtbTmFtaW5nQ29udmVudGlvbl1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIE1ldGFkYXRhU3RvcmUuIF9fUmVhZCBPbmx5X18gKi9cclxuICBuYW1pbmdDb252ZW50aW9uOiBOYW1pbmdDb252ZW50aW9uO1xyXG4gIC8qKiBUaGUgIFtbTG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgTWV0YWRhdGFTdG9yZS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGxvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9uczogTG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zO1xyXG4gIHNlcmlhbGl6ZXJGbj86IChwcm9wOiBFbnRpdHlQcm9wZXJ0eSwgdmFsOiBhbnkpID0+IGFueTtcclxuICAvKipcclxuICBBbiBbW0JyZWV6ZUV2ZW50XV0gdGhhdCBmaXJlcyBhZnRlciBhIE1ldGFkYXRhU3RvcmUgaGFzIGNvbXBsZXRlZCBmZXRjaGluZyBtZXRhZGF0YSBmcm9tIGEgcmVtb3RlIHNlcnZpY2UuXHJcbiAgXHJcbiAgQGV2ZW50QXJncyAtXHJcbiAgICAtIG1ldGFkYXRhU3RvcmUgLSBUaGUgTWV0YWRhdGFTdG9yZSBpbnRvIHdoaWNoIHRoZSBtZXRhZGF0YSB3YXMgZmV0Y2hlZC5cclxuICAgIC0gZGF0YVNlcnZpY2UgLSBUaGUgW1tEYXRhU2VydmljZV1dIHRoYXQgbWV0YWRhdGEgd2FzIGZldGNoZWQgZnJvbS5cclxuICAgIC0gcmF3TWV0YWRhdGEgLSB7T2JqZWN0fSBUaGUgcmF3IG1ldGFkYXRhIHJldHVybmVkIGZyb20gdGhlIHNlcnZpY2UuIChJdCB3aWxsIGhhdmUgYWxyZWFkeSBiZWVuIHByb2Nlc3NlZCBieSB0aGlzIHBvaW50KS5cclxuICA+ICAgICAgbGV0IG1zID0gbXlFbnRpdHlNYW5hZ2VyLm1ldGFkYXRhU3RvcmU7XHJcbiAgPiAgICAgIG1zLm1ldGFkYXRhRmV0Y2hlZC5zdWJzY3JpYmUoZnVuY3Rpb24oYXJncykge1xyXG4gID4gICAgICAgICAgbGV0IG1ldGFkYXRhU3RvcmUgPSBhcmdzLm1ldGFkYXRhU3RvcmU7XHJcbiAgPiAgICAgICAgICBsZXQgZGF0YVNlcnZpY2UgPSBhcmdzLmRhdGFTZXJ2aWNlO1xyXG4gID4gICAgICB9KTtcclxuICBAZXZlbnRcclxuICAqKi9cclxuICBtZXRhZGF0YUZldGNoZWQ6IEJyZWV6ZUV2ZW50PE1ldGFkYXRhRmV0Y2hlZEV2ZW50QXJncz47XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3Jlc291cmNlRW50aXR5VHlwZU1hcDogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZW50aXR5VHlwZVJlc291cmNlTWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCBrZXkgaXMgcXVhbGlmaWVkIHN0cnVjdHVyYWx0eXBlIG5hbWUgLSB2YWx1ZSBpcyBzdHJ1Y3R1cmFsVHlwZS4gKCBzdHJ1Y3R1cmFsID0gZW50aXR5VHlwZSBvciBjb21wbGV4VHlwZSkuICovXHJcbiAgX3N0cnVjdHVyYWxUeXBlTWFwOiBJU3RydWN0dXJhbFR5cGVNYXA7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsIGtleSBpcyBzaG9ydE5hbWUsIHZhbHVlIGlzIHF1YWxpZmllZCBuYW1lIC0gZG9lcyBub3QgbmVlZCB0byBiZSBzZXJpYWxpemVkLiAqKi9cclxuICBfc2hvcnROYW1lTWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCBrZXkgaXMgZWl0aGVyIHNob3J0IG9yIHF1YWwgdHlwZSBuYW1lIC0gdmFsdWUgaXMgY3RvcjsgKiovXHJcbiAgX2N0b3JSZWdpc3RyeTogUmVjb3JkPHN0cmluZywgQ3RvclJlY29yZD47XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsIGtleSBpcyBlbnRpdHlUeXBlTmFtZTsgdmFsdWUgaXMgYXJyYXkgb2YgbmF2IHByb3BzICoqL1xyXG4gIF9pbmNvbXBsZXRlVHlwZU1hcDogUmVjb3JkPHN0cmluZywgTmF2aWdhdGlvblByb3BlcnR5W10+O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqKi9cclxuICBfaW5jb21wbGV0ZUNvbXBsZXhUeXBlTWFwOiBSZWNvcmQ8c3RyaW5nLCBEYXRhUHJvcGVydHlbXT47XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsIHsganNvbjogYW55LCBzdHlwZTogU3RydWN0dXJhbFR5cGUgfVtdIHwgeyBlbnRpdHlUeXBlOiBFbnRpdHlUeXBlLCBjc2RsRW50aXR5VHlwZTogYW55IH1bXSAqKi9cclxuICBfZGVmZXJyZWRUeXBlczogUmVjb3JkPHN0cmluZywgYW55PjtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKiovXHJcbiAgX2lkOiBudW1iZXI7XHJcblxyXG4gIC8qKlxyXG4gIENvbnN0cnVjdHMgYSBuZXcgTWV0YWRhdGFTdG9yZS5cclxuICBcclxuICA+ICAgICBsZXQgbXMgPSBuZXcgTWV0YWRhdGFTdG9yZSgpO1xyXG5cclxuICBUaGUgc3RvcmUgY2FuIHRoZW4gYmUgYXNzb2NpYXRlZCB3aXRoIGFuIEVudGl0eU1hbmFnZXJcclxuICA+ICAgICBsZXQgZW50aXR5TWFuYWdlciA9IG5ldyBFbnRpdHlNYW5hZ2VyKCB7XHJcbiAgPiAgICAgICAgIHNlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIsIFxyXG4gID4gICAgICAgICBtZXRhZGF0YVN0b3JlOiBtcyBcclxuICA+ICAgICB9KTtcclxuXHJcbiAgb3IgZm9yIGFuIGV4aXN0aW5nIEVudGl0eU1hbmFnZXJcclxuICA+ICAgIC8vIEFzc3VtZSBlbTEgaXMgYW4gZXhpc3RpbmcgRW50aXR5TWFuYWdlclxyXG4gID4gICAgZW0xLnNldFByb3BlcnRpZXMoIHsgbWV0YWRhdGFTdG9yZTogbXMgfSk7XHJcbiAgXHJcbiAgQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gc2V0dGluZ3MgLlxyXG4gICAgLSBuYW1pbmdDb252ZW50aW9uIC0gKGRlZmF1bHQ9TmFtaW5nQ29udmVudGlvbi5kZWZhdWx0SW5zdGFuY2UpIE5hbWluZ0NvbnZlbnRpb24gdG8gYmUgdXNlZCBpbiBtYXBwaW5nIHByb3BlcnR5IG5hbWVzXHJcbiAgYmV0d2VlbiBjbGllbnQgYW5kIHNlcnZlci4gVXNlcyB0aGUgTmFtaW5nQ29udmVudGlvbi5kZWZhdWx0SW5zdGFuY2UgaWYgbm90IHNwZWNpZmllZC5cclxuICAgIC0gbG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zIC0gKGRlZmF1bHQ9TG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zLmRlZmF1bHRJbnN0YW5jZSkgVGhlIExvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucyB0byBiZVxyXG4gIHVzZWQgd2hlbiBwZXJmb3JtaW5nIFwibG9jYWwgcXVlcmllc1wiIGluIG9yZGVyIHRvIG1hdGNoIHRoZSBzZW1hbnRpY3Mgb2YgcXVlcmllcyBhZ2FpbnN0IGEgcmVtb3RlIHNlcnZpY2UuXHJcbiAgICAtIHNlcmlhbGl6ZXJGbiAtIEEgZnVuY3Rpb24gdGhhdCBpcyB1c2VkIHRvIG1lZGlhdGUgdGhlIHNlcmlhbGl6YXRpb24gb2YgaW5zdGFuY2VzIG9mIHRoaXMgdHlwZS5cclxuICAqKi9cclxuICBjb25zdHJ1Y3Rvcihjb25maWc/OiBNZXRhZGF0YVN0b3JlQ29uZmlnKSB7XHJcbiAgICBjb25maWcgPSBjb25maWcgfHwge307XHJcbiAgICBhc3NlcnRDb25maWcoY29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm5hbWluZ0NvbnZlbnRpb25cIikuaXNPcHRpb25hbCgpLmlzSW5zdGFuY2VPZihOYW1pbmdDb252ZW50aW9uKS53aXRoRGVmYXVsdChOYW1pbmdDb252ZW50aW9uLmRlZmF1bHRJbnN0YW5jZSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJsb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnNcIikuaXNPcHRpb25hbCgpLmlzSW5zdGFuY2VPZihMb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnMpLndpdGhEZWZhdWx0KExvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucy5kZWZhdWx0SW5zdGFuY2UpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwic2VyaWFsaXplckZuXCIpLmlzT3B0aW9uYWwoKS5pc0Z1bmN0aW9uKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gICAgdGhpcy5kYXRhU2VydmljZXMgPSBbXTsgLy8gYXJyYXkgb2YgZGF0YVNlcnZpY2VzO1xyXG4gICAgdGhpcy5fcmVzb3VyY2VFbnRpdHlUeXBlTWFwID0ge307IC8vIGtleSBpcyByZXNvdXJjZSBuYW1lIC0gdmFsdWUgaXMgcXVhbGlmaWVkIGVudGl0eVR5cGUgbmFtZVxyXG4gICAgdGhpcy5fc3RydWN0dXJhbFR5cGVNYXAgPSB7fTsgLy8ga2V5IGlzIHF1YWxpZmllZCBzdHJ1Y3R1cmFsdHlwZSBuYW1lIC0gdmFsdWUgaXMgc3RydWN0dXJhbFR5cGUuICggc3RydWN0dXJhbCA9IGVudGl0eVR5cGUgb3IgY29tcGxleFR5cGUpLlxyXG4gICAgdGhpcy5fc2hvcnROYW1lTWFwID0ge307IC8vIGtleSBpcyBzaG9ydE5hbWUsIHZhbHVlIGlzIHF1YWxpZmllZCBuYW1lIC0gZG9lcyBub3QgbmVlZCB0byBiZSBzZXJpYWxpemVkLlxyXG4gICAgdGhpcy5fY3RvclJlZ2lzdHJ5ID0ge307IC8vIGtleSBpcyBlaXRoZXIgc2hvcnQgb3IgcXVhbCB0eXBlIG5hbWUgLSB2YWx1ZSBpcyBjdG9yO1xyXG5cclxuICAgIHRoaXMuX2luY29tcGxldGVUeXBlTWFwID0ge307IC8vIGtleSBpcyBlbnRpdHlUeXBlTmFtZTsgdmFsdWUgaXMgYXJyYXkgb2YgbmF2IHByb3BzXHJcbiAgICB0aGlzLl9pbmNvbXBsZXRlQ29tcGxleFR5cGVNYXAgPSB7fTsgLy8ga2V5IGlzIGNvbXBsZXhUeXBlTmFtZTsgdmFsdWUgaXMgYXJyYXkgb2YgY29tcGxleFR5cGUgcHJvcHNcclxuICAgIHRoaXMuX2lkID0gTWV0YWRhdGFTdG9yZS5fX2lkKys7XHJcbiAgICB0aGlzLm1ldGFkYXRhRmV0Y2hlZCA9IG5ldyBCcmVlemVFdmVudChcIm1ldGFkYXRhRmV0Y2hlZFwiLCB0aGlzKTtcclxuXHJcbiAgfVxyXG5cclxuICAvLyBuZWVkcyB0byBiZSBtYWRlIGF2YWlsIHRvIGRhdGFTZXJ2aWNlLnh4eCBmaWxlc1xyXG4gIHN0YXRpYyBub3JtYWxpemVUeXBlTmFtZSA9IGNvcmUubWVtb2l6ZShmdW5jdGlvbiAocmF3VHlwZU5hbWU6IHN0cmluZykge1xyXG4gICAgcmV0dXJuIHJhd1R5cGVOYW1lICYmIE1ldGFkYXRhU3RvcmUucGFyc2VUeXBlTmFtZShyYXdUeXBlTmFtZSkudHlwZU5hbWU7XHJcbiAgfSk7XHJcbiAgLy8gZm9yIGRlYnVnZ2luZyB1c2UgdGhlIGxpbmUgYmVsb3cgaW5zdGVhZC5cclxuICAvL2N0b3Iubm9ybWFsaXplVHlwZU5hbWUgPSBmdW5jdGlvbiAocmF3VHlwZU5hbWUpIHsgcmV0dXJuIHBhcnNlVHlwZU5hbWUocmF3VHlwZU5hbWUpLnR5cGVOYW1lOyB9O1xyXG5cclxuICAvKipcclxuICBHZW5lcmFsIHB1cnBvc2UgcHJvcGVydHkgc2V0IG1ldGhvZFxyXG4gIFxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGVtMS5tZXRhZGF0YVN0b3JlLnNldFByb3BlcnRpZXMoIHtcclxuICA+ICAgICAgICAgdmVyc2lvbjogXCI2LjEuM1wiLFxyXG4gID4gICAgICAgICBzZXJpYWxpemVyRm46IGZ1bmN0aW9uKHByb3AsIHZhbHVlKSB7XHJcbiAgPiAgICAgICAgIHJldHVybiAocHJvcC5pc1VubWFwcGVkKSA/IHVuZGVmaW5lZCA6IHZhbHVlO1xyXG4gID4gICAgICAgICB9XHJcbiAgPiAgICAgKX07XHJcbiAgQHBhcmFtIGNvbmZpZyAtICBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgc2VsZWN0ZWQgcHJvcGVydGllcyBhbmQgdmFsdWVzIHRvIHNldC5cclxuICAqKi9cclxuICBzZXRQcm9wZXJ0aWVzKGNvbmZpZzogTWV0YWRhdGFTdG9yZUNvbmZpZykge1xyXG4gICAgYXNzZXJ0Q29uZmlnKGNvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJuYW1lXCIpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwic2VyaWFsaXplckZuXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQWRkcyBhIERhdGFTZXJ2aWNlIHRvIHRoaXMgTWV0YWRhdGFTdG9yZS4gSWYgYSBEYXRhU2VydmljZSB3aXRoIHRoZSBzYW1lIHNlcnZpY2VOYW1lIGlzIGFscmVhZHlcclxuICBpbiB0aGUgTWV0YWRhdGFTdG9yZSBhbiBleGNlcHRpb24gd2lsbCBiZSB0aHJvd24uXHJcbiAgQHBhcmFtIGRhdGFTZXJ2aWNlIC0gVGhlIFtbRGF0YVNlcnZpY2VdXSB0byBhZGRcclxuICBAcGFyYW0gc2hvdWxkT3ZlcndyaXRlIC0gKGRlZmF1bHQ9ZmFsc2UpIFBlcm1pdCBvdmVyd3JpdGUgb2YgZXhpc3RpbmcgRGF0YVNlcnZpY2UgcmF0aGVyIHRoYW4gdGhyb3cgZXhjZXB0aW9uXHJcbiAgKiovXHJcbiAgYWRkRGF0YVNlcnZpY2UoZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlLCBzaG91bGRPdmVyd3JpdGU/OiBib29sZWFuKSB7XHJcbiAgICBhc3NlcnRQYXJhbShkYXRhU2VydmljZSwgXCJkYXRhU2VydmljZVwiKS5pc0luc3RhbmNlT2YoRGF0YVNlcnZpY2UpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShzaG91bGRPdmVyd3JpdGUsIFwic2hvdWxkT3ZlcndyaXRlXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgbGV0IGl4ID0gdGhpcy5fZ2V0RGF0YVNlcnZpY2VJbmRleChkYXRhU2VydmljZS5zZXJ2aWNlTmFtZSk7XHJcbiAgICBpZiAoaXggPj0gMCkge1xyXG4gICAgICBpZiAoISFzaG91bGRPdmVyd3JpdGUpIHtcclxuICAgICAgICB0aGlzLmRhdGFTZXJ2aWNlc1tpeF0gPSBkYXRhU2VydmljZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBIGRhdGFTZXJ2aWNlIHdpdGggdGhpcyBuYW1lICdcIiArIGRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lICsgXCInIGFscmVhZHkgZXhpc3RzIGluIHRoaXMgTWV0YWRhdGFTdG9yZVwiKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5kYXRhU2VydmljZXMucHVzaChkYXRhU2VydmljZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZ2V0RGF0YVNlcnZpY2VJbmRleChzZXJ2aWNlTmFtZTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gY29yZS5hcnJheUluZGV4T2YodGhpcy5kYXRhU2VydmljZXMsIGZ1bmN0aW9uIChkcykge1xyXG4gICAgICByZXR1cm4gZHMuc2VydmljZU5hbWUgPT09IHNlcnZpY2VOYW1lO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBBZGRzIGFuIEVudGl0eVR5cGUgdG8gdGhpcyBNZXRhZGF0YVN0b3JlLiAgTm8gYWRkaXRpb25hbCBwcm9wZXJ0aWVzIG1heSBiZSBhZGRlZCB0byB0aGUgRW50aXR5VHlwZSBhZnRlciBpdHMgaGFzXHJcbiAgYmVlbiBhZGRlZCB0byB0aGUgTWV0YWRhdGFTdG9yZS5cclxuICBAcGFyYW0gc3RydWN0dXJhbFR5cGUgLSBUaGUgRW50aXR5VHlwZSBvciBDb21wbGV4VHlwZSB0byBhZGRcclxuICAqKi9cclxuICBhZGRFbnRpdHlUeXBlKHN0eXBlOiBTdHJ1Y3R1cmFsVHlwZSB8IEVudGl0eVR5cGVDb25maWcgfCBDb21wbGV4VHlwZUNvbmZpZykge1xyXG4gICAgbGV0IHN0cnVjdHVyYWxUeXBlOiBTdHJ1Y3R1cmFsVHlwZTtcclxuICAgIGlmIChzdHlwZSBpbnN0YW5jZW9mIEVudGl0eVR5cGUgfHwgc3R5cGUgaW5zdGFuY2VvZiBDb21wbGV4VHlwZSkge1xyXG4gICAgICBzdHJ1Y3R1cmFsVHlwZSA9IHN0eXBlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgc3RydWN0dXJhbFR5cGUgPSAoc3R5cGUgYXMgYW55KS5pc0NvbXBsZXhUeXBlID8gbmV3IENvbXBsZXhUeXBlKHN0eXBlKSA6IG5ldyBFbnRpdHlUeXBlKHN0eXBlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBpZiAoIXN0cnVjdHVyYWxUeXBlLmlzQ29tcGxleFR5cGUpIHsgLy8gc2FtZSBhcyBiZWxvdyBidXQgaXNuJ3QgYSAndHlwZSBndWFyZCdcclxuICAgIGlmIChzdHJ1Y3R1cmFsVHlwZSBpbnN0YW5jZW9mIEVudGl0eVR5cGUpIHtcclxuICAgICAgaWYgKHN0cnVjdHVyYWxUeXBlLmJhc2VUeXBlTmFtZSAmJiAhc3RydWN0dXJhbFR5cGUuYmFzZUVudGl0eVR5cGUpIHtcclxuICAgICAgICBsZXQgYmFzZUVudGl0eVR5cGUgPSB0aGlzLl9nZXRTdHJ1Y3R1cmFsVHlwZShzdHJ1Y3R1cmFsVHlwZS5iYXNlVHlwZU5hbWUsIHRydWUpO1xyXG4gICAgICAgIC8vIHNhZmUgY2FzdCBiZWNhdXNlIHdlIGtub3cgdGhhdCBiYXNlRW50aXR5VHlwZSBtdXN0IGJlIGFuIEVudGl0eVR5cGUgaWYgdGhlIHN0cnVjdHVyYWxUeXBlIGlzIGFuIEVudGl0eVR5cGVcclxuICAgICAgICBzdHJ1Y3R1cmFsVHlwZS5fdXBkYXRlRnJvbUJhc2UoYmFzZUVudGl0eVR5cGUgYXMgRW50aXR5VHlwZSk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHN0cnVjdHVyYWxUeXBlLmtleVByb3BlcnRpZXMubGVuZ3RoID09PSAwICYmICFzdHJ1Y3R1cmFsVHlwZS5pc0Fic3RyYWN0KSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIGFkZCBcIiArIHN0cnVjdHVyYWxUeXBlLm5hbWUgK1xyXG4gICAgICAgICAgXCIgdG8gdGhpcyBNZXRhZGF0YVN0b3JlLiAgQW4gRW50aXR5VHlwZSBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIHByb3BlcnR5IGRlc2lnbmF0ZWQgYXMgYSBrZXkgcHJvcGVydHkgLSBTZWUgdGhlICdEYXRhUHJvcGVydHkuaXNQYXJ0T2ZLZXknIHByb3BlcnR5LlwiKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHN0cnVjdHVyYWxUeXBlLm1ldGFkYXRhU3RvcmUgPSB0aGlzO1xyXG4gICAgLy8gZG9uJ3QgcmVnaXN0ZXIgYW5vbiB0eXBlc1xyXG4gICAgaWYgKCEoc3RydWN0dXJhbFR5cGUgYXMgYW55KS5pc0Fub255bW91cykge1xyXG4gICAgICBpZiAodGhpcy5fc3RydWN0dXJhbFR5cGVNYXBbc3RydWN0dXJhbFR5cGUubmFtZV0pIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUeXBlIFwiICsgc3RydWN0dXJhbFR5cGUubmFtZSArIFwiIGFscmVhZHkgZXhpc3RzIGluIHRoaXMgTWV0YWRhdGFTdG9yZS5cIik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuX3N0cnVjdHVyYWxUeXBlTWFwW3N0cnVjdHVyYWxUeXBlLm5hbWVdID0gc3RydWN0dXJhbFR5cGU7XHJcbiAgICAgIHRoaXMuX3Nob3J0TmFtZU1hcFtzdHJ1Y3R1cmFsVHlwZS5zaG9ydE5hbWVdID0gc3RydWN0dXJhbFR5cGUubmFtZTtcclxuICAgIH1cclxuXHJcbiAgICBzdHJ1Y3R1cmFsVHlwZS5nZXRQcm9wZXJ0aWVzKCkuZm9yRWFjaChwID0+IHtcclxuICAgICAgc3RydWN0dXJhbFR5cGUuX3VwZGF0ZU5hbWVzKHApO1xyXG4gICAgICBpZiAoIXAuaXNVbm1hcHBlZCkge1xyXG4gICAgICAgIHN0cnVjdHVyYWxUeXBlLl9tYXBwZWRQcm9wZXJ0aWVzQ291bnQrKztcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgc3RydWN0dXJhbFR5cGUuX3VwZGF0ZUNwcygpO1xyXG5cclxuICAgIC8vICdpc0VudGl0eVR5cGUnIGlzIGEgdHlwZSBndWFyZFxyXG4gICAgaWYgKHN0cnVjdHVyYWxUeXBlIGluc3RhbmNlb2YgRW50aXR5VHlwZSkge1xyXG4gICAgICBzdHJ1Y3R1cmFsVHlwZS5fdXBkYXRlTnBzKCk7XHJcbiAgICAgIC8vIGdpdmUgdGhlIHR5cGUgaXQncyBiYXNlJ3MgcmVzb3VyY2UgbmFtZSBpZiBpdCBkb2Vzbid0IGhhdmUgaXRzIG93bi5cclxuICAgICAgbGV0IGRlZlJlc291cmNlTmFtZSA9IHN0cnVjdHVyYWxUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUgfHwgKHN0cnVjdHVyYWxUeXBlLmJhc2VFbnRpdHlUeXBlICYmIHN0cnVjdHVyYWxUeXBlLmJhc2VFbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUpO1xyXG4gICAgICBpZiAoZGVmUmVzb3VyY2VOYW1lICYmICF0aGlzLmdldEVudGl0eVR5cGVOYW1lRm9yUmVzb3VyY2VOYW1lKGRlZlJlc291cmNlTmFtZSkpIHtcclxuICAgICAgICB0aGlzLnNldEVudGl0eVR5cGVGb3JSZXNvdXJjZU5hbWUoZGVmUmVzb3VyY2VOYW1lLCBzdHJ1Y3R1cmFsVHlwZS5uYW1lKTtcclxuICAgICAgfVxyXG4gICAgICBzdHJ1Y3R1cmFsVHlwZS5kZWZhdWx0UmVzb3VyY2VOYW1lID0gZGVmUmVzb3VyY2VOYW1lO1xyXG4gICAgICAvLyBjaGVjayBpZiB0aGlzIHN0cnVjdHVyYWwgdHlwZSdzIG5hbWUsIHNob3J0IHZlcnNpb24gb3IgcXVhbGlmaWVkIHZlcnNpb24gaGFzIGEgcmVnaXN0ZXJlZCBjdG9yLlxyXG4gICAgICBzdHJ1Y3R1cmFsVHlwZS5nZXRFbnRpdHlDdG9yKCk7XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gIEV4cG9ydHMgdGhpcyBNZXRhZGF0YVN0b3JlIHRvIGEgc2VyaWFsaXplZCBzdHJpbmcgYXBwcm9wcmlhdGUgZm9yIGxvY2FsIHN0b3JhZ2UuICAgVGhpcyBvcGVyYXRpb24gaXMgYWxzbyBjYWxsZWRcclxuICBpbnRlcm5hbGx5IHdoZW4gZXhwb3J0aW5nIGFuIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBtcyBpcyBhIHByZXZpb3VzbHkgY3JlYXRlZCBNZXRhZGF0YVN0b3JlXHJcbiAgPiAgICAgIGxldCBtZXRhZGF0YUFzU3RyaW5nID0gbXMuZXhwb3J0TWV0YWRhdGEoKTtcclxuICA+ICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKFwibWV0YWRhdGFcIiwgbWV0YWRhdGFBc1N0cmluZyk7XHJcbiAgPiAgICAgIC8vIGFuZCBsYXRlciwgdXN1YWxseSBpbiBhIGRpZmZlcmVudCBzZXNzaW9uIGltcG9ydGVkXHJcbiAgPiAgICAgIGxldCBtZXRhZGF0YUZyb21TdG9yYWdlID0gd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKFwibWV0YWRhdGFcIik7XHJcbiAgPiAgICAgIGxldCBuZXdNZXRhZGF0YVN0b3JlID0gbmV3IE1ldGFkYXRhU3RvcmUoKTtcclxuICA+ICAgICAgbmV3TWV0YWRhdGFTdG9yZS5pbXBvcnRNZXRhZGF0YShtZXRhZGF0YUZyb21TdG9yYWdlKTtcclxuICBAcmV0dXJuIEEgc2VyaWFsaXplZCB2ZXJzaW9uIG9mIHRoaXMgTWV0YWRhdGFTdG9yZSB0aGF0IG1heSBiZSBzdG9yZWQgbG9jYWxseSBhbmQgbGF0ZXIgcmVzdG9yZWQuXHJcbiAgKiovXHJcbiAgZXhwb3J0TWV0YWRhdGEoKSB7XHJcbiAgICBsZXQgcmVzdWx0ID0gSlNPTi5zdHJpbmdpZnkoe1xyXG4gICAgICBcIm1ldGFkYXRhVmVyc2lvblwiOiBNZXRhZGF0YVN0b3JlLm1ldGFkYXRhVmVyc2lvbixcclxuICAgICAgXCJuYW1lXCI6IHRoaXMubmFtZSxcclxuICAgICAgXCJuYW1pbmdDb252ZW50aW9uXCI6IHRoaXMubmFtaW5nQ29udmVudGlvbi5uYW1lLFxyXG4gICAgICBcImxvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9uc1wiOiB0aGlzLmxvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucy5uYW1lLFxyXG4gICAgICBcImRhdGFTZXJ2aWNlc1wiOiB0aGlzLmRhdGFTZXJ2aWNlcyxcclxuICAgICAgXCJzdHJ1Y3R1cmFsVHlwZXNcIjogY29yZS5vYmplY3RNYXAodGhpcy5fc3RydWN0dXJhbFR5cGVNYXApLFxyXG4gICAgICBcInJlc291cmNlRW50aXR5VHlwZU1hcFwiOiB0aGlzLl9yZXNvdXJjZUVudGl0eVR5cGVNYXBcclxuICAgIH0sIG51bGwsIGNvbmZpZy5zdHJpbmdpZnlQYWQpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEltcG9ydHMgYSBwcmV2aW91c2x5IGV4cG9ydGVkIHNlcmlhbGl6ZWQgTWV0YWRhdGFTdG9yZSBpbnRvIHRoaXMgTWV0YWRhdGFTdG9yZS5cclxuICAgIFxyXG4gID4gICAgICAvLyBhc3N1bWUgbXMgaXMgYSBwcmV2aW91c2x5IGNyZWF0ZWQgTWV0YWRhdGFTdG9yZVxyXG4gID4gICAgICBsZXQgbWV0YWRhdGFBc1N0cmluZyA9IG1zLmV4cG9ydE1ldGFkYXRhKCk7XHJcbiAgPiAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm1ldGFkYXRhXCIsIG1ldGFkYXRhQXNTdHJpbmcpO1xyXG4gID4gICAgICAvLyBhbmQgbGF0ZXIsIHVzdWFsbHkgaW4gYSBkaWZmZXJlbnQgc2Vzc2lvblxyXG4gID4gICAgICBsZXQgbWV0YWRhdGFGcm9tU3RvcmFnZSA9IHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbShcIm1ldGFkYXRhXCIpO1xyXG4gID4gICAgICBsZXQgbmV3TWV0YWRhdGFTdG9yZSA9IG5ldyBNZXRhZGF0YVN0b3JlKCk7XHJcbiAgPiAgICAgIG5ld01ldGFkYXRhU3RvcmUuaW1wb3J0TWV0YWRhdGEobWV0YWRhdGFGcm9tU3RvcmFnZSk7XHJcbiAgQHBhcmFtIGV4cG9ydGVkTWV0YWRhdGEgLSBBIHByZXZpb3VzbHkgZXhwb3J0ZWQgTWV0YWRhdGFTdG9yZS5cclxuICBAcGFyYW0gYWxsb3dNZXJnZSAtICBBbGxvd3MgY3VzdG9tIG1ldGFkYXRhIHRvIGJlIG1lcmdlZCBpbnRvIGV4aXN0aW5nIG1ldGFkYXRhIHR5cGVzLlxyXG4gIEByZXR1cm4gVGhpcyBNZXRhZGF0YVN0b3JlLlxyXG4gIEBjaGFpbmFibGVcclxuICAqKi9cclxuICBpbXBvcnRNZXRhZGF0YShleHBvcnRlZE1ldGFkYXRhOiBzdHJpbmcgfCBPYmplY3QsIGFsbG93TWVyZ2U6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oYWxsb3dNZXJnZSwgXCJhbGxvd01lcmdlXCIpLmlzT3B0aW9uYWwoKS5pc0Jvb2xlYW4oKS5jaGVjaygpO1xyXG4gICAgdGhpcy5fZGVmZXJyZWRUeXBlcyA9IHt9O1xyXG4gICAgLy8gaW5zdXJlIHRoYXQgd2UgZG9uJ3QgbXV0YXRlIGluY29taW5nIGV4cG9ydGVkTWV0YWRhdGEgKCBpZiBpdHMgYW4gb2JqZWN0KVxyXG4gICAgbGV0IG1ldGFkYXRhQXNTdHJpbmcgPSAodHlwZW9mIChleHBvcnRlZE1ldGFkYXRhKSA9PT0gXCJzdHJpbmdcIikgPyBleHBvcnRlZE1ldGFkYXRhIDogSlNPTi5zdHJpbmdpZnkoZXhwb3J0ZWRNZXRhZGF0YSk7XHJcbiAgICBjb25zdCBtZXRhZGF0YUpzb24gPSBKU09OLnBhcnNlKG1ldGFkYXRhQXNTdHJpbmcpO1xyXG5cclxuICAgIGlmIChtZXRhZGF0YUpzb24uc2NoZW1hKSB7XHJcbiAgICAgIHJldHVybiBDc2RsTWV0YWRhdGFQYXJzZXIucGFyc2UodGhpcywgbWV0YWRhdGFKc29uLnNjaGVtYSwgbWV0YWRhdGFKc29uLmFsdE1ldGFkYXRhKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQganNvbiA9IG1ldGFkYXRhSnNvbiBhcyBJTWV0YWRhdGFKc29uO1xyXG4gICAgaWYgKGpzb24ubWV0YWRhdGFWZXJzaW9uICYmIGpzb24ubWV0YWRhdGFWZXJzaW9uICE9PSBNZXRhZGF0YVN0b3JlLm1ldGFkYXRhVmVyc2lvbikge1xyXG4gICAgICBsZXQgbXNnID0gY29yZS5mb3JtYXRTdHJpbmcoXCJDYW5ub3QgaW1wb3J0IG1ldGFkYXRhIHdpdGggYSBkaWZmZXJlbnQgJ21ldGFkYXRhVmVyc2lvbicgKCUxKSB0aGFuIHRoZSBjdXJyZW50ICdNZXRhZGF0YVN0b3JlLm1ldGFkYXRhVmVyc2lvbicgKCUyKSBcIixcclxuICAgICAgICBqc29uLm1ldGFkYXRhVmVyc2lvbiwgTWV0YWRhdGFTdG9yZS5tZXRhZGF0YVZlcnNpb24pO1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgbmNOYW1lID0ganNvbi5uYW1pbmdDb252ZW50aW9uO1xyXG4gICAgbGV0IGxxY29OYW1lID0ganNvbi5sb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnM7XHJcbiAgICBpZiAodGhpcy5pc0VtcHR5KCkpIHtcclxuICAgICAgdGhpcy5uYW1pbmdDb252ZW50aW9uID0gY29uZmlnLl9mZXRjaE9iamVjdChOYW1pbmdDb252ZW50aW9uLCBuY05hbWUpIHx8IHRoaXMubmFtaW5nQ29udmVudGlvbjtcclxuICAgICAgdGhpcy5sb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnMgPSBjb25maWcuX2ZldGNoT2JqZWN0KExvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucywgbHFjb05hbWUpIHx8IHRoaXMubG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKG5jTmFtZSAmJiB0aGlzLm5hbWluZ0NvbnZlbnRpb24ubmFtZSAhPT0gbmNOYW1lKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGltcG9ydCBtZXRhZGF0YSB3aXRoIGEgZGlmZmVyZW50ICduYW1pbmdDb252ZW50aW9uJyBmcm9tIHRoZSBjdXJyZW50IE1ldGFkYXRhU3RvcmVcIik7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGxxY29OYW1lICYmIHRoaXMubG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zLm5hbWUgIT09IGxxY29OYW1lKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGltcG9ydCBtZXRhZGF0YSB3aXRoIGRpZmZlcmVudCAnbG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zJyBmcm9tIHRoZSBjdXJyZW50IE1ldGFkYXRhU3RvcmVcIik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvL25vaW5zcGVjdGlvbiBKU0hpbnRcclxuICAgIGpzb24uZGF0YVNlcnZpY2VzICYmIGpzb24uZGF0YVNlcnZpY2VzLmZvckVhY2goKGRzKSA9PiB7XHJcbiAgICAgIGxldCByZWFsRHMgPSBEYXRhU2VydmljZS5mcm9tSlNPTihkcyk7XHJcbiAgICAgIHRoaXMuYWRkRGF0YVNlcnZpY2UocmVhbERzLCB0cnVlKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGpzb24uc3RydWN0dXJhbFR5cGVzICYmIGpzb24uc3RydWN0dXJhbFR5cGVzLmZvckVhY2goKHN0eXBlKSA9PiB7XHJcbiAgICAgIHN0cnVjdHVyYWxUeXBlRnJvbUpzb24odGhpcywgc3R5cGUsIGFsbG93TWVyZ2UpO1xyXG4gICAgfSk7XHJcbiAgICBjb3JlLmV4dGVuZCh0aGlzLl9yZXNvdXJjZUVudGl0eVR5cGVNYXAsIGpzb24ucmVzb3VyY2VFbnRpdHlUeXBlTWFwKTtcclxuICAgIGNvcmUuZXh0ZW5kKHRoaXMuX2luY29tcGxldGVUeXBlTWFwLCBqc29uLmluY29tcGxldGVUeXBlTWFwKTtcclxuXHJcbiAgICByZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIENyZWF0ZXMgYSBuZXcgTWV0YWRhdGFTdG9yZSBmcm9tIGEgcHJldmlvdXNseSBleHBvcnRlZCBzZXJpYWxpemVkIE1ldGFkYXRhU3RvcmVcclxuICA+ICAgICAgLy8gYXNzdW1lIG1zIGlzIGEgcHJldmlvdXNseSBjcmVhdGVkIE1ldGFkYXRhU3RvcmVcclxuICA+ICAgICAgbGV0IG1ldGFkYXRhQXNTdHJpbmcgPSBtcy5leHBvcnRNZXRhZGF0YSgpO1xyXG4gID4gICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJtZXRhZGF0YVwiLCBtZXRhZGF0YUFzU3RyaW5nKTtcclxuICA+ICAgICAgLy8gYW5kIGxhdGVyLCB1c3VhbGx5IGluIGEgZGlmZmVyZW50IHNlc3Npb25cclxuICA+ICAgICAgbGV0IG1ldGFkYXRhRnJvbVN0b3JhZ2UgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJtZXRhZGF0YVwiKTtcclxuICA+ICAgICAgbGV0IG5ld01ldGFkYXRhU3RvcmUgPSBNZXRhZGF0YVN0b3JlLmltcG9ydE1ldGFkYXRhKG1ldGFkYXRhRnJvbVN0b3JhZ2UpO1xyXG4gIEBwYXJhbSBleHBvcnRlZFN0cmluZyAtIEEgcHJldmlvdXNseSBleHBvcnRlZCBNZXRhZGF0YVN0b3JlLlxyXG4gIEByZXR1cm4gQSBuZXcgTWV0YWRhdGFTdG9yZS5cclxuICAqKi9cclxuICBzdGF0aWMgaW1wb3J0TWV0YWRhdGEoZXhwb3J0ZWRTdHJpbmc6IHN0cmluZykge1xyXG4gICAgbGV0IG1zID0gbmV3IE1ldGFkYXRhU3RvcmUoKTtcclxuICAgIG1zLmltcG9ydE1ldGFkYXRhKGV4cG9ydGVkU3RyaW5nKTtcclxuICAgIHJldHVybiBtcztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgd2hldGhlciBNZXRhZGF0YSBoYXMgYmVlbiByZXRyaWV2ZWQgZm9yIGEgc3BlY2lmaWVkIHNlcnZpY2UgbmFtZS5cclxuICA+ICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhbiBleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBpZiAoIWVtMS5tZXRhZGF0YVN0b3JlLmhhc01ldGFkYXRhRm9yKFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIikpKSB7XHJcbiAgPiAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgaW50ZXJlc3RpbmdcclxuICA+ICAgICAgfVxyXG4gIEBwYXJhbSBzZXJ2aWNlTmFtZSAtIFRoZSBzZXJ2aWNlIG5hbWUuXHJcbiAgQHJldHVybiBXaGV0aGVyIG1ldGFkYXRhIGhhcyBhbHJlYWR5IGJlZW4gcmV0cmlldmVkIGZvciB0aGUgc3BlY2lmaWVkIHNlcnZpY2UgbmFtZS5cclxuICAqKi9cclxuICBoYXNNZXRhZGF0YUZvcihzZXJ2aWNlTmFtZTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gISF0aGlzLmdldERhdGFTZXJ2aWNlKHNlcnZpY2VOYW1lKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgdGhlIERhdGFTZXJ2aWNlIGZvciBhIHNwZWNpZmllZCBzZXJ2aWNlIG5hbWVcclxuICA+ICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhbiBleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBsZXQgZHMgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXREYXRhU2VydmljZShcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIpO1xyXG4gID4gICAgICBsZXQgYWRhcHRlck5hbWUgPSBkcy5hZGFwdGVyTmFtZTsgLy8gbWF5IGJlIG51bGxcclxuICBAcGFyYW0gc2VydmljZU5hbWUgLSBUaGUgc2VydmljZSBuYW1lLlxyXG4gIEByZXR1cm4gVGhlIERhdGFTZXJ2aWNlIHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLlxyXG4gICoqL1xyXG4gIGdldERhdGFTZXJ2aWNlKHNlcnZpY2VOYW1lOiBzdHJpbmcpIHtcclxuICAgIGFzc2VydFBhcmFtKHNlcnZpY2VOYW1lLCBcInNlcnZpY2VOYW1lXCIpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuXHJcbiAgICBzZXJ2aWNlTmFtZSA9IERhdGFTZXJ2aWNlLl9ub3JtYWxpemVTZXJ2aWNlTmFtZShzZXJ2aWNlTmFtZSk7XHJcbiAgICByZXR1cm4gY29yZS5hcnJheUZpcnN0KHRoaXMuZGF0YVNlcnZpY2VzLCBmdW5jdGlvbiAoZHM6IERhdGFTZXJ2aWNlKSB7XHJcbiAgICAgIHJldHVybiBkcy5zZXJ2aWNlTmFtZSA9PT0gc2VydmljZU5hbWU7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEZldGNoZXMgdGhlIG1ldGFkYXRhIGZvciBhIHNwZWNpZmllZCAnc2VydmljZScuIFRoaXMgbWV0aG9kIGlzIGF1dG9tYXRpY2FsbHkgY2FsbGVkXHJcbiAgaW50ZXJuYWxseSBieSBhbiBFbnRpdHlNYW5hZ2VyIGJlZm9yZSBpdHMgZmlyc3QgcXVlcnkgYWdhaW5zdCBhIG5ldyBzZXJ2aWNlLiBfX0FzeW5jX19cclxuXHJcbiAgVXN1YWxseSB5b3Ugd2lsbCBub3QgYWN0dWFsbHkgcHJvY2VzcyB0aGUgcmVzdWx0cyBvZiBhIGZldGNoTWV0YWRhdGEgY2FsbCBkaXJlY3RseSwgYnV0IHdpbGwgaW5zdGVhZFxyXG4gIGFzayBmb3IgdGhlIG1ldGFkYXRhIGZyb20gdGhlIEVudGl0eU1hbmFnZXIgYWZ0ZXIgdGhlIGZldGNoTWV0YWRhdGEgY2FsbCByZXR1cm5zLlxyXG4gID4gICAgICBsZXQgbXMgPSBuZXcgTWV0YWRhdGFTdG9yZSgpO1xyXG4gID4gICAgICAvLyBvciBtb3JlIGNvbW1vbmx5XHJcbiAgPiAgICAgIC8vIGxldCBtcyA9IGFuRW50aXR5TWFuYWdlci5tZXRhZGF0YVN0b3JlO1xyXG4gID4gICAgICBtcy5mZXRjaE1ldGFkYXRhKFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIikudGhlbihmdW5jdGlvbihyYXdNZXRhZGF0YSkge1xyXG4gID4gICAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgd2l0aCB0aGUgbWV0YWRhdGFcclxuICA+ICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oZXhjZXB0aW9uKSB7XHJcbiAgPiAgICAgICAgICAvLyBoYW5kbGUgZXhjZXB0aW9uIGhlcmVcclxuICA+ICAgICAgfSk7XHJcbiAgQHBhcmFtIGRhdGFTZXJ2aWNlIC0gIEVpdGhlciBhIERhdGFTZXJ2aWNlIG9yIGp1c3QgdGhlIG5hbWUgb2YgdGhlIERhdGFTZXJ2aWNlIHRvIGZldGNoIG1ldGFkYXRhIGZvci5cclxuICBAcGFyYW0gY2FsbGJhY2sgLSBGdW5jdGlvbiBjYWxsZWQgb24gc3VjY2Vzcy5cclxuICBAcGFyYW0gZXJyb3JDYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBmYWlsdXJlLlxyXG4gIEByZXR1cm4gUHJvbWlzZVxyXG4gICoqL1xyXG4gIGZldGNoTWV0YWRhdGEoZGF0YVNlcnZpY2U6IHN0cmluZyB8IERhdGFTZXJ2aWNlLCBjYWxsYmFjaz86IChzY2hlbWE6IGFueSkgPT4gdm9pZCwgZXJyb3JDYWxsYmFjaz86IEVycm9yQ2FsbGJhY2spIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGFzc2VydFBhcmFtKGRhdGFTZXJ2aWNlLCBcImRhdGFTZXJ2aWNlXCIpLmlzU3RyaW5nKCkub3IoKS5pc0luc3RhbmNlT2YoRGF0YVNlcnZpY2UpLmNoZWNrKCk7XHJcbiAgICAgIGFzc2VydFBhcmFtKGNhbGxiYWNrLCBcImNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgICAgYXNzZXJ0UGFyYW0oZXJyb3JDYWxsYmFjaywgXCJlcnJvckNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuXHJcbiAgICAgIGlmICh0eXBlb2YgZGF0YVNlcnZpY2UgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAvLyB1c2UgdGhlIGRhdGFTZXJ2aWNlIHdpdGggYSBtYXRjaGluZyBuYW1lIG9yIGNyZWF0ZSBhIG5ldyBvbmUuXHJcbiAgICAgICAgZGF0YVNlcnZpY2UgPSB0aGlzLmdldERhdGFTZXJ2aWNlKGRhdGFTZXJ2aWNlKSB8fCBuZXcgRGF0YVNlcnZpY2UoeyBzZXJ2aWNlTmFtZTogZGF0YVNlcnZpY2UgfSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGRhdGFTZXJ2aWNlID0gRGF0YVNlcnZpY2UucmVzb2x2ZShbZGF0YVNlcnZpY2VdKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLmhhc01ldGFkYXRhRm9yKGRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lKSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1ldGFkYXRhIGZvciBhIHNwZWNpZmljIHNlcnZpY2VOYW1lIG1heSBvbmx5IGJlIGZldGNoZWQgb25jZSBwZXIgTWV0YWRhdGFTdG9yZS4gU2VydmljZU5hbWU6IFwiICsgZGF0YVNlcnZpY2Uuc2VydmljZU5hbWUpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gZGF0YVNlcnZpY2UuYWRhcHRlckluc3RhbmNlIS5mZXRjaE1ldGFkYXRhKHRoaXMsIGRhdGFTZXJ2aWNlKS50aGVuKChyYXdNZXRhZGF0YTogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5tZXRhZGF0YUZldGNoZWQucHVibGlzaCh7IG1ldGFkYXRhU3RvcmU6IHRoaXMsIGRhdGFTZXJ2aWNlOiBkYXRhU2VydmljZSwgcmF3TWV0YWRhdGE6IHJhd01ldGFkYXRhIH0pO1xyXG4gICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2socmF3TWV0YWRhdGEpO1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmF3TWV0YWRhdGEpO1xyXG4gICAgICB9LCBmdW5jdGlvbiAoZXJyb3I6IGFueSkge1xyXG4gICAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGVycm9yKTtcclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xyXG4gICAgICB9KTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG4gIC8vIFRPRE86IHN0cm9uZ2x5IHR5cGUgaW50ZXJjZXB0b3IgYmVsb3cuXHJcbiAgLyoqXHJcbiAgVXNlZCB0byByZWdpc3RlciBhIGNvbnN0cnVjdG9yIGZvciBhbiBFbnRpdHlUeXBlIHRoYXQgaXMgbm90IGtub3duIHZpYSBzdGFuZGFyZCBNZXRhZGF0YSBkaXNjb3Zlcnk7XHJcbiAgaS5lLiBhbiB1bm1hcHBlZCB0eXBlLlxyXG4gIEBwYXJhbSBlbnRpdHlDdG9yIC0gVGhlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIGZvciB0aGUgJ3VubWFwcGVkJyB0eXBlLlxyXG4gIEBwYXJhbSBpbnRlcmNlcHRvciAtIEFuIGludGVyY2VwdG9yIGZ1bmN0aW9uXHJcbiAgKiovXHJcbiAgdHJhY2tVbm1hcHBlZFR5cGUoZW50aXR5Q3RvcjogYW55LCBpbnRlcmNlcHRvcjogYW55KSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHlDdG9yLCBcImVudGl0eUN0b3JcIikuaXNGdW5jdGlvbigpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShpbnRlcmNlcHRvciwgXCJpbnRlcmNlcHRvclwiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICAvLyBUT0RPOiB0aGluayBhYm91dCBhZGRpbmcgdGhpcyB0byB0aGUgTWV0YWRhdGFTdG9yZS5cclxuICAgIGxldCBlbnRpdHlUeXBlID0gbmV3IEVudGl0eVR5cGUodGhpcyk7XHJcbiAgICBlbnRpdHlUeXBlLl9zZXRDdG9yKGVudGl0eUN0b3IsIGludGVyY2VwdG9yKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFByb3ZpZGVzIGEgbWVjaGFuaXNtIHRvIHJlZ2lzdGVyIGEgJ2N1c3RvbScgY29uc3RydWN0b3IgdG8gYmUgdXNlZCB3aGVuIGNyZWF0aW5nIG5ldyBpbnN0YW5jZXNcclxuICBvZiB0aGUgc3BlY2lmaWVkIGVudGl0eSB0eXBlLiAgSWYgdGhpcyBjYWxsIGlzIG5vdCBtYWRlLCBhIGRlZmF1bHQgY29uc3RydWN0b3IgaXMgY3JlYXRlZCBmb3JcclxuICB0aGUgZW50aXR5IGFzIG5lZWRlZC5cclxuICBUaGlzIGNhbGwgbWF5IGJlIG1hZGUgYmVmb3JlIG9yIGFmdGVyIHRoZSBjb3JyZXNwb25kaW5nIEVudGl0eVR5cGUgaGFzIGJlZW4gZGlzY292ZXJlZCB2aWFcclxuICBNZXRhZGF0YSBkaXNjb3ZlcnkuXHJcbiAgPiAgICAgIGxldCBDdXN0b21lciA9IGZ1bmN0aW9uICgpIHtcclxuICA+ICAgICAgICAgICAgICB0aGlzLm1pc2NEYXRhID0gXCJhc2RmXCI7XHJcbiAgPiAgICAgICAgICB9O1xyXG4gID4gICAgICBDdXN0b21lci5wcm90b3R5cGUuZG9Gb28oKSB7XHJcbiAgPiAgICAgICAgICAgICAgLi4uXHJcbiAgPiAgICAgICAgICB9XHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyO1xyXG4gID4gICAgICBlbTEubWV0YWRhdGFTdG9yZS5yZWdpc3RlckVudGl0eVR5cGVDdG9yKFwiQ3VzdG9tZXJcIiwgQ3VzdG9tZXIpO1xyXG4gID4gICAgICAvLyBhbnkgcXVlcmllcyBvciBFbnRpdHlUeXBlLmNyZWF0ZSBjYWxscyBmcm9tIHRoaXMgcG9pbnQgb24gd2lsbCBjYWxsIHRoZSBDdXN0b21lciBjb25zdHJ1Y3RvclxyXG4gID4gICAgICAvLyByZWdpc3RlcmVkIGFib3ZlLlxyXG4gIEBwYXJhbSBzdHJ1Y3R1cmFsVHlwZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgRW50aXR5VHlwZSBvciBDb21wbGV4VHlwZS5cclxuICBAcGFyYW0gYUN0b3IgLSBUaGUgY29uc3RydWN0b3IgZm9yIHRoaXMgRW50aXR5VHlwZSBvciBDb21wbGV4VHlwZTsgbWF5IGJlIG51bGwgaWYgYWxsIHlvdSB3YW50IHRvIGRvIGlzIHNldCB0aGUgbmV4dCBwYXJhbWV0ZXIuXHJcbiAgQHBhcmFtIGluaXRGbiAtIEEgZnVuY3Rpb24gb3IgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiBvbiB0aGUgZW50aXR5IHRoYXQgaXMgdG8gYmUgZXhlY3V0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIGVudGl0eSBoYXMgYmVlbiBjcmVhdGVkXHJcbiAgYW5kIHBvcHVsYXRlZCB3aXRoIGFueSBpbml0aWFsIHZhbHVlcy4gQ2FsbGVkIHdpdGggJ2luaXRGbihlbnRpdHkpJ1xyXG4gIEBwYXJhbSBub1RyYWNraW5nRm4gLSBBIGZ1bmN0aW9uIHRoYXQgaXMgZXhlY3V0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgYSBub1RyYWNraW5nIGVudGl0eSBoYXMgYmVlbiBjcmVhdGVkIGFuZCB3aG9zZSByZXR1cm5cclxuICB2YWx1ZSB3aWxsIGJlIHVzZWQgaW4gcGxhY2Ugb2YgdGhlIG5vVHJhY2tpbmcgZW50aXR5LlxyXG4gICoqL1xyXG4gIHJlZ2lzdGVyRW50aXR5VHlwZUN0b3Ioc3RydWN0dXJhbFR5cGVOYW1lOiBzdHJpbmcsIGFDdG9yPzogYW55LCBpbml0Rm4/OiBGdW5jdGlvbiB8IHN0cmluZywgbm9UcmFja2luZ0ZuPzogRnVuY3Rpb24pIHtcclxuICAgIGFzc2VydFBhcmFtKHN0cnVjdHVyYWxUeXBlTmFtZSwgXCJzdHJ1Y3R1cmFsVHlwZU5hbWVcIikuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oYUN0b3IsIFwiYUN0b3JcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oaW5pdEZuLCBcImluaXRGblwiKS5pc09wdGlvbmFsKCkuaXNGdW5jdGlvbigpLm9yKCkuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0obm9UcmFja2luZ0ZuLCBcIm5vVHJhY2tpbmdGblwiKS5pc09wdGlvbmFsKCkuaXNGdW5jdGlvbigpLmNoZWNrKCk7XHJcblxyXG4gICAgbGV0IHF1YWxpZmllZFR5cGVOYW1lID0gZ2V0UXVhbGlmaWVkVHlwZU5hbWUodGhpcywgc3RydWN0dXJhbFR5cGVOYW1lLCBmYWxzZSk7XHJcbiAgICBsZXQgdHlwZU5hbWUgPSBxdWFsaWZpZWRUeXBlTmFtZSB8fCBzdHJ1Y3R1cmFsVHlwZU5hbWU7XHJcblxyXG4gICAgaWYgKGFDdG9yKSB7XHJcbiAgICAgIGlmIChhQ3Rvci5fJHR5cGVOYW1lICYmIGFDdG9yLl8kdHlwZU5hbWUgIT09IHR5cGVOYW1lKSB7XHJcbiAgICAgICAgLy8gVE9ETzogd3JhcCB0aGlzIC0gY29uc29sZSBhbmQgZXNwZWNpYWxseSBjb25zb2xlLndhcm4gZG9lcyBub3QgZXhpc3QgaW4gYWxsIGJyb3dzZXJzLlxyXG4gICAgICAgIGNvbnNvbGUud2FybihcIlJlZ2lzdGVyaW5nIGEgY29uc3RydWN0b3IgZm9yIFwiICsgdHlwZU5hbWUgKyBcIiB0aGF0IGlzIGFscmVhZHkgdXNlZCBmb3IgXCIgKyBhQ3Rvci5fJHR5cGVOYW1lICsgXCIuXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIGFDdG9yLl8kdHlwZU5hbWUgPSB0eXBlTmFtZTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl9jdG9yUmVnaXN0cnlbdHlwZU5hbWVdID0geyBjdG9yOiBhQ3RvciwgaW5pdEZuOiBpbml0Rm4sIG5vVHJhY2tpbmdGbjogbm9UcmFja2luZ0ZuIH07XHJcbiAgICBpZiAocXVhbGlmaWVkVHlwZU5hbWUpIHtcclxuICAgICAgbGV0IHN0eXBlID0gdGhpcy5fc3RydWN0dXJhbFR5cGVNYXBbcXVhbGlmaWVkVHlwZU5hbWVdO1xyXG4gICAgICBzdHlwZSAmJiBzdHlwZS5nZXRDdG9yKHRydWUpOyAvLyB0aGlzIHdpbGwgY29tcGxldGUgdGhlIHJlZ2lzdHJhdGlvbiBpZiBhdmFpbCBub3cuXHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyB3aGV0aGVyIHRoaXMgTWV0YWRhdGFTdG9yZSBjb250YWlucyBhbnkgbWV0YWRhdGEgeWV0LlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGEgcHJlZXhpc3RpbmcgRW50aXR5TWFuYWdlcjtcclxuICA+ICAgICAgaWYgKGVtMS5tZXRhZGF0YVN0b3JlLmlzRW1wdHkoKSkge1xyXG4gID4gICAgICAgICAgLy8gZG8gc29tZXRoaW5nIGludGVyZXN0aW5nXHJcbiAgPiAgICAgIH1cclxuICAqKi9cclxuICBpc0VtcHR5KCkge1xyXG4gICAgcmV0dXJuIGNvcmUuaXNFbXB0eSh0aGlzLl9zdHJ1Y3R1cmFsVHlwZU1hcCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGFuIFtbRW50aXR5VHlwZV1dIG9yIG51bGwgZ2l2ZW4gaXRzIG5hbWUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBvZFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRBc0VudGl0eVR5cGUoXCJPcmRlckRldGFpbFwiKTtcclxuXHJcbiAgb3IgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHR5cGUgaXMgbm90IGZvdW5kXHJcbiAgPiAgICAgIGxldCBiYWRUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0QXNFbnRpdHlUeXBlKFwiRm9vXCIsIGZhbHNlKTtcclxuICA+ICAgICAgLy8gYmFkVHlwZSB3aWxsIG5vdCBnZXQgc2V0IGFuZCBhbiBleGNlcHRpb24gd2lsbCBiZSB0aHJvd24uXHJcbiAgQHBhcmFtIHN0cnVjdHVyYWxUeXBlTmFtZSAtIEVpdGhlciB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb3IgYSBzaG9ydCBuYW1lIG1heSBiZSB1c2VkLiBJZiBhIHNob3J0IG5hbWUgaXMgc3BlY2lmaWVkIGFuZCBtdWx0aXBsZSB0eXBlcyBzaGFyZVxyXG4gIHRoYXQgc2FtZSBzaG9ydCBuYW1lIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi5cclxuICBAcGFyYW0gb2tJZk5vdEZvdW5kIC0gKGRlZmF1bHQ9ZmFsc2UpIFdoZXRoZXIgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHNwZWNpZmllZCBFbnRpdHlUeXBlIGlzIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIFRoZSBFbnRpdHlUeXBlLiBDb21wbGV4VHlwZSBvciAnbnVsbCcgaWYgbm90IG5vdCBmb3VuZC5cclxuICAqKi9cclxuICBnZXRBc0VudGl0eVR5cGUodHlwZU5hbWU6IHN0cmluZywgb2tJZk5vdEZvdW5kOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IHN0ID0gdGhpcy5nZXRTdHJ1Y3R1cmFsVHlwZSh0eXBlTmFtZSwgb2tJZk5vdEZvdW5kKTtcclxuICAgIGlmIChzdCBpbnN0YW5jZW9mIEVudGl0eVR5cGUpIHtcclxuICAgICAgcmV0dXJuIHN0IGFzIEVudGl0eVR5cGU7XHJcbiAgICB9IGVsc2UgaWYgKG9rSWZOb3RGb3VuZCkge1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGxldCBtc2cgPSBjb3JlLmZvcm1hdFN0cmluZyhcIlVuYWJsZSB0byBsb2NhdGUgYW4gJ0VudGl0eVR5cGUnIGJ5IHRoZSBuYW1lOiAnJTEnLiBCZSBzdXJlIHRvIGV4ZWN1dGUgYSBxdWVyeSBvciBjYWxsIGZldGNoTWV0YWRhdGEgZmlyc3QuXCIsIHR5cGVOYW1lKTtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGFuIFtbRW50aXR5VHlwZV1dIG9yIG51bGwgZ2l2ZW4gaXRzIG5hbWUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBsb2NUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0QXNDb21wbGV4VHlwZShcIkxvY2F0aW9uXCIpO1xyXG5cclxuICBvciB0byB0aHJvdyBhbiBlcnJvciBpZiB0aGUgdHlwZSBpcyBub3QgZm91bmRcclxuICA+ICAgICAgbGV0IGJhZFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRBc0NvbXBsZXhUeXBlKFwiRm9vXCIsIGZhbHNlKTtcclxuICA+ICAgICAgLy8gYmFkVHlwZSB3aWxsIG5vdCBnZXQgc2V0IGFuZCBhbiBleGNlcHRpb24gd2lsbCBiZSB0aHJvd24uXHJcbiAgQHBhcmFtIHN0cnVjdHVyYWxUeXBlTmFtZSAtIEVpdGhlciB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb3IgYSBzaG9ydCBuYW1lIG1heSBiZSB1c2VkLiBJZiBhIHNob3J0IG5hbWUgaXMgc3BlY2lmaWVkIGFuZCBtdWx0aXBsZSB0eXBlcyBzaGFyZVxyXG4gIHRoYXQgc2FtZSBzaG9ydCBuYW1lIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi5cclxuICBAcGFyYW0gb2tJZk5vdEZvdW5kIC0gKGRlZmF1bHQ9ZmFsc2UpIFdoZXRoZXIgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHNwZWNpZmllZCBFbnRpdHlUeXBlIGlzIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIFRoZSBFbnRpdHlUeXBlLiBDb21wbGV4VHlwZSBvciAnbnVsbCcgaWYgbm90IG5vdCBmb3VuZC5cclxuICAqKi9cclxuIGdldEFzQ29tcGxleFR5cGUodHlwZU5hbWU6IHN0cmluZywgb2tJZk5vdEZvdW5kOiBib29sZWFuID0gZmFsc2UpIHtcclxuICBjb25zdCBzdCA9IHRoaXMuZ2V0U3RydWN0dXJhbFR5cGUodHlwZU5hbWUsIG9rSWZOb3RGb3VuZCk7XHJcbiAgaWYgKHN0IGluc3RhbmNlb2YgQ29tcGxleFR5cGUpIHtcclxuICAgIHJldHVybiBzdCBhcyBDb21wbGV4VHlwZTtcclxuICB9IGVsc2UgaWYgKG9rSWZOb3RGb3VuZCkge1xyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfSBlbHNlIHtcclxuICAgIGxldCBtc2cgPSBjb3JlLmZvcm1hdFN0cmluZyhcIlVuYWJsZSB0byBsb2NhdGUgYW4gJ0NvbXBsZXhUeXBlJyBieSB0aGUgbmFtZTogJyUxJy4gQmUgc3VyZSB0byBleGVjdXRlIGEgcXVlcnkgb3IgY2FsbCBmZXRjaE1ldGFkYXRhIGZpcnN0LlwiLCB0eXBlTmFtZSk7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcclxuICB9XHJcbn1cclxuXHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYW4gW1tFbnRpdHlUeXBlXV0gb3IgYSBbW0NvbXBsZXhUeXBlXV0gZ2l2ZW4gaXRzIG5hbWUuXHJcbiAgQGRlcHJlY2F0ZWQgUmVwbGFjZWQgYnkgZ2V0U3RydWN0dXJhbFR5cGUgYnV0IC4uLiBpdCBpcyBwcm9iYWJseSBtb3JlIHVzZWZ1bGwgdG8gY2FsbCBlaXRoZXIgZ2V0QXNFbnRpdHlUeXBlIG9yIGdldEFzQ29tcGxleFR5cGUgaW5zdGVhZFxyXG4gIEBwYXJhbSB0eXBlTmFtZSAtIEVpdGhlciB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb3IgYSBzaG9ydCBuYW1lIG1heSBiZSB1c2VkLiBJZiBhIHNob3J0IG5hbWUgaXMgc3BlY2lmaWVkIGFuZCBtdWx0aXBsZSB0eXBlcyBzaGFyZVxyXG4gIHRoYXQgc2FtZSBzaG9ydCBuYW1lIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi5cclxuICBAcGFyYW0gb2tJZk5vdEZvdW5kIC0gKGRlZmF1bHQ9ZmFsc2UpIFdoZXRoZXIgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHNwZWNpZmllZCBFbnRpdHlUeXBlIGlzIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIFRoZSBFbnRpdHlUeXBlLiBDb21wbGV4VHlwZSBvciAnbnVsbCcgaWYgbm90IG5vdCBmb3VuZC5cclxuICAqKi9cclxuICBnZXRFbnRpdHlUeXBlKHR5cGVOYW1lOiBzdHJpbmcsIG9rSWZOb3RGb3VuZDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICByZXR1cm4gdGhpcy5nZXRTdHJ1Y3R1cmFsVHlwZSh0eXBlTmFtZSwgb2tJZk5vdEZvdW5kKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYW4gW1tFbnRpdHlUeXBlXV0gb3IgYSBbW0NvbXBsZXhUeXBlXV0gZ2l2ZW4gaXRzIG5hbWUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBvZFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRTdHJ1Y3R1cmFsVHlwZShcIk9yZGVyRGV0YWlsXCIpO1xyXG5cclxuICBvciB0byB0aHJvdyBhbiBlcnJvciBpZiB0aGUgdHlwZSBpcyBub3QgZm91bmRcclxuICA+ICAgICAgbGV0IGJhZFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRTdHJ1Y3R1cmFsVHlwZShcIkZvb1wiLCBmYWxzZSk7XHJcbiAgPiAgICAgIC8vIGJhZFR5cGUgd2lsbCBub3QgZ2V0IHNldCBhbmQgYW4gZXhjZXB0aW9uIHdpbGwgYmUgdGhyb3duLlxyXG4gIEBkZXByZWNhdGVkIFByZWZlcmFibHkgdXNlIGVpdGhlciBnZXRBc0VudGl0eVR5cGUgb3IgZ2V0QXNDb21wbGV4VHlwZS4gIEdldFxyXG4gIEBwYXJhbSB0eXBlTmFtZSAtIEVpdGhlciB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb3IgYSBzaG9ydCBuYW1lIG1heSBiZSB1c2VkLiBJZiBhIHNob3J0IG5hbWUgaXMgc3BlY2lmaWVkIGFuZCBtdWx0aXBsZSB0eXBlcyBzaGFyZVxyXG4gIHRoYXQgc2FtZSBzaG9ydCBuYW1lIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi5cclxuICBAcGFyYW0gb2tJZk5vdEZvdW5kIC0gKGRlZmF1bHQ9ZmFsc2UpIFdoZXRoZXIgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHNwZWNpZmllZCBFbnRpdHlUeXBlIGlzIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIFRoZSBFbnRpdHlUeXBlLiBDb21wbGV4VHlwZSBvciAnbnVsbCcgaWYgbm90IG5vdCBmb3VuZC5cclxuICAqKi9cclxuICBnZXRTdHJ1Y3R1cmFsVHlwZSh0eXBlTmFtZTogc3RyaW5nLCBva0lmTm90Rm91bmQ6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgYXNzZXJ0UGFyYW0odHlwZU5hbWUsIFwidHlwZU5hbWVcIikuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0ob2tJZk5vdEZvdW5kLCBcIm9rSWZOb3RGb3VuZFwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkuY2hlY2soZmFsc2UpO1xyXG4gICAgcmV0dXJuIHRoaXMuX2dldFN0cnVjdHVyYWxUeXBlKHR5cGVOYW1lLCBva0lmTm90Rm91bmQpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2dldFN0cnVjdHVyYWxUeXBlKHR5cGVOYW1lOiBzdHJpbmcsIG9rSWZOb3RGb3VuZDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICBsZXQgcXVhbFR5cGVOYW1lID0gZ2V0UXVhbGlmaWVkVHlwZU5hbWUodGhpcywgdHlwZU5hbWUsIGZhbHNlKTtcclxuICAgIGxldCB0eXBlID0gdGhpcy5fc3RydWN0dXJhbFR5cGVNYXBbcXVhbFR5cGVOYW1lXTtcclxuICAgIGlmICghdHlwZSkge1xyXG4gICAgICBpZiAob2tJZk5vdEZvdW5kKSByZXR1cm4gbnVsbDtcclxuICAgICAgbGV0IG1zZyA9IGNvcmUuZm9ybWF0U3RyaW5nKFwiVW5hYmxlIHRvIGxvY2F0ZSBhICdUeXBlJyBieSB0aGUgbmFtZTogJyUxJy4gQmUgc3VyZSB0byBleGVjdXRlIGEgcXVlcnkgb3IgY2FsbCBmZXRjaE1ldGFkYXRhIGZpcnN0LlwiLCB0eXBlTmFtZSk7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHR5cGU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIG9mIHRoZSBbW0VudGl0eVR5cGVdXXMgb3IgW1tDb21wbGV4VHlwZV1dcyBpbiB0aGlzIE1ldGFkYXRhU3RvcmUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBhbGxUeXBlcyA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGVzKCk7XHJcbiAgKiovXHJcbiAgZ2V0RW50aXR5VHlwZXMoKSB7XHJcbiAgICByZXR1cm4gZ2V0VHlwZXNGcm9tTWFwKHRoaXMuX3N0cnVjdHVyYWxUeXBlTWFwKTtcclxuICB9XHJcblxyXG4gIGdldEluY29tcGxldGVOYXZpZ2F0aW9uUHJvcGVydGllcygpIHtcclxuICAgIHJldHVybiBjb3JlLm9iamVjdE1hcCh0aGlzLl9pbmNvbXBsZXRlVHlwZU1hcCwgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcclxuICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgZnVsbHkgcXVhbGlmaWVkIGVudGl0eVR5cGVOYW1lIGZvciBhIHNwZWNpZmllZCByZXNvdXJjZSBuYW1lLiAgVGhlIHJldmVyc2Ugb2YgdGhpcyBvcGVyYXRpb25cclxuICBjYW4gYmUgb2J0YWluZWQgdmlhIHRoZSAgW1tFbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWVdXSBwcm9wZXJ0eVxyXG4gICoqL1xyXG4gIGdldEVudGl0eVR5cGVOYW1lRm9yUmVzb3VyY2VOYW1lKHJlc291cmNlTmFtZTogc3RyaW5nKSB7XHJcbiAgICBhc3NlcnRQYXJhbShyZXNvdXJjZU5hbWUsIFwicmVzb3VyY2VOYW1lXCIpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICAgIHJldHVybiB0aGlzLl9yZXNvdXJjZUVudGl0eVR5cGVNYXBbcmVzb3VyY2VOYW1lXTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEFzc29jaWF0ZXMgYSByZXNvdXJjZU5hbWUgd2l0aCBhbiBlbnRpdHlUeXBlLlxyXG5cclxuICBUaGlzIG1ldGhvZCBpcyBvbmx5IG5lZWRlZCBpbiB0aG9zZSBjYXNlcyB3aGVyZSBtdWx0aXBsZSByZXNvdXJjZXMgcmV0dXJuIHRoZSBzYW1lXHJcbiAgZW50aXR5VHlwZS4gIEluIHRoaXMgY2FzZSBNZXRhZGF0YSBkaXNjb3Zlcnkgd2lsbCBvbmx5IGRldGVybWluZSBhIHNpbmdsZSByZXNvdXJjZSBuYW1lIGZvclxyXG4gIGVhY2ggZW50aXR5VHlwZS5cclxuICBAcGFyYW0gcmVzb3VyY2VOYW1lIC0gVGhlIHJlc291cmNlIG5hbWVcclxuICBAcGFyYW0gZW50aXR5VHlwZU9yTmFtZSAtIElmIHBhc3NpbmcgYSBzdHJpbmcgZWl0aGVyIHRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZSBvciBhIHNob3J0IG5hbWUgbWF5IGJlIHVzZWQuIElmIGEgc2hvcnQgbmFtZSBpcyBzcGVjaWZpZWQgYW5kIG11bHRpcGxlIHR5cGVzIHNoYXJlXHJcbiAgdGhhdCBzYW1lIHNob3J0IG5hbWUgYW4gZXhjZXB0aW9uIHdpbGwgYmUgdGhyb3duLiBJZiB0aGUgZW50aXR5VHlwZSBoYXMgbm90IHlldCBiZWVuIGRpc2NvdmVyZWQgdGhlbiBhIGZ1bGx5IHF1YWxpZmllZCBuYW1lIG11c3QgYmUgdXNlZC5cclxuICAqKi9cclxuICBzZXRFbnRpdHlUeXBlRm9yUmVzb3VyY2VOYW1lKHJlc291cmNlTmFtZTogc3RyaW5nLCBlbnRpdHlUeXBlT3JOYW1lOiBFbnRpdHlUeXBlIHwgc3RyaW5nKSB7XHJcbiAgICBhc3NlcnRQYXJhbShyZXNvdXJjZU5hbWUsIFwicmVzb3VyY2VOYW1lXCIpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eVR5cGVPck5hbWUsIFwiZW50aXR5VHlwZU9yTmFtZVwiKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkub3IoKS5pc1N0cmluZygpLmNoZWNrKCk7XHJcblxyXG4gICAgbGV0IGVudGl0eVR5cGVOYW1lOiBzdHJpbmc7XHJcbiAgICBpZiAoZW50aXR5VHlwZU9yTmFtZSBpbnN0YW5jZW9mIEVudGl0eVR5cGUpIHtcclxuICAgICAgZW50aXR5VHlwZU5hbWUgPSBlbnRpdHlUeXBlT3JOYW1lLm5hbWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBlbnRpdHlUeXBlTmFtZSA9IGdldFF1YWxpZmllZFR5cGVOYW1lKHRoaXMsIGVudGl0eVR5cGVPck5hbWUsIHRydWUpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX3Jlc291cmNlRW50aXR5VHlwZU1hcFtyZXNvdXJjZU5hbWVdID0gZW50aXR5VHlwZU5hbWU7XHJcbiAgICBsZXQgZW50aXR5VHlwZSA9IHRoaXMuX2dldFN0cnVjdHVyYWxUeXBlKGVudGl0eVR5cGVOYW1lLCB0cnVlKTtcclxuICAgIGlmIChlbnRpdHlUeXBlICYmIGVudGl0eVR5cGUgaW5zdGFuY2VvZiBFbnRpdHlUeXBlICYmICFlbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUpIHtcclxuICAgICAgZW50aXR5VHlwZS5kZWZhdWx0UmVzb3VyY2VOYW1lID0gcmVzb3VyY2VOYW1lO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIF9fRGV2IE9ubHlfXyAtIGZvciB1c2Ugd2hlbiBjcmVhdGluZyBhIG5ldyBNZXRhZGF0YVBhcnNlckFkYXB0ZXIgICovXHJcbiAgc3RhdGljIHBhcnNlVHlwZU5hbWUoZW50aXR5VHlwZU5hbWU6IHN0cmluZykge1xyXG4gICAgLy8gVE9ETzogcmVtb3ZlZCBcclxuICAgIC8vIGlmICghZW50aXR5VHlwZU5hbWUpIHtcclxuICAgIC8vICAgcmV0dXJuIG51bGw7XHJcbiAgICAvLyB9XHJcblxyXG4gICAgbGV0IHR5cGVQYXJ0cyA9IGVudGl0eVR5cGVOYW1lLnNwbGl0KFwiOiNcIik7XHJcbiAgICBpZiAodHlwZVBhcnRzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgcmV0dXJuIE1ldGFkYXRhU3RvcmUubWFrZVR5cGVIYXNoKHR5cGVQYXJ0c1swXSwgdHlwZVBhcnRzWzFdKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoY29yZS5zdHJpbmdTdGFydHNXaXRoKGVudGl0eVR5cGVOYW1lLCBNZXRhZGF0YVN0b3JlLkFOT05UWVBFX1BSRUZJWCkpIHtcclxuICAgICAgbGV0IHR5cGVIYXNoID0gTWV0YWRhdGFTdG9yZS5tYWtlVHlwZUhhc2goZW50aXR5VHlwZU5hbWUpO1xyXG4gICAgICAodHlwZUhhc2ggYXMgYW55KS5pc0Fub255bW91cyA9IHRydWU7XHJcbiAgICAgIHJldHVybiB0eXBlSGFzaDtcclxuICAgIH1cclxuICAgIGxldCBlbnRpdHlUeXBlTmFtZU5vQXNzZW1ibHkgPSBlbnRpdHlUeXBlTmFtZS5zcGxpdChcIixcIilbMF07XHJcbiAgICB0eXBlUGFydHMgPSBlbnRpdHlUeXBlTmFtZU5vQXNzZW1ibHkuc3BsaXQoXCIuXCIpO1xyXG4gICAgaWYgKHR5cGVQYXJ0cy5sZW5ndGggPiAxKSB7XHJcbiAgICAgIGxldCBzaG9ydE5hbWUgPSB0eXBlUGFydHNbdHlwZVBhcnRzLmxlbmd0aCAtIDFdO1xyXG4gICAgICBsZXQgbmFtZXNwYWNlUGFydHMgPSB0eXBlUGFydHMuc2xpY2UoMCwgdHlwZVBhcnRzLmxlbmd0aCAtIDEpO1xyXG4gICAgICBsZXQgbnMgPSBuYW1lc3BhY2VQYXJ0cy5qb2luKFwiLlwiKTtcclxuICAgICAgcmV0dXJuIE1ldGFkYXRhU3RvcmUubWFrZVR5cGVIYXNoKHNob3J0TmFtZSwgbnMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIE1ldGFkYXRhU3RvcmUubWFrZVR5cGVIYXNoKGVudGl0eVR5cGVOYW1lKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBfX0RldiBPbmx5X18gLSBmb3IgdXNlIHdoZW4gY3JlYXRpbmcgYSBuZXcgTWV0YWRhdGFQYXJzZXJBZGFwdGVyICAqL1xyXG4gIHN0YXRpYyBtYWtlVHlwZUhhc2goc2hvcnROYW1lOiBzdHJpbmcsIG5zPzogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBzaG9ydFR5cGVOYW1lOiBzaG9ydE5hbWUsXHJcbiAgICAgIG5hbWVzcGFjZTogbnMsXHJcbiAgICAgIHR5cGVOYW1lOiBxdWFsaWZ5VHlwZU5hbWUoc2hvcnROYW1lLCBucylcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvLyBwcm90ZWN0ZWQgbWV0aG9kc1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9jaGVja0VudGl0eVR5cGUoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIGlmIChlbnRpdHkuZW50aXR5VHlwZSkgcmV0dXJuO1xyXG4gICAgbGV0IHR5cGVOYW1lID0gZW50aXR5LnByb3RvdHlwZS5fJHR5cGVOYW1lO1xyXG4gICAgaWYgKCF0eXBlTmFtZSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGVudGl0eSBoYXMgbm90IGJlZW4gcmVnaXN0ZXJlZC4gU2VlIHRoZSBNZXRhZGF0YVN0b3JlLnJlZ2lzdGVyRW50aXR5VHlwZUN0b3IgbWV0aG9kXCIpO1xyXG4gICAgfVxyXG4gICAgLy8gd2Uga25vdyB0aGF0IGl0IGlzIGFuIEVudGl0eVR5cGUgKCBhcyBvcHBvc2VkIHRvIGEgQ29tcGxleFR5cGUpXHJcbiAgICBsZXQgZW50aXR5VHlwZSA9IHRoaXMuX2dldFN0cnVjdHVyYWxUeXBlKHR5cGVOYW1lKSBhcyBFbnRpdHlUeXBlO1xyXG4gICAgaWYgKGVudGl0eVR5cGUpIHtcclxuICAgICAgZW50aXR5LmVudGl0eVR5cGUgPSBlbnRpdHlUeXBlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG59XHJcbk1ldGFkYXRhU3RvcmUucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIk1ldGFkYXRhU3RvcmVcIjtcclxuXHJcbkJyZWV6ZUV2ZW50LmJ1YmJsZUV2ZW50KE1ldGFkYXRhU3RvcmUucHJvdG90eXBlKTtcclxuXHJcbmZ1bmN0aW9uIGdldFR5cGVzRnJvbU1hcCh0eXBlTWFwOiBJU3RydWN0dXJhbFR5cGVNYXApIHtcclxuICBsZXQgdHlwZXM6IChTdHJ1Y3R1cmFsVHlwZSlbXSA9IFtdO1xyXG4gIGZvciAobGV0IGtleSBpbiB0eXBlTWFwKSB7XHJcbiAgICBsZXQgdmFsdWUgPSB0eXBlTWFwW2tleV07XHJcbiAgICAvLyBza2lwICdzaG9ydE5hbWUnIGVudHJpZXNcclxuICAgIGlmIChrZXkgPT09IHZhbHVlLm5hbWUpIHtcclxuICAgICAgdHlwZXMucHVzaCh0eXBlTWFwW2tleV0pO1xyXG4gICAgfVxyXG4gIH1cclxuICByZXR1cm4gdHlwZXM7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHN0cnVjdHVyYWxUeXBlRnJvbUpzb24obWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSwganNvbjogYW55LCBhbGxvd01lcmdlOiBib29sZWFuKSB7XHJcbiAgbGV0IHR5cGVOYW1lID0gcXVhbGlmeVR5cGVOYW1lKGpzb24uc2hvcnROYW1lLCBqc29uLm5hbWVzcGFjZSk7XHJcbiAgbGV0IHN0eXBlID0gbWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUodHlwZU5hbWUsIHRydWUpO1xyXG4gIGlmIChzdHlwZSkge1xyXG4gICAgaWYgKGFsbG93TWVyZ2UpIHtcclxuICAgICAgcmV0dXJuIG1lcmdlU3RydWN0dXJhbFR5cGUoc3R5cGUsIGpzb24pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gYWxsb3cgaXQgYnV0IGRvbid0IHJlcGxhY2UgYW55dGhpbmcuXHJcbiAgICAgIHJldHVybiBzdHlwZTtcclxuICAgIH1cclxuICB9XHJcbiAgbGV0IGNvbmZpZyA9IHtcclxuICAgIHNob3J0TmFtZToganNvbi5zaG9ydE5hbWUsXHJcbiAgICBuYW1lc3BhY2U6IGpzb24ubmFtZXNwYWNlLFxyXG4gICAgaXNBYnN0cmFjdDoganNvbi5pc0Fic3RyYWN0LFxyXG4gICAgYXV0b0dlbmVyYXRlZEtleVR5cGU6IEF1dG9HZW5lcmF0ZWRLZXlUeXBlLmZyb21OYW1lKGpzb24uYXV0b0dlbmVyYXRlZEtleVR5cGUpLFxyXG4gICAgZGVmYXVsdFJlc291cmNlTmFtZToganNvbi5kZWZhdWx0UmVzb3VyY2VOYW1lLFxyXG4gICAgY3VzdG9tOiBqc29uLmN1c3RvbVxyXG4gIH07XHJcblxyXG4gIHN0eXBlID0ganNvbi5pc0NvbXBsZXhUeXBlID8gbmV3IENvbXBsZXhUeXBlKGNvbmZpZykgOiBuZXcgRW50aXR5VHlwZShjb25maWcpO1xyXG5cclxuICAvLyBiYXNlVHlwZSBtYXkgbm90IGhhdmUgYmVlbiBpbXBvcnRlZCB5ZXQgc28gd2UgbmVlZCB0byBkZWZlciBoYW5kbGluZyB0aGlzIHR5cGUgdW50aWwgbGF0ZXIuXHJcbiAgaWYgKGpzb24uYmFzZVR5cGVOYW1lICYmIHN0eXBlIGluc3RhbmNlb2YgRW50aXR5VHlwZSkge1xyXG4gICAgc3R5cGUuYmFzZVR5cGVOYW1lID0ganNvbi5iYXNlVHlwZU5hbWU7XHJcbiAgICBsZXQgYmFzZUVudGl0eVR5cGUgPSBtZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShqc29uLmJhc2VUeXBlTmFtZSwgdHJ1ZSk7XHJcbiAgICBpZiAoYmFzZUVudGl0eVR5cGUpIHtcclxuICAgICAgY29tcGxldGVTdHJ1Y3R1cmFsVHlwZUZyb21Kc29uKG1ldGFkYXRhU3RvcmUsIGpzb24sIHN0eXBlKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvcmUuZ2V0QXJyYXkobWV0YWRhdGFTdG9yZS5fZGVmZXJyZWRUeXBlcywganNvbi5iYXNlVHlwZU5hbWUpLnB1c2goeyBqc29uOiBqc29uLCBzdHlwZTogc3R5cGUgfSk7XHJcblxyXG4gICAgfVxyXG4gIH0gZWxzZSB7XHJcbiAgICBjb21wbGV0ZVN0cnVjdHVyYWxUeXBlRnJvbUpzb24obWV0YWRhdGFTdG9yZSwganNvbiwgc3R5cGUpO1xyXG4gIH1cclxuXHJcbiAgLy8gc3R5cGUgbWF5IG9yIG1heSBub3QgaGF2ZSBiZWVuIGFkZGVkIHRvIHRoZSBtZXRhZGF0YVN0b3JlIGF0IHRoaXMgcG9pbnQuXHJcbiAgcmV0dXJuIHN0eXBlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBtZXJnZVN0cnVjdHVyYWxUeXBlKHN0eXBlOiBTdHJ1Y3R1cmFsVHlwZSwganNvbjogYW55KSB7XHJcbiAgaWYgKGpzb24uY3VzdG9tKSB7XHJcbiAgICBzdHlwZS5jdXN0b20gPSBqc29uLmN1c3RvbTtcclxuICB9XHJcblxyXG4gIG1lcmdlUHJvcHMoc3R5cGUsIGpzb24uZGF0YVByb3BlcnRpZXMpO1xyXG4gIG1lcmdlUHJvcHMoc3R5cGUsIGpzb24ubmF2aWdhdGlvblByb3BlcnRpZXMpO1xyXG4gIHJldHVybiBzdHlwZTtcclxufVxyXG5cclxuZnVuY3Rpb24gbWVyZ2VQcm9wcyhzdHlwZTogU3RydWN0dXJhbFR5cGUsIGpzb25Qcm9wczogYW55W10pIHtcclxuICBpZiAoIWpzb25Qcm9wcykgcmV0dXJuO1xyXG4gIGpzb25Qcm9wcy5mb3JFYWNoKChqc29uUHJvcCkgPT4ge1xyXG4gICAgbGV0IHByb3BOYW1lID0ganNvblByb3AubmFtZTtcclxuICAgIGlmICghcHJvcE5hbWUpIHtcclxuICAgICAgaWYgKGpzb25Qcm9wLm5hbWVPblNlcnZlcikge1xyXG4gICAgICAgIHByb3BOYW1lID0gc3R5cGUubWV0YWRhdGFTdG9yZS5uYW1pbmdDb252ZW50aW9uLnNlcnZlclByb3BlcnR5TmFtZVRvQ2xpZW50KGpzb25Qcm9wLm5hbWVPblNlcnZlciwge30pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIGJhY2tzbGFzaC1xdW90ZSB3b3JrcyBhcm91bmQgY29tcGlsZXIgYnVnXHJcbiAgICAgICAgY29uc3QgbXNnID0gXCJVbmFibGUgdG8gY29tcGxldGUgXFwnaW1wb3J0TWV0YWRhdGFcXCcgLSBjYW5ub3QgbG9jYXRlIGEgXFwnbmFtZVxcJyBvciBcXCduYW1lT25TZXJ2ZXJcXCcgZm9yIG9uZSBvZiB0aGUgaW1wb3J0ZWQgcHJvcGVydHkgbm9kZXNcIjtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKGpzb25Qcm9wLmN1c3RvbSkge1xyXG4gICAgICBsZXQgcHJvcCA9IHN0eXBlLmdldFByb3BlcnR5KHByb3BOYW1lLCB0cnVlKTtcclxuICAgICAgcHJvcCEuY3VzdG9tID0ganNvblByb3AuY3VzdG9tO1xyXG4gICAgfVxyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBjb21wbGV0ZVN0cnVjdHVyYWxUeXBlRnJvbUpzb24obWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSwganNvbjogYW55LCBzdHlwZTogYW55KSB7XHJcblxyXG4gIC8vIHZhbGlkYXRvcnMgZnJvbSBiYXNlVHlwZSB3b3JrIGJlY2F1c2UgdmFsaWRhdGlvbiB3YWxrcyB0aHJ1IGJhc2UgdHlwZXNcclxuICAvLyBzbyBubyBuZWVkIHRvIGNvcHkgZG93bi5cclxuICBpZiAoanNvbi52YWxpZGF0b3JzKSB7XHJcbiAgICBzdHlwZS52YWxpZGF0b3JzID0ganNvbi52YWxpZGF0b3JzLm1hcChWYWxpZGF0b3IuZnJvbUpTT04pO1xyXG4gIH1cclxuXHJcbiAganNvbi5kYXRhUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChkcDogT2JqZWN0KSB7XHJcbiAgICBzdHlwZS5fYWRkUHJvcGVydHlDb3JlKERhdGFQcm9wZXJ0eS5mcm9tSlNPTihkcCkpO1xyXG4gIH0pO1xyXG5cclxuXHJcbiAgbGV0IGlzRW50aXR5VHlwZSA9ICFqc29uLmlzQ29tcGxleFR5cGU7XHJcbiAgaWYgKGlzRW50aXR5VHlwZSkge1xyXG4gICAgLy9ub2luc3BlY3Rpb24gSlNIaW50XHJcbiAgICBqc29uLm5hdmlnYXRpb25Qcm9wZXJ0aWVzICYmIGpzb24ubmF2aWdhdGlvblByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAobnA6IE9iamVjdCkge1xyXG4gICAgICBzdHlwZS5fYWRkUHJvcGVydHlDb3JlKE5hdmlnYXRpb25Qcm9wZXJ0eS5mcm9tSlNPTihucCkpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBtZXRhZGF0YVN0b3JlLmFkZEVudGl0eVR5cGUoc3R5cGUpO1xyXG5cclxuICBsZXQgZGVmZXJyZWRUeXBlcyA9IG1ldGFkYXRhU3RvcmUuX2RlZmVycmVkVHlwZXM7XHJcbiAgbGV0IGRlZmVycmFscyA9IGRlZmVycmVkVHlwZXNbc3R5cGUubmFtZV07XHJcbiAgaWYgKGRlZmVycmFscykge1xyXG4gICAgZGVmZXJyYWxzLmZvckVhY2goZnVuY3Rpb24gKGQ6IGFueSkge1xyXG4gICAgICBjb21wbGV0ZVN0cnVjdHVyYWxUeXBlRnJvbUpzb24obWV0YWRhdGFTdG9yZSwgZC5qc29uLCBkLnN0eXBlKTtcclxuICAgIH0pO1xyXG4gICAgZGVsZXRlIGRlZmVycmVkVHlwZXNbc3R5cGUubmFtZV07XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRRdWFsaWZpZWRUeXBlTmFtZShtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlLCBzdHJ1Y3RUeXBlTmFtZTogc3RyaW5nLCB0aHJvd0lmTm90Rm91bmQ/OiBib29sZWFuKSB7XHJcbiAgaWYgKGlzUXVhbGlmaWVkVHlwZU5hbWUoc3RydWN0VHlwZU5hbWUpKSByZXR1cm4gc3RydWN0VHlwZU5hbWU7XHJcbiAgbGV0IHJlc3VsdCA9IG1ldGFkYXRhU3RvcmUuX3Nob3J0TmFtZU1hcFtzdHJ1Y3RUeXBlTmFtZV07XHJcbiAgaWYgKCFyZXN1bHQgJiYgdGhyb3dJZk5vdEZvdW5kKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gbG9jYXRlICdlbnRpdHlUeXBlTmFtZScgb2Y6IFwiICsgc3RydWN0VHlwZU5hbWUpO1xyXG4gIH1cclxuICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG4vKiogQ29uZmlndXJhdGlvbiBpbmZvIHRvIGJlIHBhc3NlZCB0byB0aGUgW1tFbnRpdHlUeXBlXV0gY29uc3RydWN0b3IgKi9cclxuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlUeXBlQ29uZmlnIHtcclxuICBzaG9ydE5hbWU/OiBzdHJpbmc7XHJcbiAgbmFtZXNwYWNlPzogc3RyaW5nO1xyXG4gIGJhc2VUeXBlTmFtZT86IHN0cmluZztcclxuICBpc0Fic3RyYWN0PzogYm9vbGVhbjtcclxuICBhdXRvR2VuZXJhdGVkS2V5VHlwZT86IEF1dG9HZW5lcmF0ZWRLZXlUeXBlO1xyXG4gIGRlZmF1bHRSZXNvdXJjZU5hbWU/OiBzdHJpbmc7XHJcbiAgZGF0YVByb3BlcnRpZXM/OiBEYXRhUHJvcGVydHlbXSB8IE9iamVjdFtdIHwgT2JqZWN0OyAgLy8gVE9ETzogc2VlIGlmIHdlIGNhbid0IHF1YWxpZnkgT2JqZWN0W10gYSBsaXR0bGUgYmV0dGVyLlxyXG4gIG5hdmlnYXRpb25Qcm9wZXJ0aWVzPzogTmF2aWdhdGlvblByb3BlcnR5W10gfCBPYmplY3RbXSB8IE9iamVjdDtcclxuICBzZXJpYWxpemVyRm4/OiAocHJvcDogRW50aXR5UHJvcGVydHksIHZhbDogYW55KSA9PiBhbnk7XHJcbiAgY3VzdG9tPzogYW55O1xyXG59XHJcblxyXG4vKiogQ29uZmlndXJhdGlvbiBpbmZvIHRvIGJlIHBhc3NlZCB0byB0aGUgW1tFbnRpdHlUeXBlLnNldFByb3BlcnRpZXNdXSBtZXRob2QgKi9cclxuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlUeXBlU2V0Q29uZmlnIHtcclxuICBhdXRvR2VuZXJhdGVkS2V5VHlwZT86IEF1dG9HZW5lcmF0ZWRLZXlUeXBlO1xyXG4gIGRlZmF1bHRSZXNvdXJjZU5hbWU/OiBzdHJpbmc7XHJcbiAgc2VyaWFsaXplckZuPzogKHByb3A6IEVudGl0eVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55O1xyXG4gIGN1c3RvbT86IGFueTtcclxufVxyXG5cclxuLyoqIENvbnRhaW5lciBmb3IgYWxsIG9mIHRoZSBtZXRhZGF0YSBhYm91dCBhIHNwZWNpZmljIHR5cGUgb2YgRW50aXR5LlxyXG4qKi9cclxuZXhwb3J0IGNsYXNzIEVudGl0eVR5cGUge1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIGRlY2xhcmUgXyR0eXBlTmFtZTogc3RyaW5nOyAvLyBvbiBwcm90b1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIHN0YXRpYyBfX25leHRBbm9uSXggPSAwO1xyXG4gIC8qKiBBbHdheXMgZmFsc2UgZm9yIGFuIEVudGl0eVR5cGUuICoqL1xyXG4gIGlzQ29tcGxleFR5cGUgPSBmYWxzZTtcclxuICAvKiogVGhlIFtbTWV0YWRhdGFTdG9yZV1dIHRoYXQgY29udGFpbnMgdGhpcyBFbnRpdHlUeXBlLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIG1ldGFkYXRhU3RvcmU6IE1ldGFkYXRhU3RvcmU7XHJcbiAgLyoqIFRoZSBEYXRhUHJvcGVydGllcyAoc2VlIFtbRGF0YVByb3BlcnR5XV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5VHlwZS4gX19SZWFkIE9ubHlfXyAgKiovXHJcbiAgZGF0YVByb3BlcnRpZXM6IERhdGFQcm9wZXJ0eVtdO1xyXG4gIC8qKiAgVGhlIE5hdmlnYXRpb25Qcm9wZXJ0aWVzIChzZWUgW1tOYXZpZ2F0aW9uUHJvcGVydHldXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlUeXBlLiBfX1JlYWQgT25seV9fICAqKi9cclxuICBuYXZpZ2F0aW9uUHJvcGVydGllczogTmF2aWdhdGlvblByb3BlcnR5W107XHJcbiAgLyoqXHJcbiAgVGhlIERhdGFQcm9wZXJ0aWVzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eVR5cGUgdGhhdCBtYWtlIHVwIGl0J3MgW1tFbnRpdHlLZXldXS4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBrZXlQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogVGhlIERhdGFQcm9wZXJ0aWVzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eVR5cGUgdGhhdCBhcmUgZm9yZWlnbiBrZXkgcHJvcGVydGllcy4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBmb3JlaWduS2V5UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgaW52ZXJzZUZvcmVpZ25LZXlQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogIFRoZSBEYXRhUHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlUeXBlIHRoYXQgYXJlIGNvbmN1cnJlbmN5IHByb3BlcnRpZXMuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgY29uY3VycmVuY3lQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogVGhlIERhdGFQcm9wZXJ0aWVzIGZvciB0aGlzIEVudGl0eVR5cGUgdGhhdCBjb250YWluIGluc3RhbmNlcyBvZiBhIFtbQ29tcGxleFR5cGVdXS4gX19SZWFkIE9ubHlfXyAgICoqL1xyXG4gIGNvbXBsZXhQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogVGhlIERhdGFQcm9wZXJ0aWVzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eVR5cGUgdGhhdCBhcmUgbm90IG1hcHBlZCB0byBhbnkgYmFja2VuZCBkYXRhc3RvcmUuIFRoZXNlIGFyZSBlZmZlY3RpdmVseSBmcmVlIHN0YW5kaW5nXHJcbiAgcHJvcGVydGllcy4gX19SZWFkIE9ubHlfXyAqKi9cclxuICB1bm1hcHBlZFByb3BlcnRpZXM6IERhdGFQcm9wZXJ0eVtdO1xyXG5cclxuICAvKiogVGhlIGZ1bGx5IHF1YWxpZmllZCBuYW1lIG9mIHRoaXMgRW50aXR5VHlwZS4gX19SZWFkIE9ubHlfXyAgKiovXHJcbiAgbmFtZTogc3RyaW5nO1xyXG4gIC8qKiBUaGUgc2hvcnQsIHVucXVhbGlmaWVkLCBuYW1lIGZvciB0aGlzIEVudGl0eVR5cGUuIF9fUmVhZCBPbmx5X18gICoqL1xyXG4gIHNob3J0TmFtZTogc3RyaW5nO1xyXG4gIC8qKiBUaGUgbmFtZXNwYWNlIGZvciB0aGlzIEVudGl0eVR5cGUuIF9fUmVhZCBPbmx5X18gICoqL1xyXG4gIG5hbWVzcGFjZTogc3RyaW5nO1xyXG4gIC8qKiBUaGUgbmFtZSBvZiB0aGlzIEVudGl0eVR5cGUncyBiYXNlIEVudGl0eVR5cGUgIChpZiBhbnkpICovXHJcbiAgYmFzZVR5cGVOYW1lPzogc3RyaW5nO1xyXG4gIC8qKiBUaGUgYmFzZSBFbnRpdHlUeXBlIChpZiBhbnkpIGZvciB0aGlzIEVudGl0eVR5cGUuIF9fUmVhZCBPbmx5X18gICAqKi9cclxuICBiYXNlRW50aXR5VHlwZTogRW50aXR5VHlwZTtcclxuICBzdWJ0eXBlczogRW50aXR5VHlwZVtdO1xyXG5cclxuICAvKiogIFdoZXRoZXIgdGhpcyBFbnRpdHlUeXBlIGlzIGFic3RyYWN0LiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGlzQWJzdHJhY3Q6IGJvb2xlYW47XHJcbiAgLyoqICBXaGV0aGVyIHRoaXMgRW50aXR5VHlwZSBpcyBhbm9ueW1vdXMuIEFub255bW91cyB0eXBlcyB3aWxsIG5ldmVyIGJlIGNvbW11bmljYXRlZCB0byBvciBmcm9tIHRoZSBzZXJ2ZXIuIFRoZXkgYXJlIHB1cmVseSBmb3JcclxuICBjbGllbnQgc2lkZSB1c2UgYW5kIGFyZSBnaXZlbiBhbiBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBuYW1lLiAgX19SZWFkIE9ubHlfXyAqKi9cclxuICBpc0Fub255bW91czogYm9vbGVhbjtcclxuICAvKiogV2hldGhlciB0aGlzIEVudGl0eVR5cGUgaGFzIGJlZW4gJ2Zyb3plbicuICBFbnRpdHlUeXBlcyBiZWNvbWUgZnJvemVuIGFmdGVyIHRoZSBmaXJzdCBpbnN0YW5jZSBcclxuICBvZiB0aGF0IHR5cGUgaGFzIGJlZW4gY3JlYXRlZCBhbmQgYXR0YWNoZWQgdG8gYW4gRW50aXR5TWFuYWdlci4gKi9cclxuICBpc0Zyb3plbjogYm9vbGVhbjtcclxuXHJcbiAgLyoqIFRoZSBbW0F1dG9HZW5lcmF0ZWRLZXlUeXBlXV0gZm9yIHRoaXMgRW50aXR5VHlwZS4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBhdXRvR2VuZXJhdGVkS2V5VHlwZTogQXV0b0dlbmVyYXRlZEtleVR5cGU7XHJcbiAgLyoqICAgVGhlIGRlZmF1bHQgcmVzb3VyY2UgbmFtZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlUeXBlLiAgQW4gRW50aXR5VHlwZSBtYXkgYmUgcXVlcmllZCB2aWEgYSB2YXJpZXR5IG9mICdyZXNvdXJjZSBuYW1lcycgYnV0IHRoaXMgb25lXHJcbiAgaXMgdXNlZCBhcyB0aGUgZGVmYXVsdCB3aGVuIG5vIHJlc291cmNlIG5hbWUgaXMgcHJvdmlkZWQuICBUaGlzIHdpbGwgb2NjdXIgd2hlbiBjYWxsaW5nIFtbRW50aXR5QXNwZWN0LmxvYWROYXZpZ2F0aW9uUHJvcGVydHldXVxyXG4gIG9yIHdoZW4gZXhlY3V0aW5nIGFueSBbW0VudGl0eVF1ZXJ5XV0gdGhhdCB3YXMgY3JlYXRlZCB2aWEgYW4gW1tFbnRpdHlLZXldXS4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBkZWZhdWx0UmVzb3VyY2VOYW1lOiBzdHJpbmc7XHJcbiAgLyoqIEEgZnVuY3Rpb24gdGhhdCBpcyB1c2VkIHRvIGN1c3RvbWl6ZSB0aGUgc2VyaWFsaXphdGlvbiBvZiBhbnkgRW50aXR5UHJvcGVydGllcyBvZiB0aGlzIHR5cGUuICovXHJcbiAgc2VyaWFsaXplckZuPzogKHByb3A6IEVudGl0eVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55O1xyXG4gIC8qKiAgQSBmcmVlIGZvcm0gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gZGVmaW5lIGFueSBjdXN0b20gbWV0YWRhdGEgZm9yIHRoaXMgRW50aXR5VHlwZS4gX19SZWFkIE9ubHlfXyAgKiovXHJcbiAgY3VzdG9tPzogYW55O1xyXG4gIC8qKiBUaGUgZW50aXR5IGxldmVsIHZhbGlkYXRvcnMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5VHlwZS4gVmFsaWRhdG9ycyBjYW4gYmUgYWRkZWQgYW5kXHJcbiAgcmVtb3ZlZCBmcm9tIHRoaXMgY29sbGVjdGlvbi4gX19SZWFkIE9ubHlfXy4gICAqKi9cclxuICB2YWxpZGF0b3JzOiBWYWxpZGF0b3JbXTtcclxuXHJcbiAgd2FybmluZ3M6IGFueVtdO1xyXG4gIGluaXRGbjogRnVuY3Rpb24gfCBzdHJpbmc7XHJcbiAgbm9UcmFja2luZ0ZuOiBGdW5jdGlvbjtcclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2V4dHJhOiBhbnk7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2N0b3I6IHsgbmV3ICgpOiBTdHJ1Y3R1cmFsT2JqZWN0IH07XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX21hcHBlZFByb3BlcnRpZXNDb3VudDogbnVtYmVyO1xyXG5cclxuICAvKiogXHJcbiAgQGRlcHJlY2F0ZWQgVXNlIFtbZ2V0Q3Rvcl1dIGluc3RlYWQuICAgXHJcbiAgKi9cclxuICBnZXRFbnRpdHlDdG9yID0gdGhpcy5nZXRDdG9yO1xyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBzdGF0aWMgcXVhbGlmeVR5cGVOYW1lID0gcXVhbGlmeVR5cGVOYW1lO1xyXG5cclxuXHJcbiAgLyoqIEVudGl0eVR5cGUgY29uc3RydWN0b3IgIFxyXG4gID4gICAgICBsZXQgZW50aXR5VHlwZSA9IG5ldyBFbnRpdHlUeXBlKCB7XHJcbiAgPiAgICAgICAgICBzaG9ydE5hbWU6IFwicGVyc29uXCIsXHJcbiAgPiAgICAgICAgICBuYW1lc3BhY2U6IFwibXlBcHBOYW1lc3BhY2VcIlxyXG4gID4gICAgICB9KTtcclxuICBAcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhdGlvbiBzZXR0aW5ncyBvciBhIE1ldGFkYXRhU3RvcmUuICBJZiB0aGlzIHBhcmFtZXRlciBpcyBqdXN0IGEgTWV0YWRhdGFTdG9yZVxyXG4gIHRoZW4gd2hhdCB3aWxsIGJlIGNyZWF0ZWQgaXMgYW4gJ2Fub255bW91cycgdHlwZSB0aGF0IHdpbGwgbmV2ZXIgYmUgY29tbXVuaWNhdGVkIHRvIG9yIGZyb20gdGhlIHNlcnZlci4gSXQgaXMgcHVyZWx5IGZvclxyXG4gIGNsaWVudCBzaWRlIHVzZSBhbmQgd2lsbCBiZSBnaXZlbiBhbiBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBuYW1lLiBOb3JtYWxseSwgaG93ZXZlciwgeW91IHdpbGwgdXNlIGEgY29uZmlndXJhdGlvbiBvYmplY3QuXHJcbiAgKiovXHJcbiAgY29uc3RydWN0b3IoY29uZmlnOiBNZXRhZGF0YVN0b3JlIHwgRW50aXR5VHlwZUNvbmZpZykge1xyXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBFbnRpdHlUeXBlIGN0b3IgaGFzIGEgc2luZ2xlIGFyZ3VtZW50IHRoYXQgaXMgZWl0aGVyIGEgJ01ldGFkYXRhU3RvcmUnIG9yIGEgY29uZmlndXJhdGlvbiBvYmplY3QuXCIpO1xyXG4gICAgfVxyXG4gICAgLy8gbGV0IGV0Q29uZmlnID0gIDxFbnRpdHlUeXBlQ29uZmlnPiA8YW55PiB1bmRlZmluZWQ7XHJcbiAgICBsZXQgZXRDb25maWc6IEVudGl0eVR5cGVDb25maWcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XHJcblxyXG4gICAgaWYgKChjb25maWcgYXMgYW55KS5fJHR5cGVOYW1lID09PSBcIk1ldGFkYXRhU3RvcmVcIikge1xyXG4gICAgICB0aGlzLm1ldGFkYXRhU3RvcmUgPSBjb25maWcgYXMgTWV0YWRhdGFTdG9yZTtcclxuICAgICAgdGhpcy5zaG9ydE5hbWUgPSBcIkFub25fXCIgKyAoKytFbnRpdHlUeXBlLl9fbmV4dEFub25JeCk7XHJcbiAgICAgIHRoaXMubmFtZXNwYWNlID0gXCJcIjtcclxuICAgICAgdGhpcy5pc0Fub255bW91cyA9IHRydWU7XHJcbiAgICAgIC8vIGV0Q29uZmlnID0gdW5kZWZpbmVkO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZXRDb25maWcgPSBjb25maWcgYXMgRW50aXR5VHlwZUNvbmZpZztcclxuICAgICAgYXNzZXJ0Q29uZmlnKGNvbmZpZylcclxuICAgICAgICAud2hlcmVQYXJhbShcInNob3J0TmFtZVwiKS5pc05vbkVtcHR5U3RyaW5nKClcclxuICAgICAgICAud2hlcmVQYXJhbShcIm5hbWVzcGFjZVwiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChcIlwiKVxyXG4gICAgICAgIC53aGVyZVBhcmFtKFwiYmFzZVR5cGVOYW1lXCIpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJpc0Fic3RyYWN0XCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChmYWxzZSlcclxuICAgICAgICAud2hlcmVQYXJhbShcImF1dG9HZW5lcmF0ZWRLZXlUeXBlXCIpLmlzRW51bU9mKEF1dG9HZW5lcmF0ZWRLZXlUeXBlKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoQXV0b0dlbmVyYXRlZEtleVR5cGUuTm9uZSlcclxuICAgICAgICAud2hlcmVQYXJhbShcImRlZmF1bHRSZXNvdXJjZU5hbWVcIikuaXNOb25FbXB0eVN0cmluZygpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChudWxsKVxyXG4gICAgICAgIC53aGVyZVBhcmFtKFwiZGF0YVByb3BlcnRpZXNcIikuaXNPcHRpb25hbCgpXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJuYXZpZ2F0aW9uUHJvcGVydGllc1wiKS5pc09wdGlvbmFsKClcclxuICAgICAgICAud2hlcmVQYXJhbShcInNlcmlhbGl6ZXJGblwiKS5pc09wdGlvbmFsKCkuaXNGdW5jdGlvbigpXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJjdXN0b21cIikuaXNPcHRpb25hbCgpXHJcbiAgICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMubmFtZSA9IHF1YWxpZnlUeXBlTmFtZSh0aGlzLnNob3J0TmFtZSwgdGhpcy5uYW1lc3BhY2UpO1xyXG5cclxuICAgIC8vIHRoZSBkZWZhdWx0UmVzb3VyY2VOYW1lIG1heSBhbHNvIGJlIHNldCB1cCBlaXRoZXIgdmlhIG1ldGFkYXRhIGxvb2t1cCBvciBmaXJzdCBxdWVyeSBvciB2aWEgdGhlICdzZXRQcm9wZXJ0aWVzJyBtZXRob2RcclxuICAgIHRoaXMuZGF0YVByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMubmF2aWdhdGlvblByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMuY29tcGxleFByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMua2V5UHJvcGVydGllcyA9IFtdO1xyXG4gICAgdGhpcy5mb3JlaWduS2V5UHJvcGVydGllcyA9IFtdO1xyXG4gICAgdGhpcy5pbnZlcnNlRm9yZWlnbktleVByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMuY29uY3VycmVuY3lQcm9wZXJ0aWVzID0gW107XHJcbiAgICB0aGlzLnVubWFwcGVkUHJvcGVydGllcyA9IFtdOyAvLyB3aWxsIGJlIHVwZGF0ZWQgbGF0ZXIuXHJcbiAgICB0aGlzLnZhbGlkYXRvcnMgPSBbXTtcclxuICAgIHRoaXMud2FybmluZ3MgPSBbXTtcclxuICAgIHRoaXMuX21hcHBlZFByb3BlcnRpZXNDb3VudCA9IDA7XHJcbiAgICB0aGlzLnN1YnR5cGVzID0gW107XHJcbiAgICAvLyBub3cgcHJvY2VzcyBhbnkgZGF0YS9uYXYgcHJvcHNcclxuICAgIGlmIChldENvbmZpZyAmJiBldENvbmZpZy5kYXRhUHJvcGVydGllcykge1xyXG4gICAgICBhZGRQcm9wZXJ0aWVzKHRoaXMsIGV0Q29uZmlnLmRhdGFQcm9wZXJ0aWVzLCBEYXRhUHJvcGVydHkpO1xyXG4gICAgfVxyXG4gICAgaWYgKGV0Q29uZmlnICYmIGV0Q29uZmlnLm5hdmlnYXRpb25Qcm9wZXJ0aWVzKSB7XHJcbiAgICAgIGFkZFByb3BlcnRpZXModGhpcywgZXRDb25maWcubmF2aWdhdGlvblByb3BlcnRpZXMsIE5hdmlnYXRpb25Qcm9wZXJ0eSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBHZW5lcmFsIHB1cnBvc2UgcHJvcGVydHkgc2V0IG1ldGhvZFxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBjdXN0VHlwZS5zZXRQcm9wZXJ0aWVzKCB7XHJcbiAgPiAgICAgICAgICBhdXRvR2VuZXJhdGVkS2V5VHlwZTogQXV0b0dlbmVyYXRlZEtleVR5cGUuSWRlbnRpdHk7XHJcbiAgPiAgICAgICAgICBkZWZhdWx0UmVzb3VyY2VOYW1lOiBcIkN1c3RvbWVyc0FuZEluY2x1ZGVkT3JkZXJzXCJcclxuICA+ICAgICAgKX07XHJcbiAgQHBhcmFtIGNvbmZpZyAtIGEgY29uZmlndXJhdGlvbiBvYmplY3RcclxuICAqKi9cclxuICBzZXRQcm9wZXJ0aWVzKGNvbmZpZzogRW50aXR5VHlwZVNldENvbmZpZykge1xyXG4gICAgYXNzZXJ0Q29uZmlnKGNvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJhdXRvR2VuZXJhdGVkS2V5VHlwZVwiKS5pc0VudW1PZihBdXRvR2VuZXJhdGVkS2V5VHlwZSkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiZGVmYXVsdFJlc291cmNlTmFtZVwiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcInNlcmlhbGl6ZXJGblwiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiY3VzdG9tXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAuYXBwbHlBbGwodGhpcyk7XHJcbiAgICBpZiAoY29uZmlnLmRlZmF1bHRSZXNvdXJjZU5hbWUpIHtcclxuICAgICAgdGhpcy5kZWZhdWx0UmVzb3VyY2VOYW1lID0gY29uZmlnLmRlZmF1bHRSZXNvdXJjZU5hbWU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIHdoZXRoZXIgdGhpcyB0eXBlIGlzIGEgc3VidHlwZSBvZiBhIHNwZWNpZmllZCB0eXBlLlxyXG4gICoqL1xyXG4gIGlzU3VidHlwZU9mKGVudGl0eVR5cGU6IEVudGl0eVR5cGUpIHtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eVR5cGUsIFwiZW50aXR5VHlwZVwiKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkuY2hlY2soKTtcclxuICAgIGxldCBiYXNlVHlwZTogRW50aXR5VHlwZSA9IHRoaXM7XHJcbiAgICBkbyB7XHJcbiAgICAgIGlmIChiYXNlVHlwZSA9PT0gZW50aXR5VHlwZSkgcmV0dXJuIHRydWU7XHJcbiAgICAgIGJhc2VUeXBlID0gYmFzZVR5cGUuYmFzZUVudGl0eVR5cGU7XHJcbiAgICB9IHdoaWxlIChiYXNlVHlwZSk7XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhpcyB0eXBlIGFuZCBhbnkvYWxsIHN1YnR5cGVzIG9mIHRoaXMgdHlwZSBkb3duIHRocnUgdGhlIGhpZXJhcmNoeS5cclxuICAqKi9cclxuICBnZXRTZWxmQW5kU3VidHlwZXMoKSB7XHJcbiAgICBsZXQgcmVzdWx0ID0gW3RoaXNdO1xyXG4gICAgdGhpcy5zdWJ0eXBlcy5mb3JFYWNoKGZ1bmN0aW9uIChzdCkge1xyXG4gICAgICBsZXQgc3VidHlwZXMgPSBzdC5nZXRTZWxmQW5kU3VidHlwZXMoKTtcclxuICAgICAgcmVzdWx0LnB1c2guYXBwbHkocmVzdWx0LCBzdWJ0eXBlcyk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBnZXRBbGxWYWxpZGF0b3JzKCkge1xyXG4gICAgbGV0IHJlc3VsdCA9IHRoaXMudmFsaWRhdG9ycy5zbGljZSgwKTtcclxuICAgIGxldCBidCA9IHRoaXMuYmFzZUVudGl0eVR5cGU7XHJcbiAgICB3aGlsZSAoYnQpIHtcclxuICAgICAgcmVzdWx0LnB1c2guYXBwbHkocmVzdWx0LCBidC52YWxpZGF0b3JzKTtcclxuICAgICAgYnQgPSBidC5iYXNlRW50aXR5VHlwZTtcclxuICAgIH1cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBBZGRzIGEgIFtbRGF0YVByb3BlcnR5XV0gb3IgYSBbW05hdmlnYXRpb25Qcm9wZXJ0eV1dIHRvIHRoaXMgRW50aXR5VHlwZS5cclxuICA+ICAgICAgLy8gYXNzdW1lIG15RW50aXR5VHlwZSBpcyBhIG5ld2x5IGNvbnN0cnVjdGVkIEVudGl0eVR5cGUuXHJcbiAgPiAgICAgIG15RW50aXR5VHlwZS5hZGRQcm9wZXJ0eShkYXRhUHJvcGVydHkxKTtcclxuICA+ICAgICAgbXlFbnRpdHlUeXBlLmFkZFByb3BlcnR5KGRhdGFQcm9wZXJ0eTIpO1xyXG4gID4gICAgICBteUVudGl0eVR5cGUuYWRkUHJvcGVydHkobmF2aWdhdGlvblByb3BlcnR5MSk7XHJcbiAgKiovXHJcbiAgYWRkUHJvcGVydHkocHJvcGVydHk6IEVudGl0eVByb3BlcnR5KSB7XHJcbiAgICBhc3NlcnRQYXJhbShwcm9wZXJ0eSwgXCJwcm9wZXJ0eVwiKS5pc0luc3RhbmNlT2YoRGF0YVByb3BlcnR5KS5vcigpLmlzSW5zdGFuY2VPZihOYXZpZ2F0aW9uUHJvcGVydHkpLmNoZWNrKCk7XHJcblxyXG4gICAgLy8gdHJ1ZSBpcyAybmQgYXJnIHRvIGZvcmNlIHJlc29sdmUgb2YgYW55IG5hdmlnYXRpb24gcHJvcGVydGllcy5cclxuICAgIGxldCBuZXdwcm9wID0gdGhpcy5fYWRkUHJvcGVydHlDb3JlKHByb3BlcnR5LCB0cnVlKTtcclxuXHJcbiAgICBpZiAodGhpcy5zdWJ0eXBlcyAmJiB0aGlzLnN1YnR5cGVzLmxlbmd0aCkge1xyXG4gICAgICBsZXQgc3R5cGUgPSB0aGlzO1xyXG4gICAgICBzdHlwZS5nZXRTZWxmQW5kU3VidHlwZXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChzdCkge1xyXG4gICAgICAgIGlmIChzdCAhPT0gc3R5cGUpIHtcclxuICAgICAgICAgIGlmIChwcm9wZXJ0eS5pc05hdmlnYXRpb25Qcm9wZXJ0eSkge1xyXG4gICAgICAgICAgICBzdC5fYWRkUHJvcGVydHlDb3JlKG5ldyBOYXZpZ2F0aW9uUHJvcGVydHkocHJvcGVydHkpLCB0cnVlKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHN0Ll9hZGRQcm9wZXJ0eUNvcmUobmV3IERhdGFQcm9wZXJ0eShwcm9wZXJ0eSBhcyBEYXRhUHJvcGVydHkpLCB0cnVlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5ld3Byb3A7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfdXBkYXRlRnJvbUJhc2UoYmFzZUVudGl0eVR5cGU6IEVudGl0eVR5cGUpIHtcclxuICAgIHRoaXMuYmFzZUVudGl0eVR5cGUgPSBiYXNlRW50aXR5VHlwZTtcclxuICAgIGlmICh0aGlzLmF1dG9HZW5lcmF0ZWRLZXlUeXBlID09PSBBdXRvR2VuZXJhdGVkS2V5VHlwZS5Ob25lKSB7XHJcbiAgICAgIHRoaXMuYXV0b0dlbmVyYXRlZEtleVR5cGUgPSBiYXNlRW50aXR5VHlwZS5hdXRvR2VuZXJhdGVkS2V5VHlwZTtcclxuICAgIH1cclxuXHJcbiAgICBiYXNlRW50aXR5VHlwZS5kYXRhUHJvcGVydGllcy5mb3JFYWNoKChkcCkgPT4ge1xyXG4gICAgICBsZXQgbmV3RHAgPSBuZXcgRGF0YVByb3BlcnR5KGRwKTtcclxuICAgICAgLy8gZG9uJ3QgbmVlZCB0byBjb3B5IHZhbGlkYXRvcnMgYmVjYXVlIHdlIHdpbGwgd2FsayB0aGUgaGllcmFyY2h5IHRvIGZpbmQgdGhlbVxyXG4gICAgICBuZXdEcC52YWxpZGF0b3JzID0gW107XHJcbiAgICAgIG5ld0RwLmJhc2VQcm9wZXJ0eSA9IGRwO1xyXG4gICAgICB0aGlzLl9hZGRQcm9wZXJ0eUNvcmUobmV3RHApO1xyXG4gICAgfSwgdGhpcyk7XHJcbiAgICBiYXNlRW50aXR5VHlwZS5uYXZpZ2F0aW9uUHJvcGVydGllcy5mb3JFYWNoKChucCkgPT4ge1xyXG4gICAgICBsZXQgbmV3TnAgPSBuZXcgTmF2aWdhdGlvblByb3BlcnR5KG5wKTtcclxuICAgICAgLy8gZG9uJ3QgbmVlZCB0byBjb3B5IHZhbGlkYXRvcnMgYmVjYXVlIHdlIHdpbGwgd2FsayB0aGUgaGllcmFyY2h5IHRvIGZpbmQgdGhlbVxyXG4gICAgICBuZXdOcC52YWxpZGF0b3JzID0gW107XHJcbiAgICAgIG5ld05wLmJhc2VQcm9wZXJ0eSA9IG5wO1xyXG4gICAgICB0aGlzLl9hZGRQcm9wZXJ0eUNvcmUobmV3TnApO1xyXG4gICAgfSwgdGhpcyk7XHJcbiAgICBiYXNlRW50aXR5VHlwZS5zdWJ0eXBlcy5wdXNoKHRoaXMpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2FkZFByb3BlcnR5Q29yZShwcm9wZXJ0eTogRW50aXR5UHJvcGVydHksIHNob3VsZFJlc29sdmU6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgaWYgKHRoaXMuaXNGcm96ZW4pIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlICdcIiArIHRoaXMubmFtZSArIFwiJyBFbnRpdHlUeXBlL0NvbXBsZXhUeXBlIGhhcyBiZWVuIGZyb3plbi4gWW91IGNhbiBvbmx5IGFkZCBwcm9wZXJ0aWVzIHRvIGFuIEVudGl0eVR5cGUvQ29tcGxleFR5cGUgYmVmb3JlIGFueSBpbnN0YW5jZXMgb2YgdGhhdCB0eXBlIGhhdmUgYmVlbiBjcmVhdGVkIGFuZCBhdHRhY2hlZCB0byBhbiBlbnRpdHlNYW5hZ2VyLlwiKTtcclxuICAgIH1cclxuICAgIGxldCBwYXJlbnRUeXBlID0gcHJvcGVydHkucGFyZW50VHlwZTtcclxuICAgIGlmIChwYXJlbnRUeXBlKSB7XHJcbiAgICAgIGlmIChwYXJlbnRUeXBlICE9PSB0aGlzKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBwcm9wZXJ0eTogXCIgKyBwcm9wZXJ0eS5uYW1lICsgXCIgaGFzIGFscmVhZHkgYmVlbiBhZGRlZCB0byBcIiArIHByb3BlcnR5LnBhcmVudFR5cGUubmFtZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gYWRkaW5nIHRoZSBzYW1lIHByb3BlcnR5IG1vcmUgdGhhbiBvbmNlIHRvIHRoZSBzYW1lIGVudGl0eVR5cGUgaXMganVzdCBpZ25vcmVkLlxyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcHJvcGVydHkucGFyZW50VHlwZSA9IHRoaXM7XHJcbiAgICBsZXQgbXMgPSB0aGlzLm1ldGFkYXRhU3RvcmU7XHJcbiAgICAvLyBpZiAocHJvcGVydHkuaXNEYXRhUHJvcGVydHkpIHsgLy8gbW9kaWZpZWQgYmVjYXVzZSBkb2Vzbid0IGFjdCBhcyBhIHR5cGUgZ3VhcmQgXHJcbiAgICBpZiAocHJvcGVydHkgaW5zdGFuY2VvZiBEYXRhUHJvcGVydHkpIHtcclxuICAgICAgdGhpcy5fYWRkRGF0YVByb3BlcnR5KHByb3BlcnR5KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuX2FkZE5hdmlnYXRpb25Qcm9wZXJ0eShwcm9wZXJ0eSk7XHJcbiAgICAgIC8vIG1ldGFkYXRhU3RvcmUgY2FuIGJlIHVuZGVmaW5lZCBpZiB0aGlzIGVudGl0eVR5cGUgaGFzIG5vdCB5ZXQgYmVlbiBhZGRlZCB0byBhIE1ldGFkYXRhU3RvcmUuXHJcbiAgICAgIGlmIChzaG91bGRSZXNvbHZlICYmIG1zKSB7XHJcbiAgICAgICAgdHJ5UmVzb2x2ZU5wKHByb3BlcnR5LCBtcyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIHVubWFwcGVkIHByb3BlcnRpZXMgY2FuIGJlIGFkZGVkIEFGVEVSIGVudGl0eVR5cGUgaGFzIGFscmVhZHkgcmVzb2x2ZWQgYWxsIHByb3BlcnR5IG5hbWVzLlxyXG4gICAgaWYgKG1zICYmICEocHJvcGVydHkubmFtZSAmJiBwcm9wZXJ0eS5uYW1lT25TZXJ2ZXIpKSB7XHJcbiAgICAgIHVwZGF0ZUNsaWVudFNlcnZlck5hbWVzKG1zLm5hbWluZ0NvbnZlbnRpb24sIHByb3BlcnR5LCBcIm5hbWVcIik7XHJcbiAgICB9XHJcbiAgICAvLyBwcm9wcyBjYW4gYmUgYWRkZWQgYWZ0ZXIgZW50aXR5IHByb3RvdHlwZSBoYXMgYWxyZWFkeSBiZWVuIHdyYXBwZWQuXHJcbiAgICBpZiAobXMgJiYgdGhpcy5fZXh0cmEpIHtcclxuICAgICAgaWYgKHRoaXMuX2V4dHJhLmFscmVhZHlXcmFwcGVkUHJvcHMpIHtcclxuICAgICAgICBsZXQgcHJvdG8gPSB0aGlzLl9jdG9yLnByb3RvdHlwZTtcclxuICAgICAgICBjb25maWcuaW50ZXJmYWNlUmVnaXN0cnkubW9kZWxMaWJyYXJ5LmdldERlZmF1bHRJbnN0YW5jZSgpLmluaXRpYWxpemVFbnRpdHlQcm90b3R5cGUocHJvdG8pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBDcmVhdGUgYSBuZXcgZW50aXR5IG9mIHRoaXMgdHlwZS5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEFzRW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgY3VzdDEgPSBjdXN0VHlwZS5jcmVhdGVFbnRpdHkoKTtcclxuICA+ICAgICAgZW0xLmFkZEVudGl0eShjdXN0MSk7XHJcbiAgQHBhcmFtIGluaXRpYWxWYWx1ZXMtIENvbmZpZ3VyYXRpb24gb2JqZWN0IG9mIHRoZSBwcm9wZXJ0aWVzIHRvIHNldCBpbW1lZGlhdGVseSBhZnRlciBjcmVhdGlvbi5cclxuICBAcmV0dXJuIFRoZSBuZXcgZW50aXR5LlxyXG4gICoqL1xyXG4gIGNyZWF0ZUVudGl0eShpbml0aWFsVmFsdWVzPzogYW55KTogYW55IHtcclxuICAgIC8vIGlnbm9yZSB0aGUgXyRlcmVmIG9uY2UgdGhlIGVudGl0eSBpcyBhdHRhY2hlZCB0byBhbiBlbnRpdHlNYW5hZ2VyLlxyXG4gICAgaWYgKGluaXRpYWxWYWx1ZXMgJiYgaW5pdGlhbFZhbHVlcy5fJGVyZWYgJiYgIWluaXRpYWxWYWx1ZXMuXyRlcmVmLmVudGl0eUFzcGVjdC5lbnRpdHlNYW5hZ2VyKSByZXR1cm4gaW5pdGlhbFZhbHVlcy5fJGVyZWY7XHJcblxyXG4gICAgbGV0IGluc3RhbmNlID0gdGhpcy5fY3JlYXRlSW5zdGFuY2VDb3JlKCk7XHJcblxyXG4gICAgaWYgKGluaXRpYWxWYWx1ZXMpIHtcclxuICAgICAgLy8gb25seSBhc3NpZ24gYW4gX2VyZWYgaWYgdGhlIG9iamVjdCBpcyBmdWxseSBcImtleWVkXCJcclxuICAgICAgaWYgKHRoaXMua2V5UHJvcGVydGllcy5ldmVyeShmdW5jdGlvbiAoa3ApIHtcclxuICAgICAgICByZXR1cm4gaW5pdGlhbFZhbHVlc1trcC5uYW1lXSAhPSBudWxsO1xyXG4gICAgICB9KSkge1xyXG4gICAgICAgIGluaXRpYWxWYWx1ZXMuXyRlcmVmID0gaW5zdGFuY2U7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuX3VwZGF0ZVRhcmdldEZyb21SYXcoaW5zdGFuY2UsIGluaXRpYWxWYWx1ZXMsIGdldFJhd1ZhbHVlRnJvbUNvbmZpZyk7XHJcblxyXG4gICAgICB0aGlzLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKG5wKSB7XHJcbiAgICAgICAgbGV0IHJlbGF0ZWRFbnRpdHk6IGFueTtcclxuICAgICAgICBsZXQgdmFsID0gaW5pdGlhbFZhbHVlc1tucC5uYW1lXTtcclxuICAgICAgICBpZiAodmFsICE9IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgbGV0IG5hdkVudGl0eVR5cGUgPSBucC5lbnRpdHlUeXBlO1xyXG4gICAgICAgICAgaWYgKG5wLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICAgIHJlbGF0ZWRFbnRpdHkgPSB2YWwuZW50aXR5QXNwZWN0ID8gdmFsIDogbmF2RW50aXR5VHlwZS5jcmVhdGVFbnRpdHkodmFsKTtcclxuICAgICAgICAgICAgaW5zdGFuY2Uuc2V0UHJvcGVydHkobnAubmFtZSwgcmVsYXRlZEVudGl0eSk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBsZXQgcmVsYXRlZEVudGl0aWVzID0gaW5zdGFuY2UuZ2V0UHJvcGVydHkobnAubmFtZSk7XHJcbiAgICAgICAgICAgIHZhbC5mb3JFYWNoKCh2OiBhbnkpID0+IHtcclxuICAgICAgICAgICAgICByZWxhdGVkRW50aXR5ID0gdi5lbnRpdHlBc3BlY3QgPyB2IDogbmF2RW50aXR5VHlwZS5jcmVhdGVFbnRpdHkodik7XHJcbiAgICAgICAgICAgICAgcmVsYXRlZEVudGl0aWVzLnB1c2gocmVsYXRlZEVudGl0eSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5faW5pdGlhbGl6ZUluc3RhbmNlKGluc3RhbmNlKTtcclxuICAgIHJldHVybiBpbnN0YW5jZTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9jcmVhdGVJbnN0YW5jZUNvcmUoKSB7XHJcbiAgICBsZXQgYUN0b3IgPSB0aGlzLmdldEN0b3IoKTtcclxuICAgIGxldCBpbnN0YW5jZSA9IG5ldyBhQ3RvcigpO1xyXG4gICAgbmV3IEVudGl0eUFzcGVjdChpbnN0YW5jZSBhcyBFbnRpdHkpO1xyXG4gICAgcmV0dXJuIGluc3RhbmNlO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2luaXRpYWxpemVJbnN0YW5jZShpbnN0YW5jZTogYW55KSB7XHJcbiAgICBpZiAodGhpcy5iYXNlRW50aXR5VHlwZSkge1xyXG4gICAgICB0aGlzLmJhc2VFbnRpdHlUeXBlLl9pbml0aWFsaXplSW5zdGFuY2UoaW5zdGFuY2UpO1xyXG4gICAgfVxyXG4gICAgbGV0IGluaXRGbiA9IHRoaXMuaW5pdEZuO1xyXG4gICAgaWYgKGluaXRGbikge1xyXG4gICAgICBsZXQgZm4gPSAodHlwZW9mIGluaXRGbiA9PT0gXCJzdHJpbmdcIikgPyBpbnN0YW5jZVtpbml0Rm5dIDogaW5pdEZuO1xyXG4gICAgICBmbihpbnN0YW5jZSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmNvbXBsZXhQcm9wZXJ0aWVzICYmIHRoaXMuY29tcGxleFByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAoY3ApIHtcclxuICAgICAgbGV0IGNvbXBsZXhUeXBlID0gY3AuZGF0YVR5cGUgYXMgQ29tcGxleFR5cGU7XHJcbiAgICAgIGxldCBjdEluc3RhbmNlID0gaW5zdGFuY2UuZ2V0UHJvcGVydHkoY3AubmFtZSk7XHJcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGN0SW5zdGFuY2UpKSB7XHJcbiAgICAgICAgY3RJbnN0YW5jZS5mb3JFYWNoKChjdEluc3QpID0+IHtcclxuICAgICAgICAgIGNvbXBsZXhUeXBlLl9pbml0aWFsaXplSW5zdGFuY2UoY3RJbnN0KTtcclxuICAgICAgICB9KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb21wbGV4VHlwZS5faW5pdGlhbGl6ZUluc3RhbmNlKGN0SW5zdGFuY2UpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIC8vIG5vdCBuZWVkZWQgZm9yIGNvbXBsZXhPYmplY3RzXHJcbiAgICBpZiAoaW5zdGFuY2UuZW50aXR5QXNwZWN0KSB7XHJcbiAgICAgIGluc3RhbmNlLmVudGl0eUFzcGVjdC5faW5pdGlhbGl6ZWQgPSB0cnVlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyB0aGUgY29uc3RydWN0b3IgZm9yIHRoaXMgRW50aXR5VHlwZS5cclxuICBAcGFyYW0gZm9yY2VSZWZyZXNoIC0gV2hldGhlciB0byBpZ25vcmUgYW55IGNhY2hlZCB2ZXJzaW9uIG9mIHRoaXMgY29uc3RydWN0b3IuIChkZWZhdWx0ID09IGZhbHNlKVxyXG4gIEByZXR1cm4gVGhlIGNvbnN0cnVjdG9yIGZvciB0aGlzIEVudGl0eVR5cGUuXHJcbiAgKiovXHJcbiAgZ2V0Q3Rvcihmb3JjZVJlZnJlc2g6IGJvb2xlYW4gPSBmYWxzZSk6IHsgbmV3ICgpOiBTdHJ1Y3R1cmFsT2JqZWN0IH0ge1xyXG4gICAgaWYgKHRoaXMuX2N0b3IgJiYgIWZvcmNlUmVmcmVzaCkgcmV0dXJuIHRoaXMuX2N0b3I7XHJcblxyXG4gICAgbGV0IGN0b3JSZWdpc3RyeSA9IHRoaXMubWV0YWRhdGFTdG9yZS5fY3RvclJlZ2lzdHJ5O1xyXG4gICAgbGV0IHIgPSBjdG9yUmVnaXN0cnlbdGhpcy5uYW1lXSB8fCBjdG9yUmVnaXN0cnlbdGhpcy5zaG9ydE5hbWVdIHx8IHt9IGFzIEN0b3JSZWNvcmQ7XHJcbiAgICBsZXQgYUN0b3IgPSByLmN0b3IgfHwgdGhpcy5fY3RvcjtcclxuXHJcbiAgICBsZXQgY3RvclR5cGUgPSBhQ3RvciAmJiBhQ3Rvci5wcm90b3R5cGUgJiYgKGFDdG9yLnByb3RvdHlwZS5lbnRpdHlUeXBlIHx8IGFDdG9yLnByb3RvdHlwZS5jb21wbGV4VHlwZSk7XHJcbiAgICBpZiAoY3RvclR5cGUgJiYgY3RvclR5cGUubWV0YWRhdGFTdG9yZSAhPT0gdGhpcy5tZXRhZGF0YVN0b3JlKSB7XHJcbiAgICAgIC8vIFdlIGNhbid0IHJpc2sgYSBtaXNtYXRjaCBiZXR3ZWVuIHRoZSBjdG9yIGFuZCB0aGUgdHlwZSBpbmZvIGluIGEgc3BlY2lmaWMgbWV0YWRhdGFzdG9yZVxyXG4gICAgICAvLyBiZWNhdXNlIG1vZGVsTGlicmFyaWVzIHJlbHkgb24gdHlwZSBpbmZvIHRvIGludGVyY2VwdCBjdG9yIHByb3BlcnRpZXNcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IHJlZ2lzdGVyIHRoZSBzYW1lIGNvbnN0cnVjdG9yIGZvciBcIiArIHRoaXMubmFtZSArIFwiIGluIGRpZmZlcmVudCBtZXRhZGF0YSBzdG9yZXMuICBQbGVhc2UgZGVmaW5lIGEgc2VwYXJhdGUgY29uc3RydWN0b3IgZm9yIGVhY2ggbWV0YWRhdGEgc3RvcmUuXCIpO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICBpZiAoci5jdG9yICYmIGZvcmNlUmVmcmVzaCkge1xyXG4gICAgICB0aGlzLl9leHRyYSA9IHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIWFDdG9yKSB7XHJcbiAgICAgIGxldCBjcmVhdGVDdG9yID0gY29uZmlnLmludGVyZmFjZVJlZ2lzdHJ5Lm1vZGVsTGlicmFyeS5nZXREZWZhdWx0SW5zdGFuY2UoKS5jcmVhdGVDdG9yO1xyXG4gICAgICBhQ3RvciA9IGNyZWF0ZUN0b3IgPyBjcmVhdGVDdG9yKHRoaXMpIDogY3JlYXRlRW1wdHlDdG9yKHRoaXMpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaW5pdEZuID0gci5pbml0Rm47XHJcbiAgICB0aGlzLm5vVHJhY2tpbmdGbiA9IHIubm9UcmFja2luZ0ZuO1xyXG5cclxuICAgIGFDdG9yLnByb3RvdHlwZS5fJHR5cGVOYW1lID0gdGhpcy5uYW1lO1xyXG4gICAgdGhpcy5fc2V0Q3RvcihhQ3Rvcik7XHJcbiAgICByZXR1cm4gYUN0b3I7XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgLy8gTWF5IG1ha2UgcHVibGljIGxhdGVyLlxyXG4gIF9zZXRDdG9yKGFDdG9yOiB7IG5ldyAoKTogU3RydWN0dXJhbE9iamVjdCB9LCBpbnRlcmNlcHRvcj86IGFueSkge1xyXG5cclxuICAgIGxldCBpbnN0YW5jZVByb3RvID0gYUN0b3IucHJvdG90eXBlO1xyXG5cclxuICAgIC8vIHBsYWNlIGZvciBleHRyYSBicmVlemUgcmVsYXRlZCBkYXRhXHJcbiAgICB0aGlzLl9leHRyYSA9IHRoaXMuX2V4dHJhIHx8IHt9O1xyXG5cclxuICAgIGxldCBpbnN0YW5jZSA9IG5ldyBhQ3RvcigpO1xyXG4gICAgY2FsY1VubWFwcGVkUHJvcGVydGllcyh0aGlzLCBpbnN0YW5jZSk7XHJcblxyXG4gICAgaWYgKHRoaXMuXyR0eXBlTmFtZSA9PT0gXCJFbnRpdHlUeXBlXCIpIHtcclxuICAgICAgLy8gaW5zdXJlIHRoYXQgYWxsIG9mIHRoZSBwcm9wZXJ0aWVzIGFyZSBvbiB0aGUgJ3RlbXBsYXRlJyBpbnN0YW5jZSBiZWZvcmUgd2F0Y2hpbmcgdGhlIGNsYXNzLlxyXG4gICAgICBpbnN0YW5jZVByb3RvLmVudGl0eVR5cGUgPSB0aGlzO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaW5zdGFuY2VQcm90by5jb21wbGV4VHlwZSA9IHRoaXM7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZGVmYXVsdFByb3BlcnR5SW50ZXJjZXB0b3IgaXMgYSAnZ2xvYmFsJyAoYnV0IGludGVybmFsIHRvIGJyZWV6ZSkgZnVuY3Rpb247XHJcbiAgICAoaW5zdGFuY2VQcm90byBhcyBhbnkpLl8kaW50ZXJjZXB0b3IgPSBpbnRlcmNlcHRvciB8fCBkZWZhdWx0UHJvcGVydHlJbnRlcmNlcHRvcjtcclxuICAgIGNvbmZpZy5pbnRlcmZhY2VSZWdpc3RyeS5tb2RlbExpYnJhcnkuZ2V0RGVmYXVsdEluc3RhbmNlKCkuaW5pdGlhbGl6ZUVudGl0eVByb3RvdHlwZShpbnN0YW5jZVByb3RvKTtcclxuICAgIHRoaXMuX2N0b3IgPSBhQ3RvcjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEFkZHMgZWl0aGVyIGFuIGVudGl0eSBvciBwcm9wZXJ0eSBsZXZlbCB2YWxpZGF0b3IgdG8gdGhpcyBFbnRpdHlUeXBlLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgY291bnRyeVByb3AgPSBjdXN0VHlwZS5nZXRQcm9wZXJ0eShcIkNvdW50cnlcIik7XHJcbiAgPiAgICAgIGxldCB2YWxGbiA9IGZ1bmN0aW9uICh2KSB7XHJcbiAgPiAgICAgICAgICAgICAgaWYgKHYgPT0gbnVsbCkgcmV0dXJuIHRydWU7XHJcbiAgPiAgICAgICAgICAgICAgcmV0dXJuIChjb3JlLnN0cmluZ1N0YXJ0c1dpdGgodiwgXCJVU1wiKSk7XHJcbiAgPiAgICAgICAgICB9O1xyXG4gID4gICAgICBsZXQgY291bnRyeVZhbGlkYXRvciA9IG5ldyBWYWxpZGF0b3IoXCJjb3VudHJ5SXNVU1wiLCB2YWxGbixcclxuICA+ICAgICAgeyBkaXNwbGF5TmFtZTogXCJDb3VudHJ5XCIsIG1lc3NhZ2VUZW1wbGF0ZTogXCInJWRpc3BsYXlOYW1lJScgbXVzdCBzdGFydCB3aXRoICdVUydcIiB9KTtcclxuICA+ICAgICAgY3VzdFR5cGUuYWRkVmFsaWRhdG9yKGNvdW50cnlWYWxpZGF0b3IsIGNvdW50cnlQcm9wKTtcclxuXHJcbiAgVGhpcyBpcyB0aGUgc2FtZSBhcyBhZGRpbmcgYW4gZW50aXR5IGxldmVsIHZhbGlkYXRvciB2aWEgdGhlICd2YWxpZGF0b3JzJyBwcm9wZXJ0eSBvZiBEYXRhUHJvcGVydHkgb3IgTmF2aWdhdGlvblByb3BlcnR5XHJcbiAgPiAgICAgIGNvdW50cnlQcm9wLnZhbGlkYXRvcnMucHVzaChjb3VudHJ5VmFsaWRhdG9yKTtcclxuXHJcbiAgRW50aXR5IGxldmVsIHZhbGlkYXRvcnMgY2FuIGFsc28gYmUgYWRkZWQgYnkgb21pdHRpbmcgdGhlICdwcm9wZXJ0eScgcGFyYW1ldGVyLlxyXG4gID4gICAgICBjdXN0VHlwZS5hZGRWYWxpZGF0b3Ioc29tZUVudGl0eUxldmVsVmFsaWRhdG9yKTtcclxuXHJcbiAgb3JcclxuICA+ICAgICAgY3VzdFR5cGUudmFsaWRhdG9ycy5wdXNoKHNvbWVFbnRpdHlMZXZlbFZhbGlkYXRvcik7XHJcbiAgQHBhcmFtIHZhbGlkYXRvciAtIFZhbGlkYXRvciB0byBhZGQuXHJcbiAgQHBhcmFtIHByb3BlcnR5IC0gUHJvcGVydHkgdG8gYWRkIHRoaXMgdmFsaWRhdG9yIHRvLiAgSWYgb21pdHRlZCwgdGhlIHZhbGlkYXRvciBpcyBhc3N1bWVkIHRvIGJlIGFuXHJcbiAgZW50aXR5IGxldmVsIHZhbGlkYXRvciBhbmQgaXMgYWRkZWQgdG8gdGhlIEVudGl0eVR5cGUncyAndmFsaWRhdG9ycycuXHJcbiAgKiovXHJcbiAgYWRkVmFsaWRhdG9yKHZhbGlkYXRvcjogVmFsaWRhdG9yLCBwcm9wZXJ0eT86IEVudGl0eVByb3BlcnR5IHwgc3RyaW5nKSB7XHJcbiAgICBhc3NlcnRQYXJhbSh2YWxpZGF0b3IsIFwidmFsaWRhdG9yXCIpLmlzSW5zdGFuY2VPZihWYWxpZGF0b3IpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShwcm9wZXJ0eSwgXCJwcm9wZXJ0eVwiKS5pc09wdGlvbmFsKCkuaXNTdHJpbmcoKS5vcigpLmlzRW50aXR5UHJvcGVydHkoKS5jaGVjaygpO1xyXG4gICAgaWYgKHByb3BlcnR5ICE9IG51bGwpIHtcclxuICAgICAgbGV0IHByb3AgPSAodHlwZW9mIHByb3BlcnR5ID09PSAnc3RyaW5nJykgPyB0aGlzLmdldFByb3BlcnR5KHByb3BlcnR5LCB0cnVlKSA6IHByb3BlcnR5O1xyXG4gICAgICBwcm9wIS52YWxpZGF0b3JzLnB1c2godmFsaWRhdG9yKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMudmFsaWRhdG9ycy5wdXNoKHZhbGlkYXRvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGFsbCBvZiB0aGUgcHJvcGVydGllcyAoIGRhdGFQcm9wZXJ0aWVzIGFuZCBuYXZpZ2F0aW9uUHJvcGVydGllcykgZm9yIHRoaXMgRW50aXR5VHlwZS5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IGFycmF5T2ZQcm9wcyA9IGN1c3RUeXBlLmdldFByb3BlcnRpZXMoKTtcclxuICBAcmV0dXJuIEFuIGFycmF5IG9mIERhdGEgYW5kIE5hdmlnYXRpb24gcHJvcGVydGllcy5cclxuICAqKi9cclxuICBnZXRQcm9wZXJ0aWVzKCk6IEVudGl0eVByb3BlcnR5W10ge1xyXG4gICAgcmV0dXJuICh0aGlzLmRhdGFQcm9wZXJ0aWVzIGFzIEVudGl0eVByb3BlcnR5W10pLmNvbmNhdCh0aGlzLm5hdmlnYXRpb25Qcm9wZXJ0aWVzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYWxsIG9mIHRoZSBwcm9wZXJ0eSBuYW1lcyAoIGZvciBib3RoIGRhdGFQcm9wZXJ0aWVzIGFuZCBuYXZpZ2F0aW9uUHJvcGVydGllcykgZm9yIHRoaXMgRW50aXR5VHlwZS5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IGFycmF5T2ZQcm9wTmFtZXMgPSBjdXN0VHlwZS5nZXRQcm9wZXJ0eU5hbWVzKCk7XHJcbiAgKiovXHJcbiAgZ2V0UHJvcGVydHlOYW1lcygpIHtcclxuICAgIHJldHVybiB0aGlzLmdldFByb3BlcnRpZXMoKS5tYXAoY29yZS5wbHVjaygnbmFtZScpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBkYXRhIHByb3BlcnR5IHdpdGggdGhlIHNwZWNpZmllZCBuYW1lIG9yIG51bGwuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBjdXN0b21lck5hbWVEYXRhUHJvcCA9IGN1c3RUeXBlLmdldERhdGFQcm9wZXJ0eShcIkN1c3RvbWVyTmFtZVwiKTtcclxuICBAcmV0dXJuIEEgRGF0YVByb3BlcnR5IG9yIG51bGwgaWYgbm90IGZvdW5kLlxyXG4gICoqL1xyXG4gIGdldERhdGFQcm9wZXJ0eShwcm9wZXJ0eU5hbWU6IHN0cmluZykge1xyXG4gICAgcmV0dXJuIGNvcmUuYXJyYXlGaXJzdCh0aGlzLmRhdGFQcm9wZXJ0aWVzLCBjb3JlLnByb3BFcSgnbmFtZScsIHByb3BlcnR5TmFtZSkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIG5hdmlnYXRpb24gcHJvcGVydHkgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUgb3IgbnVsbC5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IGN1c3RvbWVyT3JkZXJzTmF2UHJvcCA9IGN1c3RUeXBlLmdldERhdGFQcm9wZXJ0eShcIk9yZGVyc1wiKTtcclxuICBAcmV0dXJuIEEgTmF2aWdhdGlvblByb3BlcnR5IG9yIG51bGwgaWYgbm90IGZvdW5kLlxyXG4gICoqL1xyXG4gIGdldE5hdmlnYXRpb25Qcm9wZXJ0eShwcm9wZXJ0eU5hbWU6IHN0cmluZykge1xyXG4gICAgcmV0dXJuIGNvcmUuYXJyYXlGaXJzdCh0aGlzLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLCBjb3JlLnByb3BFcSgnbmFtZScsIHByb3BlcnR5TmFtZSkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBlaXRoZXIgYSBEYXRhUHJvcGVydHkgb3IgYSBOYXZpZ2F0aW9uUHJvcGVydHkgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUgb3IgbnVsbC5cclxuICBcclxuICBUaGlzIG1ldGhvZCBhbHNvIGFjY2VwdHMgYSAnLicgZGVsaW1pdGVkIHByb3BlcnR5IHBhdGggYW5kIHdpbGwgcmV0dXJuIHRoZSAncHJvcGVydHknIGF0IHRoZVxyXG4gIGVuZCBvZiB0aGUgcGF0aC5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgY29tcGFueU5hbWVQcm9wID0gY3VzdFR5cGUuZ2V0UHJvcGVydHkoXCJDb21wYW55TmFtZVwiKTtcclxuXHJcbiAgVGhpcyBtZXRob2QgY2FuIGFsc28gd2FsayBhIHByb3BlcnR5IHBhdGggdG8gcmV0dXJuIGEgcHJvcGVydHlcclxuICA+ICAgICAgbGV0IG9yZGVyRGV0YWlsVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJPcmRlckRldGFpbFwiKTtcclxuICA+ICAgICAgbGV0IGNvbXBhbnlOYW1lUHJvcDIgPSBvcmRlckRldGFpbFR5cGUuZ2V0UHJvcGVydHkoXCJPcmRlci5DdXN0b21lci5Db21wYW55TmFtZVwiKTtcclxuICA+ICAgICAgLy8gY29tcGFueU5hbWVQcm9wID09PSBjb21wYW55TmFtZVByb3AyXHJcbiAgQHBhcmFtIFt0aHJvd0lmTm90Rm91bmQ9ZmFsc2VdIHtCb29sZWFufSBXaGV0aGVyIHRvIHRocm93IGFuIGV4Y2VwdGlvbiBpZiBub3QgZm91bmQuXHJcbiAgQHJldHVybiBBIERhdGFQcm9wZXJ0eSBvciBOYXZpZ2F0aW9uUHJvcGVydHkgb3IgbnVsbCBpZiBub3QgZm91bmQuXHJcbiAgKiovXHJcbiAgZ2V0UHJvcGVydHkocHJvcGVydHlQYXRoOiBzdHJpbmcsIHRocm93SWZOb3RGb3VuZDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICBsZXQgcHJvcHMgPSB0aGlzLmdldFByb3BlcnRpZXNPblBhdGgocHJvcGVydHlQYXRoLCBmYWxzZSwgdGhyb3dJZk5vdEZvdW5kKTtcclxuICAgIHJldHVybiAocHJvcHMgJiYgcHJvcHMubGVuZ3RoID4gMCkgPyBwcm9wc1twcm9wcy5sZW5ndGggLSAxXSA6IG51bGw7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICAvLyBUT0RPOiBoYXZlIHRoaXMgcmV0dXJuIGVtcHR5IGFycmF5IGluc3RlYWQgb2YgbnVsbCBhbmQgZml4IGNvbnN1bWVycy5cclxuICAvLyBUT0RPOiB0aGluayBhYm91dCByZW5hbWluZyB3aXRoICdfJyBwcmVmaXguXHJcbiAgZ2V0UHJvcGVydGllc09uUGF0aChwcm9wZXJ0eVBhdGg6IHN0cmluZywgdXNlU2VydmVyTmFtZTogYm9vbGVhbiB8IG51bGwsIHRocm93SWZOb3RGb3VuZDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICBsZXQgcHJvcGVydHlOYW1lczogc3RyaW5nW10gPSAoQXJyYXkuaXNBcnJheShwcm9wZXJ0eVBhdGgpKSA/IHByb3BlcnR5UGF0aCA6IHByb3BlcnR5UGF0aC50cmltKCkuc3BsaXQoJy4nKTtcclxuXHJcbiAgICBsZXQgb2sgPSB0cnVlO1xyXG4gICAgbGV0IGtleSA9IHVzZVNlcnZlck5hbWUgPT09IHRydWUgPyBcIm5hbWVPblNlcnZlclwiIDogdXNlU2VydmVyTmFtZSA9PT0gZmFsc2UgPyBcIm5hbWVcIiA6IG51bGw7XHJcbiAgICBsZXQgcGFyZW50VHlwZSA9IHRoaXMgYXMgU3RydWN0dXJhbFR5cGU7XHJcbiAgICBcclxuICAgIGNvbnN0IGdldFByb3BzID0gKHByb3BOYW1lOiBzdHJpbmcpID0+IHsgXHJcbiAgICAgIGNvbnN0IGZuID0ga2V5ID09PSBudWxsID8gY29yZS5wcm9wc0VxKFwibmFtZVwiLCBcIm5hbWVPblNlcnZlclwiLCBwcm9wTmFtZSkgOiBjb3JlLnByb3BFcShrZXksIHByb3BOYW1lKTtcclxuICAgICAgbGV0IHByb3AgPSBjb3JlLmFycmF5Rmlyc3QocGFyZW50VHlwZS5nZXRQcm9wZXJ0aWVzKCksIGZuKTtcclxuICAgICAgaWYgKHByb3ApIHtcclxuICAgICAgICBwYXJlbnRUeXBlID0gKHByb3AgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uUHJvcGVydHkpID8gcHJvcC5lbnRpdHlUeXBlIDogcHJvcC5kYXRhVHlwZSBhcyBDb21wbGV4VHlwZTtcclxuICAgICAgICAvLyBwYXJlbnRUeXBlID0gcHJvcC5pc05hdmlnYXRpb25Qcm9wZXJ0eSA/IHByb3AuZW50aXR5VHlwZSA6IHByb3AuZGF0YVR5cGU7XHJcbiAgICAgIH0gZWxzZSBpZiAodGhyb3dJZk5vdEZvdW5kKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidW5hYmxlIHRvIGxvY2F0ZSBwcm9wZXJ0eTogXCIgKyBwcm9wTmFtZSArIFwiIG9uIGVudGl0eVR5cGU6IFwiICsgcGFyZW50VHlwZS5uYW1lKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBvayA9IGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBwcm9wO1xyXG4gICAgfTtcclxuXHJcbiAgICBsZXQgcHJvcHMgPSBwcm9wZXJ0eU5hbWVzLm1hcChnZXRQcm9wcykgYXMgRW50aXR5UHJvcGVydHlbXTtcclxuICAgIHJldHVybiBvayA/IHByb3BzIDogbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKiBGb3IgdXNlIGluIHBsdWdnYWJsZSBhZGFwdGVycy4gKi9cclxuICAvLyBUT0RPOiBkb2N1bWVudCB1c2VcclxuICBjbGllbnRQcm9wZXJ0eVBhdGhUb1NlcnZlcihwcm9wZXJ0eVBhdGg6IHN0cmluZywgZGVsaW1pdGVyOiBzdHJpbmcgPSAnLicpIHtcclxuICAgIGxldCBwcm9wTmFtZXM6IHN0cmluZ1tdO1xyXG4gICAgaWYgKHRoaXMuaXNBbm9ueW1vdXMpIHtcclxuICAgICAgbGV0IGZuID0gdGhpcy5tZXRhZGF0YVN0b3JlLm5hbWluZ0NvbnZlbnRpb24uY2xpZW50UHJvcGVydHlOYW1lVG9TZXJ2ZXI7XHJcbiAgICAgIHByb3BOYW1lcyA9IHByb3BlcnR5UGF0aC5zcGxpdChcIi5cIikubWFwKGZ1bmN0aW9uIChwcm9wTmFtZSkge1xyXG4gICAgICAgIHJldHVybiBmbihwcm9wTmFtZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgbGV0IHByb3BzID0gdGhpcy5nZXRQcm9wZXJ0aWVzT25QYXRoKHByb3BlcnR5UGF0aCwgZmFsc2UsIHRydWUpO1xyXG4gICAgICBwcm9wTmFtZXMgPSBwcm9wcyEubWFwKChwcm9wOiBFbnRpdHlQcm9wZXJ0eSkgPT4gcHJvcC5uYW1lT25TZXJ2ZXIpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHByb3BOYW1lcy5qb2luKGRlbGltaXRlcik7XHJcbiAgfVxyXG5cclxuICAvKiogRm9yIHVzZSBpbiBwbHVnZ2FibGUgYWRhcHRlcnMuICovXHJcbiAgLy8gVE9ETzogZG9jdW1lbnQgdXNlXHJcbiAgZ2V0RW50aXR5S2V5RnJvbVJhd0VudGl0eShyYXdFbnRpdHk6IGFueSwgcmF3VmFsdWVGbjogRnVuY3Rpb24pIHtcclxuICAgIGxldCBrZXlWYWx1ZXMgPSB0aGlzLmtleVByb3BlcnRpZXMubWFwKChkcCkgPT4ge1xyXG4gICAgICBsZXQgdmFsID0gcmF3VmFsdWVGbihyYXdFbnRpdHksIGRwKTtcclxuICAgICAgcmV0dXJuIERhdGFUeXBlLnBhcnNlUmF3VmFsdWUodmFsLCBkcC5kYXRhVHlwZSBhcyBEYXRhVHlwZSk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBuZXcgRW50aXR5S2V5KHRoaXMsIGtleVZhbHVlcyk7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfdXBkYXRlVGFyZ2V0RnJvbVJhdyh0YXJnZXQ6IFN0cnVjdHVyYWxPYmplY3QsIHJhdzogYW55LCByYXdWYWx1ZUZuOiBGdW5jdGlvbikge1xyXG4gICAgLy8gY2FsbGVkIHJlY3Vyc2l2ZWx5IGZvciBjb21wbGV4IHByb3BlcnRpZXNcclxuICAgIHRoaXMuZGF0YVByb3BlcnRpZXMuZm9yRWFjaCgoZHApID0+IHtcclxuICAgICAgaWYgKCFkcC5pc1NldHRhYmxlKSByZXR1cm47XHJcbiAgICAgIGxldCByYXdWYWwgPSByYXdWYWx1ZUZuKHJhdywgZHApO1xyXG4gICAgICBpZiAocmF3VmFsID09PSB1bmRlZmluZWQpIHJldHVybjtcclxuICAgICAgbGV0IGRhdGFUeXBlID0gZHAuZGF0YVR5cGU7IC8vIHRoaXMgd2lsbCBiZSBhIGNvbXBsZXhUeXBlIHdoZW4gZHAgaXMgYSBjb21wbGV4UHJvcGVydHlcclxuICAgICAgbGV0IG9sZFZhbDogYW55O1xyXG4gICAgICBpZiAoZHAuaXNDb21wbGV4UHJvcGVydHkpIHtcclxuICAgICAgICBsZXQgY29tcGxleFR5cGUgPSBkcC5kYXRhVHlwZSBhcyBDb21wbGV4VHlwZTtcclxuICAgICAgICBpZiAocmF3VmFsID09PSBudWxsKSByZXR1cm47IC8vIHJhd1ZhbCBtYXkgYmUgbnVsbCBpbiBub3NxbCBkYnMgd2hlcmUgaXQgd2FzIG5ldmVyIGRlZmluZWQgZm9yIHRoZSBnaXZlbiByb3cuXHJcbiAgICAgICAgb2xkVmFsID0gdGFyZ2V0LmdldFByb3BlcnR5KGRwLm5hbWUpO1xyXG4gICAgICAgIGlmIChkcC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgY29tcGxleFR5cGUuX3VwZGF0ZVRhcmdldEZyb21SYXcob2xkVmFsLCByYXdWYWwsIHJhd1ZhbHVlRm4pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyYXdWYWwpKSB7XHJcbiAgICAgICAgICAgIGxldCBuZXdWYWwgPSByYXdWYWwubWFwKGZ1bmN0aW9uIChyYXdDbykge1xyXG4gICAgICAgICAgICAgIGxldCBuZXdDbyA9IGNvbXBsZXhUeXBlLl9jcmVhdGVJbnN0YW5jZUNvcmUodGFyZ2V0LCBkcCk7XHJcbiAgICAgICAgICAgICAgY29tcGxleFR5cGUuX3VwZGF0ZVRhcmdldEZyb21SYXcobmV3Q28sIHJhd0NvLCByYXdWYWx1ZUZuKTtcclxuICAgICAgICAgICAgICBjb21wbGV4VHlwZS5faW5pdGlhbGl6ZUluc3RhbmNlKG5ld0NvKTtcclxuICAgICAgICAgICAgICByZXR1cm4gbmV3Q287XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICBpZiAoIWNvcmUuYXJyYXlFcXVhbHMob2xkVmFsLCBuZXdWYWwsIGNvRXF1YWxzKSkge1xyXG4gICAgICAgICAgICAgIC8vIGNsZWFyIHRoZSBvbGQgYXJyYXkgYW5kIHB1c2ggbmV3IG9iamVjdHMgaW50byBpdC5cclxuICAgICAgICAgICAgICBvbGRWYWwubGVuZ3RoID0gMDtcclxuICAgICAgICAgICAgICBuZXdWYWwuZm9yRWFjaChmdW5jdGlvbiAobnYpIHtcclxuICAgICAgICAgICAgICAgIG9sZFZhbC5wdXNoKG52KTtcclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgb2xkVmFsLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGlmIChkcC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgbGV0IG5ld1ZhbCA9IERhdGFUeXBlLnBhcnNlUmF3VmFsdWUocmF3VmFsLCBkYXRhVHlwZSBhcyBEYXRhVHlwZSk7XHJcbiAgICAgICAgICB0YXJnZXQuc2V0UHJvcGVydHkoZHAubmFtZSwgbmV3VmFsKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgb2xkVmFsID0gdGFyZ2V0LmdldFByb3BlcnR5KGRwLm5hbWUpO1xyXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmF3VmFsKSkge1xyXG4gICAgICAgICAgICAvLyBuZWVkIHRvIGNvbXBhcmUgdmFsdWVzXHJcbiAgICAgICAgICAgIGxldCBuZXdWYWwgPSByYXdWYWwubWFwKChydikgPT4ge1xyXG4gICAgICAgICAgICAgIHJldHVybiBEYXRhVHlwZS5wYXJzZVJhd1ZhbHVlKHJ2LCBkYXRhVHlwZSBhcyBEYXRhVHlwZSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICBpZiAoIWNvcmUuYXJyYXlFcXVhbHMob2xkVmFsLCBuZXdWYWwpKSB7XHJcbiAgICAgICAgICAgICAgLy8gY2xlYXIgdGhlIG9sZCBhcnJheSBhbmQgcHVzaCBuZXcgb2JqZWN0cyBpbnRvIGl0LlxyXG4gICAgICAgICAgICAgIG9sZFZhbC5sZW5ndGggPSAwO1xyXG4gICAgICAgICAgICAgIG5ld1ZhbC5mb3JFYWNoKGZ1bmN0aW9uIChudikge1xyXG4gICAgICAgICAgICAgICAgb2xkVmFsLnB1c2gobnYpO1xyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBvbGRWYWwubGVuZ3RoID0gMDtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBpZiBtZXJnaW5nIGZyb20gYW4gaW1wb3J0IHRoZW4gcmF3IHdpbGwgaGF2ZSBhbiBlbnRpdHlBc3BlY3Qgb3IgYSBjb21wbGV4QXNwZWN0XHJcbiAgICBsZXQgcmF3QXNwZWN0ID0gcmF3LmVudGl0eUFzcGVjdCB8fCByYXcuY29tcGxleEFzcGVjdDtcclxuICAgIGlmIChyYXdBc3BlY3QpIHtcclxuXHJcbiAgICAgIGxldCB0YXJnZXRBc3BlY3QgPSBFbnRpdHlBc3BlY3QuaXNFbnRpdHkodGFyZ2V0KSA/IHRhcmdldC5lbnRpdHlBc3BlY3QgOiB0YXJnZXQuY29tcGxleEFzcGVjdDtcclxuICAgICAgaWYgKHJhd0FzcGVjdC5vcmlnaW5hbFZhbHVlc01hcCkge1xyXG4gICAgICAgIHRhcmdldEFzcGVjdC5vcmlnaW5hbFZhbHVlcyA9IHJhd0FzcGVjdC5vcmlnaW5hbFZhbHVlc01hcDtcclxuICAgICAgfVxyXG4gICAgICBpZiAocmF3QXNwZWN0LmV4dHJhTWV0YWRhdGEpIHtcclxuICAgICAgICB0YXJnZXRBc3BlY3QuZXh0cmFNZXRhZGF0YSA9IHJhd0FzcGVjdC5leHRyYU1ldGFkYXRhO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuXHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBFbnRpdHlUeXBlLlxyXG4gICoqL1xyXG4gIHRvU3RyaW5nKCkge1xyXG4gICAgcmV0dXJuIHRoaXMubmFtZTtcclxuICB9XHJcblxyXG4gIHRvSlNPTigpIHtcclxuICAgIHJldHVybiBjb3JlLnRvSnNvbih0aGlzLCB7XHJcbiAgICAgIHNob3J0TmFtZTogbnVsbCxcclxuICAgICAgbmFtZXNwYWNlOiBudWxsLFxyXG4gICAgICBiYXNlVHlwZU5hbWU6IG51bGwsXHJcbiAgICAgIGlzQWJzdHJhY3Q6IGZhbHNlLFxyXG4gICAgICBhdXRvR2VuZXJhdGVkS2V5VHlwZTogbnVsbCwgLy8gZG8gbm90IHN1cHByZXNzIGRlZmF1bHQgdmFsdWVcclxuICAgICAgZGVmYXVsdFJlc291cmNlTmFtZTogbnVsbCxcclxuICAgICAgZGF0YVByb3BlcnRpZXM6IGxvY2FsUHJvcHNPbmx5LFxyXG4gICAgICBuYXZpZ2F0aW9uUHJvcGVydGllczogbG9jYWxQcm9wc09ubHksXHJcbiAgICAgIHZhbGlkYXRvcnM6IG51bGwsXHJcbiAgICAgIGN1c3RvbTogbnVsbFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfdXBkYXRlTmFtZXMocHJvcGVydHk6IEVudGl0eVByb3BlcnR5KSB7XHJcbiAgICBsZXQgbmMgPSB0aGlzLm1ldGFkYXRhU3RvcmUubmFtaW5nQ29udmVudGlvbjtcclxuICAgIHVwZGF0ZUNsaWVudFNlcnZlck5hbWVzKG5jLCBwcm9wZXJ0eSwgXCJuYW1lXCIpO1xyXG5cclxuICAgIGlmIChwcm9wZXJ0eS5pc05hdmlnYXRpb25Qcm9wZXJ0eSkge1xyXG4gICAgICB1cGRhdGVDbGllbnRTZXJ2ZXJOYW1lcyhuYywgcHJvcGVydHksIFwiZm9yZWlnbktleU5hbWVzXCIpO1xyXG4gICAgICB1cGRhdGVDbGllbnRTZXJ2ZXJOYW1lcyhuYywgcHJvcGVydHksIFwiaW52Rm9yZWlnbktleU5hbWVzXCIpO1xyXG5cclxuICAgICAgLy8gdGhlc2Ugd2lsbCBnZXQgc2V0IGxhdGVyIHZpYSBfdXBkYXRlTnBzXHJcbiAgICAgIC8vIHRoaXMuaW52ZXJzZVxyXG4gICAgICAvLyB0aGlzLmVudGl0eVR5cGVcclxuICAgICAgLy8gdGhpcy5yZWxhdGVkRGF0YVByb3BlcnRpZXNcclxuICAgICAgLy8gICAgZGF0YVByb3BlcnR5LnJlbGF0ZWROYXZpZ2F0aW9uUHJvcGVydHlcclxuICAgICAgLy8gICAgZGF0YVByb3BlcnR5LmludmVyc2VOYXZpZ2F0aW9uUHJvcGVydHlcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9jaGVja05hdlByb3BlcnR5KG5hdmlnYXRpb25Qcm9wZXJ0eTogTmF2aWdhdGlvblByb3BlcnR5IHwgc3RyaW5nKSB7XHJcbiAgICAvLyBpZiAobmF2aWdhdGlvblByb3BlcnR5LmlzTmF2aWdhdGlvblByb3BlcnR5KSB7XHJcbiAgICBpZiAobmF2aWdhdGlvblByb3BlcnR5IGluc3RhbmNlb2YgTmF2aWdhdGlvblByb3BlcnR5KSB7XHJcbiAgICAgIGlmIChuYXZpZ2F0aW9uUHJvcGVydHkucGFyZW50VHlwZSAhPT0gdGhpcykge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihjb3JlLmZvcm1hdFN0cmluZyhcIlRoZSBuYXZpZ2F0aW9uUHJvcGVydHkgJyUxJyBpcyBub3QgYSBwcm9wZXJ0eSBvZiBlbnRpdHkgdHlwZSAnJTInXCIsXHJcbiAgICAgICAgICBuYXZpZ2F0aW9uUHJvcGVydHkubmFtZSwgdGhpcy5uYW1lKSk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIG5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZW9mIChuYXZpZ2F0aW9uUHJvcGVydHkpID09PSAnc3RyaW5nJykge1xyXG4gICAgICBsZXQgbnAgPSB0aGlzLmdldFByb3BlcnR5KG5hdmlnYXRpb25Qcm9wZXJ0eSk7XHJcbiAgICAgIC8vIGlmIChucCAmJiBucC5pc05hdmlnYXRpb25Qcm9wZXJ0eSkgcmV0dXJuIG5wO1xyXG4gICAgICBpZiAobnAgJiYgbnAgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uUHJvcGVydHkpIHJldHVybiBucDtcclxuICAgIH1cclxuICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSAnbmF2aWdhdGlvblByb3BlcnR5JyBwYXJhbWV0ZXIgbXVzdCBlaXRoZXIgYmUgYSBOYXZpZ2F0aW9uUHJvcGVydHkgb3IgdGhlIG5hbWUgb2YgYSBOYXZpZ2F0aW9uUHJvcGVydHlcIik7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfYWRkRGF0YVByb3BlcnR5KGRwOiBEYXRhUHJvcGVydHkpIHtcclxuXHJcbiAgICB0aGlzLmRhdGFQcm9wZXJ0aWVzLnB1c2goZHApO1xyXG5cclxuICAgIGlmIChkcC5pc1BhcnRPZktleSkge1xyXG4gICAgICB0aGlzLmtleVByb3BlcnRpZXMucHVzaChkcCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGRwLmlzQ29tcGxleFByb3BlcnR5KSB7XHJcbiAgICAgIHRoaXMuY29tcGxleFByb3BlcnRpZXMucHVzaChkcCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGRwLmNvbmN1cnJlbmN5TW9kZSAmJiBkcC5jb25jdXJyZW5jeU1vZGUgIT09IFwiTm9uZVwiKSB7XHJcbiAgICAgIHRoaXMuY29uY3VycmVuY3lQcm9wZXJ0aWVzLnB1c2goZHApO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChkcC5pc1VubWFwcGVkKSB7XHJcbiAgICAgIHRoaXMudW5tYXBwZWRQcm9wZXJ0aWVzLnB1c2goZHApO1xyXG4gICAgfVxyXG5cclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9hZGROYXZpZ2F0aW9uUHJvcGVydHkobnA6IE5hdmlnYXRpb25Qcm9wZXJ0eSkge1xyXG5cclxuICAgIHRoaXMubmF2aWdhdGlvblByb3BlcnRpZXMucHVzaChucCk7XHJcblxyXG4gICAgaWYgKCFpc1F1YWxpZmllZFR5cGVOYW1lKG5wLmVudGl0eVR5cGVOYW1lKSkge1xyXG4gICAgICBucC5lbnRpdHlUeXBlTmFtZSA9IHF1YWxpZnlUeXBlTmFtZShucC5lbnRpdHlUeXBlTmFtZSwgdGhpcy5uYW1lc3BhY2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VwZGF0ZUNwcygpIHtcclxuICAgIGxldCBtZXRhZGF0YVN0b3JlID0gdGhpcy5tZXRhZGF0YVN0b3JlO1xyXG4gICAgbGV0IGluY29tcGxldGVUeXBlTWFwID0gbWV0YWRhdGFTdG9yZS5faW5jb21wbGV0ZUNvbXBsZXhUeXBlTWFwO1xyXG4gICAgdGhpcy5jb21wbGV4UHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChjcCkge1xyXG4gICAgICBpZiAoY3AuY29tcGxleFR5cGUpIHJldHVybjtcclxuICAgICAgaWYgKCFyZXNvbHZlQ3AoY3AsIG1ldGFkYXRhU3RvcmUpKSB7XHJcbiAgICAgICAgY29yZS5nZXRBcnJheShpbmNvbXBsZXRlVHlwZU1hcCwgY3AuY29tcGxleFR5cGVOYW1lKS5wdXNoKGNwKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKHRoaXMuaXNDb21wbGV4VHlwZSkge1xyXG4gICAgICAoaW5jb21wbGV0ZVR5cGVNYXBbdGhpcy5uYW1lXSB8fCBbXSkuZm9yRWFjaChmdW5jdGlvbiAoY3A6IERhdGFQcm9wZXJ0eSkge1xyXG4gICAgICAgIHJlc29sdmVDcChjcCwgbWV0YWRhdGFTdG9yZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgICBkZWxldGUgaW5jb21wbGV0ZVR5cGVNYXBbdGhpcy5uYW1lXTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF91cGRhdGVOcHMoKSB7XHJcbiAgICBsZXQgbWV0YWRhdGFTdG9yZSA9IHRoaXMubWV0YWRhdGFTdG9yZTtcclxuXHJcbiAgICAvLyByZXNvbHZlIGFsbCBuYXZQcm9wcyBmb3IgdGhpcyBlbnRpdHlUeXBlXHJcbiAgICB0aGlzLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKG5wKSB7XHJcbiAgICAgIHRyeVJlc29sdmVOcChucCwgbWV0YWRhdGFTdG9yZSk7XHJcbiAgICB9KTtcclxuICAgIGxldCBpbmNvbXBsZXRlVHlwZU1hcCA9IG1ldGFkYXRhU3RvcmUuX2luY29tcGxldGVUeXBlTWFwO1xyXG4gICAgLy8gbmV4dCByZXNvbHZlIGFsbCBuYXZQcm9wIHRoYXQgcG9pbnQgdG8gdGhpcyBlbnRpdHlUeXBlLlxyXG4gICAgKGluY29tcGxldGVUeXBlTWFwW3RoaXMubmFtZV0gfHwgW10pLmZvckVhY2goZnVuY3Rpb24gKG5wOiBOYXZpZ2F0aW9uUHJvcGVydHkpIHtcclxuICAgICAgdHJ5UmVzb2x2ZU5wKG5wLCBtZXRhZGF0YVN0b3JlKTtcclxuICAgIH0pO1xyXG4gICAgLy8gZXZlcnkgbmF2UHJvcCB0aGF0IHBvaW50ZWQgdG8gdGhpcyB0eXBlIHNob3VsZCBub3cgYmUgcmVzb2x2ZWRcclxuICAgIGRlbGV0ZSBpbmNvbXBsZXRlVHlwZU1hcFt0aGlzLm5hbWVdO1xyXG4gIH1cclxufVxyXG5cclxuRW50aXR5VHlwZS5wcm90b3R5cGUuXyR0eXBlTmFtZSA9IFwiRW50aXR5VHlwZVwiO1xyXG5cclxuZnVuY3Rpb24gZ2V0UmF3VmFsdWVGcm9tQ29uZmlnKHJhd0VudGl0eTogYW55LCBkcDogRGF0YVByb3BlcnR5KSB7XHJcbiAgLy8gJ3RydWUnIGZvcmsgY2FuIGhhcHBlbiBpZiBhbiBpbml0aWFsaXplciBjb250YWlucyBhbiBhY3RhdWwgaW5zdGFuY2Ugb2YgYW4gYWxyZWFkeSBjcmVhdGVkIGNvbXBsZXggb2JqZWN0LlxyXG4gIHJldHVybiAocmF3RW50aXR5LmVudGl0eUFzcGVjdCB8fCByYXdFbnRpdHkuY29tcGxleEFzcGVjdCkgPyByYXdFbnRpdHkuZ2V0UHJvcGVydHkoZHAubmFtZSkgOiByYXdFbnRpdHlbZHAubmFtZV07XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVwZGF0ZUNsaWVudFNlcnZlck5hbWVzKG5jOiBOYW1pbmdDb252ZW50aW9uLCBwYXJlbnQ6IGFueSwgY2xpZW50UHJvcE5hbWU6IHN0cmluZykge1xyXG4gIGxldCBzZXJ2ZXJQcm9wTmFtZSA9IGNsaWVudFByb3BOYW1lICsgXCJPblNlcnZlclwiO1xyXG4gIGxldCBjbGllbnROYW1lID0gcGFyZW50W2NsaWVudFByb3BOYW1lXTtcclxuICBpZiAoY2xpZW50TmFtZSAmJiBjbGllbnROYW1lLmxlbmd0aCkge1xyXG4gICAgLy8gaWYgKHBhcmVudC5pc1VubWFwcGVkKSByZXR1cm47XHJcbiAgICBsZXQgc2VydmVyTmFtZXMgPSBjb3JlLnRvQXJyYXkoY2xpZW50TmFtZSkubWFwKGZ1bmN0aW9uIChjTmFtZSkge1xyXG4gICAgICBsZXQgc05hbWUgPSBuYy5jbGllbnRQcm9wZXJ0eU5hbWVUb1NlcnZlcihjTmFtZSwgcGFyZW50KTtcclxuICAgICAgbGV0IHRlc3ROYW1lID0gbmMuc2VydmVyUHJvcGVydHlOYW1lVG9DbGllbnQoc05hbWUsIHBhcmVudCk7XHJcbiAgICAgIGlmIChjTmFtZSAhPT0gdGVzdE5hbWUpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1pbmdDb252ZW50aW9uIGZvciB0aGlzIGNsaWVudCBwcm9wZXJ0eSBuYW1lIGRvZXMgbm90IHJvdW5kdHJpcCBwcm9wZXJseTpcIiArIGNOYW1lICsgXCItLT5cIiArIHRlc3ROYW1lKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gc05hbWU7XHJcbiAgICB9KTtcclxuICAgIHBhcmVudFtzZXJ2ZXJQcm9wTmFtZV0gPSBBcnJheS5pc0FycmF5KGNsaWVudE5hbWUpID8gc2VydmVyTmFtZXMgOiBzZXJ2ZXJOYW1lc1swXTtcclxuICB9IGVsc2Uge1xyXG4gICAgbGV0IHNlcnZlck5hbWUgPSBwYXJlbnRbc2VydmVyUHJvcE5hbWVdO1xyXG4gICAgaWYgKCghc2VydmVyTmFtZSkgfHwgc2VydmVyTmFtZS5sZW5ndGggPT09IDApIHJldHVybjtcclxuICAgIGxldCBjbGllbnROYW1lcyA9IGNvcmUudG9BcnJheShzZXJ2ZXJOYW1lKS5tYXAoZnVuY3Rpb24gKHNOYW1lKSB7XHJcbiAgICAgIGxldCBjTmFtZSA9IG5jLnNlcnZlclByb3BlcnR5TmFtZVRvQ2xpZW50KHNOYW1lLCBwYXJlbnQpO1xyXG4gICAgICBsZXQgdGVzdE5hbWUgPSBuYy5jbGllbnRQcm9wZXJ0eU5hbWVUb1NlcnZlcihjTmFtZSwgcGFyZW50KTtcclxuICAgICAgaWYgKHNOYW1lICE9PSB0ZXN0TmFtZSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWluZ0NvbnZlbnRpb24gZm9yIHRoaXMgc2VydmVyIHByb3BlcnR5IG5hbWUgZG9lcyBub3Qgcm91bmR0cmlwIHByb3Blcmx5OlwiICsgc05hbWUgKyBcIi0tPlwiICsgdGVzdE5hbWUpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBjTmFtZTtcclxuICAgIH0pO1xyXG4gICAgcGFyZW50W2NsaWVudFByb3BOYW1lXSA9IEFycmF5LmlzQXJyYXkoc2VydmVyTmFtZSkgPyBjbGllbnROYW1lcyA6IGNsaWVudE5hbWVzWzBdO1xyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlRW1wdHlDdG9yKHR5cGU6IGFueSkge1xyXG4gIGlmIChjb25maWcubm9FdmFsKSB7XHJcbiAgICBsZXQgRW50aXR5ID0gZnVuY3Rpb24oKSB7fTtcclxuICAgIHJldHVybiBFbnRpdHk7XHJcbiAgfSBlbHNlIHtcclxuICAgIGxldCBuYW1lID0gdHlwZS5uYW1lLnJlcGxhY2UoL1xcVy9nLCAnXycpO1xyXG4gICAgcmV0dXJuIEZ1bmN0aW9uKCdyZXR1cm4gZnVuY3Rpb24gJyArIG5hbWUgKyAnKCl7fScpKCk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBjb0VxdWFscyhjbzE6IENvbXBsZXhPYmplY3QsIGNvMjogQ29tcGxleE9iamVjdCk6IGJvb2xlYW4ge1xyXG4gIGxldCBjb21wbGV4VHlwZSA9IGNvMS5jb21wbGV4QXNwZWN0IS5wYXJlbnRQcm9wZXJ0eSEuZGF0YVR5cGUgYXMgQ29tcGxleFR5cGU7XHJcbiAgbGV0IGRhdGFQcm9wcyA9IGNvbXBsZXhUeXBlLmRhdGFQcm9wZXJ0aWVzO1xyXG4gIGxldCBhcmVFcXVhbCA9IGRhdGFQcm9wcy5ldmVyeShmdW5jdGlvbiAoZHApIHtcclxuICAgIGlmICghZHAuaXNTZXR0YWJsZSkgcmV0dXJuIHRydWU7XHJcbiAgICBsZXQgdjEgPSBjbzEuZ2V0UHJvcGVydHkoZHAubmFtZSk7XHJcbiAgICBsZXQgdjIgPSBjbzIuZ2V0UHJvcGVydHkoZHAubmFtZSk7XHJcbiAgICBpZiAoZHAuaXNDb21wbGV4UHJvcGVydHkgJiYgZHAuaXNTY2FsYXIpIHtcclxuICAgICAgcmV0dXJuIGNvRXF1YWxzKHYxLCB2Mik7XHJcbiAgICB9XHJcbiAgICBlbHNlIGlmIChkcC5pc0NvbXBsZXhQcm9wZXJ0eSAmJiAhZHAuaXNTY2FsYXIpIHtcclxuICAgICAgcmV0dXJuIGNvcmUuYXJyYXlFcXVhbHModjEsIHYyLCBjb0VxdWFscyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXQgZGF0YVR5cGUgPSA8YW55PmRwLmRhdGFUeXBlOyAvLyB0aGlzIHdpbGwgYmUgYSBjb21wbGV4VHlwZSB3aGVuIGRwIGlzIGEgY29tcGxleFByb3BlcnR5XHJcbiAgICAgIHJldHVybiAodjEgPT09IHYyIHx8IChkYXRhVHlwZSAmJiBkYXRhVHlwZS5ub3JtYWxpemUgJiYgdjEgJiYgdjIgJiYgZGF0YVR5cGUubm9ybWFsaXplKHYxKSA9PT0gZGF0YVR5cGUubm9ybWFsaXplKHYyKSkpO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiBhcmVFcXVhbDtcclxufVxyXG5cclxuZnVuY3Rpb24gbG9jYWxQcm9wc09ubHkocHJvcHM6IEVudGl0eVByb3BlcnR5W10pIHtcclxuICByZXR1cm4gcHJvcHMuZmlsdGVyKGZ1bmN0aW9uIChwcm9wKSB7XHJcbiAgICByZXR1cm4gcHJvcC5iYXNlUHJvcGVydHkgPT0gbnVsbDtcclxuICB9KTtcclxufVxyXG5cclxuXHJcbmZ1bmN0aW9uIHJlc29sdmVDcChjcDogRGF0YVByb3BlcnR5LCBtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlKSB7XHJcbiAgbGV0IGNvbXBsZXhUeXBlID0gbWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoY3AuY29tcGxleFR5cGVOYW1lLCB0cnVlKTtcclxuICBpZiAoIWNvbXBsZXhUeXBlKSByZXR1cm4gZmFsc2U7XHJcbiAgaWYgKCEoY29tcGxleFR5cGUgaW5zdGFuY2VvZiBDb21wbGV4VHlwZSkpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byByZXNvbHZlIENvbXBsZXhUeXBlIHdpdGggdGhlIG5hbWU6IFwiICsgY3AuY29tcGxleFR5cGVOYW1lICsgXCIgZm9yIHRoZSBwcm9wZXJ0eTogXCIgKyBjcC5uYW1lKTtcclxuICB9XHJcbiAgY3AuZGF0YVR5cGUgPSBjb21wbGV4VHlwZTtcclxuICBjcC5kZWZhdWx0VmFsdWUgPSBudWxsO1xyXG4gIHJldHVybiB0cnVlO1xyXG59XHJcblxyXG5mdW5jdGlvbiB0cnlSZXNvbHZlTnAobnA6IE5hdmlnYXRpb25Qcm9wZXJ0eSwgbWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSkge1xyXG4gIGlmIChucC5lbnRpdHlUeXBlKSByZXR1cm4gdHJ1ZTtcclxuXHJcbiAgbGV0IGVudGl0eVR5cGUgPSBtZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShucC5lbnRpdHlUeXBlTmFtZSwgdHJ1ZSkgYXMgRW50aXR5VHlwZTtcclxuICBpZiAoZW50aXR5VHlwZSkge1xyXG4gICAgbnAuZW50aXR5VHlwZSA9IGVudGl0eVR5cGU7XHJcbiAgICBucC5fcmVzb2x2ZU5wKCk7XHJcbiAgICAvLyBkb24ndCBib3RoZXIgcmVtb3ZpbmcgLSBfdXBkYXRlTnBzIHdpbGwgZG8gaXQgbGF0ZXIuXHJcbiAgICAvLyBfX2FycmF5UmVtb3ZlSXRlbShpbmNvbXBsZXRlTnBzLCBucCwgZmFsc2UpO1xyXG4gIH0gZWxzZSB7XHJcbiAgICBsZXQgaW5jb21wbGV0ZU5wcyA9IGNvcmUuZ2V0QXJyYXkobWV0YWRhdGFTdG9yZS5faW5jb21wbGV0ZVR5cGVNYXAsIG5wLmVudGl0eVR5cGVOYW1lKTtcclxuICAgIGNvcmUuYXJyYXlBZGRJdGVtVW5pcXVlKGluY29tcGxldGVOcHMsIG5wKTtcclxuICB9XHJcbiAgcmV0dXJuICEhZW50aXR5VHlwZTtcclxufVxyXG5cclxuZnVuY3Rpb24gY2FsY1VubWFwcGVkUHJvcGVydGllcyhzdHlwZTogU3RydWN0dXJhbFR5cGUsIGluc3RhbmNlOiBhbnkpIHtcclxuICBsZXQgbWV0YWRhdGFQcm9wTmFtZXMgPSBzdHlwZS5nZXRQcm9wZXJ0eU5hbWVzKCk7XHJcbiAgbGV0IG1vZGVsTGliID0gY29uZmlnLmludGVyZmFjZVJlZ2lzdHJ5Lm1vZGVsTGlicmFyeS5nZXREZWZhdWx0SW5zdGFuY2UoKTtcclxuICBsZXQgdHJhY2thYmxlUHJvcE5hbWVzID0gbW9kZWxMaWIuZ2V0VHJhY2thYmxlUHJvcGVydHlOYW1lcyhpbnN0YW5jZSk7XHJcbiAgdHJhY2thYmxlUHJvcE5hbWVzLmZvckVhY2goZnVuY3Rpb24gKHBuOiBzdHJpbmcpIHtcclxuICAgIGlmIChtZXRhZGF0YVByb3BOYW1lcy5pbmRleE9mKHBuKSA9PT0gLTEpIHtcclxuICAgICAgbGV0IHZhbCA9IGluc3RhbmNlW3BuXTtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gXCJmdW5jdGlvblwiKSB2YWwgPSB2YWwoKTtcclxuICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICB9XHJcbiAgICAgIGxldCBkdCA9IERhdGFUeXBlLmZyb21WYWx1ZSh2YWwpO1xyXG4gICAgICBsZXQgbmV3UHJvcCA9IG5ldyBEYXRhUHJvcGVydHkoe1xyXG4gICAgICAgIG5hbWU6IHBuLFxyXG4gICAgICAgIGRhdGFUeXBlOiBkdCxcclxuICAgICAgICBpc051bGxhYmxlOiB0cnVlLFxyXG4gICAgICAgIGlzVW5tYXBwZWQ6IHRydWVcclxuICAgICAgfSk7XHJcbiAgICAgIG5ld1Byb3AuaXNTZXR0YWJsZSA9IGNvcmUuaXNTZXR0YWJsZShpbnN0YW5jZSwgcG4pO1xyXG4gICAgICBpZiAoc3R5cGUgaW5zdGFuY2VvZiBFbnRpdHlUeXBlICYmIHN0eXBlLnN1YnR5cGVzICE9IG51bGwgJiYgc3R5cGUuc3VidHlwZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgc3R5cGUuZ2V0U2VsZkFuZFN1YnR5cGVzKCkuZm9yRWFjaCgoc3QpID0+IHtcclxuICAgICAgICAgIHN0Ll9hZGRQcm9wZXJ0eUNvcmUobmV3IERhdGFQcm9wZXJ0eShuZXdQcm9wKSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgc3R5cGUuX2FkZFByb3BlcnR5Q29yZShuZXdQcm9wKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0pO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIENvbXBsZXhUeXBlQ29uZmlnIHtcclxuICBzaG9ydE5hbWU/OiBzdHJpbmc7XHJcbiAgbmFtZXNwYWNlPzogc3RyaW5nO1xyXG4gIGRhdGFQcm9wZXJ0aWVzPzogRGF0YVByb3BlcnR5W10gfCBPYmplY3RbXSB8IE9iamVjdDtcclxuICBpc0NvbXBsZXhUeXBlPzogYm9vbGVhbjsgIC8vIG5lZWRlZCBiZWNhdXNlIHRoaXMgY3RvciBjYW4gZ2V0IGNhbGxlZCBmcm9tIHRoZSBhZGRFbnRpdHlUeXBlIG1ldGhvZCB3aGljaCBuZWVkcyB0aGUgaXNDb21wbGV4VHlwZSBwcm9wXHJcbiAgY3VzdG9tPzogYW55O1xyXG59XHJcblxyXG4vKiogIENvbnRhaW5lciBmb3IgYWxsIG9mIHRoZSBtZXRhZGF0YSBhYm91dCBhIHNwZWNpZmljIHR5cGUgb2YgQ29tcGxleCBvYmplY3QuXHJcbj4gICAgIGxldCBjb21wbGV4VHlwZSA9IG5ldyBDb21wbGV4VHlwZSgge1xyXG4+ICAgICAgICAgc2hvcnROYW1lOiBcImFkZHJlc3NcIixcclxuPiAgICAgICAgIG5hbWVzcGFjZTogXCJteUFwcE5hbWVzcGFjZVwiXHJcbj4gICAgIH0pO1xyXG5AcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhdGlvbiBzZXR0aW5nc1xyXG4qKi9cclxuZXhwb3J0IGNsYXNzIENvbXBsZXhUeXBlIHtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBkZWNsYXJlIF8kdHlwZU5hbWU6IHN0cmluZzsgLy8gb24gcHJvdG9cclxuICAvKiogRm9yIHBvbHltb3JwaGljIHB1cnBvc2Ugb25seSAtIGFsd2F5cyB0cnVlIGhlcmUgKi9cclxuICBpc0NvbXBsZXhUeXBlID0gdHJ1ZTtcclxuXHJcbiAgLyoqIFRoZSBbW01ldGFkYXRhU3RvcmVdXSBjb250YWluaW5nIHRoaXMgQ29tcGxleFR5cGUuICovXHJcbiAgbWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZTtcclxuXHJcbiAgLyoqICBUaGUgZnVsbHkgcXVhbGlmZWQgbmFtZSBvZiB0aGlzIENvbXBsZXhUeXBlLiBfX1JlYWQgT25seV9fICAqKi9cclxuICBuYW1lOiBzdHJpbmc7XHJcbiAgLyoqICBUaGUgc2hvcnQsIHVucXVhbGlmaWVkLCBuYW1lIGZvciB0aGlzIENvbXBsZXhUeXBlLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIHNob3J0TmFtZTogc3RyaW5nO1xyXG5cclxuICAvKiogVGhlIG5hbWVzcGFjZSBmb3IgdGhpcyBDb21wbGV4VHlwZS4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBuYW1lc3BhY2U6IHN0cmluZztcclxuICAvKiogVGhlIERhdGFQcm9wZXJ0aWVzIChzZWUgW1tEYXRhUHJvcGVydHldXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBDb21wbGV4VHlwZS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRhdGFQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogVGhlIERhdGFQcm9wZXJ0aWVzIGZvciB0aGlzIENvbXBsZXhUeXBlIHRoYXQgY29udGFpbiBpbnN0YW5jZXMgb2YgYSBbW0NvbXBsZXhUeXBlXV0uIF9fUmVhZCBPbmx5X18gKi9cclxuICBjb21wbGV4UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcblxyXG4gIC8qKlxyXG4gIFRoZSBlbnRpdHkgbGV2ZWwgdmFsaWRhdG9ycyBhc3NvY2lhdGVkIHdpdGggdGhpcyBDb21wbGV4VHlwZS4gVmFsaWRhdG9ycyBjYW4gYmUgYWRkZWQgYW5kXHJcbiAgcmVtb3ZlZCBmcm9tIHRoaXMgY29sbGVjdGlvbi4gX19SZWFkIE9ubHlfXyAgKiovXHJcbiAgdmFsaWRhdG9yczogVmFsaWRhdG9yW107XHJcbiAgLyoqIEZvciBwb2x5bW9ycGhpYyBwdXJwb3NlIG9ubHkgLSBhbHdheXMgZW1wdHkgaGVyZSAqL1xyXG4gIGNvbmN1cnJlbmN5UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgLyoqIFRoZSBEYXRhUHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyBDb21wbGV4VHlwZSB0aGF0IGFyZSBub3QgbWFwcGVkIHRvIGFueSBiYWNrZW5kIGRhdGFzdG9yZS4gVGhlc2UgYXJlIGVmZmVjdGl2ZWx5IGZyZWUgc3RhbmRpbmdcclxuICBwcm9wZXJ0aWVzLiBfX1JlYWQgT25seV9fICAgKiovXHJcbiAgdW5tYXBwZWRQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuXHJcbiAgLy8ga2V5UHJvcGVydGllcyBhbmQgbmF2aWdhdGlvblByb3BlcnRpZXMgYXJlIG5vdCB1c2VkIG9uIGNvbXBsZXhUeXBlcyAtIGJ1dCBoZXJlIHRvIGFsbG93IHNoYXJpbmcgb2YgY29kZSBiZXR3ZWVuIEVudGl0eVR5cGUgYW5kIENvbXBsZXhUeXBlLlxyXG4gIG5hdmlnYXRpb25Qcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvLyBhbmQgbWF5IGJlIHVzZWQgbGF0ZXIgdG8gZW5mb3JjZSB1bmlxdWVuZXNzIG9uIGFycmF5cyBvZiBjb21wbGV4dHlwZXMuXHJcbiAga2V5UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgd2FybmluZ3M6IGFueVtdO1xyXG4gIHNlcmlhbGl6ZXJGbj86IChwcm9wOiBFbnRpdHlQcm9wZXJ0eSwgdmFsOiBhbnkpID0+IGFueTtcclxuXHJcbiAgLyoqIEEgZnJlZSBmb3JtIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIGRlZmluZSBhbnkgY3VzdG9tIG1ldGFkYXRhIGZvciB0aGlzIENvbXBsZXhUeXBlLiAqKiovXHJcbiAgY3VzdG9tPzogYW55O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9tYXBwZWRQcm9wZXJ0aWVzQ291bnQ6IG51bWJlcjtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZXh0cmE/OiBhbnk7XHJcblxyXG4gIC8vIGNvcHkgZW50aXR5VHlwZSBtZXRob2RzIG9udG8gY29tcGxleFR5cGVcclxuICAvKiogU2VlIFtbRW50aXR5VHlwZS5nZXRDdG9yXV0gKi9cclxuICBnZXRDdG9yID0gRW50aXR5VHlwZS5wcm90b3R5cGUuZ2V0Q3RvcjtcclxuICAvLyBub3RlIHRoZSBuYW1lIGNoYW5nZS5cclxuICBjcmVhdGVJbnN0YW5jZSA9IEVudGl0eVR5cGUucHJvdG90eXBlLmNyZWF0ZUVudGl0eTtcclxuICAvKiogU2VlIFtFbnRpdHlUeXBlLmFkZFZhbGlkYXRvcl0gKi9cclxuICBhZGRWYWxpZGF0b3IgPSBFbnRpdHlUeXBlLnByb3RvdHlwZS5hZGRWYWxpZGF0b3I7XHJcbiAgZ2V0UHJvcGVydHkgPSBFbnRpdHlUeXBlLnByb3RvdHlwZS5nZXRQcm9wZXJ0eTtcclxuICBnZXRQcm9wZXJ0aWVzT25QYXRoID0gRW50aXR5VHlwZS5wcm90b3R5cGUuZ2V0UHJvcGVydGllc09uUGF0aDtcclxuICBnZXRQcm9wZXJ0eU5hbWVzID0gRW50aXR5VHlwZS5wcm90b3R5cGUuZ2V0UHJvcGVydHlOYW1lcztcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfYWRkUHJvcGVydHlDb3JlID0gRW50aXR5VHlwZS5wcm90b3R5cGUuX2FkZFByb3BlcnR5Q29yZTtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfYWRkRGF0YVByb3BlcnR5ID0gRW50aXR5VHlwZS5wcm90b3R5cGUuX2FkZERhdGFQcm9wZXJ0eTtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfdXBkYXRlTmFtZXMgPSBFbnRpdHlUeXBlLnByb3RvdHlwZS5fdXBkYXRlTmFtZXM7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VwZGF0ZUNwcyA9IEVudGl0eVR5cGUucHJvdG90eXBlLl91cGRhdGVDcHM7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2luaXRpYWxpemVJbnN0YW5jZSA9IEVudGl0eVR5cGUucHJvdG90eXBlLl9pbml0aWFsaXplSW5zdGFuY2U7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VwZGF0ZVRhcmdldEZyb21SYXcgPSBFbnRpdHlUeXBlLnByb3RvdHlwZS5fdXBkYXRlVGFyZ2V0RnJvbVJhdztcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfc2V0Q3RvciA9IEVudGl0eVR5cGUucHJvdG90eXBlLl9zZXRDdG9yO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihjb25maWc6IENvbXBsZXhUeXBlQ29uZmlnKSB7XHJcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIENvbXBsZXhUeXBlIGN0b3IgaGFzIGEgc2luZ2xlIGFyZ3VtZW50IHRoYXQgaXMgYSBjb25maWd1cmF0aW9uIG9iamVjdC5cIik7XHJcbiAgICB9XHJcblxyXG4gICAgYXNzZXJ0Q29uZmlnKGNvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJzaG9ydE5hbWVcIikuaXNOb25FbXB0eVN0cmluZygpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwibmFtZXNwYWNlXCIpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KFwiXCIpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiZGF0YVByb3BlcnRpZXNcIikuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaXNDb21wbGV4VHlwZVwiKS5pc09wdGlvbmFsKCkuaXNCb29sZWFuKCkgICAvLyBuZWVkZWQgYmVjYXVzZSB0aGlzIGN0b3IgY2FuIGdldCBjYWxsZWQgZnJvbSB0aGUgYWRkRW50aXR5VHlwZSBtZXRob2Qgd2hpY2ggbmVlZHMgdGhlIGlzQ29tcGxleFR5cGUgcHJvcFxyXG4gICAgICAud2hlcmVQYXJhbShcImN1c3RvbVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG5cclxuICAgIHRoaXMubmFtZSA9IHF1YWxpZnlUeXBlTmFtZSh0aGlzLnNob3J0TmFtZSwgdGhpcy5uYW1lc3BhY2UpO1xyXG4gICAgdGhpcy5pc0NvbXBsZXhUeXBlID0gdHJ1ZTtcclxuICAgIHRoaXMuZGF0YVByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMuY29tcGxleFByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMudmFsaWRhdG9ycyA9IFtdO1xyXG4gICAgdGhpcy5jb25jdXJyZW5jeVByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMudW5tYXBwZWRQcm9wZXJ0aWVzID0gW107XHJcbiAgICB0aGlzLl9tYXBwZWRQcm9wZXJ0aWVzQ291bnQgPSAwO1xyXG4gICAgLy8ga2V5UHJvcGVydGllcyBhbmQgbmF2aWdhdGlvblByb3BlcnRpZXMgYXJlIG5vdCB1c2VkIG9uIGNvbXBsZXhUeXBlcyAtIGJ1dCBoZXJlIHRvIGFsbG93IHNoYXJpbmcgb2YgY29kZSBiZXR3ZWVuIEVudGl0eVR5cGUgYW5kIENvbXBsZXhUeXBlLlxyXG4gICAgdGhpcy5uYXZpZ2F0aW9uUHJvcGVydGllcyA9IFtdO1xyXG4gICAgdGhpcy5rZXlQcm9wZXJ0aWVzID0gW107IC8vIG1heSBiZSB1c2VkIGxhdGVyIHRvIGVuZm9yY2UgdW5pcXVlbmVzcyBvbiBhcnJheXMgb2YgY29tcGxleHR5cGVzLlxyXG4gICAgaWYgKGNvbmZpZy5kYXRhUHJvcGVydGllcykge1xyXG4gICAgICBhZGRQcm9wZXJ0aWVzKHRoaXMsIGNvbmZpZy5kYXRhUHJvcGVydGllcywgRGF0YVByb3BlcnR5KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEdlbmVyYWwgcHVycG9zZSBwcm9wZXJ0eSBzZXQgbWV0aG9kXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlclxyXG4gID4gICAgICBsZXQgYWRkcmVzc3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkFkZHJlc3NcIik7XHJcbiAgPiAgICAgIGFkZHJlc3NUeXBlLnNldFByb3BlcnRpZXMoIHtcclxuICA+ICAgICAgICAgIGN1c3RvbTogeyBmb286IDcsIGJhcjogXCJ0ZXN0XCIgfVxyXG4gID4gICAgICB9KTtcclxuICBAcGFyYW0gY29uZmlnIC0gQ3VzdG9tIGNvbmZpZyBvYmplY3RcclxuICBAcGFyYW0gY29uZmlnLmN1c3RvbSAtIHtPYmplY3R9XHJcbiAgKiovXHJcbiAgc2V0UHJvcGVydGllcyhjb25maWc6IHsgY3VzdG9tPzogYW55IH0pIHtcclxuICAgIGFzc2VydENvbmZpZyhjb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiY3VzdG9tXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAuYXBwbHlBbGwodGhpcyk7XHJcbiAgfVxyXG5cclxuXHJcbiAgZ2V0QWxsVmFsaWRhdG9ycygpIHtcclxuICAgIC8vIENvbXBsZXhUeXBlIGluaGVyaXRhbmNlIGlzIG5vdCBZRVQgc3VwcG9ydGVkLlxyXG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdG9ycztcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9jcmVhdGVJbnN0YW5jZUNvcmUocGFyZW50OiBTdHJ1Y3R1cmFsT2JqZWN0LCBwYXJlbnRQcm9wZXJ0eTogRGF0YVByb3BlcnR5KSB7XHJcbiAgICBsZXQgYUN0b3IgPSB0aGlzLmdldEN0b3IoKTtcclxuICAgIGxldCBpbnN0YW5jZSA9IG5ldyBhQ3RvcigpIGFzIENvbXBsZXhPYmplY3Q7XHJcbiAgICBuZXcgQ29tcGxleEFzcGVjdChpbnN0YW5jZSwgcGFyZW50LCBwYXJlbnRQcm9wZXJ0eSk7XHJcbiAgICAvLyBpbml0aWFsaXphdGlvbiBvY2N1cnMgZHVyaW5nIGVpdGhlciBhdHRhY2ggb3IgaW4gY3JlYXRlSW5zdGFuY2UgY2FsbC5cclxuICAgIHJldHVybiBpbnN0YW5jZTtcclxuICB9XHJcblxyXG5cclxuICBhZGRQcm9wZXJ0eShkYXRhUHJvcGVydHk6IERhdGFQcm9wZXJ0eSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oZGF0YVByb3BlcnR5LCBcImRhdGFQcm9wZXJ0eVwiKS5pc0luc3RhbmNlT2YoRGF0YVByb3BlcnR5KS5jaGVjaygpO1xyXG4gICAgcmV0dXJuIHRoaXMuX2FkZFByb3BlcnR5Q29yZShkYXRhUHJvcGVydHkpO1xyXG4gIH1cclxuXHJcbiAgZ2V0UHJvcGVydGllcygpOiBFbnRpdHlQcm9wZXJ0eVtdIHtcclxuICAgIHJldHVybiB0aGlzLmRhdGFQcm9wZXJ0aWVzO1xyXG4gIH1cclxuXHJcbiAgdG9KU09OKCkge1xyXG4gICAgcmV0dXJuIGNvcmUudG9Kc29uKHRoaXMsIHtcclxuICAgICAgc2hvcnROYW1lOiBudWxsLFxyXG4gICAgICBuYW1lc3BhY2U6IG51bGwsXHJcbiAgICAgIGlzQ29tcGxleFR5cGU6IG51bGwsXHJcbiAgICAgIGRhdGFQcm9wZXJ0aWVzOiBudWxsLFxyXG4gICAgICB2YWxpZGF0b3JzOiBudWxsLFxyXG4gICAgICBjdXN0b206IG51bGxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbn1cclxuQ29tcGxleFR5cGUucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIkNvbXBsZXhUeXBlXCI7XHJcbi8qKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIHRoaXMgY29tcGxleFR5cGUgKi9cclxuQ29tcGxleFR5cGUucHJvdG90eXBlLmNyZWF0ZUluc3RhbmNlID0gRW50aXR5VHlwZS5wcm90b3R5cGUuY3JlYXRlRW50aXR5O1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBEYXRhUHJvcGVydHlDb25maWcge1xyXG4gIG5hbWU/OiBzdHJpbmc7XHJcbiAgbmFtZU9uU2VydmVyPzogc3RyaW5nO1xyXG4gIGRhdGFUeXBlPzogRGF0YVR5cGUgfCBzdHJpbmcgfCBDb21wbGV4VHlwZTtcclxuICBjb21wbGV4VHlwZU5hbWU/OiBzdHJpbmc7XHJcbiAgaXNOdWxsYWJsZT86IGJvb2xlYW47XHJcbiAgaXNTY2FsYXI/OiBib29sZWFuOyAvLyB3aWxsIGJlIGZhbHNlIGZvciBzb21lIE5vU1FMIGRhdGFiYXNlcy5cclxuICBkZWZhdWx0VmFsdWU/OiBhbnk7XHJcbiAgaXNQYXJ0T2ZLZXk/OiBib29sZWFuO1xyXG4gIGlzVW5tYXBwZWQ/OiBib29sZWFuO1xyXG4gIGlzU2V0dGFibGU/OiBib29sZWFuO1xyXG4gIGNvbmN1cnJlbmN5TW9kZT86IHN0cmluZztcclxuICBtYXhMZW5ndGg/OiBudW1iZXI7XHJcbiAgdmFsaWRhdG9ycz86IFZhbGlkYXRvcltdO1xyXG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nO1xyXG4gIGVudW1UeXBlPzogc3RyaW5nO1xyXG4gIHJhd1R5cGVOYW1lPzogc3RyaW5nOyAgLy8gb2NjdXJzIHdpdGggdW5kZWZpbmVkIGRhdGF0eXBlc1xyXG4gIGN1c3RvbT86IGFueTtcclxufVxyXG5cclxuLyoqXHJcbkEgRGF0YVByb3BlcnR5IGRlc2NyaWJlcyB0aGUgbWV0YWRhdGEgZm9yIGEgc2luZ2xlIHByb3BlcnR5IG9mIGFuICBbW0VudGl0eVR5cGVdXSB0aGF0IGNvbnRhaW5zIHNpbXBsZSBkYXRhLlxyXG5cclxuSW5zdGFuY2VzIG9mIHRoZSBEYXRhUHJvcGVydHkgY2xhc3MgYXJlIGNvbnN0cnVjdGVkIGF1dG9tYXRpY2FsbHkgZHVyaW5nIE1ldGFkYXRhIHJldHJpZXZhbC4gSG93ZXZlciBpdCBpcyBhbHNvIHBvc3NpYmxlIHRvIGNvbnN0cnVjdCB0aGVtXHJcbmRpcmVjdGx5IHZpYSB0aGUgY29uc3RydWN0b3IuXHJcbioqL1xyXG5leHBvcnQgY2xhc3MgRGF0YVByb3BlcnR5IHtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBkZWNsYXJlIF8kdHlwZU5hbWU6IHN0cmluZzsgLy8gb24gcHJvdG9cclxuICAvKiogSXMgdGhpcyBhIERhdGFQcm9wZXJ0eT8gLSBhbHdheXMgdHJ1ZSBoZXJlLiBBbGxvd3MgcG9seW1vcnBoaWMgdHJlYXRtZW50IG9mIERhdGFQcm9wZXJ0aWVzIGFuZCBOYXZpZ2F0aW9uUHJvcGVydGllcy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGlzRGF0YVByb3BlcnR5ID0gdHJ1ZTtcclxuICAvKiogSXMgdGhpcyBhIE5hdmlnYXRpb25Qcm9wZXJ0eT8gLSBhbHdheXMgZmFsc2UgaGVyZS4gIEFsbG93cyBwb2x5bW9ycGhpYyB0cmVhdG1lbnQgb2YgRGF0YVByb3BlcnRpZXMgYW5kIE5hdmlnYXRpb25Qcm9wZXJ0aWVzLiBfX1JlYWQgT25seV9fICovXHJcbiAgaXNOYXZpZ2F0aW9uUHJvcGVydHkgPSBmYWxzZTtcclxuICAvKiogVGhlIG5hbWUgb2YgdGhpcyBwcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAgKiovXHJcbiAgZGVjbGFyZSBuYW1lOiBzdHJpbmc7XHJcbiAgLyoqIFRoZSBuYW1lIG9mIHRoaXMgcHJvcGVydHkgb24gdGhlIHNlcnZlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBkZWNsYXJlIG5hbWVPblNlcnZlcjogc3RyaW5nO1xyXG4gIC8qKiBUaGUgW1tEYXRhVHlwZV1dIG9mIHRoaXMgcHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGRhdGFUeXBlOiBEYXRhVHlwZSB8IENvbXBsZXhUeXBlOyAvLyB0aGlzIHdpbGwgYmUgYSBjb21wbGV4VHlwZSB3aGVuIGRwIGlzIGEgY29tcGxleFByb3BlcnR5XHJcbiAgLyoqIFRoZSBuYW1lIG9mIHRoZSBbW0NvbXBsZXhUeXBlXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgcHJvcGVydHk7IG1heSBiZSBudWxsLiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBjb21wbGV4VHlwZU5hbWU6IHN0cmluZztcclxuICAvKiogVGhlIFtbQ29tcGxleFR5cGVdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBwcm9wZXJ0eTsgbWF5IGJlIHVuZGVmaW5lZC4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRlY2xhcmUgY29tcGxleFR5cGU/OiBDb21wbGV4VHlwZTtcclxuICAvKiogIFdoZXRoZXIgdGhlIGNvbnRlbnRzIG9mIHRoaXMgcHJvcGVydHkgaXMgYW4gaW5zdGFuY2Ugb2YgYSBbW0NvbXBsZXhUeXBlXV0uIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGlzQ29tcGxleFByb3BlcnR5OiBib29sZWFuO1xyXG4gIC8qKiBXaGV0aGVyIHRoaXMgcHJvcGVydHkgaXMgbnVsbGFibGUuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGlzTnVsbGFibGU6IGJvb2xlYW47XHJcbiAgLyoqICBXaGV0aGVyIHRoaXMgcHJvcGVydHkgaXMgc2NhbGFyIChpLmUuLCByZXR1cm5zIGEgc2luZ2xlIHZhbHVlIGFzIG9wcG9zZWQgdG8gYW4gYXJyYXkpLiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBpc1NjYWxhcjogYm9vbGVhbjsgLy8gd2lsbCBiZSBmYWxzZSBmb3Igc29tZSBOb1NRTCBkYXRhYmFzZXMuXHJcbiAgLyoqIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGlzIHByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBkZWZhdWx0VmFsdWU6IGFueTtcclxuICAvKiogIFdoZXRoZXIgdGhpcyBwcm9wZXJ0eSBpcyBhICdrZXknIHByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBpc1BhcnRPZktleTogYm9vbGVhbjtcclxuICAvKiogV2hldGhlciB0aGlzIHByb3BlcnR5IGlzIGFuICd1bm1hcHBlZCcgcHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGlzVW5tYXBwZWQ6IGJvb2xlYW47XHJcbiAgLyoqIFdoZXRoZXIgdGhpcyBwcm9wZXJ0eSBpcyAnc2V0dGFibGUnLiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBpc1NldHRhYmxlOiBib29sZWFuO1xyXG4gIC8vIFRPRE86IGRvYyB0aGlzXHJcbiAgZGVjbGFyZSBjb25jdXJyZW5jeU1vZGU6IHN0cmluZztcclxuICAvKiogIFRoZSBtYXhpbXVtIGxlbmd0aCBmb3IgdGhlIHZhbHVlIG9mIHRoaXMgcHJvcGVydHkuIE9ubHkgbWVhbmluZ2Z1bCBmb3Igc3RyaW5ncy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRlY2xhcmUgbWF4TGVuZ3RoPzogbnVtYmVyO1xyXG4gIC8qKiBUaGUgW1tWYWxpZGF0b3JdXSBpbnN0YW5jZXMgdGhhdCBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgcHJvcGVydHkuIFZhbGlkYXRvcnMgY2FuIGJlIGFkZGVkIGFuZFxyXG4gIHJlbW92ZWQgZnJvbSB0aGlzIGNvbGxlY3Rpb24uIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIHZhbGlkYXRvcnM6IFZhbGlkYXRvcltdO1xyXG4gIC8qKiBUaGUgZGlzcGxheSBuYW1lIG9mIHRoaXMgcHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGRpc3BsYXlOYW1lOiBzdHJpbmc7XHJcbiAgLyoqIFRoZSBmdWxsIG5hbWUgb2YgdGhlIGVudW0gdHlwZSAqL1xyXG4gIGRlY2xhcmUgZW51bVR5cGU/OiBzdHJpbmc7XHJcbiAgLyoqIFRoZSByYXcgdHlwZSBuYW1lIG9mIHRoaXMgcHJvcGVydHkuIHdpbGwgb25seSBiZSBkZWZpbmVkIGZvciBwcm9wZXJ0aWVzIHdpdGggYSBEYXRhVHlwZSBvZiAnVW5kZWZpbmVkJyAqL1xyXG4gIGRlY2xhcmUgcmF3VHlwZU5hbWU/OiBzdHJpbmc7ICAvLyBvY2N1cnMgd2l0aCB1bmRlZmluZWQgZGF0YXR5cGVzXHJcbiAgLyoqICBBIGZyZWUgZm9ybSBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgYW55IGN1c3RvbSBtZXRhZGF0YSBmb3IgdGhpcyBEYXRhUHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGN1c3RvbT86IGFueTtcclxuICAvLyBUT0RPOiBkb2MgdGhpc1xyXG4gIGRlY2xhcmUgaW52ZXJzZU5hdmlnYXRpb25Qcm9wZXJ0eT86IE5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuICAvKipcclxuICBUaGUgbmF2aWdhdGlvbiBwcm9wZXJ0eSByZWxhdGVkIHRvIHRoaXMgcHJvcGVydHkuICBXaWxsIG9ubHkgYmUgc2V0IGlmIHRoaXMgaXMgYSBmb3JlaWduIGtleSBwcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRlY2xhcmUgcmVsYXRlZE5hdmlnYXRpb25Qcm9wZXJ0eT86IE5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuICAvKiogVGhlIHBhcmVudCB0eXBlIHRoYXQgdGhpcyBwcm9wZXJ0eSBiZWxvbmdzIHRvIC0gd2lsbCBiZSBlaXRoZXIgYSBbW0VudGl0eVR5cGVdXSBvciBhIFtbQ29tcGxleFR5cGVdXS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRlY2xhcmUgcGFyZW50VHlwZTogU3RydWN0dXJhbFR5cGU7XHJcbiAgLyoqIFByb3BlcnR5IG9uIHRoZSBiYXNlIHR5cGUgdGhhdCB0aGlzIHByb3BlcnR5IGlzIGluaGVyaXRlZCBmcm9tLiBXaWxsIGJlIG51bGwgaWYgdGhlIHByb3BlcnR5IGlzIG5vdCBvbiB0aGUgYmFzZSB0eXBlLiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBiYXNlUHJvcGVydHk/OiBEYXRhUHJvcGVydHk7XHJcblxyXG4gIC8qKiBEYXRhUHJvcGVydHkgY29uc3RydWN0b3JcclxuICA+ICAgICAgbGV0IGxhc3ROYW1lUHJvcCA9IG5ldyBEYXRhUHJvcGVydHkoIHtcclxuICA+ICAgICAgICAgIG5hbWU6IFwibGFzdE5hbWVcIixcclxuICA+ICAgICAgICAgIGRhdGFUeXBlOiBEYXRhVHlwZS5TdHJpbmcsXHJcbiAgPiAgICAgICAgICBpc051bGxhYmxlOiB0cnVlLFxyXG4gID4gICAgICAgICAgbWF4TGVuZ3RoOiAyMFxyXG4gID4gICAgICB9KTtcclxuICA+ICAgICAgLy8gYXNzdW1pbmcgcGVyc29uRW50aXR5VHlwZSBpcyBhIG5ld2x5IGNvbnN0cnVjdGVkIEVudGl0eVR5cGVcclxuICA+ICAgICAgcGVyc29uRW50aXR5VHlwZS5hZGRQcm9wZXJ0eShsYXN0TmFtZVByb3BlcnR5KTtcclxuICBAcGFyYW0gY29uZmlnIC0gQSBjb25maWd1cmF0aW9uIE9iamVjdCBvciBhIERhdGFQcm9wZXJ0eVxyXG4gICovXHJcbiAgY29uc3RydWN0b3IoY29uZmlnOiBEYXRhUHJvcGVydHlDb25maWcgfCBEYXRhUHJvcGVydHkpIHtcclxuICAgIGFzc2VydENvbmZpZyhjb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwibmFtZVwiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm5hbWVPblNlcnZlclwiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImRhdGFUeXBlXCIpLmlzRW51bU9mKERhdGFUeXBlKS5pc09wdGlvbmFsKCkub3IoKS5pc1N0cmluZygpLm9yKCkuaXNJbnN0YW5jZU9mKENvbXBsZXhUeXBlKVxyXG4gICAgICAud2hlcmVQYXJhbShcImNvbXBsZXhUeXBlTmFtZVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJpc051bGxhYmxlXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdCh0cnVlKVxyXG4gICAgICAud2hlcmVQYXJhbShcImlzU2NhbGFyXCIpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdCh0cnVlKS8vIHdpbGwgYmUgZmFsc2UgZm9yIHNvbWUgTm9TUUwgZGF0YWJhc2VzLlxyXG4gICAgICAud2hlcmVQYXJhbShcImRlZmF1bHRWYWx1ZVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJpc1BhcnRPZktleVwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJpc1VubWFwcGVkXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImlzU2V0dGFibGVcIikuaXNCb29sZWFuKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KHRydWUpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiY29uY3VycmVuY3lNb2RlXCIpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwibWF4TGVuZ3RoXCIpLmlzTnVtYmVyKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwidmFsaWRhdG9yc1wiKS5pc0luc3RhbmNlT2YoVmFsaWRhdG9yKS5pc0FycmF5KCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KFtdKVxyXG4gICAgICAud2hlcmVQYXJhbShcImRpc3BsYXlOYW1lXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImVudW1UeXBlXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcInJhd1R5cGVOYW1lXCIpLmlzT3B0aW9uYWwoKSAvLyBvY2N1cnMgd2l0aCB1bmRlZmluZWQgZGF0YXR5cGVzXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiY3VzdG9tXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAuYXBwbHlBbGwodGhpcyk7XHJcbiAgICBsZXQgaGFzTmFtZSA9ICEhKHRoaXMubmFtZSB8fCB0aGlzLm5hbWVPblNlcnZlcik7XHJcbiAgICBpZiAoIWhhc05hbWUpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQSBEYXRhUHJvcGVydHkgbXVzdCBiZSBpbnN0YW50aWF0ZWQgd2l0aCBlaXRoZXIgYSAnbmFtZScgb3IgYSAnbmFtZU9uU2VydmVyJyBwcm9wZXJ0eVwiKTtcclxuICAgIH1cclxuICAgIC8vIG5hbWUvbmFtZU9uU2VydmVyIGlzIHJlc29sdmVkIGxhdGVyIHdoZW4gYSBtZXRhZGF0YVN0b3JlIGlzIGF2YWlsYWJsZS5cclxuXHJcbiAgICBpZiAodGhpcy5jb21wbGV4VHlwZU5hbWUpIHtcclxuICAgICAgdGhpcy5pc0NvbXBsZXhQcm9wZXJ0eSA9IHRydWU7XHJcbiAgICAgIC8vIHRoaXMuZGF0YVR5cGUgPSBudWxsOyAvLyBUT0RPOiB3b3VsZCBsaWtlIHRvIHJlbW92ZSB0aGlzIGxpbmUgYmVjYXVzZSBkYXRhVHlwZSB3aWxsIGJlIHNldCBsYXRlci5cclxuICAgIH0gZWxzZSBpZiAodHlwZW9mICh0aGlzLmRhdGFUeXBlKSA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICBsZXQgZHQgPSBEYXRhVHlwZS5mcm9tTmFtZSh0aGlzLmRhdGFUeXBlKTtcclxuICAgICAgaWYgKCFkdCkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBmaW5kIGEgRGF0YVR5cGUgZW51bWVyYXRpb24gYnkgdGhlIG5hbWUgb2Y6IFwiICsgdGhpcy5kYXRhVHlwZSk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5kYXRhVHlwZSA9IGR0O1xyXG4gICAgfSBlbHNlIGlmICghdGhpcy5kYXRhVHlwZSkge1xyXG4gICAgICB0aGlzLmRhdGFUeXBlID0gRGF0YVR5cGUuU3RyaW5nO1xyXG4gICAgfVxyXG5cclxuICAgIC8vID09IGFzIG9wcG9zZWQgdG8gPT09IGlzIGRlbGliZXJhdGUgaGVyZS5cclxuICAgIGlmICh0aGlzLmRlZmF1bHRWYWx1ZSA9PSBudWxsKSB7XHJcbiAgICAgIGlmICh0aGlzLmlzTnVsbGFibGUpIHtcclxuICAgICAgICB0aGlzLmRlZmF1bHRWYWx1ZSA9IG51bGw7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNDb21wbGV4UHJvcGVydHkpIHtcclxuICAgICAgICAgIC8vIHdoYXQgdG8gZG8/IC0gc2hvdWxkbid0IGhhcHBlbiBmcm9tIEVGIC0gYnV0IG90aGVyd2lzZSA/Pz9cclxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YVR5cGUgPT09IERhdGFUeXBlLkJpbmFyeSkge1xyXG4gICAgICAgICAgdGhpcy5kZWZhdWx0VmFsdWUgPSBcIkFBQUFBQUFBSjNVPVwiOyAvLyBoYWNrIGZvciBhbGwgYmluYXJ5IGZpZWxkcyBidXQgdmFsdWUgaXMgc3BlY2lmaWNhbGx5IHZhbGlkIGZvciB0aW1lc3RhbXAgZmllbGRzIC0gYXJiaXRyYXJ5IHZhbGlkIDggYnl0ZSBiYXNlNjQgdmFsdWUuXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMuZGVmYXVsdFZhbHVlID0gKHRoaXMuZGF0YVR5cGUgYXMgYW55KS5kZWZhdWx0VmFsdWU7XHJcbiAgICAgICAgICBjb25zdCBtc2cgPSBcIkEgbm9ubnVsbGFibGUgRGF0YVByb3BlcnR5IGNhbm5vdCBoYXZlIGEgbnVsbCBkZWZhdWx0VmFsdWUuIE5hbWU6IFwiICsgKHRoaXMubmFtZSB8fCB0aGlzLm5hbWVPblNlcnZlcik7XHJcbiAgICAgICAgICBpZiAodGhpcy5kZWZhdWx0VmFsdWUgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7ICAvLyBpZiBkZWZhdWx0VmFsdWUgaXMgZXhwbGljaXR5IHNldCB0byBudWxsLCB0aGF0J3MgYW4gZXJyb3JcclxuICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5kZWZhdWx0VmFsdWUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICBjb25zb2xlLndhcm4obXNnKTsgIC8vIGlmIGRlZmF1bHRWYWx1ZSBpcyBub3Qgc2V0LCB0aGF0J3MgYSB3YXJuaW5nXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9IGVsc2UgaWYgKCh0aGlzLmRhdGFUeXBlIGFzIGFueSkuaXNOdW1lcmljKSB7XHJcbiAgICAgIC8vIGluIGNhc2UgdGhlIGRlZmF1bHRWYWx1ZSBjb21lcyBpbiBhcyBhIHN0cmluZyAoIHdoaWNoIGl0IGRvZXMgaW4gRUY2KS5cclxuICAgICAgaWYgKHR5cGVvZiAodGhpcy5kZWZhdWx0VmFsdWUpID09PSBcInN0cmluZ1wiKSB7XHJcbiAgICAgICAgdGhpcy5kZWZhdWx0VmFsdWUgPSBwYXJzZUZsb2F0KHRoaXMuZGVmYXVsdFZhbHVlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmlzQ29tcGxleFByb3BlcnR5KSB7XHJcbiAgICAgIHRoaXMuaXNTY2FsYXIgPSB0aGlzLmlzU2NhbGFyID09IG51bGwgfHwgdGhpcy5pc1NjYWxhciA9PT0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgfVxyXG5cclxuICBzdGF0aWMgZ2V0UmF3VmFsdWVGcm9tU2VydmVyKHJhd0VudGl0eTogT2JqZWN0ICYgUmVjb3JkPHN0cmluZywgYW55PiwgZHA6IERhdGFQcm9wZXJ0eSkge1xyXG4gICAgaWYgKGRwLmlzVW5tYXBwZWQpIHtcclxuICAgICAgcmV0dXJuIHJhd0VudGl0eVtkcC5uYW1lT25TZXJ2ZXIgfHwgZHAubmFtZV07XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXQgdmFsID0gcmF3RW50aXR5W2RwLm5hbWVPblNlcnZlcl07XHJcbiAgICAgIHJldHVybiB2YWwgIT09IHVuZGVmaW5lZCA/IHZhbCA6IGRwLmRlZmF1bHRWYWx1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHN0YXRpYyBnZXRSYXdWYWx1ZUZyb21DbGllbnQocmF3RW50aXR5OiBPYmplY3QgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBkcDogRGF0YVByb3BlcnR5KSB7XHJcbiAgICBsZXQgdmFsID0gcmF3RW50aXR5W2RwLm5hbWVdO1xyXG4gICAgcmV0dXJuIHZhbCAhPT0gdW5kZWZpbmVkID8gdmFsIDogZHAuZGVmYXVsdFZhbHVlO1xyXG4gIH1cclxuXHJcbiAgcmVzb2x2ZVByb3BlcnR5KHByb3BOYW1lOiBzdHJpbmcpIHtcclxuICAgIGxldCByZXN1bHQgPSB0aGlzW3Byb3BOYW1lXTtcclxuICAgIGxldCBiYXNlUHJvcCA9IHRoaXMuYmFzZVByb3BlcnR5O1xyXG4gICAgd2hpbGUgKHJlc3VsdCA9PSB1bmRlZmluZWQgJiYgYmFzZVByb3AgIT0gbnVsbCkge1xyXG4gICAgICByZXN1bHQgPSBiYXNlUHJvcFtwcm9wTmFtZV07XHJcbiAgICAgIGJhc2VQcm9wID0gYmFzZVByb3AuYmFzZVByb3BlcnR5O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIGZvcm1hdE5hbWUoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5wYXJlbnRUeXBlLm5hbWUgKyBcIi0tXCIgKyB0aGlzLm5hbWU7XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgR2VuZXJhbCBwdXJwb3NlIHByb3BlcnR5IHNldCBtZXRob2RcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBwcm9wID0gbXlFbnRpdHlUeXBlLmdldFByb3BlcnR5KFwibXlQcm9wZXJ0eVwiKTtcclxuICA+ICAgICAgcHJvcC5zZXRQcm9wZXJ0aWVzKCB7XHJcbiAgPiAgICAgICAgICBjdXN0b206IHsgZm9vOiA3LCBiYXI6IFwidGVzdFwiIH1cclxuICA+ICAgICAgfSk7XHJcbiAgQHBhcmFtIGNvbmZpZyAtIEEgY29uZmlndXJhdGlvbiBvYmplY3QuXHJcbiAgKiovXHJcbiAgc2V0UHJvcGVydGllcyhjb25maWc6IHsgZGlzcGxheU5hbWU/OiBzdHJpbmcsIGN1c3RvbT86IE9iamVjdCB9KSB7XHJcbiAgICBhc3NlcnRDb25maWcoY29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcImRpc3BsYXlOYW1lXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImN1c3RvbVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gIH1cclxuXHJcbiAgZ2V0QWxsVmFsaWRhdG9ycygpIHtcclxuICAgIGxldCB2YWxpZGF0b3JzID0gdGhpcy52YWxpZGF0b3JzLnNsaWNlKDApO1xyXG4gICAgbGV0IGJhc2VQcm9wID0gdGhpcy5iYXNlUHJvcGVydHk7XHJcbiAgICB3aGlsZSAoYmFzZVByb3ApIHtcclxuICAgICAgdmFsaWRhdG9ycy5wdXNoLmFwcGx5KHZhbGlkYXRvcnMsIGJhc2VQcm9wLnZhbGlkYXRvcnMpO1xyXG4gICAgICBiYXNlUHJvcCA9IGJhc2VQcm9wLmJhc2VQcm9wZXJ0eTtcclxuICAgIH1cclxuICAgIHJldHVybiB2YWxpZGF0b3JzO1xyXG4gIH1cclxuXHJcbiAgdG9KU09OKCkge1xyXG4gICAgLy8gZG8gbm90IHNlcmlhbGl6ZSBkYXRhVHlwZXMgdGhhdCBhcmUgY29tcGxleFR5cGVzXHJcbiAgICByZXR1cm4gY29yZS50b0pzb24odGhpcywge1xyXG4gICAgICBuYW1lOiBudWxsLFxyXG4gICAgICBkYXRhVHlwZTogZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICAgIHJldHVybiAodiAmJiB2IGluc3RhbmNlb2YgRGF0YVR5cGUpID8gdi5uYW1lIDogdW5kZWZpbmVkO1xyXG4gICAgICB9LCAvLyBkbyBub3Qgc2VyaWFsaXplIGRhdGFUeXBlcyB0aGF0IGFyZSBjb21wbGV4VHlwZXNcclxuICAgICAgY29tcGxleFR5cGVOYW1lOiBudWxsLFxyXG4gICAgICBpc051bGxhYmxlOiB0cnVlLFxyXG4gICAgICBkZWZhdWx0VmFsdWU6IG51bGwsXHJcbiAgICAgIGlzUGFydE9mS2V5OiBmYWxzZSxcclxuICAgICAgaXNVbm1hcHBlZDogZmFsc2UsXHJcbiAgICAgIGlzU2V0dGFibGU6IHRydWUsXHJcbiAgICAgIGNvbmN1cnJlbmN5TW9kZTogbnVsbCxcclxuICAgICAgbWF4TGVuZ3RoOiBudWxsLFxyXG4gICAgICB2YWxpZGF0b3JzOiBudWxsLFxyXG4gICAgICBkaXNwbGF5TmFtZTogbnVsbCxcclxuICAgICAgZW51bVR5cGU6IG51bGwsXHJcbiAgICAgIHJhd1R5cGVOYW1lOiBudWxsLFxyXG4gICAgICBpc1NjYWxhcjogdHJ1ZSxcclxuICAgICAgY3VzdG9tOiBudWxsXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHN0YXRpYyBmcm9tSlNPTihqc29uOiBhbnkpIHtcclxuICAgIGpzb24uZGF0YVR5cGUgPSBEYXRhVHlwZS5mcm9tTmFtZShqc29uLmRhdGFUeXBlKTtcclxuICAgIC8vIFBhcnNlIGRlZmF1bHQgdmFsdWUgaW50byBjb3JyZWN0IGRhdGEgdHlwZS4gKGRhdGVUaW1lIGluc3RhbmNlcyByZXF1aXJlIGV4dHJhIHdvcmsgdG8gZGVzZXJpYWxpemUgcHJvcGVybHkuKVxyXG4gICAgaWYgKGpzb24uZGVmYXVsdFZhbHVlICYmIGpzb24uZGF0YVR5cGUgJiYganNvbi5kYXRhVHlwZS5wYXJzZSkge1xyXG4gICAgICBqc29uLmRlZmF1bHRWYWx1ZSA9IGpzb24uZGF0YVR5cGUucGFyc2UoanNvbi5kZWZhdWx0VmFsdWUsIHR5cGVvZiBqc29uLmRlZmF1bHRWYWx1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGpzb24udmFsaWRhdG9ycykge1xyXG4gICAgICBqc29uLnZhbGlkYXRvcnMgPSBqc29uLnZhbGlkYXRvcnMubWFwKFZhbGlkYXRvci5mcm9tSlNPTik7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG5ldyBEYXRhUHJvcGVydHkoanNvbik7XHJcbiAgfVxyXG5cclxufVxyXG5EYXRhUHJvcGVydHkucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIkRhdGFQcm9wZXJ0eVwiO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBOYXZpZ2F0aW9uUHJvcGVydHlDb25maWcge1xyXG4gIG5hbWU/OiBzdHJpbmc7XHJcbiAgbmFtZU9uU2VydmVyPzogc3RyaW5nO1xyXG4gIGVudGl0eVR5cGVOYW1lPzogc3RyaW5nO1xyXG4gIGlzU2NhbGFyPzogYm9vbGVhbjtcclxuICBhc3NvY2lhdGlvbk5hbWU/OiBzdHJpbmc7XHJcbiAgZm9yZWlnbktleU5hbWVzPzogc3RyaW5nW107XHJcbiAgZm9yZWlnbktleU5hbWVzT25TZXJ2ZXI/OiBzdHJpbmdbXTtcclxuICBpbnZGb3JlaWduS2V5TmFtZXM/OiBzdHJpbmdbXTtcclxuICBpbnZGb3JlaWduS2V5TmFtZXNPblNlcnZlcj86IHN0cmluZ1tdO1xyXG4gIHZhbGlkYXRvcnM/OiBWYWxpZGF0b3JbXTtcclxuICBkaXNwbGF5TmFtZT86IHN0cmluZztcclxuICBjdXN0b20/OiBhbnk7XHJcbn1cclxuXHJcbi8qKiAgIEEgTmF2aWdhdGlvblByb3BlcnR5IGRlc2NyaWJlcyB0aGUgbWV0YWRhdGEgZm9yIGEgc2luZ2xlIHByb3BlcnR5IG9mIGFuIFtbRW50aXR5VHlwZV1dIHRoYXQgcmV0dXJuIGluc3RhbmNlcyBvZiBvdGhlciBFbnRpdHlUeXBlcy5cclxuXHJcbkluc3RhbmNlcyBvZiB0aGUgTmF2aWdhdGlvblByb3BlcnR5IGNsYXNzIGFyZSBjb25zdHJ1Y3RlZCBhdXRvbWF0aWNhbGx5IGR1cmluZyBNZXRhZGF0YSByZXRyaWV2YWwuICAgSG93ZXZlciBpdCBpcyBhbHNvIHBvc3NpYmxlIHRvIGNvbnN0cnVjdCB0aGVtXHJcbmRpcmVjdGx5IHZpYSB0aGUgY29uc3RydWN0b3IuXHJcbioqL1xyXG5leHBvcnQgY2xhc3MgTmF2aWdhdGlvblByb3BlcnR5IHtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBkZWNsYXJlIF8kdHlwZU5hbWU6IHN0cmluZztcclxuICAvKiogSXMgdGhpcyBhIERhdGFQcm9wZXJ0eT8gLSBhbHdheXMgZmFsc2UgaGVyZSBcclxuICBBbGxvd3MgcG9seW1vcnBoaWMgdHJlYXRtZW50IG9mIERhdGFQcm9wZXJ0aWVzIGFuZCBOYXZpZ2F0aW9uUHJvcGVydGllcy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGlzRGF0YVByb3BlcnR5ID0gZmFsc2U7XHJcbiAgLyoqIElzIHRoaXMgYSBOYXZpZ2F0aW9uUHJvcGVydHk/IC0gYWx3YXlzIHRydWUgaGVyZVxyXG4gIEFsbG93cyBwb2x5bW9ycGhpYyB0cmVhdG1lbnQgb2YgRGF0YVByb3BlcnRpZXMgYW5kIE5hdmlnYXRpb25Qcm9wZXJ0aWVzLiBfX1JlYWQgT25seV9fICovXHJcbiAgaXNOYXZpZ2F0aW9uUHJvcGVydHkgPSB0cnVlO1xyXG5cclxuICBmb3JtYXROYW1lID0gRGF0YVByb3BlcnR5LnByb3RvdHlwZS5mb3JtYXROYW1lO1xyXG4gIGdldEFsbFZhbGlkYXRvcnMgPSBEYXRhUHJvcGVydHkucHJvdG90eXBlLmdldEFsbFZhbGlkYXRvcnM7XHJcbiAgcmVzb2x2ZVByb3BlcnR5ID0gRGF0YVByb3BlcnR5LnByb3RvdHlwZS5yZXNvbHZlUHJvcGVydHk7XHJcblxyXG4gIC8qKiBUaGUgW1tFbnRpdHlUeXBlXV0gcmV0dXJuZWQgYnkgdGhpcyBwcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRlY2xhcmUgZW50aXR5VHlwZTogRW50aXR5VHlwZTtcclxuICAvKiogVGhlIG5hbWUgb2YgdGhlIFtbRW50aXR5VHlwZV1dIHJldHVybmVkIGJ5IHRoaXMgcHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGVudGl0eVR5cGVOYW1lOiBzdHJpbmc7XHJcbiAgLyoqIFRoZSBbW0VudGl0eVR5cGVdXSB0aGF0IHRoaXMgcHJvcGVydHkgYmVsb25ncyB0by4gKCBzYW1lIGFzIGVudGl0eVR5cGUpLiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBwYXJlbnRUeXBlOiBFbnRpdHlUeXBlOyAvLyA/PyBzYW1lIGFzIGVudGl0eVR5cGVcclxuICAvKiogVGhlIFtbRW50aXR5VHlwZV1dIHRoYXQgdGhpcyBwcm9wZXJ0eSBiZWxvbmdzIHRvLiAoIHNhbWUgYXMgZW50aXR5VHlwZSkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIHBhcmVudEVudGl0eVR5cGU6IEVudGl0eVR5cGU7IC8vID8/IHNhbWUgYXMgYWJvdmVcclxuICAvKiogUHJvcGVydHkgb24gdGhlIGJhc2UgdHlwZSB0aGF0IHRoaXMgcHJvcGVydHkgaXMgaW5oZXJpdGVkIGZyb20uIFdpbGwgYmUgbnVsbCBpZiB0aGUgcHJvcGVydHkgaXMgbm90IG9uIHRoZSBiYXNlIHR5cGUuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGJhc2VQcm9wZXJ0eT86IE5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuICAvKiogVGhlIGludmVyc2Ugb2YgdGhpcyBOYXZpZ2F0aW9uUHJvcGVydHkuICBUaGUgTmF2aWdhdGlvblByb3BlcnR5IHRoYXQgcmVwcmVzZW50cyBhIG5hdmlnYXRpb24gaW4gdGhlIG9wcG9zaXRlIGRpcmVjdGlvblxyXG4gIHRvIHRoaXMgTmF2aWdhdGlvblByb3BlcnR5LiBNYXkgYmUgdW5kZWZpbmVkIGZvciBhIHVuZGlyZWN0aW9uYWwgTmF2aWdhdGlvblByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBwcml2YXRlIF9pbnZlcnNlPzogTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gIC8qKiBUaGUgbmFtZSBvZiB0aGlzIHByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBuYW1lOiBzdHJpbmc7XHJcbiAgLyoqIFRoZSBuYW1lIG9mIHRoaXMgcHJvcGVydHkgb24gdGhlIHNlcnZlci4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRlY2xhcmUgbmFtZU9uU2VydmVyOiBzdHJpbmc7XHJcbiAgLyoqXHJcbiAgV2hldGhlciB0aGlzIHByb3BlcnR5IHJldHVybnMgYSBzaW5nbGUgZW50aXR5IGFzIG9wcG9zZWQgdG8gIGFuIGFycmF5IG9mIGVudGl0aWVzLiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBpc1NjYWxhcjogYm9vbGVhbjtcclxuICAvKiogVGhlIG5hbWUgb2YgdGhlIGFzc29jaWF0aW9uIHRvIHdoaWNoIHRoYXQgdGhpcyBwcm9wZXJ0eSBiZWxvbmdzLiAgVGhpcyBhc3NvY2lhdGlvbk5hbWUgd2lsbCBiZSBzaGFyZWQgd2l0aCB0aGlzXHJcbiAgcHJvcGVydGllcyAnaW52ZXJzZScuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGFzc29jaWF0aW9uTmFtZTogc3RyaW5nO1xyXG4gIC8qKiBUaGUgbmFtZXMgb2YgdGhlIGZvcmVpZ24ga2V5IERhdGFQcm9wZXJ0aWVzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIE5hdmlnYXRpb25Qcm9wZXJ0eS4gVGhlcmUgd2lsbCB1c3VhbGx5IG9ubHkgYmUgYSBzaW5nbGUgRGF0YVByb3BlcnR5IGFzc29jaWF0ZWRcclxuICB3aXRoIGEgTmF2aWdhdGlvbiBwcm9wZXJ0eSBleGNlcHQgaW4gdGhlIGNhc2Ugb2YgZW50aXRpZXMgd2l0aCBtdWx0aXBhcnQga2V5cy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRlY2xhcmUgZm9yZWlnbktleU5hbWVzOiBzdHJpbmdbXTtcclxuICAvKiogVGhlIHNlcnZlciBzaWRlIG5hbWVzIG9mIHRoZSBmb3JlaWduIGtleSBEYXRhUHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyBOYXZpZ2F0aW9uUHJvcGVydHkuIFRoZXJlIHdpbGwgdXN1YWxseSBvbmx5IGJlIGEgc2luZ2xlIERhdGFQcm9wZXJ0eSBhc3NvY2lhdGVkXHJcbiAgd2l0aCBhIE5hdmlnYXRpb24gcHJvcGVydHkgZXhjZXB0IGluIHRoZSBjYXNlIG9mIGVudGl0aWVzIHdpdGggbXVsdGlwYXJ0IGtleXMuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGZvcmVpZ25LZXlOYW1lc09uU2VydmVyOiBzdHJpbmdbXTtcclxuICAvKiogVGhlIG5hbWVzIG9mIHRoZSBmb3JlaWduIGtleSBEYXRhUHJvcGVydGllcyBhdCB0aGUgb3RoZXIgZW5kIG9mIHRoZSByZWxhdGlvbnNoaXAuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkZWNsYXJlIGludkZvcmVpZ25LZXlOYW1lczogc3RyaW5nW107XHJcbiAgLyoqIFRoZSBzZXJ2ZXIgc2lkZSBuYW1lcyBvZiB0aGUgZm9yZWlnbiBrZXkgRGF0YVByb3BlcnRpZXMgYXQgdGhlIG90aGVyIGVuZCBvZiB0aGUgcmVsYXRpb25zaGlwLiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBpbnZGb3JlaWduS2V5TmFtZXNPblNlcnZlcjogc3RyaW5nW107XHJcbiAgLyoqIFRoZSAnZm9yZWlnbiBrZXknIERhdGFQcm9wZXJ0aWVzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIE5hdmlnYXRpb25Qcm9wZXJ0eS4gVGhlcmUgd2lsbCB1c3VhbGx5IG9ubHkgYmUgYSBzaW5nbGUgRGF0YVByb3BlcnR5IGFzc29jaWF0ZWRcclxuICB3aXRoIGEgTmF2aWdhdGlvbiBwcm9wZXJ0eSBleGNlcHQgaW4gdGhlIGNhc2Ugb2YgZW50aXRpZXMgd2l0aCBtdWx0aXBhcnQga2V5cy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRlY2xhcmUgcmVsYXRlZERhdGFQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogVGhlIFtbVmFsaWRhdG9yXV0gaW5zdGFuY2VzIHRoYXQgYXJlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHByb3BlcnR5LiBWYWxpZGF0b3JzIGNhbiBiZSBhZGRlZCBhbmRcclxuICByZW1vdmVkIGZyb20gdGhpcyBjb2xsZWN0aW9uLiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSB2YWxpZGF0b3JzOiBWYWxpZGF0b3JbXTtcclxuICAvKiogVGhlIGRpc3BsYXkgbmFtZSBvZiB0aGlzIHByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVjbGFyZSBkaXNwbGF5TmFtZTogc3RyaW5nO1xyXG4gIGRlY2xhcmUgaXNVbm1hcHBlZDogYm9vbGVhbjtcclxuICAvKiogQSBmcmVlIGZvcm0gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gZGVmaW5lIGFueSBjdXN0b20gbWV0YWRhdGEgZm9yIHRoaXMgTmF2aWdhdGlvblByb3BlcnR5LiAgICoqL1xyXG4gIGRlY2xhcmUgY3VzdG9tOiBhbnk7XHJcblxyXG4gIC8qKiBOYXZpZ2F0aW9uUHJvcGVydHkgY29uc3RydWN0b3JcclxuICA+ICAgICAgbGV0IGhvbWVBZGRyZXNzUHJvcCA9IG5ldyBOYXZpZ2F0aW9uUHJvcGVydHkoIHtcclxuICA+ICAgICAgICAgIG5hbWU6IFwiaG9tZUFkZHJlc3NcIixcclxuICA+ICAgICAgICAgIGVudGl0eVR5cGVOYW1lOiBcIkFkZHJlc3M6I215TmFtZXNwYWNlXCIsXHJcbiAgPiAgICAgICAgICBpc1NjYWxhcjogdHJ1ZSxcclxuICA+ICAgICAgICAgIGFzc29jaWF0aW9uTmFtZTogXCJhZGRyZXNzX3BlcnNvblwiLFxyXG4gID4gICAgICAgICAgZm9yZWlnbktleU5hbWVzOiBbXCJob21lQWRkcmVzc0lkXCJdXHJcbiAgPiAgICAgIH0pO1xyXG4gID4gICAgICBsZXQgaG9tZUFkZHJlc3NJZFByb3AgPSBuZXcgRGF0YVByb3BlcnR5KCB7XHJcbiAgPiAgICAgICAgICBuYW1lOiBcImhvbWVBZGRyZXNzSWRcIlxyXG4gID4gICAgICAgICAgZGF0YVR5cGU6IERhdGFUeXBlLkludGVnZXJcclxuICA+ICAgICAgfSk7XHJcbiAgPiAgICAgIC8vIGFzc3VtaW5nIHBlcnNvbkVudGl0eVR5cGUgaXMgYSBuZXdseSBjb25zdHJ1Y3RlZCBFbnRpdHlUeXBlXHJcbiAgPiAgICAgIHBlcnNvbkVudGl0eVR5cGUuYWRkUHJvcGVydHkoaG9tZUFkZHJlc3NQcm9wKTtcclxuICA+ICAgICAgcGVyc29uRW50aXR5VHlwZS5hZGRQcm9wZXJ0eShob21lQWRkcmVzc0lkUHJvcCk7XHJcbiAgQHBhcmFtIGNvbmZpZyAtIEEgY29uZmlndXJhdGlvbiBvYmplY3QuXHJcbiAgKiovXHJcbiAgY29uc3RydWN0b3IoY29uZmlnOiBOYXZpZ2F0aW9uUHJvcGVydHlDb25maWcpIHtcclxuICAgIGFzc2VydENvbmZpZyhjb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwibmFtZVwiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm5hbWVPblNlcnZlclwiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImVudGl0eVR5cGVOYW1lXCIpLmlzU3RyaW5nKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJpc1NjYWxhclwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQodHJ1ZSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJhc3NvY2lhdGlvbk5hbWVcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJmb3JlaWduS2V5TmFtZXNcIikuaXNBcnJheSgpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KFtdKVxyXG4gICAgICAud2hlcmVQYXJhbShcImZvcmVpZ25LZXlOYW1lc09uU2VydmVyXCIpLmlzQXJyYXkoKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChbXSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJpbnZGb3JlaWduS2V5TmFtZXNcIikuaXNBcnJheSgpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KFtdKVxyXG4gICAgICAud2hlcmVQYXJhbShcImludkZvcmVpZ25LZXlOYW1lc09uU2VydmVyXCIpLmlzQXJyYXkoKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChbXSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJ2YWxpZGF0b3JzXCIpLmlzSW5zdGFuY2VPZihWYWxpZGF0b3IpLmlzQXJyYXkoKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoW10pXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiZGlzcGxheU5hbWVcIikuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiY3VzdG9tXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAuYXBwbHlBbGwodGhpcyk7XHJcbiAgICBsZXQgaGFzTmFtZSA9ICEhKHRoaXMubmFtZSB8fCB0aGlzLm5hbWVPblNlcnZlcik7XHJcblxyXG4gICAgaWYgKCFoYXNOYW1lKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkEgTmF2aWdhdGlvbiBwcm9wZXJ0eSBtdXN0IGJlIGluc3RhbnRpYXRlZCB3aXRoIGVpdGhlciBhICduYW1lJyBvciBhICduYW1lT25TZXJ2ZXInIHByb3BlcnR5XCIpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgR2VuZXJhbCBwdXJwb3NlIHByb3BlcnR5IHNldCBtZXRob2RcclxuICA+ICAgICAgLy8gYXNzdW1lIG15RW50aXR5VHlwZSBpcyBhbiBFbnRpdHlUeXBlXHJcbiAgPiAgICAgIGxldCBwcm9wID0gbXlFbnRpdHlUeXBlLmdldFByb3BlcnR5KFwibXlQcm9wZXJ0eVwiKTtcclxuICA+ICAgICAgcHJvcC5zZXRQcm9wZXJ0aWVzKCB7XHJcbiAgPiAgICAgICAgICBjdXN0b206IHsgZm9vOiA3LCBiYXI6IFwidGVzdFwiIH1cclxuICA+ICAgICAgfSk7XHJcbiAgQHBhcmFtIGNvbmZpZyAtIEEgY29uZmlnIG9iamVjdFxyXG4gICoqL1xyXG4gIC8vIFRPRE86IGNyZWF0ZSBhbiBpbnRlcmZhY2UgZm9yIHRoaXMuXHJcbiAgc2V0UHJvcGVydGllcyhjb25maWc6IHtcclxuICAgIGRpc3BsYXlOYW1lPzogc3RyaW5nLFxyXG4gICAgZm9yZWlnbktleU5hbWVzPzogc3RyaW5nW10sXHJcbiAgICBpbnZGb3JlaWduS2V5TmFtZXM/OiBzdHJpbmdbXSxcclxuICAgIGludmVyc2U/OiBOYXZpZ2F0aW9uUHJvcGVydHkgfCBzdHJpbmcsXHJcbiAgICBjdXN0b20/OiBhbnlcclxuICB9KSB7XHJcbiAgICBpZiAoIXRoaXMucGFyZW50VHlwZSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgY2FsbCBOYXZpZ2F0aW9uUHJvcGVydHkuc2V0UHJvcGVydGllcyB1bnRpbCB0aGUgcGFyZW50IEVudGl0eVR5cGUgb2YgdGhlIE5hdmlnYXRpb25Qcm9wZXJ0eSBoYXMgYmVlbiBzZXQuXCIpO1xyXG4gICAgfVxyXG4gICAgbGV0IGludmVyc2UgPSBjb25maWcuaW52ZXJzZTtcclxuICAgIGlmIChpbnZlcnNlKSBkZWxldGUgY29uZmlnLmludmVyc2U7XHJcbiAgICBhc3NlcnRDb25maWcoY29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcImRpc3BsYXlOYW1lXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImZvcmVpZ25LZXlOYW1lc1wiKS5pc0FycmF5KCkuaXNTdHJpbmcoKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoW10pXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaW52Rm9yZWlnbktleU5hbWVzXCIpLmlzQXJyYXkoKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChbXSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJjdXN0b21cIikuaXNPcHRpb25hbCgpXHJcbiAgICAgIC5hcHBseUFsbCh0aGlzKTtcclxuICAgIHRoaXMucGFyZW50VHlwZS5fdXBkYXRlTmFtZXModGhpcyk7XHJcblxyXG4gICAgdGhpcy5fcmVzb2x2ZU5wKCk7XHJcbiAgICBpZiAoaW52ZXJzZSkge1xyXG4gICAgICB0aGlzLnNldEludmVyc2UoaW52ZXJzZSk7XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgLyoqIFRoZSBpbnZlcnNlIG9mIHRoaXMgTmF2aWdhdGlvblByb3BlcnR5LiAgVGhlIE5hdmlnYXRpb25Qcm9wZXJ0eSB0aGF0IHJlcHJlc2VudHMgYSBuYXZpZ2F0aW9uIGluIHRoZSBvcHBvc2l0ZSBkaXJlY3Rpb25cclxuICB0byB0aGlzIE5hdmlnYXRpb25Qcm9wZXJ0eS4gTWF5IGJlIHVuZGVmaW5lZCBmb3IgYSB1bmRpcmVjdGlvbmFsIE5hdmlnYXRpb25Qcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGdldCBpbnZlcnNlKCk6IE5hdmlnYXRpb25Qcm9wZXJ0eSB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy5nZXRJbnZlcnNlKCk7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBnZXRJbnZlcnNlKCk6IE5hdmlnYXRpb25Qcm9wZXJ0eSB8IHVuZGVmaW5lZCB7XHJcbiAgICBsZXQgbnA6IE5hdmlnYXRpb25Qcm9wZXJ0eSA9IHRoaXM7XHJcbiAgICB3aGlsZSAoIW5wLl9pbnZlcnNlICYmIG5wLmJhc2VQcm9wZXJ0eSkge1xyXG4gICAgICBucCA9IG5wLmJhc2VQcm9wZXJ0eTtcclxuICAgIH1cclxuICAgIHJldHVybiBucC5faW52ZXJzZTtcclxuICB9XHJcblxyXG4gIHNldEludmVyc2UoaW52ZXJzZU5wOiBOYXZpZ2F0aW9uUHJvcGVydHkgfCBzdHJpbmcpIHtcclxuICAgIC8vIGxldCBpbnZOcDogTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gICAgbGV0IGludk5wID0gKGludmVyc2VOcCBpbnN0YW5jZW9mIE5hdmlnYXRpb25Qcm9wZXJ0eSkgPyBpbnZlcnNlTnAgOiB0aGlzLmVudGl0eVR5cGUuZ2V0TmF2aWdhdGlvblByb3BlcnR5KGludmVyc2VOcCk7XHJcblxyXG4gICAgaWYgKCFpbnZOcCkge1xyXG4gICAgICB0aHJvdyB0aHJvd1NldEludmVyc2VFcnJvcih0aGlzLCBcIlVuYWJsZSB0byBmaW5kIGludmVyc2UgcHJvcGVydHk6IFwiICsgaW52ZXJzZU5wKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5faW52ZXJzZSB8fCBpbnZOcC5faW52ZXJzZSkge1xyXG4gICAgICB0aHJvd1NldEludmVyc2VFcnJvcih0aGlzLCBcIkl0IGhhcyBhbHJlYWR5IGJlZW4gc2V0IG9uIG9uZSBzaWRlIG9yIHRoZSBvdGhlci5cIik7XHJcbiAgICB9XHJcbiAgICBpZiAoaW52TnAuZW50aXR5VHlwZSAhPT0gdGhpcy5wYXJlbnRUeXBlKSB7XHJcbiAgICAgIHRocm93U2V0SW52ZXJzZUVycm9yKHRoaXMsIGludk5wLmZvcm1hdE5hbWUgKyBcIiBpcyBub3QgYSB2YWxpZCBpbnZlcnNlIHByb3BlcnR5IGZvciB0aGlzLlwiKTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmFzc29jaWF0aW9uTmFtZSkge1xyXG4gICAgICBpbnZOcC5hc3NvY2lhdGlvbk5hbWUgPSB0aGlzLmFzc29jaWF0aW9uTmFtZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICghaW52TnAuYXNzb2NpYXRpb25OYW1lKSB7XHJcbiAgICAgICAgaW52TnAuYXNzb2NpYXRpb25OYW1lID0gdGhpcy5mb3JtYXROYW1lKCkgKyBcIl9cIiArIGludk5wLmZvcm1hdE5hbWUoKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmFzc29jaWF0aW9uTmFtZSA9IGludk5wLmFzc29jaWF0aW9uTmFtZTtcclxuICAgIH1cclxuICAgIHRoaXMuX3Jlc29sdmVOcCgpO1xyXG4gICAgaW52TnAuX3Jlc29sdmVOcCgpO1xyXG4gIH1cclxuXHJcbiAgLy8gLy8gSW4gcHJvZ3Jlc3MgLSB3aWxsIGJlIHVzZWQgZm9yIG1hbnVhbCBtZXRhZGF0YSBjb25maWdcclxuICAvLyBjcmVhdGVJbnZlcnNlKGNvbmZpZzogYW55KSB7XHJcblxyXG4gIC8vICAgaWYgKCF0aGlzLmVudGl0eVR5cGUpIHtcclxuICAvLyAgICAgdGhyb3dDcmVhdGVJbnZlcnNlRXJyb3IodGhpcywgXCJoYXMgbm90IHlldCBiZWVuIGRlZmluZWQuXCIpO1xyXG4gIC8vICAgfVxyXG4gIC8vICAgaWYgKHRoaXMuZW50aXR5VHlwZS5pc0Zyb3plbikge1xyXG4gIC8vICAgICB0aHJvd0NyZWF0ZUludmVyc2VFcnJvcih0aGlzLCBcImlzIGZyb3plbi5cIik7XHJcbiAgLy8gICB9XHJcbiAgLy8gICBsZXQgbWV0YWRhdGFTdG9yZSA9IHRoaXMuZW50aXR5VHlwZS5tZXRhZGF0YVN0b3JlO1xyXG4gIC8vICAgaWYgKG1ldGFkYXRhU3RvcmUgPT0gbnVsbCkge1xyXG4gIC8vICAgICB0aHJvd0NyZWF0ZUludmVyc2VFcnJvcih0aGlzLCBcImhhcyBub3QgeWV0IGJlZW4gYWRkZWQgdG8gdGhlIG1ldGFkYXRhU3RvcmUuXCIpO1xyXG4gIC8vICAgfVxyXG5cclxuICAvLyAgIGNvbmZpZy5lbnRpdHlUeXBlTmFtZSA9IHRoaXMucGFyZW50RW50aXR5VHlwZS5uYW1lO1xyXG4gIC8vICAgY29uZmlnLmFzc29jaWF0aW9uTmFtZSA9IHRoaXMuYXNzb2NpYXRpb25OYW1lO1xyXG4gIC8vICAgbGV0IGludk5wID0gbmV3IE5hdmlnYXRpb25Qcm9wZXJ0eShjb25maWcpO1xyXG4gIC8vICAgdGhpcy5wYXJlbnRFbnRpdHlUeXBlLmFkZE5hdmlnYXRpb25Qcm9wZXJ0eShpbnZOcCk7XHJcbiAgLy8gICByZXR1cm4gaW52TnA7XHJcbiAgLy8gfTtcclxuXHJcblxyXG5cclxuICB0b0pTT04oKSB7XHJcbiAgICByZXR1cm4gY29yZS50b0pzb24odGhpcywge1xyXG4gICAgICBuYW1lOiBudWxsLFxyXG4gICAgICBlbnRpdHlUeXBlTmFtZTogbnVsbCxcclxuICAgICAgaXNTY2FsYXI6IG51bGwsXHJcbiAgICAgIGFzc29jaWF0aW9uTmFtZTogbnVsbCxcclxuICAgICAgdmFsaWRhdG9yczogbnVsbCxcclxuICAgICAgZGlzcGxheU5hbWU6IG51bGwsXHJcbiAgICAgIGZvcmVpZ25LZXlOYW1lczogbnVsbCxcclxuICAgICAgaW52Rm9yZWlnbktleU5hbWVzOiBudWxsLFxyXG4gICAgICBjdXN0b206IG51bGxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc3RhdGljIGZyb21KU09OKGpzb246IGFueSkge1xyXG4gICAgaWYgKGpzb24udmFsaWRhdG9ycykge1xyXG4gICAgICBqc29uLnZhbGlkYXRvcnMgPSBqc29uLnZhbGlkYXRvcnMubWFwKFZhbGlkYXRvci5mcm9tSlNPTik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbmV3IE5hdmlnYXRpb25Qcm9wZXJ0eShqc29uKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9yZXNvbHZlTnAoKSB7XHJcbiAgICBsZXQgbnAgPSB0aGlzO1xyXG4gICAgbGV0IGVudGl0eVR5cGUgPSBucC5lbnRpdHlUeXBlO1xyXG4gICAgbGV0IGludk5wID0gY29yZS5hcnJheUZpcnN0KGVudGl0eVR5cGUubmF2aWdhdGlvblByb3BlcnRpZXMsIChhbHROcCkgPT4ge1xyXG4gICAgICAvLyBDYW4ndCBkbyB0aGlzIGJlY2F1c2Ugb2YgcG9zc2liaWxpdHkgb2YgY29tcGFyaW5nIGEgYmFzZSBjbGFzcyBucCB3aXRoIGEgc3ViY2xhc3MgYWx0TnAuXHJcbiAgICAgIC8vIHJldHVybiBhbHROcC5hc3NvY2lhdGlvbk5hbWUgPT09IG5wLmFzc29jaWF0aW9uTmFtZVxyXG4gICAgICAvLyAgICAmJiBhbHROcCAhPT0gbnA7XHJcbiAgICAgIC8vIFNvIHVzZSB0aGlzIGluc3RlYWQuXHJcbiAgICAgIHJldHVybiBhbHROcC5hc3NvY2lhdGlvbk5hbWUgPT09IG5wLmFzc29jaWF0aW9uTmFtZSAmJlxyXG4gICAgICAgIChhbHROcC5uYW1lICE9PSBucC5uYW1lIHx8IGFsdE5wLmVudGl0eVR5cGVOYW1lICE9PSBucC5lbnRpdHlUeXBlTmFtZSk7XHJcbiAgICB9KTtcclxuICAgIG5wLl9pbnZlcnNlID0gaW52TnAgfHwgdW5kZWZpbmVkO1xyXG4gICAgLy9pZiAoaW52TnAgJiYgaW52TnAuaW52ZXJzZSA9PSBudWxsKSB7XHJcbiAgICAvLyAgICBpbnZOcC5fcmVzb2x2ZU5wKCk7XHJcbiAgICAvL31cclxuICAgIGlmICghaW52TnApIHtcclxuICAgICAgLy8gdW5pZGlyZWN0aW9uYWwgMS1uIHJlbGF0aW9uc2hpcFxyXG4gICAgICBucC5pbnZGb3JlaWduS2V5TmFtZXMuZm9yRWFjaChmdW5jdGlvbiAoaW52RmtOYW1lKSB7XHJcbiAgICAgICAgbGV0IGZrUHJvcCA9IGVudGl0eVR5cGUuZ2V0RGF0YVByb3BlcnR5KGludkZrTmFtZSk7XHJcbiAgICAgICAgaWYgKGZrUHJvcCA9PSBudWxsKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFbnRpdHlUeXBlICdcIiArIG5wLmVudGl0eVR5cGVOYW1lICsgXCInIGhhcyBubyBmb3JlaWduIGtleSBtYXRjaGluZyAnXCIgKyBpbnZGa05hbWUgKyBcIidcIik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGxldCBpbnZFbnRpdHlUeXBlID0gbnAucGFyZW50VHlwZTtcclxuICAgICAgICBpbnZOcCA9IGNvcmUuYXJyYXlGaXJzdChpbnZFbnRpdHlUeXBlLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLCAobnAyKSA9PiB7XHJcbiAgICAgICAgICByZXR1cm4gbnAyLmludkZvcmVpZ25LZXlOYW1lcyAmJiBucDIuaW52Rm9yZWlnbktleU5hbWVzLmluZGV4T2YoZmtQcm9wIS5uYW1lKSA+PSAwICYmIG5wMi5lbnRpdHlUeXBlID09PSBma1Byb3AhLnBhcmVudFR5cGU7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgZmtQcm9wLmludmVyc2VOYXZpZ2F0aW9uUHJvcGVydHkgPSBpbnZOcCB8fCB1bmRlZmluZWQ7XHJcbiAgICAgICAgY29yZS5hcnJheUFkZEl0ZW1VbmlxdWUoZW50aXR5VHlwZS5mb3JlaWduS2V5UHJvcGVydGllcywgZmtQcm9wKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmVzb2x2ZVJlbGF0ZWQobnApO1xyXG4gIH1cclxuXHJcbn1cclxuTmF2aWdhdGlvblByb3BlcnR5LnByb3RvdHlwZS5fJHR5cGVOYW1lID0gXCJOYXZpZ2F0aW9uUHJvcGVydHlcIjtcclxuXHJcbmZ1bmN0aW9uIHRocm93U2V0SW52ZXJzZUVycm9yKG5wOiBOYXZpZ2F0aW9uUHJvcGVydHksIG1lc3NhZ2U6IHN0cmluZykge1xyXG4gIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBzZXQgdGhlIGludmVyc2UgcHJvcGVydHkgZm9yOiBcIiArIG5wLmZvcm1hdE5hbWUoKSArIFwiLiBcIiArIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vLyBOb3QgY3VycmVudCB1c2VkLlxyXG4vLyBmdW5jdGlvbiB0aHJvd0NyZWF0ZUludmVyc2VFcnJvcihucDogTmF2aWdhdGlvblByb3BlcnR5LCBtZXNzYWdlOiBzdHJpbmcpIHtcclxuLy8gICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgY3JlYXRlIGludmVyc2UgZm9yOiBcIiArIG5wLmZvcm1hdE5hbWUoKSArIFwiLiBUaGUgZW50aXR5VHlwZSBmb3IgdGhpcyBuYXZpZ2F0aW9uIHByb3BlcnR5IFwiICsgbWVzc2FnZSk7XHJcbi8vIH1cclxuXHJcbi8vIHNldHMgbmF2aWdhdGlvbiBwcm9wZXJ0eTogcmVsYXRlZERhdGFQcm9wZXJ0aWVzIGFuZCBkYXRhUHJvcGVydHk6IHJlbGF0ZWROYXZpZ2F0aW9uUHJvcGVydHlcclxuZnVuY3Rpb24gcmVzb2x2ZVJlbGF0ZWQobnA6IE5hdmlnYXRpb25Qcm9wZXJ0eSkge1xyXG5cclxuICBsZXQgZmtOYW1lcyA9IG5wLmZvcmVpZ25LZXlOYW1lcztcclxuICBpZiAoZmtOYW1lcy5sZW5ndGggPT09IDApIHJldHVybjtcclxuXHJcbiAgbGV0IHBhcmVudEVudGl0eVR5cGUgPSBucC5wYXJlbnRUeXBlO1xyXG4gIGxldCBma1Byb3BzID0gZmtOYW1lcy5tYXAoZnVuY3Rpb24gKGZrTmFtZSkge1xyXG4gICAgcmV0dXJuIHBhcmVudEVudGl0eVR5cGUuZ2V0RGF0YVByb3BlcnR5KGZrTmFtZSk7XHJcbiAgfSk7XHJcbiAgbGV0IGZrUHJvcENvbGxlY3Rpb24gPSBwYXJlbnRFbnRpdHlUeXBlLmZvcmVpZ25LZXlQcm9wZXJ0aWVzO1xyXG5cclxuICBma1Byb3BzLmZvckVhY2goKGRwOiBEYXRhUHJvcGVydHkpID0+IHtcclxuICAgIGNvcmUuYXJyYXlBZGRJdGVtVW5pcXVlKGZrUHJvcENvbGxlY3Rpb24sIGRwKTtcclxuICAgIGRwLnJlbGF0ZWROYXZpZ2F0aW9uUHJvcGVydHkgPSBucDtcclxuICAgIC8vIG5vdyB1cGRhdGUgdGhlIGludmVyc2VcclxuICAgIGNvcmUuYXJyYXlBZGRJdGVtVW5pcXVlKG5wLmVudGl0eVR5cGUuaW52ZXJzZUZvcmVpZ25LZXlQcm9wZXJ0aWVzLCBkcCk7XHJcbiAgICBpZiAobnAucmVsYXRlZERhdGFQcm9wZXJ0aWVzKSB7XHJcbiAgICAgIGNvcmUuYXJyYXlBZGRJdGVtVW5pcXVlKG5wLnJlbGF0ZWREYXRhUHJvcGVydGllcywgZHApO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgbnAucmVsYXRlZERhdGFQcm9wZXJ0aWVzID0gW2RwXTtcclxuICAgIH1cclxuICB9KTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG5BdXRvR2VuZXJhdGVkS2V5VHlwZSBpcyBhbiAnRW51bScgY29udGFpbmluZyBhbGwgb2YgdGhlIHZhbGlkIHN0YXRlcyBmb3IgYW4gYXV0b21hdGljYWxseSBnZW5lcmF0ZWQga2V5LlxyXG4qKi9cclxuZXhwb3J0IGNsYXNzIEF1dG9HZW5lcmF0ZWRLZXlUeXBlIGV4dGVuZHMgQnJlZXplRW51bSB7XHJcblxyXG4gIC8qKlxyXG4gIFRoaXMgZW50aXR5IGRvZXMgbm90IGhhdmUgYW4gYXV0b2dlbmVyYXRlZCBrZXkuXHJcbiAgVGhlIGNsaWVudCBtdXN0IHNldCB0aGUga2V5IGJlZm9yZSBhZGRpbmcgdGhlIGVudGl0eSB0byB0aGUgRW50aXR5TWFuYWdlclxyXG4gICoqL1xyXG4gIHN0YXRpYyBOb25lID0gbmV3IEF1dG9HZW5lcmF0ZWRLZXlUeXBlKCk7XHJcbiAgLyoqIFxyXG4gIFRoaXMgZW50aXR5J3Mga2V5IGlzIGFuIElkZW50aXR5IGNvbHVtbiBhbmQgaXMgc2V0IGJ5IHRoZSBiYWNrZW5kIGRhdGFiYXNlLlxyXG4gIEtleXMgZm9yIG5ldyBlbnRpdGllcyB3aWxsIGJlIHRlbXBvcmFyeSB1bnRpbCB0aGUgZW50aXRpZXMgYXJlIHNhdmVkIGF0IHdoaWNoIHBvaW50IHRoZSBrZXlzIHdpbGxcclxuICBiZSBjb252ZXJ0ZWQgdG8gdGhlaXIgJ3JlYWwnIHZlcnNpb25zLlxyXG4gICoqL1xyXG4gIHN0YXRpYyBJZGVudGl0eSA9IG5ldyBBdXRvR2VuZXJhdGVkS2V5VHlwZSgpO1xyXG4gIC8qKlxyXG4gIFRoaXMgZW50aXR5J3Mga2V5IGlzIGdlbmVyYXRlZCBieSBhIEtleUdlbmVyYXRvciBhbmQgaXMgc2V0IGJ5IHRoZSBiYWNrZW5kIGRhdGFiYXNlLlxyXG4gIEtleXMgZm9yIG5ldyBlbnRpdGllcyB3aWxsIGJlIHRlbXBvcmFyeSB1bnRpbCB0aGUgZW50aXRpZXMgYXJlIHNhdmVkIGF0IHdoaWNoIHBvaW50IHRoZSBrZXlzIHdpbGxcclxuICBiZSBjb252ZXJ0ZWQgdG8gdGhlaXIgJ3JlYWwnIHZlcnNpb25zLlxyXG4gICoqL1xyXG4gIHN0YXRpYyBLZXlHZW5lcmF0b3IgPSBuZXcgQXV0b0dlbmVyYXRlZEtleVR5cGUoKTtcclxuXHJcbn1cclxuQXV0b0dlbmVyYXRlZEtleVR5cGUucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIkF1dG9HZW5lcmF0ZWRLZXlUeXBlXCI7XHJcbkVycm9yWyd4J10gPSBBdXRvR2VuZXJhdGVkS2V5VHlwZS5yZXNvbHZlU3ltYm9scygpO1xyXG5cclxuXHJcbi8vIG1peGluIG1ldGhvZHNcclxuLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbmRlY2xhcmUgbW9kdWxlIFwiLi9hc3NlcnQtcGFyYW1cIiB7XHJcbiAgaW50ZXJmYWNlIFBhcmFtIHtcclxuICAgIGlzRW50aXR5KCk6IFBhcmFtO1xyXG4gICAgaXNFbnRpdHlQcm9wZXJ0eSgpOiBQYXJhbTtcclxuICB9XHJcbn1cclxuXHJcbmxldCBwcm90byA9IFBhcmFtLnByb3RvdHlwZTtcclxuXHJcbi8vICd0aGlzJyBiZWxvdyBpcyBUUyBhbm5vdGF0aW9uIFxyXG5wcm90by5pc0VudGl0eSA9IGZ1bmN0aW9uICh0aGlzOiBQYXJhbSkge1xyXG4gIHJldHVybiB0aGlzLl9hZGRDb250ZXh0KHtcclxuICAgIGZuOiBpc0VudGl0eSxcclxuICAgIG1zZzogXCIgbXVzdCBiZSBhbiBlbnRpdHlcIlxyXG4gIH0pO1xyXG59O1xyXG5cclxuZnVuY3Rpb24gaXNFbnRpdHkoY29udGV4dDogYW55LCB2OiBhbnkpIHtcclxuICBpZiAodiA9PSBudWxsKSByZXR1cm4gZmFsc2U7XHJcbiAgcmV0dXJuICh2LmVudGl0eVR5cGUgIT09IHVuZGVmaW5lZCk7XHJcbn1cclxuXHJcbnByb3RvLmlzRW50aXR5UHJvcGVydHkgPSBmdW5jdGlvbiAodGhpczogUGFyYW0pIHtcclxuICByZXR1cm4gdGhpcy5fYWRkQ29udGV4dCh7XHJcbiAgICBmbjogaXNFbnRpdHlQcm9wZXJ0eSxcclxuICAgIG1zZzogXCIgbXVzdCBiZSBlaXRoZXIgYSBEYXRhUHJvcGVydHkgb3IgYSBOYXZpZ2F0aW9uUHJvcGVydHlcIlxyXG4gIH0pO1xyXG59O1xyXG5cclxuZnVuY3Rpb24gaXNFbnRpdHlQcm9wZXJ0eShjb250ZXh0OiBhbnksIHY6IGFueSkge1xyXG4gIGlmICh2ID09IG51bGwpIHJldHVybiBmYWxzZTtcclxuICByZXR1cm4gKHYuaXNEYXRhUHJvcGVydHkgfHwgdi5pc05hdmlnYXRpb25Qcm9wZXJ0eSk7XHJcbn1cclxuXHJcbi8vIGZ1bmN0aW9ucyBzaGFyZWQgYmV0d2VlbiBjbGFzc2VzIHJlbGF0ZWQgdG8gTWV0YWRhdGFcclxuXHJcbmZ1bmN0aW9uIGlzUXVhbGlmaWVkVHlwZU5hbWUoZW50aXR5VHlwZU5hbWU6IHN0cmluZykge1xyXG4gIHJldHVybiBlbnRpdHlUeXBlTmFtZS5pbmRleE9mKFwiOiNcIikgPj0gMDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHF1YWxpZnlUeXBlTmFtZShzaG9ydE5hbWU6IHN0cmluZywgbnM/OiBzdHJpbmcpIHtcclxuICBpZiAobnMgJiYgbnMubGVuZ3RoID4gMCkge1xyXG4gICAgcmV0dXJuIHNob3J0TmFtZSArIFwiOiNcIiArIG5zO1xyXG4gIH0gZWxzZSB7XHJcbiAgICByZXR1cm4gc2hvcnROYW1lO1xyXG4gIH1cclxufVxyXG5cclxuLy8gVXNlZCBieSBib3RoIENvbXBsZXhUeXBlIGFuZCBFbnRpdHlUeXBlXHJcbmZ1bmN0aW9uIGFkZFByb3BlcnRpZXMoZW50aXR5VHlwZTogU3RydWN0dXJhbFR5cGUsIHByb3BPYmo6IE9iamVjdCB8IHVuZGVmaW5lZCwgY3RvcjogYW55KSB7XHJcbiAgaWYgKHByb3BPYmogPT0gbnVsbCkgcmV0dXJuO1xyXG4gIGlmIChBcnJheS5pc0FycmF5KHByb3BPYmopKSB7XHJcbiAgICBwcm9wT2JqLmZvckVhY2goZW50aXR5VHlwZS5fYWRkUHJvcGVydHlDb3JlLmJpbmQoZW50aXR5VHlwZSkpO1xyXG4gIH0gZWxzZSBpZiAodHlwZW9mIChwcm9wT2JqKSA9PT0gJ29iamVjdCcpIHtcclxuICAgIGZvciAobGV0IGtleSBpbiBwcm9wT2JqKSB7XHJcbiAgICAgIGlmIChjb3JlLmhhc093blByb3BlcnR5KHByb3BPYmosIGtleSkpIHtcclxuICAgICAgICBsZXQgdmFsdWUgPSBwcm9wT2JqW2tleV07XHJcbiAgICAgICAgdmFsdWUubmFtZSA9IGtleTtcclxuICAgICAgICBsZXQgcHJvcCA9IG5ldyBjdG9yKHZhbHVlKTtcclxuICAgICAgICBlbnRpdHlUeXBlLl9hZGRQcm9wZXJ0eUNvcmUocHJvcCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9IGVsc2Uge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlICdkYXRhUHJvcGVydGllcycgb3IgJ25hdmlnYXRpb25Qcm9wZXJ0aWVzJyB2YWx1ZXMgbXVzdCBiZSBlaXRoZXIgYW4gYXJyYXkgb2YgZGF0YS9uYXYgcHJvcGVydGllcyBvciBhbiBvYmplY3Qgd2hlcmUgZWFjaCBwcm9wZXJ0eSBkZWZpbmVzIGEgZGF0YS9uYXYgcHJvcGVydHlcIik7XHJcbiAgfVxyXG59XHJcblxyXG5cclxuXHJcblxyXG5cclxuIl19