breeze-client 2.2.1-cjs → 2.2.2

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