breeze-client 2.1.5-mjs → 2.1.5

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 (394) hide show
  1. package/adapter-ajax-angularjs/{index.d.ts → breeze-client-adapter-ajax-angularjs.d.ts} +0 -1
  2. package/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.metadata.json +1 -0
  3. package/adapter-ajax-angularjs/package.json +13 -0
  4. package/adapter-ajax-fetch/{index.d.ts → breeze-client-adapter-ajax-fetch.d.ts} +0 -1
  5. package/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.metadata.json +1 -0
  6. package/adapter-ajax-fetch/package.json +13 -0
  7. package/adapter-ajax-httpclient/{index.d.ts → breeze-client-adapter-ajax-httpclient.d.ts} +0 -1
  8. package/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.metadata.json +1 -0
  9. package/adapter-ajax-httpclient/package.json +13 -0
  10. package/adapter-ajax-jquery/{index.d.ts → breeze-client-adapter-ajax-jquery.d.ts} +0 -1
  11. package/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.metadata.json +1 -0
  12. package/adapter-ajax-jquery/package.json +13 -0
  13. package/adapter-ajax-post/{index.d.ts → breeze-client-adapter-ajax-post.d.ts} +0 -1
  14. package/adapter-ajax-post/breeze-client-adapter-ajax-post.metadata.json +1 -0
  15. package/adapter-ajax-post/package.json +13 -0
  16. package/adapter-data-service-odata/{index.d.ts → breeze-client-adapter-data-service-odata.d.ts} +0 -1
  17. package/adapter-data-service-odata/breeze-client-adapter-data-service-odata.metadata.json +1 -0
  18. package/adapter-data-service-odata/package.json +13 -0
  19. package/adapter-data-service-webapi/{index.d.ts → breeze-client-adapter-data-service-webapi.d.ts} +0 -1
  20. package/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.metadata.json +1 -0
  21. package/adapter-data-service-webapi/package.json +13 -0
  22. package/adapter-model-library-backing-store/{index.d.ts → breeze-client-adapter-model-library-backing-store.d.ts} +0 -1
  23. package/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.metadata.json +1 -0
  24. package/adapter-model-library-backing-store/package.json +13 -0
  25. package/adapter-model-library-ko/{index.d.ts → breeze-client-adapter-model-library-ko.d.ts} +0 -1
  26. package/adapter-model-library-ko/breeze-client-adapter-model-library-ko.metadata.json +1 -0
  27. package/adapter-model-library-ko/package.json +13 -0
  28. package/adapter-uri-builder-json/{index.d.ts → breeze-client-adapter-uri-builder-json.d.ts} +0 -1
  29. package/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.metadata.json +1 -0
  30. package/adapter-uri-builder-json/package.json +13 -0
  31. package/adapter-uri-builder-odata/{index.d.ts → breeze-client-adapter-uri-builder-odata.d.ts} +0 -1
  32. package/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.metadata.json +1 -0
  33. package/adapter-uri-builder-odata/package.json +13 -0
  34. package/breeze-client.d.ts +8 -0
  35. package/breeze-client.metadata.json +1 -0
  36. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js +190 -0
  37. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js.map +1 -0
  38. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js +2 -0
  39. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js.map +1 -0
  40. package/bundles/breeze-client-adapter-ajax-fetch.umd.js +190 -0
  41. package/bundles/breeze-client-adapter-ajax-fetch.umd.js.map +1 -0
  42. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js +2 -0
  43. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js.map +1 -0
  44. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js +195 -0
  45. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js.map +1 -0
  46. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js +2 -0
  47. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js.map +1 -0
  48. package/bundles/breeze-client-adapter-ajax-jquery.umd.js +115 -0
  49. package/bundles/breeze-client-adapter-ajax-jquery.umd.js.map +1 -0
  50. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js +2 -0
  51. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js.map +1 -0
  52. package/bundles/breeze-client-adapter-ajax-post.umd.js +92 -0
  53. package/bundles/breeze-client-adapter-ajax-post.umd.js.map +1 -0
  54. package/bundles/breeze-client-adapter-ajax-post.umd.min.js +2 -0
  55. package/bundles/breeze-client-adapter-ajax-post.umd.min.js.map +1 -0
  56. package/bundles/breeze-client-adapter-data-service-odata.umd.js +743 -0
  57. package/bundles/breeze-client-adapter-data-service-odata.umd.js.map +1 -0
  58. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js +16 -0
  59. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js.map +1 -0
  60. package/bundles/breeze-client-adapter-data-service-webapi.umd.js +326 -0
  61. package/bundles/breeze-client-adapter-data-service-webapi.umd.js.map +1 -0
  62. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js +16 -0
  63. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js.map +1 -0
  64. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js +280 -0
  65. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js.map +1 -0
  66. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js +2 -0
  67. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js.map +1 -0
  68. package/bundles/breeze-client-adapter-model-library-ko.umd.js +252 -0
  69. package/bundles/breeze-client-adapter-model-library-ko.umd.js.map +1 -0
  70. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js +2 -0
  71. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js.map +1 -0
  72. package/bundles/breeze-client-adapter-uri-builder-json.umd.js +96 -0
  73. package/bundles/breeze-client-adapter-uri-builder-json.umd.js.map +1 -0
  74. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js +2 -0
  75. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js.map +1 -0
  76. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js +262 -0
  77. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js.map +1 -0
  78. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js +2 -0
  79. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js.map +1 -0
  80. package/bundles/breeze-client-mixin-get-entity-graph.umd.js +258 -0
  81. package/bundles/breeze-client-mixin-get-entity-graph.umd.js.map +1 -0
  82. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js +2 -0
  83. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js.map +1 -0
  84. package/bundles/breeze-client-mixin-save-queuing.umd.js +579 -0
  85. package/bundles/breeze-client-mixin-save-queuing.umd.js.map +1 -0
  86. package/bundles/breeze-client-mixin-save-queuing.umd.min.js +16 -0
  87. package/bundles/breeze-client-mixin-save-queuing.umd.min.js.map +1 -0
  88. package/bundles/breeze-client.umd.js +14098 -0
  89. package/bundles/breeze-client.umd.js.map +1 -0
  90. package/bundles/breeze-client.umd.min.js +16 -0
  91. package/bundles/breeze-client.umd.min.js.map +1 -0
  92. package/esm2015/adapter-ajax-angularjs/adapter-ajax-angularjs.js +130 -0
  93. package/esm2015/adapter-ajax-angularjs/adapter-core.js +49 -0
  94. package/esm2015/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +5 -0
  95. package/esm2015/adapter-ajax-fetch/adapter-ajax-fetch.js +130 -0
  96. package/esm2015/adapter-ajax-fetch/adapter-core.js +49 -0
  97. package/esm2015/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +5 -0
  98. package/esm2015/adapter-ajax-httpclient/adapter-ajax-httpclient.js +137 -0
  99. package/esm2015/adapter-ajax-httpclient/adapter-core.js +49 -0
  100. package/esm2015/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +5 -0
  101. package/esm2015/adapter-ajax-jquery/adapter-ajax-jquery.js +103 -0
  102. package/esm2015/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +5 -0
  103. package/esm2015/adapter-ajax-post/adapter-ajax-post.js +77 -0
  104. package/esm2015/adapter-ajax-post/breeze-client-adapter-ajax-post.js +5 -0
  105. package/esm2015/adapter-data-service-odata/adapter-core.js +49 -0
  106. package/esm2015/adapter-data-service-odata/adapter-data-service-odata.js +459 -0
  107. package/esm2015/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +5 -0
  108. package/esm2015/adapter-data-service-webapi/adapter-data-service-webapi.js +93 -0
  109. package/esm2015/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +5 -0
  110. package/esm2015/adapter-model-library-backing-store/adapter-model-library-backing-store.js +268 -0
  111. package/esm2015/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +5 -0
  112. package/esm2015/adapter-model-library-ko/adapter-model-library-ko.js +240 -0
  113. package/esm2015/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +5 -0
  114. package/esm2015/adapter-uri-builder-json/adapter-core.js +49 -0
  115. package/esm2015/adapter-uri-builder-json/adapter-uri-builder-json.js +36 -0
  116. package/esm2015/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +5 -0
  117. package/esm2015/adapter-uri-builder-odata/adapter-core.js +49 -0
  118. package/esm2015/adapter-uri-builder-odata/adapter-uri-builder-odata.js +192 -0
  119. package/esm2015/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +5 -0
  120. package/esm2015/breeze-client.js +9 -0
  121. package/esm2015/index.js +2 -0
  122. package/esm2015/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +5 -0
  123. package/esm2015/mixin-get-entity-graph/mixin-get-entity-graph.js +269 -0
  124. package/esm2015/mixin-save-queuing/breeze-client-mixin-save-queuing.js +5 -0
  125. package/esm2015/mixin-save-queuing/mixin-save-queuing.js +400 -0
  126. package/esm2015/src/abstract-data-service-adapter.js +296 -0
  127. package/esm2015/src/array.js +4 -0
  128. package/esm2015/src/assert-param.js +312 -0
  129. package/esm2015/src/breeze.js +85 -0
  130. package/esm2015/src/complex-array.js +119 -0
  131. package/esm2015/src/config.js +223 -0
  132. package/esm2015/src/core.js +709 -0
  133. package/esm2015/src/csdl-metadata-parser.js +385 -0
  134. package/esm2015/src/data-service.js +203 -0
  135. package/esm2015/src/data-type.js +444 -0
  136. package/esm2015/src/default-property-interceptor.js +460 -0
  137. package/esm2015/src/entity-action.js +45 -0
  138. package/esm2015/src/entity-aspect.js +806 -0
  139. package/esm2015/src/entity-group.js +187 -0
  140. package/esm2015/src/entity-key.js +116 -0
  141. package/esm2015/src/entity-manager.js +2094 -0
  142. package/esm2015/src/entity-metadata.js +2109 -0
  143. package/esm2015/src/entity-query.js +996 -0
  144. package/esm2015/src/entity-state.js +99 -0
  145. package/esm2015/src/enum.js +141 -0
  146. package/esm2015/src/event.js +256 -0
  147. package/esm2015/src/interface-registry.js +41 -0
  148. package/esm2015/src/key-generator.js +108 -0
  149. package/esm2015/src/local-query-comparison-options.js +65 -0
  150. package/esm2015/src/mapping-context.js +405 -0
  151. package/esm2015/src/naming-convention.js +88 -0
  152. package/esm2015/src/observable-array.js +185 -0
  153. package/esm2015/src/predicate.js +1235 -0
  154. package/esm2015/src/primitive-array.js +87 -0
  155. package/esm2015/src/query-options.js +152 -0
  156. package/esm2015/src/relation-array.js +175 -0
  157. package/esm2015/src/save-options.js +41 -0
  158. package/esm2015/src/unattached-children-map.js +58 -0
  159. package/esm2015/src/validate.js +991 -0
  160. package/esm2015/src/validation-options.js +64 -0
  161. package/esm5/adapter-ajax-angularjs/adapter-ajax-angularjs.js +132 -0
  162. package/esm5/adapter-ajax-angularjs/adapter-core.js +49 -0
  163. package/esm5/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +5 -0
  164. package/esm5/adapter-ajax-fetch/adapter-ajax-fetch.js +132 -0
  165. package/esm5/adapter-ajax-fetch/adapter-core.js +49 -0
  166. package/esm5/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +5 -0
  167. package/esm5/adapter-ajax-httpclient/adapter-ajax-httpclient.js +139 -0
  168. package/esm5/adapter-ajax-httpclient/adapter-core.js +49 -0
  169. package/esm5/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +5 -0
  170. package/esm5/adapter-ajax-jquery/adapter-ajax-jquery.js +105 -0
  171. package/esm5/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +5 -0
  172. package/esm5/adapter-ajax-post/adapter-ajax-post.js +81 -0
  173. package/esm5/adapter-ajax-post/breeze-client-adapter-ajax-post.js +5 -0
  174. package/esm5/adapter-data-service-odata/adapter-core.js +49 -0
  175. package/esm5/adapter-data-service-odata/adapter-data-service-odata.js +466 -0
  176. package/esm5/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +5 -0
  177. package/esm5/adapter-data-service-webapi/adapter-data-service-webapi.js +98 -0
  178. package/esm5/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +5 -0
  179. package/esm5/adapter-model-library-backing-store/adapter-model-library-backing-store.js +270 -0
  180. package/esm5/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +5 -0
  181. package/esm5/adapter-model-library-ko/adapter-model-library-ko.js +242 -0
  182. package/esm5/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +5 -0
  183. package/esm5/adapter-uri-builder-json/adapter-core.js +49 -0
  184. package/esm5/adapter-uri-builder-json/adapter-uri-builder-json.js +38 -0
  185. package/esm5/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +5 -0
  186. package/esm5/adapter-uri-builder-odata/adapter-core.js +49 -0
  187. package/esm5/adapter-uri-builder-odata/adapter-uri-builder-odata.js +197 -0
  188. package/esm5/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +5 -0
  189. package/esm5/breeze-client.js +9 -0
  190. package/esm5/index.js +2 -0
  191. package/esm5/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +5 -0
  192. package/esm5/mixin-get-entity-graph/mixin-get-entity-graph.js +269 -0
  193. package/esm5/mixin-save-queuing/breeze-client-mixin-save-queuing.js +5 -0
  194. package/esm5/mixin-save-queuing/mixin-save-queuing.js +412 -0
  195. package/esm5/src/abstract-data-service-adapter.js +302 -0
  196. package/esm5/src/array.js +4 -0
  197. package/esm5/src/assert-param.js +317 -0
  198. package/esm5/src/breeze.js +85 -0
  199. package/esm5/src/complex-array.js +119 -0
  200. package/esm5/src/config.js +228 -0
  201. package/esm5/src/core.js +717 -0
  202. package/esm5/src/csdl-metadata-parser.js +385 -0
  203. package/esm5/src/data-service.js +207 -0
  204. package/esm5/src/data-type.js +451 -0
  205. package/esm5/src/default-property-interceptor.js +460 -0
  206. package/esm5/src/entity-action.js +52 -0
  207. package/esm5/src/entity-aspect.js +812 -0
  208. package/esm5/src/entity-group.js +189 -0
  209. package/esm5/src/entity-key.js +118 -0
  210. package/esm5/src/entity-manager.js +2112 -0
  211. package/esm5/src/entity-metadata.js +2144 -0
  212. package/esm5/src/entity-query.js +1023 -0
  213. package/esm5/src/entity-state.js +106 -0
  214. package/esm5/src/enum.js +144 -0
  215. package/esm5/src/event.js +259 -0
  216. package/esm5/src/interface-registry.js +43 -0
  217. package/esm5/src/key-generator.js +111 -0
  218. package/esm5/src/local-query-comparison-options.js +67 -0
  219. package/esm5/src/mapping-context.js +407 -0
  220. package/esm5/src/naming-convention.js +90 -0
  221. package/esm5/src/observable-array.js +201 -0
  222. package/esm5/src/predicate.js +1300 -0
  223. package/esm5/src/primitive-array.js +87 -0
  224. package/esm5/src/query-options.js +167 -0
  225. package/esm5/src/relation-array.js +175 -0
  226. package/esm5/src/save-options.js +43 -0
  227. package/esm5/src/unattached-children-map.js +60 -0
  228. package/esm5/src/validate.js +996 -0
  229. package/esm5/src/validation-options.js +66 -0
  230. package/fesm2015/{breeze-client-adapter-ajax-angularjs.mjs → breeze-client-adapter-ajax-angularjs.js} +1 -2
  231. package/fesm2015/breeze-client-adapter-ajax-angularjs.js.map +1 -0
  232. package/fesm2015/{breeze-client-adapter-ajax-fetch.mjs → breeze-client-adapter-ajax-fetch.js} +3 -6
  233. package/fesm2015/breeze-client-adapter-ajax-fetch.js.map +1 -0
  234. package/fesm2015/{breeze-client-adapter-ajax-httpclient.mjs → breeze-client-adapter-ajax-httpclient.js} +1 -2
  235. package/fesm2015/breeze-client-adapter-ajax-httpclient.js.map +1 -0
  236. package/fesm2015/{breeze-client-adapter-ajax-jquery.mjs → breeze-client-adapter-ajax-jquery.js} +2 -3
  237. package/fesm2015/breeze-client-adapter-ajax-jquery.js.map +1 -0
  238. package/{fesm2020/breeze-client-adapter-ajax-post.mjs → fesm2015/breeze-client-adapter-ajax-post.js} +1 -2
  239. package/fesm2015/breeze-client-adapter-ajax-post.js.map +1 -0
  240. package/fesm2015/{breeze-client-adapter-data-service-odata.mjs → breeze-client-adapter-data-service-odata.js} +22 -21
  241. package/fesm2015/breeze-client-adapter-data-service-odata.js.map +1 -0
  242. package/fesm2015/{breeze-client-adapter-data-service-webapi.mjs → breeze-client-adapter-data-service-webapi.js} +13 -14
  243. package/fesm2015/breeze-client-adapter-data-service-webapi.js.map +1 -0
  244. package/{fesm2020/breeze-client-adapter-model-library-backing-store.mjs → fesm2015/breeze-client-adapter-model-library-backing-store.js} +13 -14
  245. package/fesm2015/breeze-client-adapter-model-library-backing-store.js.map +1 -0
  246. package/{fesm2020/breeze-client-adapter-model-library-ko.mjs → fesm2015/breeze-client-adapter-model-library-ko.js} +13 -14
  247. package/fesm2015/breeze-client-adapter-model-library-ko.js.map +1 -0
  248. package/{fesm2020/breeze-client-adapter-uri-builder-json.mjs → fesm2015/breeze-client-adapter-uri-builder-json.js} +8 -9
  249. package/fesm2015/breeze-client-adapter-uri-builder-json.js.map +1 -0
  250. package/{fesm2020/breeze-client-adapter-uri-builder-odata.mjs → fesm2015/breeze-client-adapter-uri-builder-odata.js} +86 -86
  251. package/fesm2015/breeze-client-adapter-uri-builder-odata.js.map +1 -0
  252. package/fesm2015/{breeze-client-mixin-get-entity-graph.mjs → breeze-client-mixin-get-entity-graph.js} +1 -2
  253. package/fesm2015/breeze-client-mixin-get-entity-graph.js.map +1 -0
  254. package/fesm2015/{breeze-client-mixin-save-queuing.mjs → breeze-client-mixin-save-queuing.js} +1 -2
  255. package/fesm2015/breeze-client-mixin-save-queuing.js.map +1 -0
  256. package/fesm2015/{breeze-client.mjs → breeze-client.js} +417 -408
  257. package/fesm2015/breeze-client.js.map +1 -0
  258. package/{fesm2020/breeze-client-adapter-ajax-angularjs.mjs → fesm5/breeze-client-adapter-ajax-angularjs.js} +42 -42
  259. package/fesm5/breeze-client-adapter-ajax-angularjs.js.map +1 -0
  260. package/{fesm2020/breeze-client-adapter-ajax-fetch.mjs → fesm5/breeze-client-adapter-ajax-fetch.js} +43 -45
  261. package/fesm5/breeze-client-adapter-ajax-fetch.js.map +1 -0
  262. package/{fesm2020/breeze-client-adapter-ajax-httpclient.mjs → fesm5/breeze-client-adapter-ajax-httpclient.js} +44 -44
  263. package/fesm5/breeze-client-adapter-ajax-httpclient.js.map +1 -0
  264. package/{fesm2020/breeze-client-adapter-ajax-jquery.mjs → fesm5/breeze-client-adapter-ajax-jquery.js} +19 -19
  265. package/fesm5/breeze-client-adapter-ajax-jquery.js.map +1 -0
  266. package/{fesm2015/breeze-client-adapter-ajax-post.mjs → fesm5/breeze-client-adapter-ajax-post.js} +11 -9
  267. package/fesm5/breeze-client-adapter-ajax-post.js.map +1 -0
  268. package/{fesm2020/breeze-client-adapter-data-service-odata.mjs → fesm5/breeze-client-adapter-data-service-odata.js} +134 -127
  269. package/fesm5/breeze-client-adapter-data-service-odata.js.map +1 -0
  270. package/{fesm2020/breeze-client-adapter-data-service-webapi.mjs → fesm5/breeze-client-adapter-data-service-webapi.js} +42 -39
  271. package/fesm5/breeze-client-adapter-data-service-webapi.js.map +1 -0
  272. package/{fesm2015/breeze-client-adapter-model-library-backing-store.mjs → fesm5/breeze-client-adapter-model-library-backing-store.js} +64 -64
  273. package/fesm5/breeze-client-adapter-model-library-backing-store.js.map +1 -0
  274. package/{fesm2015/breeze-client-adapter-model-library-ko.mjs → fesm5/breeze-client-adapter-model-library-ko.js} +58 -58
  275. package/fesm5/breeze-client-adapter-model-library-ko.js.map +1 -0
  276. package/fesm5/breeze-client-adapter-uri-builder-json.js +92 -0
  277. package/fesm5/breeze-client-adapter-uri-builder-json.js.map +1 -0
  278. package/fesm5/breeze-client-adapter-uri-builder-odata.js +250 -0
  279. package/fesm5/breeze-client-adapter-uri-builder-odata.js.map +1 -0
  280. package/{fesm2020/breeze-client-mixin-get-entity-graph.mjs → fesm5/breeze-client-mixin-get-entity-graph.js} +45 -46
  281. package/fesm5/breeze-client-mixin-get-entity-graph.js.map +1 -0
  282. package/{fesm2020/breeze-client-mixin-save-queuing.mjs → fesm5/breeze-client-mixin-save-queuing.js} +126 -117
  283. package/fesm5/breeze-client-mixin-save-queuing.js.map +1 -0
  284. package/{fesm2020/breeze-client.mjs → fesm5/breeze-client.js} +3629 -3413
  285. package/fesm5/breeze-client.js.map +1 -0
  286. package/mixin-get-entity-graph/{index.d.ts → breeze-client-mixin-get-entity-graph.d.ts} +0 -1
  287. package/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.metadata.json +1 -0
  288. package/mixin-get-entity-graph/package.json +13 -0
  289. package/mixin-save-queuing/{index.d.ts → breeze-client-mixin-save-queuing.d.ts} +0 -1
  290. package/mixin-save-queuing/breeze-client-mixin-save-queuing.metadata.json +1 -0
  291. package/mixin-save-queuing/package.json +13 -0
  292. package/package.json +11 -125
  293. package/src/entity-metadata.d.ts +4 -6
  294. package/src/entity-query.d.ts +1 -1
  295. package/esm2020/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +0 -130
  296. package/esm2020/adapter-ajax-angularjs/adapter-core.mjs +0 -49
  297. package/esm2020/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +0 -5
  298. package/esm2020/adapter-ajax-fetch/adapter-ajax-fetch.mjs +0 -132
  299. package/esm2020/adapter-ajax-fetch/adapter-core.mjs +0 -49
  300. package/esm2020/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +0 -5
  301. package/esm2020/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +0 -137
  302. package/esm2020/adapter-ajax-httpclient/adapter-core.mjs +0 -49
  303. package/esm2020/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +0 -5
  304. package/esm2020/adapter-ajax-jquery/adapter-ajax-jquery.mjs +0 -103
  305. package/esm2020/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +0 -5
  306. package/esm2020/adapter-ajax-post/adapter-ajax-post.mjs +0 -77
  307. package/esm2020/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +0 -5
  308. package/esm2020/adapter-data-service-odata/adapter-core.mjs +0 -49
  309. package/esm2020/adapter-data-service-odata/adapter-data-service-odata.mjs +0 -456
  310. package/esm2020/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +0 -5
  311. package/esm2020/adapter-data-service-webapi/adapter-data-service-webapi.mjs +0 -93
  312. package/esm2020/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +0 -5
  313. package/esm2020/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +0 -268
  314. package/esm2020/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +0 -5
  315. package/esm2020/adapter-model-library-ko/adapter-model-library-ko.mjs +0 -240
  316. package/esm2020/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +0 -5
  317. package/esm2020/adapter-uri-builder-json/adapter-core.mjs +0 -49
  318. package/esm2020/adapter-uri-builder-json/adapter-uri-builder-json.mjs +0 -36
  319. package/esm2020/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +0 -5
  320. package/esm2020/adapter-uri-builder-odata/adapter-core.mjs +0 -49
  321. package/esm2020/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +0 -190
  322. package/esm2020/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +0 -5
  323. package/esm2020/breeze-client.mjs +0 -5
  324. package/esm2020/index.mjs +0 -2
  325. package/esm2020/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +0 -5
  326. package/esm2020/mixin-get-entity-graph/mixin-get-entity-graph.mjs +0 -269
  327. package/esm2020/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +0 -5
  328. package/esm2020/mixin-save-queuing/mixin-save-queuing.mjs +0 -400
  329. package/esm2020/src/abstract-data-service-adapter.mjs +0 -296
  330. package/esm2020/src/array.mjs +0 -4
  331. package/esm2020/src/assert-param.mjs +0 -312
  332. package/esm2020/src/breeze.mjs +0 -85
  333. package/esm2020/src/complex-array.mjs +0 -117
  334. package/esm2020/src/config.mjs +0 -223
  335. package/esm2020/src/core.mjs +0 -707
  336. package/esm2020/src/csdl-metadata-parser.mjs +0 -385
  337. package/esm2020/src/data-service.mjs +0 -203
  338. package/esm2020/src/data-type.mjs +0 -444
  339. package/esm2020/src/default-property-interceptor.mjs +0 -460
  340. package/esm2020/src/entity-action.mjs +0 -45
  341. package/esm2020/src/entity-aspect.mjs +0 -806
  342. package/esm2020/src/entity-group.mjs +0 -187
  343. package/esm2020/src/entity-key.mjs +0 -116
  344. package/esm2020/src/entity-manager.mjs +0 -2094
  345. package/esm2020/src/entity-metadata.mjs +0 -2109
  346. package/esm2020/src/entity-query.mjs +0 -996
  347. package/esm2020/src/entity-state.mjs +0 -99
  348. package/esm2020/src/enum.mjs +0 -141
  349. package/esm2020/src/event.mjs +0 -256
  350. package/esm2020/src/interface-registry.mjs +0 -41
  351. package/esm2020/src/key-generator.mjs +0 -108
  352. package/esm2020/src/local-query-comparison-options.mjs +0 -65
  353. package/esm2020/src/mapping-context.mjs +0 -405
  354. package/esm2020/src/naming-convention.mjs +0 -88
  355. package/esm2020/src/observable-array.mjs +0 -183
  356. package/esm2020/src/predicate.mjs +0 -1232
  357. package/esm2020/src/primitive-array.mjs +0 -85
  358. package/esm2020/src/query-options.mjs +0 -152
  359. package/esm2020/src/relation-array.mjs +0 -173
  360. package/esm2020/src/save-options.mjs +0 -41
  361. package/esm2020/src/unattached-children-map.mjs +0 -58
  362. package/esm2020/src/validate.mjs +0 -988
  363. package/esm2020/src/validation-options.mjs +0 -64
  364. package/fesm2015/breeze-client-adapter-ajax-angularjs.mjs.map +0 -1
  365. package/fesm2015/breeze-client-adapter-ajax-fetch.mjs.map +0 -1
  366. package/fesm2015/breeze-client-adapter-ajax-httpclient.mjs.map +0 -1
  367. package/fesm2015/breeze-client-adapter-ajax-jquery.mjs.map +0 -1
  368. package/fesm2015/breeze-client-adapter-ajax-post.mjs.map +0 -1
  369. package/fesm2015/breeze-client-adapter-data-service-odata.mjs.map +0 -1
  370. package/fesm2015/breeze-client-adapter-data-service-webapi.mjs.map +0 -1
  371. package/fesm2015/breeze-client-adapter-model-library-backing-store.mjs.map +0 -1
  372. package/fesm2015/breeze-client-adapter-model-library-ko.mjs.map +0 -1
  373. package/fesm2015/breeze-client-adapter-uri-builder-json.mjs +0 -92
  374. package/fesm2015/breeze-client-adapter-uri-builder-json.mjs.map +0 -1
  375. package/fesm2015/breeze-client-adapter-uri-builder-odata.mjs +0 -246
  376. package/fesm2015/breeze-client-adapter-uri-builder-odata.mjs.map +0 -1
  377. package/fesm2015/breeze-client-mixin-get-entity-graph.mjs.map +0 -1
  378. package/fesm2015/breeze-client-mixin-save-queuing.mjs.map +0 -1
  379. package/fesm2015/breeze-client.mjs.map +0 -1
  380. package/fesm2020/breeze-client-adapter-ajax-angularjs.mjs.map +0 -1
  381. package/fesm2020/breeze-client-adapter-ajax-fetch.mjs.map +0 -1
  382. package/fesm2020/breeze-client-adapter-ajax-httpclient.mjs.map +0 -1
  383. package/fesm2020/breeze-client-adapter-ajax-jquery.mjs.map +0 -1
  384. package/fesm2020/breeze-client-adapter-ajax-post.mjs.map +0 -1
  385. package/fesm2020/breeze-client-adapter-data-service-odata.mjs.map +0 -1
  386. package/fesm2020/breeze-client-adapter-data-service-webapi.mjs.map +0 -1
  387. package/fesm2020/breeze-client-adapter-model-library-backing-store.mjs.map +0 -1
  388. package/fesm2020/breeze-client-adapter-model-library-ko.mjs.map +0 -1
  389. package/fesm2020/breeze-client-adapter-uri-builder-json.mjs.map +0 -1
  390. package/fesm2020/breeze-client-adapter-uri-builder-odata.mjs.map +0 -1
  391. package/fesm2020/breeze-client-mixin-get-entity-graph.mjs.map +0 -1
  392. package/fesm2020/breeze-client-mixin-save-queuing.mjs.map +0 -1
  393. package/fesm2020/breeze-client.mjs.map +0 -1
  394. package/mjs/README.md +0 -17
@@ -0,0 +1,996 @@
1
+ import { core } from './core';
2
+ import { assertParam } from './assert-param';
3
+ import { config } from './config';
4
+ export var INT16_MIN = -32768;
5
+ export var INT16_MAX = 32767;
6
+ export var INT32_MIN = -2147483648;
7
+ export var INT32_MAX = 2147483647;
8
+ export var BYTE_MIN = 0;
9
+ export var BYTE_MAX = 255;
10
+ var ɵ0 = function (context) {
11
+ if (context.property) {
12
+ return context.property.resolveProperty("displayName") || context.propertyName || context.property.name;
13
+ }
14
+ else {
15
+ return "Value";
16
+ }
17
+ };
18
+ // add common props and methods for every validator 'context' here.
19
+ var rootContext = {
20
+ displayName: ɵ0
21
+ };
22
+ /**
23
+ Instances of the Validator class provide the logic to validate another object and provide a description of any errors
24
+ encountered during the validation process. They are typically associated with a 'validators' property on the following types: [[EntityType]],
25
+ [[DataProperty]] or [[NavigationProperty]].
26
+
27
+ A number of property level validators are registered automatically, i.e added to each DataProperty.validators property
28
+ based on [[DataProperty]] metadata. For example,
29
+
30
+ - DataProperty.dataType -> one of the 'dataType' validator methods such as Validator.int64, Validator.date, Validator.bool etc.
31
+ - DataProperty.maxLength -> Validator.maxLength
32
+ - DataProperty.isNullable -> Validator.required (if not nullable)
33
+
34
+ @class Validator
35
+ **/
36
+ /**
37
+ Validator constructor - This method is used to create create custom validations. Several
38
+ basic "Validator" construction methods are also provided as static methods to this class. These methods
39
+ provide a simpler syntax for creating basic validations.
40
+
41
+ Many of these stock validators are inspired by and implemented to conform to the validators defined at
42
+ http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx
43
+
44
+ Sometimes a custom validator will be required.
45
+ @example
46
+ Most validators will be 'property' level validators, like this.
47
+ @example
48
+ // v is this function is the value to be validated, in this case a "country" string.
49
+ var valFn = function (v) {
50
+ if (v == null) return true;
51
+ return (core.stringStartsWith(v, "US"));
52
+ };
53
+ var countryValidator = new Validator("countryIsUS", valFn, {
54
+ displayName: "Country",
55
+ messageTemplate: "'%displayName%' must start with 'US'"
56
+ });
57
+
58
+ // Now plug it into Breeze.
59
+ // Assume em1 is a preexisting EntityManager.
60
+ var custType = metadataStore.getEntityType("Customer");
61
+ var countryProp = custType.getProperty("Country");
62
+ // Note that validator is added to a 'DataProperty' validators collection.
63
+ prop.validators.push(countryValidator);
64
+ Entity level validators are also possible
65
+ @example
66
+ function isValidZipCode(value) {
67
+ var re = /^\d{5}([\-]\d{4})?$/;
68
+ return (re.test(value));
69
+ }
70
+
71
+ // v in this case will be a Customer entity
72
+ var valFn = function (v) {
73
+ // This validator only validates US Zip Codes.
74
+ if ( v.getProperty("Country") === "USA") {
75
+ var postalCode = v.getProperty("PostalCode");
76
+ return isValidZipCode(postalCode);
77
+ }
78
+ return true;
79
+ };
80
+ var zipCodeValidator = new Validator("zipCodeValidator", valFn,
81
+ { messageTemplate: "For the US, this is not a valid PostalCode" });
82
+
83
+ // Now plug it into Breeze.
84
+ // Assume em1 is a preexisting EntityManager.
85
+ var custType = em1.metadataStore.getEntityType("Customer");
86
+ // Note that validator is added to an 'EntityType' validators collection.
87
+ custType.validators.push(zipCodeValidator);
88
+ What is commonly needed is a way of creating a parameterized function that will itself
89
+ return a new Validator. This requires the use of a 'context' object.
90
+ @example
91
+ // create a function that will take in a config object
92
+ // and will return a validator
93
+ var numericRangeValidator = function(context) {
94
+ var valFn = function(v, ctx) {
95
+ if (v == null) return true;
96
+ if (typeof(v) !== "number") return false;
97
+ if (ctx.min != null && v < ctx.min) return false;
98
+ if (ctx.max != null && v > ctx.max) return false;
99
+ return true;
100
+ };
101
+ // The last parameter below is the 'context' object that will be passed into the 'ctx' parameter above
102
+ // when this validator executes. Several other properties, such as displayName will get added to this object as well.
103
+ return new Validator("numericRange", valFn, {
104
+ messageTemplate: "'%displayName%' must be a number between the values of %min% and %max%",
105
+ min: context.min,
106
+ max: context.max
107
+ });
108
+ };
109
+ // Assume that freightProperty is a DataEntityProperty that describes numeric values.
110
+ // register the validator
111
+ freightProperty.validators.push(numericRangeValidator({ min: 100, max: 500 }));
112
+
113
+ Breeze substitutes context values and functions for the tokens in the messageTemplate when preparing the runtime error message;
114
+ 'displayName' is a pre-defined context function that is always available.
115
+
116
+ Please note that Breeze substitutes the empty string for falsey parameters. That usually works in your favor.
117
+ Sometimes it doesn't as when the 'min' value is zero in which case the message text would have a hole
118
+ where the 'min' value goes, saying: "... an integer between the values of and ...". That is not what you want.
119
+
120
+ To avoid this effect, you may can bake certain of the context values into the 'messageTemplate' itself
121
+ as shown in this revision to the pertinent part of the previous example:
122
+ @example
123
+ // ... as before
124
+ // ... but bake the min/max values into the message template.
125
+ var template = breeze.core.formatString(
126
+ "'%displayName%' must be a number between the values of %1 and %2",
127
+ context.min, context.max);
128
+ return new Validator("numericRange", valFn, {
129
+ messageTemplate: template,
130
+ min: context.min,
131
+ max: context.max
132
+ });
133
+
134
+ @method <ctor> Validator
135
+ @param name {String} The name of this validator.
136
+ @param validatorFn {Function} A function to perform validation.
137
+
138
+ validatorFn(value, context)
139
+ @param validatorFn.value {Object} Value to be validated
140
+ @param validatorFn.context {Object} The same context object passed into the constructor with the following additional properties if not
141
+ otherwise specified.
142
+ @param validatorFn.context.value {Object} The value being validated.
143
+ @param validatorFn.context.name {String} The name of the validator being executed.
144
+ @param validatorFn.context.displayName {String} This will be either the value of the property's 'displayName' property or
145
+ the value of its 'name' property or the string 'Value'
146
+ @param validatorFn.context.messageTemplate {String} This will either be the value of Validator.messageTemplates[ {this validators name}] or null. Validator.messageTemplates
147
+ is an object that is keyed by validator name and that can be added to in order to 'register' your own message for a given validator.
148
+ The following property can also be specified for any validator to force a specific errorMessage string
149
+ @param [validatorFn.context.message] {String} If this property is set it will be used instead of the 'messageTemplate' property when an
150
+ error message is generated.
151
+
152
+ @param [context] {Object} A free form object whose properties will made available during the validation and error message creation process.
153
+ This object will be passed into the Validator's validation function whenever 'validate' is called. See above for a description
154
+ of additional properties that will be automatically added to this object if not otherwise specified.
155
+ @dynamic
156
+ **/
157
+ var Validator = /** @class */ (function () {
158
+ function Validator(name, valFn, context) {
159
+ // _baseContext is what will get serialized
160
+ this._baseContext = context || {};
161
+ this._baseContext.name = name;
162
+ context = core.extend(Object.create(rootContext), this._baseContext);
163
+ context.messageTemplate = context.messageTemplate || Validator.messageTemplates[name];
164
+ this.name = name;
165
+ this.valFn = valFn;
166
+ this.context = context;
167
+ }
168
+ /**
169
+ The name of this validator.
170
+
171
+ __readOnly__
172
+ @property name {String}
173
+ **/
174
+ /**
175
+ The context for this validator.
176
+
177
+ This object will typically contain at a minimum the following properties. "name", "displayName", and "message" or "messageTemplate".
178
+ __readOnly__
179
+ @property context {Object}
180
+ **/
181
+ /**
182
+ Run this validator against the specified value. This method will usually be called internally either
183
+ automatically by an property change, entity attach, query or save operation, or manually as a result of
184
+ a validateEntity call on the EntityAspect. The resulting ValidationResults are available via the
185
+ EntityAspect.getValidationErrors method.
186
+
187
+ However, you can also call a validator directly either for testing purposes or some other reason if needed.
188
+ @example
189
+ // using one of the predefined validators
190
+ var validator = Validator.maxLength({ maxLength: 5, displayName: "City" });
191
+ // should be ok because "asdf".length < 5
192
+ var result = validator.validate("asdf");
193
+ ok(result === null);
194
+ result = validator.validate("adasdfasdf");
195
+ // extract all of the properties of the 'result'
196
+ var errMsg = result.errorMessage;
197
+ var context = result.context;
198
+ var sameValidator = result.validator;
199
+ @method validate
200
+ @param value {Object} Value to validate
201
+ @param additionalContext {Object} Any additional contextual information that the Validator
202
+ can make use of.
203
+ @return {ValidationError|null} A ValidationError if validation fails, null otherwise
204
+ **/
205
+ Validator.prototype.validate = function (value, additionalContext) {
206
+ var currentContext; // { value?: Object };
207
+ if (additionalContext) {
208
+ currentContext = core.extend(Object.create(this.context), additionalContext);
209
+ }
210
+ else {
211
+ currentContext = this.context;
212
+ }
213
+ this.currentContext = currentContext;
214
+ try {
215
+ if (this.valFn(value, currentContext)) {
216
+ return null;
217
+ }
218
+ else {
219
+ currentContext.value = value;
220
+ return new ValidationError(this, currentContext, this.getMessage());
221
+ }
222
+ }
223
+ catch (e) {
224
+ return new ValidationError(this, currentContext, "Exception occured while executing this validator: " + this.name);
225
+ }
226
+ };
227
+ // context.value is not avail unless validate was called first.
228
+ /**
229
+ Returns the message generated by the most recent execution of this Validator.
230
+ @example
231
+ var v0 = Validator.maxLength({ maxLength: 5, displayName: "City" });
232
+ v0.validate("adasdfasdf");
233
+ var errMessage = v0.getMessage());
234
+ @method getMessage
235
+ @return {String}
236
+ **/
237
+ Validator.prototype.getMessage = function () {
238
+ try {
239
+ var context = this.currentContext;
240
+ var message = context.message;
241
+ if (message) {
242
+ if (typeof (message) === "function") {
243
+ return message(context);
244
+ }
245
+ else {
246
+ return message;
247
+ }
248
+ }
249
+ else if (context.messageTemplate) {
250
+ return formatTemplate(context.messageTemplate, context);
251
+ }
252
+ else {
253
+ return "invalid value: " + (this.name || "{unnamed validator}");
254
+ }
255
+ }
256
+ catch (e) {
257
+ return "Unable to format error message" + e.toString();
258
+ }
259
+ };
260
+ Validator.prototype.toJSON = function () {
261
+ return this._baseContext;
262
+ };
263
+ /**
264
+ Creates a validator instance from a JSON object or an array of instances from an array of JSON objects.
265
+ @method fromJSON
266
+ @static
267
+ @param json {Object} JSON object that represents the serialized version of a validator.
268
+ **/
269
+ Validator.fromJSON = function (json) {
270
+ if (Array.isArray(json)) {
271
+ return json.map(function (js) {
272
+ return Validator.fromJSON(js);
273
+ });
274
+ }
275
+ if (json instanceof Validator) {
276
+ return json;
277
+ }
278
+ var validatorName = "Validator." + json.name;
279
+ var fn = config.getRegisteredFunction(validatorName);
280
+ if (!fn) {
281
+ throw new Error("Unable to locate a validator named:" + json.name);
282
+ }
283
+ return fn(json);
284
+ };
285
+ /**
286
+ Register a validator instance so that any deserialized metadata can reference it.
287
+ @method register
288
+ @static
289
+ @param validator {Validator} Validator to register.
290
+ **/
291
+ Validator.register = function (validator) {
292
+ config.registerFunction(function () {
293
+ return validator;
294
+ }, "Validator." + validator.name);
295
+ };
296
+ /**
297
+ Register a validator factory so that any deserialized metadata can reference it.
298
+ @method registerFactory
299
+ @static
300
+ @param validatorFactory {Function} A function that optionally takes a context property and returns a Validator instance.
301
+ @param name {String} The name of the validator.
302
+ **/
303
+ Validator.registerFactory = function (validatorFactory, name) {
304
+ config.registerFunction(validatorFactory, "Validator." + name);
305
+ };
306
+ /**
307
+ Map of standard error message templates keyed by validator name.
308
+ You can add to or modify this object to customize the template used for any validation error message.
309
+ @example
310
+ // v is this function is the value to be validated, in this case a "country" string.
311
+ var valFn = function (v) {
312
+ if (v == null) return true;
313
+ return (core.stringStartsWith(v, "US"));
314
+ };
315
+ var countryValidator = new Validator("countryIsUS", valFn, { displayName: "Country" });
316
+ Validator.messageTemplates.countryIsUS = "'%displayName%' must start with 'US'";
317
+ // This will have a similar effect to this
318
+ var countryValidator = new Validator("countryIsUS", valFn, {
319
+ displayName: "Country",
320
+ messageTemplate: "'%displayName%' must start with 'US'"
321
+ });
322
+ @property messageTemplates {Object}
323
+ @static
324
+ **/
325
+ Validator.messageTemplates = {
326
+ bool: "'%displayName%' must be a 'true' or 'false' value",
327
+ creditCard: "The %displayName% is not a valid credit card number",
328
+ date: "'%displayName%' must be a date",
329
+ duration: "'%displayName%' must be a ISO8601 duration string, such as 'P3H24M60S'",
330
+ emailAddress: "The %displayName% '%value%' is not a valid email address",
331
+ guid: "'%displayName%' must be a GUID",
332
+ integer: "'%displayName%' must be an integer",
333
+ integerRange: "'%displayName%' must be an integer between the values of %minValue% and %maxValue%",
334
+ maxLength: "'%displayName%' must be a string with %maxLength% characters or less",
335
+ number: "'%displayName%' must be a number",
336
+ phone: "The %displayName% '%value%' is not a valid phone number",
337
+ regularExpression: "The %displayName% '%value%' does not match '%expression%'",
338
+ required: "'%displayName%' is required",
339
+ string: "'%displayName%' must be a string",
340
+ stringLength: "'%displayName%' must be a string with between %minLength% and %maxLength% characters",
341
+ url: "The %displayName% '%value%' is not a valid url"
342
+ };
343
+ /**
344
+ Returns a standard 'required value' Validator
345
+ @example
346
+ // Assume em1 is a preexisting EntityManager.
347
+ var custType = em1.metadataStore.getEntityType("Customer");
348
+ var regionProperty - custType.getProperty("Region");
349
+ // Makes "Region" on Customer a required property.
350
+ regionProperty.validators.push(Validator.required());
351
+ // or to allow empty strings
352
+ regionProperty.validators.push(Validator.required({ allowEmptyStrings: true }););
353
+ @method required
354
+ @static
355
+ @param context {Object}
356
+ @param [context.allowEmptyStrings] {Boolean} If this parameter is omitted or false then empty strings do NOT pass validation.
357
+ @return {Validator} A new Validator
358
+ **/
359
+ Validator.required = function (context) {
360
+ var valFn = function (v, ctx) {
361
+ if (typeof v === "string") {
362
+ if (ctx && ctx.allowEmptyStrings)
363
+ return true;
364
+ return v.length > 0;
365
+ }
366
+ else {
367
+ return v != null;
368
+ }
369
+ };
370
+ return new Validator("required", valFn, context);
371
+ };
372
+ /**
373
+ Returns a standard maximum string length Validator; the maximum length must be specified
374
+ @example
375
+ // Assume em1 is a preexisting EntityManager.
376
+ var custType = em1.metadataStore.getEntityType("Customer");
377
+ var regionProperty - custType.getProperty("Region");
378
+ // Validates that the value of the Region property on Customer will be less than or equal to 5 characters.
379
+ regionProperty.validators.push(Validator.maxLength( {maxLength: 5}));
380
+ @method maxLength
381
+ @static
382
+ @param context {Object}
383
+ @param context.maxLength {Integer}
384
+ @return {Validator} A new Validator
385
+ **/
386
+ Validator.maxLength = function (context) {
387
+ var valFn = function (v, ctx) {
388
+ if (v == null)
389
+ return true;
390
+ if (typeof (v) !== "string")
391
+ return false;
392
+ return v.length <= ctx.maxLength;
393
+ };
394
+ return new Validator("maxLength", valFn, context);
395
+ };
396
+ /**
397
+ Returns a standard string length Validator; both minimum and maximum lengths must be specified.
398
+ @example
399
+ // Assume em1 is a preexisting EntityManager.
400
+ var custType = em1.metadataStore.getEntityType("Customer");
401
+ var regionProperty - custType.getProperty("Region");
402
+ // Validates that the value of the Region property on Customer will be
403
+ // between 2 and 5 characters
404
+ regionProperty.validators.push(Validator.stringLength( {minLength: 2, maxLength: 5});
405
+ @method stringLength
406
+ @static
407
+ @param context {Object}
408
+ @param context.maxLength {Integer}
409
+ @param context.minLength {Integer}
410
+ @return {Validator} A new Validator
411
+ **/
412
+ Validator.stringLength = function (context) {
413
+ var valFn = function (v, ctx) {
414
+ if (v == null)
415
+ return true;
416
+ if (typeof (v) !== "string")
417
+ return false;
418
+ if (ctx.minLength != null && v.length < ctx.minLength)
419
+ return false;
420
+ if (ctx.maxLength != null && v.length > ctx.maxLength)
421
+ return false;
422
+ return true;
423
+ };
424
+ return new Validator("stringLength", valFn, context);
425
+ };
426
+ /**
427
+ Returns a standard string dataType Validator.
428
+ @example
429
+ // Assume em1 is a preexisting EntityManager.
430
+ var custType = em1.metadataStore.getEntityType("Customer");
431
+ var regionProperty - custType.getProperty("Region");
432
+ // Validates that the value of the Region property on Customer is a string.
433
+ regionProperty.validators.push(Validator.string());
434
+ @method string
435
+ @static
436
+ @return {Validator} A new Validator
437
+ **/
438
+ Validator.string = function () {
439
+ var valFn = function (v) {
440
+ if (v == null)
441
+ return true;
442
+ return (typeof v === "string");
443
+ };
444
+ return new Validator("string", valFn);
445
+ };
446
+ /**
447
+ Returns a Guid data type Validator.
448
+ @example
449
+ // Assume em1 is a preexisting EntityManager.
450
+ var custType = em1.metadataStore.getEntityType("Customer");
451
+ var customerIdProperty - custType.getProperty("CustomerID");
452
+ // Validates that the value of the CustomerID property on Customer is a Guid.
453
+ customerIdProperty.validators.push(Validator.guid());
454
+ @method guid
455
+ @static
456
+ @return {Validator} A new Validator
457
+ **/
458
+ Validator.guid = function () {
459
+ var valFn = function (v) {
460
+ if (v == null)
461
+ return true;
462
+ return core.isGuid(v);
463
+ };
464
+ return new Validator("guid", valFn);
465
+ };
466
+ /**
467
+ Returns a ISO 8601 duration string Validator.
468
+ @example
469
+ // Assume em1 is a preexisting EntityManager.
470
+ var eventType = em1.metadataStore.getEntityType("Event");
471
+ var elapsedTimeProperty - eventType.getProperty("ElapsedTime");
472
+ // Validates that the value of the ElapsedTime property on Customer is a duration.
473
+ elapsedTimeProperty.validators.push(Validator.duration());
474
+ @method duration
475
+ @static
476
+ @return {Validator} A new Validator
477
+ **/
478
+ Validator.duration = function () {
479
+ var valFn = function (v) {
480
+ if (v == null)
481
+ return true;
482
+ return core.isDuration(v);
483
+ };
484
+ return new Validator("duration", valFn);
485
+ };
486
+ /**
487
+ Returns a standard numeric data type Validator.
488
+ @example
489
+ // Assume em1 is a preexisting EntityManager.
490
+ var orderType = em1.metadataStore.getEntityType("Order");
491
+ var freightProperty - orderType.getProperty("Freight");
492
+ // Validates that the value of the Freight property on Order is a number.
493
+ freightProperty.validators.push(Validator.number());
494
+ @method number
495
+ @static
496
+ @return {Validator} A new Validator
497
+ **/
498
+ // TODO: may need to have seperate logic for single.
499
+ Validator.number = function (context) {
500
+ var valFn = function (v, ctx) {
501
+ if (v == null)
502
+ return true;
503
+ if (typeof v === "string" && ctx && ctx.allowString) {
504
+ v = parseFloat(v);
505
+ }
506
+ return (typeof v === "number" && !isNaN(v));
507
+ };
508
+ return new Validator("number", valFn, context);
509
+ };
510
+ Validator.double = Validator.number;
511
+ Validator.single = Validator.number;
512
+ /**
513
+ Returns a standard large integer data type - 64 bit - Validator.
514
+ @example
515
+ // Assume em1 is a preexisting EntityManager.
516
+ var orderType = em1.metadataStore.getEntityType("Order");
517
+ var freightProperty - orderType.getProperty("Freight");
518
+ // Validates that the value of the Freight property on Order is within the range of a 64 bit integer.
519
+ freightProperty.validators.push(Validator.int64());
520
+ @method int64
521
+ @static
522
+ @return {Validator} A new Validator
523
+ **/
524
+ Validator.integer = function (context) {
525
+ var valFn = function (v, ctx) {
526
+ if (v == null)
527
+ return true;
528
+ if (typeof v === "string" && ctx && ctx.allowString) {
529
+ v = parseInt(v, 10);
530
+ }
531
+ return (typeof v === "number") && (!isNaN(v)) && Math.floor(v) === v;
532
+ };
533
+ return new Validator("integer", valFn, context);
534
+ };
535
+ Validator.int64 = Validator.integer;
536
+ /**
537
+ Returns a standard 32 bit integer data type Validator.
538
+ @example
539
+ // Assume em1 is a preexisting EntityManager.
540
+ var orderType = em1.metadataStore.getEntityType("Order");
541
+ var freightProperty - orderType.getProperty("Freight");
542
+ freightProperty.validators.push(Validator.int32());
543
+ @method int32
544
+ @static
545
+ @return {Validator} A new Validator
546
+ **/
547
+ Validator.int32 = function (context) {
548
+ return intRangeValidatorCtor("int32", INT32_MIN, INT32_MAX, context)();
549
+ };
550
+ /**
551
+ Returns a standard 16 bit integer data type Validator.
552
+ @example
553
+ // Assume em1 is a preexisting EntityManager.
554
+ var orderType = em1.metadataStore.getEntityType("Order");
555
+ var freightProperty - orderType.getProperty("Freight");
556
+ // Validates that the value of the Freight property on Order is within the range of a 16 bit integer.
557
+ freightProperty.validators.push(Validator.int16());
558
+ @method int16
559
+ @static
560
+ @return {Validator} A new Validator
561
+ **/
562
+ Validator.int16 = function (context) {
563
+ return intRangeValidatorCtor("int16", INT16_MIN, INT16_MAX, context)();
564
+ };
565
+ /**
566
+ Returns a standard byte data type Validator. (This is a integer between 0 and 255 inclusive for js purposes).
567
+ @example
568
+ // Assume em1 is a preexisting EntityManager.
569
+ var orderType = em1.metadataStore.getEntityType("Order");
570
+ var freightProperty - orderType.getProperty("Freight");
571
+ // Validates that the value of the Freight property on Order is within the range of a 16 bit integer.
572
+ // Probably not a very good validation to place on the Freight property.
573
+ regionProperty.validators.push(Validator.byte());
574
+ @method byte
575
+ @static
576
+ @return {Validator} A new Validator
577
+ **/
578
+ Validator.byte = function (context) {
579
+ return intRangeValidatorCtor("byte", BYTE_MIN, BYTE_MAX, context)();
580
+ };
581
+ /**
582
+ Returns a standard boolean data type Validator.
583
+ @example
584
+ // Assume em1 is a preexisting EntityManager.
585
+ var productType = em1.metadataStore.getEntityType("Product");
586
+ var discontinuedProperty - productType.getProperty("Discontinued");
587
+ // Validates that the value of the Discontinued property on Product is a boolean
588
+ discontinuedProperty.validators.push(Validator.bool());
589
+ @method bool
590
+ @static
591
+ @return {Validator} A new Validator
592
+ **/
593
+ Validator.bool = function () {
594
+ var valFn = function (v) {
595
+ if (v == null)
596
+ return true;
597
+ return (v === true) || (v === false);
598
+ };
599
+ return new Validator("bool", valFn);
600
+ };
601
+ Validator.none = function () {
602
+ var valFn = function (v) {
603
+ return true;
604
+ };
605
+ return new Validator("none", valFn);
606
+ };
607
+ /**
608
+ Returns a standard date data type Validator.
609
+ @example
610
+ // Assume em1 is a preexisting EntityManager.
611
+ var orderType = em1.metadataStore.getEntityType("Order");
612
+ var orderDateProperty - orderType.getProperty("OrderDate");
613
+ // Validates that the value of the OrderDate property on Order is a date
614
+ // Probably not a very good validation to place on the Freight property.
615
+ orderDateProperty.validators.push(Validator.date());
616
+ @method date
617
+ @static
618
+ @return {Validator} A new Validator
619
+ **/
620
+ Validator.date = function () {
621
+ var valFn = function (v) {
622
+ if (v == null)
623
+ return true;
624
+ if (typeof v === "string") {
625
+ try {
626
+ return !isNaN(Date.parse(v));
627
+ // old code
628
+ // return __isDate(new Date(v));
629
+ }
630
+ catch (e) {
631
+ return false;
632
+ }
633
+ }
634
+ else {
635
+ return core.isDate(v);
636
+ }
637
+ };
638
+ return new Validator("date", valFn);
639
+ };
640
+ /**
641
+ Returns a credit card number validator
642
+ Performs a luhn algorithm checksum test for plausability
643
+ catches simple mistakes; only service knows for sure
644
+ @example
645
+ // Assume em is a preexisting EntityManager.
646
+ var personType = em.metadataStore.getEntityType("Person");
647
+ var creditCardProperty = personType.getProperty("creditCard");
648
+ // Validates that the value of the Person.creditCard property is credit card.
649
+ creditCardProperty.validators.push(Validator.creditCard());
650
+ @method creditCard
651
+ @static
652
+ @param [context] {Object} optional parameters to pass through to validation constructor
653
+ @return {Validator} A new Validator
654
+ **/
655
+ Validator.creditCard = function (context) {
656
+ function valFn(v) {
657
+ if (v == null || v === '')
658
+ return true;
659
+ if (typeof (v) !== 'string')
660
+ return false;
661
+ v = v.replace(/(\-|\s)/g, ""); // remove dashes and spaces
662
+ if (!v || /\D/.test(v))
663
+ return false; // all digits, not empty
664
+ return luhn(v);
665
+ }
666
+ return new Validator('creditCard', valFn, context);
667
+ };
668
+ /**
669
+ Returns a regular expression validator; the expression must be specified
670
+ @example
671
+ // Add validator to a property. Assume em is a preexisting EntityManager.
672
+ var customerType = em.metadataStore.getEntityType("Customer");
673
+ var regionProperty = customerType.getProperty("Region");
674
+ // Validates that the value of Customer.Region is 2 char uppercase alpha.
675
+ regionProperty.validators.push(Validator.regularExpression( {expression: '^[A-Z]{2}$'} );
676
+ @method regularExpression
677
+ @static
678
+ @param context {Object}
679
+ @param context.expression {String} String form of the regular expression to apply
680
+ @return {Validator} A new Validator
681
+ **/
682
+ Validator.regularExpression = function (context) {
683
+ function valFn(v, ctx) {
684
+ // do not invalidate if empty; use a separate required test
685
+ if (v == null || v === '')
686
+ return true;
687
+ if (typeof (v) !== 'string')
688
+ return false;
689
+ try {
690
+ var re = new RegExp(ctx.expression);
691
+ return re.test(v);
692
+ }
693
+ catch (e) {
694
+ throw new Error('Missing or invalid expression parameter to regExp validator');
695
+ }
696
+ }
697
+ return new Validator('regularExpression', valFn, context);
698
+ };
699
+ /**
700
+ Returns the email address validator
701
+ @example
702
+ // Assume em is a preexisting EntityManager.
703
+ var personType = em.metadataStore.getEntityType("Person");
704
+ var emailProperty = personType.getProperty("email");
705
+ // Validates that the value of the Person.email property is an email address.
706
+ emailProperty.validators.push(Validator.emailAddress());
707
+ @method emailAddress
708
+ @static
709
+ @param [context] {Object} optional parameters to pass through to validation constructor
710
+ @return {Validator} A new Validator
711
+ **/
712
+ Validator.emailAddress = function (context) {
713
+ // See https://github.com/srkirkland/DataAnnotationsExtensions/blob/master/DataAnnotationsExtensions/EmailAttribute.cs
714
+ var reEmailAddress = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i;
715
+ return makeRegExpValidator('emailAddress', reEmailAddress, null, context);
716
+ };
717
+ /**
718
+ Returns the phone validator
719
+ Provides basic assertions on the format and will help to eliminate most nonsense input
720
+ Matches:
721
+ International dialing prefix: {{}, +, 0, 0000} (with or without a trailing break character, if not '+': [-/. ])
722
+ > ((\+)|(0(\d+)?[-/.\s]))
723
+ Country code: {{}, 1, ..., 999} (with or without a trailing break character: [-/. ])
724
+ > [1-9]\d{,2}[-/.\s]?
725
+ Area code: {(0), ..., (000000), 0, ..., 000000} (with or without a trailing break character: [-/. ])
726
+ > ((\(\d{1,6}\)|\d{1,6})[-/.\s]?)?
727
+ Local: {0, ...}+ (with or without a trailing break character: [-/. ])
728
+ > (\d+[-/.\s]?)+\d+
729
+ @example
730
+ // Assume em is a preexisting EntityManager.
731
+ var customerType = em.metadataStore.getEntityType("Customer");
732
+ var phoneProperty = customerType.getProperty("phone");
733
+ // Validates that the value of the Customer.phone property is phone.
734
+ phoneProperty.validators.push(Validator.phone());
735
+ @method phone
736
+ @static
737
+ @param [context] {Object} optional parameters to pass through to validation constructor
738
+ @return {Validator} A new Validator
739
+ **/
740
+ Validator.phone = function (context) {
741
+ // See https://github.com/srkirkland/DataAnnotationsExtensions/blob/master/DataAnnotationsExtensions/Expressions.cs
742
+ var rePhone = /^((\+|(0(\d+)?[-/.\s]?))[1-9]\d{0,2}[-/.\s]?)?((\(\d{1,6}\)|\d{1,6})[-/.\s]?)?(\d+[-/.\s]?)+\d+$/;
743
+ return makeRegExpValidator('phone', rePhone, null, context);
744
+ };
745
+ /**
746
+ Returns the URL (protocol required) validator
747
+ @example
748
+ // Assume em is a preexisting EntityManager.
749
+ var personType = em.metadataStore.getEntityType("Person");
750
+ var websiteProperty = personType.getProperty("website");
751
+ // Validates that the value of the Person.website property is a URL.
752
+ websiteProperty.validators.push(Validator.url());
753
+ @method url
754
+ @static
755
+ @param [context] {Object} optional parameters to pass through to validation constructor
756
+ @return {Validator} A new Validator
757
+ **/
758
+ Validator.url = function (context) {
759
+ //See https://github.com/srkirkland/DataAnnotationsExtensions/blob/master/DataAnnotationsExtensions/UrlAttribute.cs
760
+ var reUrlProtocolRequired = /^(https?|ftp):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|([a-zA-Z][\-a-zA-Z0-9]*)|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/;
761
+ return makeRegExpValidator('url', reUrlProtocolRequired, null, context);
762
+ };
763
+ /**
764
+ Creates a regular expression validator with a fixed expression.
765
+ Many of the stock validators are built with this factory method.
766
+ Their expressions are often derived from
767
+ https://github.com/srkirkland/DataAnnotationsExtensions/blob/master/DataAnnotationsExtensions
768
+ You can try many of them at http://dataannotationsextensions.org/
769
+ @example
770
+ // Make a zipcode validator
771
+ function zipValidator = Validator.makeRegExpValidator(
772
+ "zipVal,
773
+ /^\d{5}([\-]\d{4})?$/,
774
+ "The %displayName% '%value%' is not a valid U.S. zipcode");
775
+ // Register it.
776
+ Validator.register(zipValidator);
777
+ // Add it to a data property. Assume em is a preexisting EntityManager.
778
+ var custType = em.metadataStore.getEntityType("Customer");
779
+ var zipProperty = custType.getProperty("PostalCode");
780
+ zipProperty.validators.push(zipValidator);
781
+ @method makeRegExpValidator
782
+ @static
783
+ @param validatorName {String} name of this validator
784
+ @param expression {String | RegExp} regular expression to apply
785
+ @param [defaultMessage] {String} default message for failed validations
786
+ @param [context] {Object} optional parameters to pass through to validation constructor
787
+ @return {Validator} A new Validator
788
+ **/
789
+ Validator.makeRegExpValidator = makeRegExpValidator;
790
+ return Validator;
791
+ }());
792
+ export { Validator };
793
+ Validator.prototype._$typeName = "Validator";
794
+ // register all validators
795
+ Error['x'] = core.objectForEach(Validator, function (key, value) {
796
+ if (typeof (value) !== "function") {
797
+ return;
798
+ }
799
+ if (key === "fromJSON" || key === "register" ||
800
+ key === "registerFactory" || key === "makeRegExpValidator") {
801
+ return;
802
+ }
803
+ config.registerFunction(value, "Validator." + key);
804
+ });
805
+ function formatTemplate(template, vars, ownPropertiesOnly) {
806
+ if (ownPropertiesOnly === void 0) { ownPropertiesOnly = false; }
807
+ if (!vars)
808
+ return template;
809
+ return template.replace(/%([^%]+)%/g, function (_, key) {
810
+ var valOrFn;
811
+ if (ownPropertiesOnly) {
812
+ valOrFn = vars.hasOwnProperty(key) ? vars[key] : '';
813
+ }
814
+ else {
815
+ valOrFn = vars[key];
816
+ }
817
+ if (valOrFn != null) {
818
+ if (core.isFunction(valOrFn)) {
819
+ return valOrFn(vars);
820
+ }
821
+ else {
822
+ return valOrFn;
823
+ }
824
+ }
825
+ else {
826
+ return "";
827
+ }
828
+ });
829
+ }
830
+ function intRangeValidatorCtor(validatorName, minValue, maxValue, context) {
831
+ context = context || {};
832
+ if (minValue !== undefined) {
833
+ context.min = minValue;
834
+ }
835
+ if (maxValue !== undefined) {
836
+ context.max = maxValue;
837
+ }
838
+ var templateExists = context.messageTemplate || Validator.messageTemplates[validatorName];
839
+ if (!templateExists) {
840
+ Validator.messageTemplates[validatorName] = core.formatString("'%displayName%' must be an integer between the values of %1 and %2", minValue, maxValue);
841
+ }
842
+ return function () {
843
+ var valFn = function (v, ctx) {
844
+ if (v == null)
845
+ return true;
846
+ if (typeof v === "string" && ctx && ctx.allowString) {
847
+ v = parseInt(v, 0);
848
+ }
849
+ if ((typeof v === "number") && (!isNaN(v)) && Math.floor(v) === v) {
850
+ if (minValue != null && v < minValue) {
851
+ return false;
852
+ }
853
+ if (maxValue != null && v > maxValue) {
854
+ return false;
855
+ }
856
+ return true;
857
+ }
858
+ else {
859
+ return false;
860
+ }
861
+ };
862
+ return new Validator(validatorName, valFn, context);
863
+ };
864
+ }
865
+ export function makeRegExpValidator(validatorName, expression, defaultMessage, context) {
866
+ if (defaultMessage) {
867
+ Validator.messageTemplates[validatorName] = defaultMessage;
868
+ }
869
+ var re = (typeof (expression) === 'string') ? new RegExp(expression) : expression;
870
+ var valFn = function (v) {
871
+ // do not invalidate if empty; use a separate required test
872
+ if (v == null || v === '')
873
+ return true;
874
+ if (typeof (v) !== 'string')
875
+ return false;
876
+ return re.test(v);
877
+ };
878
+ return new Validator(validatorName, valFn, context);
879
+ }
880
+ var ɵ1 = function () {
881
+ var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
882
+ return function (str) {
883
+ var counter = 0;
884
+ var incNum;
885
+ var odd = false;
886
+ var temp = String(str).replace(/[^\d]/g, "");
887
+ if (temp.length === 0)
888
+ return false;
889
+ for (var i = temp.length - 1; i >= 0; --i) {
890
+ incNum = parseInt(temp.charAt(i), 10);
891
+ counter += (odd = !odd) ? incNum : luhnArr[incNum];
892
+ }
893
+ return (counter % 10 === 0);
894
+ };
895
+ };
896
+ // http://rosettacode.org/wiki/Luhn_test_of_credit_card_numbers#JavaScript
897
+ // function luhn(a: string, b: number, c: number, d: number, e: number) {
898
+ // for (d = +a[b = a.length - 1], e = 0; b--; ) {
899
+ // c = +a[b], d += ++e % 2 ? 2 * c % 10 + (c > 4) : c;
900
+ // }
901
+ // return !(d % 10);
902
+ // };
903
+ var luhn = (ɵ1)();
904
+ /**
905
+ A ValidationError is used to describe a failed validation.
906
+
907
+ @class ValidationError
908
+ **/
909
+ /**
910
+ Constructs a new ValidationError
911
+ @method <ctor> ValidationError
912
+
913
+ @param validator {Validator || null} The Validator used to create this error, if any.
914
+ @param context { ContextObject || null} The Context object used in conjunction with the Validator to create this error.
915
+ @param errorMessage { String} The actual error message
916
+ @param [key] {String} An optional key used to define a key for this error. One will be created automatically if not provided here.
917
+ **/
918
+ var ValidationError = /** @class */ (function () {
919
+ function ValidationError(validator, context, errorMessage, key) {
920
+ // Error is with isInstanceOf(Validator)
921
+ assertParam(validator, "validator").isOptional().isInstanceOf(Validator).check();
922
+ assertParam(errorMessage, "errorMessage").isNonEmptyString().check();
923
+ assertParam(key, "key").isOptional().isNonEmptyString().check();
924
+ this.validator = validator || undefined;
925
+ context = context || {};
926
+ this.context = context;
927
+ this.errorMessage = errorMessage;
928
+ this.property = context.property;
929
+ this.propertyName = context.propertyName || (context.property && context.property.name);
930
+ if (key) {
931
+ this.key = key;
932
+ }
933
+ else {
934
+ this.key = ValidationError.getKey(validator || errorMessage, this.propertyName);
935
+ }
936
+ this.isServerError = false;
937
+ }
938
+ /**
939
+ The Validator associated with this ValidationError.
940
+
941
+ __readOnly__
942
+ @property validator {Validator}
943
+ **/
944
+ /**
945
+ A 'context' object associated with this ValidationError.
946
+
947
+ __readOnly__
948
+ @property context {Object}
949
+ **/
950
+ /**
951
+ The DataProperty or NavigationProperty associated with this ValidationError.
952
+
953
+ __readOnly__
954
+ @property property {DataProperty|NavigationProperty}
955
+ **/
956
+ /**
957
+ The property name associated with this ValidationError. This will be a "property path" for any properties of a complex object.
958
+
959
+ __readOnly__
960
+ @property propertyName {String}
961
+ **/
962
+ /**
963
+ The error message associated with the ValidationError.
964
+
965
+ __readOnly__
966
+ @property errorMessage {string}
967
+ **/
968
+ /**
969
+ The key by which this validation error may be removed from a collection of ValidationErrors.
970
+
971
+ __readOnly__
972
+ @property key {string}
973
+ **/
974
+ /**
975
+ Whether this is a server error.
976
+
977
+ __readOnly__
978
+ @property isServerError {bool}
979
+ **/
980
+ /**
981
+ Composes a ValidationError 'key' given a validator or an errorName and an optional propertyName
982
+ @method getKey
983
+ @static
984
+ @param validator {ValidatorOrErrorKey} A Validator or an "error name" if no validator is available.
985
+ @param [propertyName] A property name
986
+ @return {String} A ValidationError 'key'
987
+ **/
988
+ ValidationError.getKey = function (validatorOrErrorName, propertyName) {
989
+ var name = (typeof validatorOrErrorName === 'string') ? validatorOrErrorName : validatorOrErrorName.name;
990
+ return name + (propertyName ? ":" + propertyName : "");
991
+ };
992
+ return ValidationError;
993
+ }());
994
+ export { ValidationError };
995
+ export { ɵ0, ɵ1 };
996
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9icmVlemUtY2xpZW50LyIsInNvdXJjZXMiOlsic3JjL3ZhbGlkYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDOUIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFJbEMsTUFBTSxDQUFDLElBQU0sU0FBUyxHQUFHLENBQUMsS0FBSyxDQUFDO0FBQ2hDLE1BQU0sQ0FBQyxJQUFNLFNBQVMsR0FBRyxLQUFLLENBQUM7QUFFL0IsTUFBTSxDQUFDLElBQU0sU0FBUyxHQUFHLENBQUMsVUFBVSxDQUFDO0FBQ3JDLE1BQU0sQ0FBQyxJQUFNLFNBQVMsR0FBRyxVQUFVLENBQUM7QUFFcEMsTUFBTSxDQUFDLElBQU0sUUFBUSxHQUFHLENBQUMsQ0FBQztBQUMxQixNQUFNLENBQUMsSUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDO1NBMEJiLFVBQVUsT0FBMEI7SUFDL0MsSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFO1FBQ3BCLE9BQU8sT0FBTyxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLElBQUksT0FBTyxDQUFDLFlBQVksSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztLQUN6RztTQUFNO1FBQ0wsT0FBTyxPQUFPLENBQUM7S0FDaEI7QUFDSCxDQUFDO0FBUkgsbUVBQW1FO0FBQ25FLElBQUksV0FBVyxHQUFHO0lBQ2hCLFdBQVcsSUFNVjtDQUNGLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7OztHQWFHO0FBRUg7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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QyxvQkFBb0IsQ0FBQyxJQUFJLENBQUM7UUFDekcsT0FBTyxJQUFJLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFSCxzQkFBQztBQUFELENBQUMsQUE5RkQsSUE4RkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjb3JlIH0gZnJvbSAnLi9jb3JlJztcclxuaW1wb3J0IHsgYXNzZXJ0UGFyYW0gfSBmcm9tICcuL2Fzc2VydC1wYXJhbSc7XHJcbmltcG9ydCB7IGNvbmZpZyB9IGZyb20gJy4vY29uZmlnJztcclxuaW1wb3J0IHsgTmF2aWdhdGlvblByb3BlcnR5LCBEYXRhUHJvcGVydHkgfSBmcm9tICcuL2VudGl0eS1tZXRhZGF0YSc7XHJcbmltcG9ydCB7IEVudGl0eSB9IGZyb20gJy4vZW50aXR5LWFzcGVjdCc7XHJcblxyXG5leHBvcnQgY29uc3QgSU5UMTZfTUlOID0gLTMyNzY4O1xyXG5leHBvcnQgY29uc3QgSU5UMTZfTUFYID0gMzI3Njc7XHJcblxyXG5leHBvcnQgY29uc3QgSU5UMzJfTUlOID0gLTIxNDc0ODM2NDg7XHJcbmV4cG9ydCBjb25zdCBJTlQzMl9NQVggPSAyMTQ3NDgzNjQ3O1xyXG5cclxuZXhwb3J0IGNvbnN0IEJZVEVfTUlOID0gMDtcclxuZXhwb3J0IGNvbnN0IEJZVEVfTUFYID0gMjU1O1xyXG5cclxuLyoqIFBhc3NlZCB0byBWYWxpZGF0aW9uRm4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0aW9uQ29udGV4dCB7XHJcbiAgZW50aXR5PzogRW50aXR5O1xyXG4gIHByb3BlcnR5PzogRGF0YVByb3BlcnR5IHwgTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gIHByb3BlcnR5TmFtZT86IHN0cmluZztcclxuICB2YWx1ZT86IGFueTtcclxufVxyXG5cclxuLyoqIFVzZWQgYnkgVmFsaWRhdG9yIHRvIGNvbXBvc2UgbWVzc2FnZXMgKi9cclxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0aW9uTWVzc2FnZUNvbnRleHQgZXh0ZW5kcyBWYWxpZGF0aW9uQ29udGV4dCB7XHJcbiAgbmFtZT86IHN0cmluZztcclxuICBkaXNwbGF5TmFtZT86IHN0cmluZztcclxuICBtZXNzYWdlVGVtcGxhdGU/OiBzdHJpbmc7XHJcbiAgbWVzc2FnZT86IHN0cmluZyB8ICgodmM6IFZhbGlkYXRpb25Db250ZXh0KSA9PiBzdHJpbmcpO1xyXG4gIFtrZXk6c3RyaW5nXTogYW55O1xyXG59XHJcblxyXG4vKiogRnVuY3Rpb24gY2FsbGVkIHRvIHZhbGlkYXRlIGFuIGVudGl0eSBvciBwcm9wZXJ0eSAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRpb25GbiB7XHJcbiAgICAodmFsdWU6IGFueSwgY29udGV4dD86IFZhbGlkYXRpb25Db250ZXh0KTogYm9vbGVhbjtcclxufVxyXG5cclxuLy8gYWRkIGNvbW1vbiBwcm9wcyBhbmQgbWV0aG9kcyBmb3IgZXZlcnkgdmFsaWRhdG9yICdjb250ZXh0JyBoZXJlLlxyXG5sZXQgcm9vdENvbnRleHQgPSB7XHJcbiAgZGlzcGxheU5hbWU6IGZ1bmN0aW9uIChjb250ZXh0OiBWYWxpZGF0aW9uQ29udGV4dCkge1xyXG4gICAgaWYgKGNvbnRleHQucHJvcGVydHkpIHtcclxuICAgICAgcmV0dXJuIGNvbnRleHQucHJvcGVydHkucmVzb2x2ZVByb3BlcnR5KFwiZGlzcGxheU5hbWVcIikgfHwgY29udGV4dC5wcm9wZXJ0eU5hbWUgfHwgY29udGV4dC5wcm9wZXJ0eS5uYW1lO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIFwiVmFsdWVcIjtcclxuICAgIH1cclxuICB9XHJcbn07XHJcblxyXG4vKipcclxuSW5zdGFuY2VzIG9mIHRoZSBWYWxpZGF0b3IgY2xhc3MgcHJvdmlkZSB0aGUgbG9naWMgdG8gdmFsaWRhdGUgYW5vdGhlciBvYmplY3QgYW5kIHByb3ZpZGUgYSBkZXNjcmlwdGlvbiBvZiBhbnkgZXJyb3JzXHJcbmVuY291bnRlcmVkIGR1cmluZyB0aGUgdmFsaWRhdGlvbiBwcm9jZXNzLiAgVGhleSBhcmUgdHlwaWNhbGx5IGFzc29jaWF0ZWQgd2l0aCBhICd2YWxpZGF0b3JzJyBwcm9wZXJ0eSBvbiB0aGUgZm9sbG93aW5nIHR5cGVzOiBbW0VudGl0eVR5cGVdXSxcclxuW1tEYXRhUHJvcGVydHldXSBvciBbW05hdmlnYXRpb25Qcm9wZXJ0eV1dLlxyXG5cclxuQSBudW1iZXIgb2YgcHJvcGVydHkgbGV2ZWwgdmFsaWRhdG9ycyBhcmUgcmVnaXN0ZXJlZCBhdXRvbWF0aWNhbGx5LCBpLmUgYWRkZWQgdG8gZWFjaCBEYXRhUHJvcGVydHkudmFsaWRhdG9ycyBwcm9wZXJ0eVxyXG5iYXNlZCBvbiBbW0RhdGFQcm9wZXJ0eV1dIG1ldGFkYXRhLiAgRm9yIGV4YW1wbGUsXHJcblxyXG4tIERhdGFQcm9wZXJ0eS5kYXRhVHlwZSAtPiBvbmUgb2YgdGhlICdkYXRhVHlwZScgdmFsaWRhdG9yIG1ldGhvZHMgc3VjaCBhcyBWYWxpZGF0b3IuaW50NjQsIFZhbGlkYXRvci5kYXRlLCBWYWxpZGF0b3IuYm9vbCBldGMuXHJcbi0gRGF0YVByb3BlcnR5Lm1heExlbmd0aCAtPiBWYWxpZGF0b3IubWF4TGVuZ3RoXHJcbi0gRGF0YVByb3BlcnR5LmlzTnVsbGFibGUgLT4gVmFsaWRhdG9yLnJlcXVpcmVkIChpZiBub3QgbnVsbGFibGUpXHJcblxyXG5AY2xhc3MgVmFsaWRhdG9yXHJcbioqL1xyXG5cclxuLyoqXHJcblZhbGlkYXRvciBjb25zdHJ1Y3RvciAtIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gY3JlYXRlIGNyZWF0ZSBjdXN0b20gdmFsaWRhdGlvbnMuICBTZXZlcmFsXHJcbmJhc2ljIFwiVmFsaWRhdG9yXCIgY29uc3RydWN0aW9uIG1ldGhvZHMgYXJlIGFsc28gcHJvdmlkZWQgYXMgc3RhdGljIG1ldGhvZHMgdG8gdGhpcyBjbGFzcy4gVGhlc2UgbWV0aG9kc1xyXG5wcm92aWRlIGEgc2ltcGxlciBzeW50YXggZm9yIGNyZWF0aW5nIGJhc2ljIHZhbGlkYXRpb25zLlxyXG5cclxuTWFueSBvZiB0aGVzZSBzdG9jayB2YWxpZGF0b3JzIGFyZSBpbnNwaXJlZCBieSBhbmQgaW1wbGVtZW50ZWQgdG8gY29uZm9ybSB0byB0aGUgdmFsaWRhdG9ycyBkZWZpbmVkIGF0XHJcbmh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9zeXN0ZW0uY29tcG9uZW50bW9kZWwuZGF0YWFubm90YXRpb25zLmFzcHhcclxuXHJcblNvbWV0aW1lcyBhIGN1c3RvbSB2YWxpZGF0b3Igd2lsbCBiZSByZXF1aXJlZC5cclxuQGV4YW1wbGVcclxuTW9zdCB2YWxpZGF0b3JzIHdpbGwgYmUgJ3Byb3BlcnR5JyBsZXZlbCB2YWxpZGF0b3JzLCBsaWtlIHRoaXMuXHJcbkBleGFtcGxlXHJcbiAgICAvLyB2IGlzIHRoaXMgZnVuY3Rpb24gaXMgdGhlIHZhbHVlIHRvIGJlIHZhbGlkYXRlZCwgaW4gdGhpcyBjYXNlIGEgXCJjb3VudHJ5XCIgc3RyaW5nLlxyXG4gICAgdmFyIHZhbEZuID0gZnVuY3Rpb24gKHYpIHtcclxuICAgICAgICBpZiAodiA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcclxuICAgICAgICByZXR1cm4gKGNvcmUuc3RyaW5nU3RhcnRzV2l0aCh2LCBcIlVTXCIpKTtcclxuICAgIH07XHJcbiAgICB2YXIgY291bnRyeVZhbGlkYXRvciA9IG5ldyBWYWxpZGF0b3IoXCJjb3VudHJ5SXNVU1wiLCB2YWxGbiwge1xyXG4gICAgICAgIGRpc3BsYXlOYW1lOiBcIkNvdW50cnlcIiwgXHJcbiAgICAgICAgbWVzc2FnZVRlbXBsYXRlOiBcIiclZGlzcGxheU5hbWUlJyBtdXN0IHN0YXJ0IHdpdGggJ1VTJ1wiIFxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gTm93IHBsdWcgaXQgaW50byBCcmVlemUuXHJcbiAgICAvLyBBc3N1bWUgZW0xIGlzIGEgcHJlZXhpc3RpbmcgRW50aXR5TWFuYWdlci5cclxuICAgIHZhciBjdXN0VHlwZSA9IG1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gICAgdmFyIGNvdW50cnlQcm9wID0gY3VzdFR5cGUuZ2V0UHJvcGVydHkoXCJDb3VudHJ5XCIpO1xyXG4gICAgLy8gTm90ZSB0aGF0IHZhbGlkYXRvciBpcyBhZGRlZCB0byBhICdEYXRhUHJvcGVydHknIHZhbGlkYXRvcnMgY29sbGVjdGlvbi5cclxuICAgIHByb3AudmFsaWRhdG9ycy5wdXNoKGNvdW50cnlWYWxpZGF0b3IpO1xyXG5FbnRpdHkgbGV2ZWwgdmFsaWRhdG9ycyBhcmUgYWxzbyBwb3NzaWJsZVxyXG5AZXhhbXBsZVxyXG4gICAgZnVuY3Rpb24gaXNWYWxpZFppcENvZGUodmFsdWUpIHtcclxuICAgICAgICB2YXIgcmUgPSAvXlxcZHs1fShbXFwtXVxcZHs0fSk/JC87XHJcbiAgICAgICAgcmV0dXJuIChyZS50ZXN0KHZhbHVlKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gdiBpbiB0aGlzIGNhc2Ugd2lsbCBiZSBhIEN1c3RvbWVyIGVudGl0eVxyXG4gICAgdmFyIHZhbEZuID0gZnVuY3Rpb24gKHYpIHtcclxuICAgICAgICAvLyBUaGlzIHZhbGlkYXRvciBvbmx5IHZhbGlkYXRlcyBVUyBaaXAgQ29kZXMuXHJcbiAgICAgICAgaWYgKCB2LmdldFByb3BlcnR5KFwiQ291bnRyeVwiKSA9PT0gXCJVU0FcIikge1xyXG4gICAgICAgICAgICB2YXIgcG9zdGFsQ29kZSA9IHYuZ2V0UHJvcGVydHkoXCJQb3N0YWxDb2RlXCIpO1xyXG4gICAgICAgICAgICByZXR1cm4gaXNWYWxpZFppcENvZGUocG9zdGFsQ29kZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfTtcclxuICAgIHZhciB6aXBDb2RlVmFsaWRhdG9yID0gbmV3IFZhbGlkYXRvcihcInppcENvZGVWYWxpZGF0b3JcIiwgdmFsRm4sXHJcbiAgICAgICAgeyBtZXNzYWdlVGVtcGxhdGU6IFwiRm9yIHRoZSBVUywgdGhpcyBpcyBub3QgYSB2YWxpZCBQb3N0YWxDb2RlXCIgfSk7XHJcblxyXG4gICAgLy8gTm93IHBsdWcgaXQgaW50byBCcmVlemUuXHJcbiAgICAvLyBBc3N1bWUgZW0xIGlzIGEgcHJlZXhpc3RpbmcgRW50aXR5TWFuYWdlci5cclxuICAgIHZhciBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICAgIC8vIE5vdGUgdGhhdCB2YWxpZGF0b3IgaXMgYWRkZWQgdG8gYW4gJ0VudGl0eVR5cGUnIHZhbGlkYXRvcnMgY29sbGVjdGlvbi5cclxuICAgIGN1c3RUeXBlLnZhbGlkYXRvcnMucHVzaCh6aXBDb2RlVmFsaWRhdG9yKTtcclxuV2hhdCBpcyBjb21tb25seSBuZWVkZWQgaXMgYSB3YXkgb2YgY3JlYXRpbmcgYSBwYXJhbWV0ZXJpemVkIGZ1bmN0aW9uIHRoYXQgd2lsbCBpdHNlbGZcclxucmV0dXJuIGEgbmV3IFZhbGlkYXRvci4gIFRoaXMgcmVxdWlyZXMgdGhlIHVzZSBvZiBhICdjb250ZXh0JyBvYmplY3QuXHJcbkBleGFtcGxlXHJcbiAgICAvLyBjcmVhdGUgYSBmdW5jdGlvbiB0aGF0IHdpbGwgdGFrZSBpbiBhIGNvbmZpZyBvYmplY3RcclxuICAgIC8vIGFuZCB3aWxsIHJldHVybiBhIHZhbGlkYXRvclxyXG4gICAgdmFyIG51bWVyaWNSYW5nZVZhbGlkYXRvciA9IGZ1bmN0aW9uKGNvbnRleHQpIHtcclxuICAgICAgICB2YXIgdmFsRm4gPSBmdW5jdGlvbih2LCBjdHgpIHtcclxuICAgICAgICAgICAgaWYgKHYgPT0gbnVsbCkgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YodikgIT09IFwibnVtYmVyXCIpIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgaWYgKGN0eC5taW4gIT0gbnVsbCAmJiB2IDwgY3R4Lm1pbikgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICBpZiAoY3R4Lm1heCAhPSBudWxsICYmIHYgPiBjdHgubWF4KSByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgLy8gVGhlIGxhc3QgcGFyYW1ldGVyIGJlbG93IGlzIHRoZSAnY29udGV4dCcgb2JqZWN0IHRoYXQgd2lsbCBiZSBwYXNzZWQgaW50byB0aGUgJ2N0eCcgcGFyYW1ldGVyIGFib3ZlXHJcbiAgICAgICAgLy8gd2hlbiB0aGlzIHZhbGlkYXRvciBleGVjdXRlcy4gU2V2ZXJhbCBvdGhlciBwcm9wZXJ0aWVzLCBzdWNoIGFzIGRpc3BsYXlOYW1lIHdpbGwgZ2V0IGFkZGVkIHRvIHRoaXMgb2JqZWN0IGFzIHdlbGwuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBWYWxpZGF0b3IoXCJudW1lcmljUmFuZ2VcIiwgdmFsRm4sIHtcclxuICAgICAgICAgICAgbWVzc2FnZVRlbXBsYXRlOiBcIiclZGlzcGxheU5hbWUlJyBtdXN0IGJlIGEgbnVtYmVyIGJldHdlZW4gdGhlIHZhbHVlcyBvZiAlbWluJSBhbmQgJW1heCVcIixcclxuICAgICAgICAgICAgbWluOiBjb250ZXh0Lm1pbixcclxuICAgICAgICAgICAgbWF4OiBjb250ZXh0Lm1heFxyXG4gICAgICAgIH0pO1xyXG4gICAgfTtcclxuICAgIC8vIEFzc3VtZSB0aGF0IGZyZWlnaHRQcm9wZXJ0eSBpcyBhIERhdGFFbnRpdHlQcm9wZXJ0eSB0aGF0IGRlc2NyaWJlcyBudW1lcmljIHZhbHVlcy5cclxuICAgIC8vIHJlZ2lzdGVyIHRoZSB2YWxpZGF0b3JcclxuICAgIGZyZWlnaHRQcm9wZXJ0eS52YWxpZGF0b3JzLnB1c2gobnVtZXJpY1JhbmdlVmFsaWRhdG9yKHsgbWluOiAxMDAsIG1heDogNTAwIH0pKTtcclxuXHJcbkJyZWV6ZSBzdWJzdGl0dXRlcyBjb250ZXh0IHZhbHVlcyBhbmQgZnVuY3Rpb25zIGZvciB0aGUgdG9rZW5zIGluIHRoZSBtZXNzYWdlVGVtcGxhdGUgd2hlbiBwcmVwYXJpbmcgdGhlIHJ1bnRpbWUgZXJyb3IgbWVzc2FnZTtcclxuJ2Rpc3BsYXlOYW1lJyBpcyBhIHByZS1kZWZpbmVkIGNvbnRleHQgZnVuY3Rpb24gdGhhdCBpcyBhbHdheXMgYXZhaWxhYmxlLlxyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBCcmVlemUgc3Vic3RpdHV0ZXMgdGhlIGVtcHR5IHN0cmluZyBmb3IgZmFsc2V5IHBhcmFtZXRlcnMuIFRoYXQgdXN1YWxseSB3b3JrcyBpbiB5b3VyIGZhdm9yLlxyXG5Tb21ldGltZXMgaXQgZG9lc24ndCBhcyB3aGVuIHRoZSAnbWluJyB2YWx1ZSBpcyB6ZXJvIGluIHdoaWNoIGNhc2UgdGhlIG1lc3NhZ2UgdGV4dCB3b3VsZCBoYXZlIGEgaG9sZVxyXG53aGVyZSB0aGUgJ21pbicgdmFsdWUgZ29lcywgc2F5aW5nOiBcIi4uLiBhbiBpbnRlZ2VyIGJldHdlZW4gdGhlIHZhbHVlcyBvZiBhbmQgLi4uXCIuIFRoYXQgaXMgbm90IHdoYXQgeW91IHdhbnQuXHJcblxyXG5UbyBhdm9pZCB0aGlzIGVmZmVjdCwgeW91IG1heSBjYW4gYmFrZSBjZXJ0YWluIG9mIHRoZSBjb250ZXh0IHZhbHVlcyBpbnRvIHRoZSAnbWVzc2FnZVRlbXBsYXRlJyBpdHNlbGZcclxuYXMgc2hvd24gaW4gdGhpcyByZXZpc2lvbiB0byB0aGUgcGVydGluZW50IHBhcnQgb2YgdGhlIHByZXZpb3VzIGV4YW1wbGU6XHJcbkBleGFtcGxlXHJcbiAgICAvLyAuLi4gYXMgYmVmb3JlXHJcbiAgICAvLyAuLi4gYnV0IGJha2UgdGhlIG1pbi9tYXggdmFsdWVzIGludG8gdGhlIG1lc3NhZ2UgdGVtcGxhdGUuXHJcbiAgICB2YXIgdGVtcGxhdGUgPSBicmVlemUuY29yZS5mb3JtYXRTdHJpbmcoXHJcbiAgICAgICAgXCInJWRpc3BsYXlOYW1lJScgbXVzdCBiZSBhIG51bWJlciBiZXR3ZWVuIHRoZSB2YWx1ZXMgb2YgJTEgYW5kICUyXCIsXHJcbiAgICAgICAgY29udGV4dC5taW4sIGNvbnRleHQubWF4KTtcclxuICAgIHJldHVybiBuZXcgVmFsaWRhdG9yKFwibnVtZXJpY1JhbmdlXCIsIHZhbEZuLCB7XHJcbiAgICAgICAgbWVzc2FnZVRlbXBsYXRlOiB0ZW1wbGF0ZSxcclxuICAgICAgICBtaW46IGNvbnRleHQubWluLFxyXG4gICAgICAgIG1heDogY29udGV4dC5tYXhcclxuICAgIH0pO1xyXG5cclxuQG1ldGhvZCA8Y3Rvcj4gVmFsaWRhdG9yXHJcbkBwYXJhbSBuYW1lIHtTdHJpbmd9IFRoZSBuYW1lIG9mIHRoaXMgdmFsaWRhdG9yLlxyXG5AcGFyYW0gdmFsaWRhdG9yRm4ge0Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIHBlcmZvcm0gdmFsaWRhdGlvbi5cclxuXHJcbnZhbGlkYXRvckZuKHZhbHVlLCBjb250ZXh0KVxyXG5AcGFyYW0gdmFsaWRhdG9yRm4udmFsdWUge09iamVjdH0gVmFsdWUgdG8gYmUgdmFsaWRhdGVkXHJcbkBwYXJhbSB2YWxpZGF0b3JGbi5jb250ZXh0IHtPYmplY3R9IFRoZSBzYW1lIGNvbnRleHQgb2JqZWN0IHBhc3NlZCBpbnRvIHRoZSBjb25zdHJ1Y3RvciB3aXRoIHRoZSBmb2xsb3dpbmcgYWRkaXRpb25hbCBwcm9wZXJ0aWVzIGlmIG5vdFxyXG5vdGhlcndpc2Ugc3BlY2lmaWVkLlxyXG5AcGFyYW0gdmFsaWRhdG9yRm4uY29udGV4dC52YWx1ZSB7T2JqZWN0fSBUaGUgdmFsdWUgYmVpbmcgdmFsaWRhdGVkLlxyXG5AcGFyYW0gdmFsaWRhdG9yRm4uY29udGV4dC5uYW1lIHtTdHJpbmd9IFRoZSBuYW1lIG9mIHRoZSB2YWxpZGF0b3IgYmVpbmcgZXhlY3V0ZWQuXHJcbkBwYXJhbSB2YWxpZGF0b3JGbi5jb250ZXh0LmRpc3BsYXlOYW1lIHtTdHJpbmd9IFRoaXMgd2lsbCBiZSBlaXRoZXIgdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSdzICdkaXNwbGF5TmFtZScgcHJvcGVydHkgb3JcclxudGhlIHZhbHVlIG9mIGl0cyAnbmFtZScgcHJvcGVydHkgb3IgdGhlIHN0cmluZyAnVmFsdWUnXHJcbkBwYXJhbSB2YWxpZGF0b3JGbi5jb250ZXh0Lm1lc3NhZ2VUZW1wbGF0ZSB7U3RyaW5nfSBUaGlzIHdpbGwgZWl0aGVyIGJlIHRoZSB2YWx1ZSBvZiBWYWxpZGF0b3IubWVzc2FnZVRlbXBsYXRlc1sge3RoaXMgdmFsaWRhdG9ycyBuYW1lfV0gb3IgbnVsbC4gVmFsaWRhdG9yLm1lc3NhZ2VUZW1wbGF0ZXNcclxuaXMgYW4gb2JqZWN0IHRoYXQgaXMga2V5ZWQgYnkgdmFsaWRhdG9yIG5hbWUgYW5kIHRoYXQgY2FuIGJlIGFkZGVkIHRvIGluIG9yZGVyIHRvICdyZWdpc3RlcicgeW91ciBvd24gbWVzc2FnZSBmb3IgYSBnaXZlbiB2YWxpZGF0b3IuXHJcblRoZSBmb2xsb3dpbmcgcHJvcGVydHkgY2FuIGFsc28gYmUgc3BlY2lmaWVkIGZvciBhbnkgdmFsaWRhdG9yIHRvIGZvcmNlIGEgc3BlY2lmaWMgZXJyb3JNZXNzYWdlIHN0cmluZ1xyXG5AcGFyYW0gW3ZhbGlkYXRvckZuLmNvbnRleHQubWVzc2FnZV0ge1N0cmluZ30gSWYgdGhpcyBwcm9wZXJ0eSBpcyBzZXQgaXQgd2lsbCBiZSB1c2VkIGluc3RlYWQgb2YgdGhlICdtZXNzYWdlVGVtcGxhdGUnIHByb3BlcnR5IHdoZW4gYW5cclxuZXJyb3IgbWVzc2FnZSBpcyBnZW5lcmF0ZWQuXHJcblxyXG5AcGFyYW0gW2NvbnRleHRdIHtPYmplY3R9IEEgZnJlZSBmb3JtIG9iamVjdCB3aG9zZSBwcm9wZXJ0aWVzIHdpbGwgbWFkZSBhdmFpbGFibGUgZHVyaW5nIHRoZSB2YWxpZGF0aW9uIGFuZCBlcnJvciBtZXNzYWdlIGNyZWF0aW9uIHByb2Nlc3MuXHJcblRoaXMgb2JqZWN0IHdpbGwgYmUgcGFzc2VkIGludG8gdGhlIFZhbGlkYXRvcidzIHZhbGlkYXRpb24gZnVuY3Rpb24gd2hlbmV2ZXIgJ3ZhbGlkYXRlJyBpcyBjYWxsZWQuIFNlZSBhYm92ZSBmb3IgYSBkZXNjcmlwdGlvblxyXG5vZiBhZGRpdGlvbmFsIHByb3BlcnRpZXMgdGhhdCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYWRkZWQgdG8gdGhpcyBvYmplY3QgaWYgbm90IG90aGVyd2lzZSBzcGVjaWZpZWQuXHJcbkBkeW5hbWljXHJcbioqL1xyXG5leHBvcnQgY2xhc3MgVmFsaWRhdG9yIHtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfJHR5cGVOYW1lOiBzdHJpbmc7IC8vIG9uIHByb3RvXHJcblxyXG4gIG5hbWU6IHN0cmluZztcclxuICB2YWxGbjogVmFsaWRhdGlvbkZuO1xyXG4gIGNvbnRleHQ6IFZhbGlkYXRpb25NZXNzYWdlQ29udGV4dDtcclxuICBjdXJyZW50Q29udGV4dDogVmFsaWRhdGlvbk1lc3NhZ2VDb250ZXh0O1xyXG4gIHByaXZhdGUgX2Jhc2VDb250ZXh0OiBWYWxpZGF0aW9uTWVzc2FnZUNvbnRleHQ7XHJcblxyXG4gIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgdmFsRm46IFZhbGlkYXRpb25GbiwgY29udGV4dD86IFZhbGlkYXRpb25NZXNzYWdlQ29udGV4dCkge1xyXG4gICAgLy8gX2Jhc2VDb250ZXh0IGlzIHdoYXQgd2lsbCBnZXQgc2VyaWFsaXplZFxyXG4gICAgdGhpcy5fYmFzZUNvbnRleHQgPSBjb250ZXh0IHx8IHt9IGFzIFZhbGlkYXRpb25NZXNzYWdlQ29udGV4dDtcclxuICAgIHRoaXMuX2Jhc2VDb250ZXh0Lm5hbWUgPSBuYW1lO1xyXG4gICAgY29udGV4dCA9IGNvcmUuZXh0ZW5kKE9iamVjdC5jcmVhdGUocm9vdENvbnRleHQpLCB0aGlzLl9iYXNlQ29udGV4dCkgYXMgVmFsaWRhdGlvbk1lc3NhZ2VDb250ZXh0O1xyXG4gICAgY29udGV4dC5tZXNzYWdlVGVtcGxhdGUgPSBjb250ZXh0Lm1lc3NhZ2VUZW1wbGF0ZSB8fCBWYWxpZGF0b3IubWVzc2FnZVRlbXBsYXRlc1tuYW1lXTtcclxuICAgIHRoaXMubmFtZSA9IG5hbWU7XHJcbiAgICB0aGlzLnZhbEZuID0gdmFsRm47XHJcbiAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgVGhlIG5hbWUgb2YgdGhpcyB2YWxpZGF0b3IuXHJcblxyXG4gIF9fcmVhZE9ubHlfX1xyXG4gIEBwcm9wZXJ0eSBuYW1lIHtTdHJpbmd9XHJcbiAgKiovXHJcblxyXG4gIC8qKlxyXG4gIFRoZSBjb250ZXh0IGZvciB0aGlzIHZhbGlkYXRvci5cclxuXHJcbiAgVGhpcyBvYmplY3Qgd2lsbCB0eXBpY2FsbHkgY29udGFpbiBhdCBhIG1pbmltdW0gdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzLiBcIm5hbWVcIiwgXCJkaXNwbGF5TmFtZVwiLCBhbmQgXCJtZXNzYWdlXCIgb3IgXCJtZXNzYWdlVGVtcGxhdGVcIi5cclxuICBfX3JlYWRPbmx5X19cclxuICBAcHJvcGVydHkgY29udGV4dCB7T2JqZWN0fVxyXG4gICoqL1xyXG5cclxuXHJcbiAgLyoqXHJcbiAgUnVuIHRoaXMgdmFsaWRhdG9yIGFnYWluc3QgdGhlIHNwZWNpZmllZCB2YWx1ZS4gIFRoaXMgbWV0aG9kIHdpbGwgdXN1YWxseSBiZSBjYWxsZWQgaW50ZXJuYWxseSBlaXRoZXJcclxuICBhdXRvbWF0aWNhbGx5IGJ5IGFuIHByb3BlcnR5IGNoYW5nZSwgZW50aXR5IGF0dGFjaCwgcXVlcnkgb3Igc2F2ZSBvcGVyYXRpb24sIG9yIG1hbnVhbGx5IGFzIGEgcmVzdWx0IG9mXHJcbiAgYSB2YWxpZGF0ZUVudGl0eSBjYWxsIG9uIHRoZSBFbnRpdHlBc3BlY3QuIFRoZSByZXN1bHRpbmcgVmFsaWRhdGlvblJlc3VsdHMgYXJlIGF2YWlsYWJsZSB2aWEgdGhlXHJcbiAgRW50aXR5QXNwZWN0LmdldFZhbGlkYXRpb25FcnJvcnMgbWV0aG9kLlxyXG5cclxuICBIb3dldmVyLCB5b3UgY2FuIGFsc28gY2FsbCBhIHZhbGlkYXRvciBkaXJlY3RseSBlaXRoZXIgZm9yIHRlc3RpbmcgcHVycG9zZXMgb3Igc29tZSBvdGhlciByZWFzb24gaWYgbmVlZGVkLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIHVzaW5nIG9uZSBvZiB0aGUgcHJlZGVmaW5lZCB2YWxpZGF0b3JzXHJcbiAgICAgIHZhciB2YWxpZGF0b3IgPSBWYWxpZGF0b3IubWF4TGVuZ3RoKHsgbWF4TGVuZ3RoOiA1LCBkaXNwbGF5TmFtZTogXCJDaXR5XCIgfSk7XHJcbiAgICAgIC8vIHNob3VsZCBiZSBvayBiZWNhdXNlIFwiYXNkZlwiLmxlbmd0aCA8IDVcclxuICAgICAgdmFyIHJlc3VsdCA9IHZhbGlkYXRvci52YWxpZGF0ZShcImFzZGZcIik7XHJcbiAgICAgIG9rKHJlc3VsdCA9PT0gbnVsbCk7XHJcbiAgICAgIHJlc3VsdCA9IHZhbGlkYXRvci52YWxpZGF0ZShcImFkYXNkZmFzZGZcIik7XHJcbiAgICAgIC8vIGV4dHJhY3QgYWxsIG9mIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSAncmVzdWx0J1xyXG4gICAgICB2YXIgZXJyTXNnID0gcmVzdWx0LmVycm9yTWVzc2FnZTtcclxuICAgICAgdmFyIGNvbnRleHQgPSByZXN1bHQuY29udGV4dDtcclxuICAgICAgdmFyIHNhbWVWYWxpZGF0b3IgPSByZXN1bHQudmFsaWRhdG9yO1xyXG4gIEBtZXRob2QgdmFsaWRhdGVcclxuICBAcGFyYW0gdmFsdWUge09iamVjdH0gVmFsdWUgdG8gdmFsaWRhdGVcclxuICBAcGFyYW0gYWRkaXRpb25hbENvbnRleHQge09iamVjdH0gQW55IGFkZGl0aW9uYWwgY29udGV4dHVhbCBpbmZvcm1hdGlvbiB0aGF0IHRoZSBWYWxpZGF0b3JcclxuICBjYW4gbWFrZSB1c2Ugb2YuXHJcbiAgQHJldHVybiB7VmFsaWRhdGlvbkVycm9yfG51bGx9IEEgVmFsaWRhdGlvbkVycm9yIGlmIHZhbGlkYXRpb24gZmFpbHMsIG51bGwgb3RoZXJ3aXNlXHJcbiAgKiovXHJcbiAgdmFsaWRhdGUodmFsdWU6IGFueSwgYWRkaXRpb25hbENvbnRleHQ/OiBWYWxpZGF0aW9uTWVzc2FnZUNvbnRleHQpIHtcclxuICAgIGxldCBjdXJyZW50Q29udGV4dDogVmFsaWRhdGlvbk1lc3NhZ2VDb250ZXh0OyAvLyB7IHZhbHVlPzogT2JqZWN0IH07XHJcbiAgICBpZiAoYWRkaXRpb25hbENvbnRleHQpIHtcclxuICAgICAgY3VycmVudENvbnRleHQgPSBjb3JlLmV4dGVuZChPYmplY3QuY3JlYXRlKHRoaXMuY29udGV4dCksIGFkZGl0aW9uYWxDb250ZXh0KSBhcyBWYWxpZGF0aW9uTWVzc2FnZUNvbnRleHQ7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjdXJyZW50Q29udGV4dCA9IHRoaXMuY29udGV4dDtcclxuICAgIH1cclxuICAgIHRoaXMuY3VycmVudENvbnRleHQgPSBjdXJyZW50Q29udGV4dDtcclxuXHJcbiAgICB0cnkge1xyXG4gICAgICBpZiAodGhpcy52YWxGbih2YWx1ZSwgY3VycmVudENvbnRleHQpKSB7XHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY3VycmVudENvbnRleHQudmFsdWUgPSB2YWx1ZTtcclxuICAgICAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25FcnJvcih0aGlzLCBjdXJyZW50Q29udGV4dCwgdGhpcy5nZXRNZXNzYWdlKCkpO1xyXG4gICAgICB9XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgIHJldHVybiBuZXcgVmFsaWRhdGlvbkVycm9yKHRoaXMsIGN1cnJlbnRDb250ZXh0LCBcIkV4Y2VwdGlvbiBvY2N1cmVkIHdoaWxlIGV4ZWN1dGluZyB0aGlzIHZhbGlkYXRvcjogXCIgKyB0aGlzLm5hbWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG4gIC8vIGNvbnRleHQudmFsdWUgaXMgbm90IGF2YWlsIHVubGVzcyB2YWxpZGF0ZSB3YXMgY2FsbGVkIGZpcnN0LlxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIHRoZSBtZXNzYWdlIGdlbmVyYXRlZCBieSB0aGUgbW9zdCByZWNlbnQgZXhlY3V0aW9uIG9mIHRoaXMgVmFsaWRhdG9yLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIHZhciB2MCA9IFZhbGlkYXRvci5tYXhMZW5ndGgoeyBtYXhMZW5ndGg6IDUsIGRpc3BsYXlOYW1lOiBcIkNpdHlcIiB9KTtcclxuICAgICAgdjAudmFsaWRhdGUoXCJhZGFzZGZhc2RmXCIpO1xyXG4gICAgICB2YXIgZXJyTWVzc2FnZSA9IHYwLmdldE1lc3NhZ2UoKSk7XHJcbiAgQG1ldGhvZCBnZXRNZXNzYWdlXHJcbiAgQHJldHVybiB7U3RyaW5nfVxyXG4gICoqL1xyXG4gIGdldE1lc3NhZ2UoKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICBsZXQgY29udGV4dCA9IHRoaXMuY3VycmVudENvbnRleHQ7XHJcbiAgICAgIGxldCBtZXNzYWdlID0gY29udGV4dC5tZXNzYWdlO1xyXG4gICAgICBpZiAobWVzc2FnZSkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgKG1lc3NhZ2UpID09PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgICAgICAgIHJldHVybiBtZXNzYWdlKGNvbnRleHQpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSBpZiAoY29udGV4dC5tZXNzYWdlVGVtcGxhdGUpIHtcclxuICAgICAgICByZXR1cm4gZm9ybWF0VGVtcGxhdGUoY29udGV4dC5tZXNzYWdlVGVtcGxhdGUsIGNvbnRleHQpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiBcImludmFsaWQgdmFsdWU6IFwiICsgKHRoaXMubmFtZSB8fCBcInt1bm5hbWVkIHZhbGlkYXRvcn1cIik7XHJcbiAgICAgIH1cclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgcmV0dXJuIFwiVW5hYmxlIHRvIGZvcm1hdCBlcnJvciBtZXNzYWdlXCIgKyBlLnRvU3RyaW5nKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0b0pTT04oKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fYmFzZUNvbnRleHQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBDcmVhdGVzIGEgdmFsaWRhdG9yIGluc3RhbmNlIGZyb20gYSBKU09OIG9iamVjdCBvciBhbiBhcnJheSBvZiBpbnN0YW5jZXMgZnJvbSBhbiBhcnJheSBvZiBKU09OIG9iamVjdHMuXHJcbiAgQG1ldGhvZCBmcm9tSlNPTlxyXG4gIEBzdGF0aWNcclxuICBAcGFyYW0ganNvbiB7T2JqZWN0fSBKU09OIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIHNlcmlhbGl6ZWQgdmVyc2lvbiBvZiBhIHZhbGlkYXRvci5cclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIGZyb21KU09OKGpzb246IGFueSk6IGFueSB7XHJcbiAgICBpZiAoQXJyYXkuaXNBcnJheShqc29uKSkge1xyXG4gICAgICByZXR1cm4ganNvbi5tYXAoZnVuY3Rpb24gKGpzKSB7XHJcbiAgICAgICAgcmV0dXJuIFZhbGlkYXRvci5mcm9tSlNPTihqcyk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgaWYgKGpzb24gaW5zdGFuY2VvZiBWYWxpZGF0b3IpIHtcclxuICAgICAgcmV0dXJuIGpzb247XHJcbiAgICB9XHJcbiAgICBsZXQgdmFsaWRhdG9yTmFtZSA9IFwiVmFsaWRhdG9yLlwiICsganNvbi5uYW1lO1xyXG4gICAgbGV0IGZuID0gY29uZmlnLmdldFJlZ2lzdGVyZWRGdW5jdGlvbih2YWxpZGF0b3JOYW1lKTtcclxuICAgIGlmICghZm4pIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIGxvY2F0ZSBhIHZhbGlkYXRvciBuYW1lZDpcIiArIGpzb24ubmFtZSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZm4oanNvbik7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZWdpc3RlciBhIHZhbGlkYXRvciBpbnN0YW5jZSBzbyB0aGF0IGFueSBkZXNlcmlhbGl6ZWQgbWV0YWRhdGEgY2FuIHJlZmVyZW5jZSBpdC5cclxuICBAbWV0aG9kIHJlZ2lzdGVyXHJcbiAgQHN0YXRpY1xyXG4gIEBwYXJhbSB2YWxpZGF0b3Ige1ZhbGlkYXRvcn0gVmFsaWRhdG9yIHRvIHJlZ2lzdGVyLlxyXG4gICoqL1xyXG4gIHB1YmxpYyBzdGF0aWMgcmVnaXN0ZXIodmFsaWRhdG9yOiBWYWxpZGF0b3IpIHtcclxuICAgIGNvbmZpZy5yZWdpc3RlckZ1bmN0aW9uKGZ1bmN0aW9uICgpIHtcclxuICAgICAgcmV0dXJuIHZhbGlkYXRvcjtcclxuICAgIH0sIFwiVmFsaWRhdG9yLlwiICsgdmFsaWRhdG9yLm5hbWUpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmVnaXN0ZXIgYSB2YWxpZGF0b3IgZmFjdG9yeSBzbyB0aGF0IGFueSBkZXNlcmlhbGl6ZWQgbWV0YWRhdGEgY2FuIHJlZmVyZW5jZSBpdC5cclxuICBAbWV0aG9kIHJlZ2lzdGVyRmFjdG9yeVxyXG4gIEBzdGF0aWNcclxuICBAcGFyYW0gdmFsaWRhdG9yRmFjdG9yeSB7RnVuY3Rpb259IEEgZnVuY3Rpb24gdGhhdCBvcHRpb25hbGx5IHRha2VzIGEgY29udGV4dCBwcm9wZXJ0eSBhbmQgcmV0dXJucyBhIFZhbGlkYXRvciBpbnN0YW5jZS5cclxuICBAcGFyYW0gbmFtZSB7U3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgdmFsaWRhdG9yLlxyXG4gICoqL1xyXG4gIHB1YmxpYyBzdGF0aWMgcmVnaXN0ZXJGYWN0b3J5KHZhbGlkYXRvckZhY3Rvcnk6IChvcHRpb25zPzogYW55KSA9PiBWYWxpZGF0b3IsIG5hbWU6IHN0cmluZykge1xyXG4gICAgY29uZmlnLnJlZ2lzdGVyRnVuY3Rpb24odmFsaWRhdG9yRmFjdG9yeSwgXCJWYWxpZGF0b3IuXCIgKyBuYW1lKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIE1hcCBvZiBzdGFuZGFyZCBlcnJvciBtZXNzYWdlIHRlbXBsYXRlcyBrZXllZCBieSB2YWxpZGF0b3IgbmFtZS5cclxuICBZb3UgY2FuIGFkZCB0byBvciBtb2RpZnkgdGhpcyBvYmplY3QgdG8gY3VzdG9taXplIHRoZSB0ZW1wbGF0ZSB1c2VkIGZvciBhbnkgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIHYgaXMgdGhpcyBmdW5jdGlvbiBpcyB0aGUgdmFsdWUgdG8gYmUgdmFsaWRhdGVkLCBpbiB0aGlzIGNhc2UgYSBcImNvdW50cnlcIiBzdHJpbmcuXHJcbiAgICAgIHZhciB2YWxGbiA9IGZ1bmN0aW9uICh2KSB7XHJcbiAgICAgICAgICBpZiAodiA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgIHJldHVybiAoY29yZS5zdHJpbmdTdGFydHNXaXRoKHYsIFwiVVNcIikpO1xyXG4gICAgICB9O1xyXG4gICAgICB2YXIgY291bnRyeVZhbGlkYXRvciA9IG5ldyBWYWxpZGF0b3IoXCJjb3VudHJ5SXNVU1wiLCB2YWxGbiwgeyBkaXNwbGF5TmFtZTogXCJDb3VudHJ5XCIgfSk7XHJcbiAgICAgIFZhbGlkYXRvci5tZXNzYWdlVGVtcGxhdGVzLmNvdW50cnlJc1VTID0gXCInJWRpc3BsYXlOYW1lJScgbXVzdCBzdGFydCB3aXRoICdVUydcIjtcclxuICAgICAgLy8gVGhpcyB3aWxsIGhhdmUgYSBzaW1pbGFyIGVmZmVjdCB0byB0aGlzXHJcbiAgICAgIHZhciBjb3VudHJ5VmFsaWRhdG9yID0gbmV3IFZhbGlkYXRvcihcImNvdW50cnlJc1VTXCIsIHZhbEZuLCB7XHJcbiAgICAgICAgICBkaXNwbGF5TmFtZTogXCJDb3VudHJ5XCIsIFxyXG4gICAgICAgICAgbWVzc2FnZVRlbXBsYXRlOiBcIiclZGlzcGxheU5hbWUlJyBtdXN0IHN0YXJ0IHdpdGggJ1VTJ1wiIFxyXG4gICAgICB9KTtcclxuICBAcHJvcGVydHkgbWVzc2FnZVRlbXBsYXRlcyB7T2JqZWN0fVxyXG4gIEBzdGF0aWNcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIG1lc3NhZ2VUZW1wbGF0ZXMgPSB7XHJcbiAgICBib29sOiBcIiclZGlzcGxheU5hbWUlJyBtdXN0IGJlIGEgJ3RydWUnIG9yICdmYWxzZScgdmFsdWVcIixcclxuICAgIGNyZWRpdENhcmQ6IFwiVGhlICVkaXNwbGF5TmFtZSUgaXMgbm90IGEgdmFsaWQgY3JlZGl0IGNhcmQgbnVtYmVyXCIsXHJcbiAgICBkYXRlOiBcIiclZGlzcGxheU5hbWUlJyBtdXN0IGJlIGEgZGF0ZVwiLFxyXG4gICAgZHVyYXRpb246IFwiJyVkaXNwbGF5TmFtZSUnIG11c3QgYmUgYSBJU084NjAxIGR1cmF0aW9uIHN0cmluZywgc3VjaCBhcyAnUDNIMjRNNjBTJ1wiLFxyXG4gICAgZW1haWxBZGRyZXNzOiBcIlRoZSAlZGlzcGxheU5hbWUlICcldmFsdWUlJyBpcyBub3QgYSB2YWxpZCBlbWFpbCBhZGRyZXNzXCIsXHJcbiAgICBndWlkOiBcIiclZGlzcGxheU5hbWUlJyBtdXN0IGJlIGEgR1VJRFwiLFxyXG4gICAgaW50ZWdlcjogXCInJWRpc3BsYXlOYW1lJScgbXVzdCBiZSBhbiBpbnRlZ2VyXCIsXHJcbiAgICBpbnRlZ2VyUmFuZ2U6IFwiJyVkaXNwbGF5TmFtZSUnIG11c3QgYmUgYW4gaW50ZWdlciBiZXR3ZWVuIHRoZSB2YWx1ZXMgb2YgJW1pblZhbHVlJSBhbmQgJW1heFZhbHVlJVwiLFxyXG4gICAgbWF4TGVuZ3RoOiBcIiclZGlzcGxheU5hbWUlJyBtdXN0IGJlIGEgc3RyaW5nIHdpdGggJW1heExlbmd0aCUgY2hhcmFjdGVycyBvciBsZXNzXCIsXHJcbiAgICBudW1iZXI6IFwiJyVkaXNwbGF5TmFtZSUnIG11c3QgYmUgYSBudW1iZXJcIixcclxuICAgIHBob25lOiBcIlRoZSAlZGlzcGxheU5hbWUlICcldmFsdWUlJyBpcyBub3QgYSB2YWxpZCBwaG9uZSBudW1iZXJcIixcclxuICAgIHJlZ3VsYXJFeHByZXNzaW9uOiBcIlRoZSAlZGlzcGxheU5hbWUlICcldmFsdWUlJyBkb2VzIG5vdCBtYXRjaCAnJWV4cHJlc3Npb24lJ1wiLFxyXG4gICAgcmVxdWlyZWQ6IFwiJyVkaXNwbGF5TmFtZSUnIGlzIHJlcXVpcmVkXCIsXHJcbiAgICBzdHJpbmc6IFwiJyVkaXNwbGF5TmFtZSUnIG11c3QgYmUgYSBzdHJpbmdcIixcclxuICAgIHN0cmluZ0xlbmd0aDogXCInJWRpc3BsYXlOYW1lJScgbXVzdCBiZSBhIHN0cmluZyB3aXRoIGJldHdlZW4gJW1pbkxlbmd0aCUgYW5kICVtYXhMZW5ndGglIGNoYXJhY3RlcnNcIixcclxuICAgIHVybDogXCJUaGUgJWRpc3BsYXlOYW1lJSAnJXZhbHVlJScgaXMgbm90IGEgdmFsaWQgdXJsXCJcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgc3RhbmRhcmQgJ3JlcXVpcmVkIHZhbHVlJyBWYWxpZGF0b3JcclxuICBAZXhhbXBsZVxyXG4gICAgICAvLyBBc3N1bWUgZW0xIGlzIGEgcHJlZXhpc3RpbmcgRW50aXR5TWFuYWdlci5cclxuICAgICAgdmFyIGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gICAgICB2YXIgcmVnaW9uUHJvcGVydHkgLSBjdXN0VHlwZS5nZXRQcm9wZXJ0eShcIlJlZ2lvblwiKTtcclxuICAgICAgLy8gTWFrZXMgXCJSZWdpb25cIiBvbiBDdXN0b21lciBhIHJlcXVpcmVkIHByb3BlcnR5LlxyXG4gICAgICByZWdpb25Qcm9wZXJ0eS52YWxpZGF0b3JzLnB1c2goVmFsaWRhdG9yLnJlcXVpcmVkKCkpO1xyXG4gICAgICAvLyBvciB0byBhbGxvdyBlbXB0eSBzdHJpbmdzXHJcbiAgICAgIHJlZ2lvblByb3BlcnR5LnZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3IucmVxdWlyZWQoeyBhbGxvd0VtcHR5U3RyaW5nczogdHJ1ZSB9KTspO1xyXG4gIEBtZXRob2QgcmVxdWlyZWRcclxuICBAc3RhdGljXHJcbiAgQHBhcmFtIGNvbnRleHQge09iamVjdH1cclxuICBAcGFyYW0gW2NvbnRleHQuYWxsb3dFbXB0eVN0cmluZ3NdIHtCb29sZWFufSBJZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkIG9yIGZhbHNlIHRoZW4gZW1wdHkgc3RyaW5ncyBkbyBOT1QgcGFzcyB2YWxpZGF0aW9uLlxyXG4gIEByZXR1cm4ge1ZhbGlkYXRvcn0gQSBuZXcgVmFsaWRhdG9yXHJcbiAgKiovXHJcbiAgcHVibGljIHN0YXRpYyByZXF1aXJlZCA9IGZ1bmN0aW9uKGNvbnRleHQ/OiBhbnkpIHtcclxuICAgIGxldCB2YWxGbiA9IGZ1bmN0aW9uICh2OiBhbnksIGN0eDogYW55KSB7XHJcbiAgICAgIGlmICh0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgIGlmIChjdHggJiYgY3R4LmFsbG93RW1wdHlTdHJpbmdzKSByZXR1cm4gdHJ1ZTtcclxuICAgICAgICByZXR1cm4gdi5sZW5ndGggPiAwO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiB2ICE9IG51bGw7XHJcbiAgICAgIH1cclxuICAgIH07XHJcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRvcihcInJlcXVpcmVkXCIsIHZhbEZuLCBjb250ZXh0KTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgc3RhbmRhcmQgbWF4aW11bSBzdHJpbmcgbGVuZ3RoIFZhbGlkYXRvcjsgdGhlIG1heGltdW0gbGVuZ3RoIG11c3QgYmUgc3BlY2lmaWVkXHJcbiAgQGV4YW1wbGVcclxuICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhIHByZWV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgICAgIHZhciBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICAgICAgdmFyIHJlZ2lvblByb3BlcnR5IC0gY3VzdFR5cGUuZ2V0UHJvcGVydHkoXCJSZWdpb25cIik7XHJcbiAgICAgIC8vIFZhbGlkYXRlcyB0aGF0IHRoZSB2YWx1ZSBvZiB0aGUgUmVnaW9uIHByb3BlcnR5IG9uIEN1c3RvbWVyIHdpbGwgYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIDUgY2hhcmFjdGVycy5cclxuICAgICAgcmVnaW9uUHJvcGVydHkudmFsaWRhdG9ycy5wdXNoKFZhbGlkYXRvci5tYXhMZW5ndGgoIHttYXhMZW5ndGg6IDV9KSk7XHJcbiAgQG1ldGhvZCBtYXhMZW5ndGhcclxuICBAc3RhdGljXHJcbiAgQHBhcmFtIGNvbnRleHQge09iamVjdH1cclxuICBAcGFyYW0gY29udGV4dC5tYXhMZW5ndGgge0ludGVnZXJ9XHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIG1heExlbmd0aCA9IGZ1bmN0aW9uKGNvbnRleHQ6IGFueSkge1xyXG4gICAgbGV0IHZhbEZuID0gZnVuY3Rpb24gKHY6IGFueSwgY3R4OiBhbnkpIHtcclxuICAgICAgaWYgKHYgPT0gbnVsbCkgcmV0dXJuIHRydWU7XHJcbiAgICAgIGlmICh0eXBlb2YgKHYpICE9PSBcInN0cmluZ1wiKSByZXR1cm4gZmFsc2U7XHJcbiAgICAgIHJldHVybiB2Lmxlbmd0aCA8PSBjdHgubWF4TGVuZ3RoO1xyXG4gICAgfTtcclxuICAgIHJldHVybiBuZXcgVmFsaWRhdG9yKFwibWF4TGVuZ3RoXCIsIHZhbEZuLCBjb250ZXh0KTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgc3RhbmRhcmQgc3RyaW5nIGxlbmd0aCBWYWxpZGF0b3I7IGJvdGggbWluaW11bSBhbmQgbWF4aW11bSBsZW5ndGhzIG11c3QgYmUgc3BlY2lmaWVkLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgICB2YXIgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgICAgIHZhciByZWdpb25Qcm9wZXJ0eSAtIGN1c3RUeXBlLmdldFByb3BlcnR5KFwiUmVnaW9uXCIpO1xyXG4gICAgICAvLyBWYWxpZGF0ZXMgdGhhdCB0aGUgdmFsdWUgb2YgdGhlIFJlZ2lvbiBwcm9wZXJ0eSBvbiBDdXN0b21lciB3aWxsIGJlXHJcbiAgICAgIC8vIGJldHdlZW4gMiBhbmQgNSBjaGFyYWN0ZXJzXHJcbiAgICAgIHJlZ2lvblByb3BlcnR5LnZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3Iuc3RyaW5nTGVuZ3RoKCB7bWluTGVuZ3RoOiAyLCBtYXhMZW5ndGg6IDV9KTtcclxuICBAbWV0aG9kIHN0cmluZ0xlbmd0aFxyXG4gIEBzdGF0aWNcclxuICBAcGFyYW0gY29udGV4dCB7T2JqZWN0fVxyXG4gIEBwYXJhbSBjb250ZXh0Lm1heExlbmd0aCB7SW50ZWdlcn1cclxuICBAcGFyYW0gY29udGV4dC5taW5MZW5ndGgge0ludGVnZXJ9XHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIHN0cmluZ0xlbmd0aCA9IGZ1bmN0aW9uIChjb250ZXh0OiBhbnkpIHtcclxuICAgIGxldCB2YWxGbiA9IGZ1bmN0aW9uICh2OiBhbnksIGN0eDogYW55KSB7XHJcbiAgICAgIGlmICh2ID09IG51bGwpIHJldHVybiB0cnVlO1xyXG4gICAgICBpZiAodHlwZW9mICh2KSAhPT0gXCJzdHJpbmdcIikgcmV0dXJuIGZhbHNlO1xyXG4gICAgICBpZiAoY3R4Lm1pbkxlbmd0aCAhPSBudWxsICYmIHYubGVuZ3RoIDwgY3R4Lm1pbkxlbmd0aCkgcmV0dXJuIGZhbHNlO1xyXG4gICAgICBpZiAoY3R4Lm1heExlbmd0aCAhPSBudWxsICYmIHYubGVuZ3RoID4gY3R4Lm1heExlbmd0aCkgcmV0dXJuIGZhbHNlO1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRvcihcInN0cmluZ0xlbmd0aFwiLCB2YWxGbiwgY29udGV4dCk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIHN0YW5kYXJkIHN0cmluZyBkYXRhVHlwZSBWYWxpZGF0b3IuXHJcbiAgQGV4YW1wbGVcclxuICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhIHByZWV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgICAgIHZhciBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICAgICAgdmFyIHJlZ2lvblByb3BlcnR5IC0gY3VzdFR5cGUuZ2V0UHJvcGVydHkoXCJSZWdpb25cIik7XHJcbiAgICAgIC8vIFZhbGlkYXRlcyB0aGF0IHRoZSB2YWx1ZSBvZiB0aGUgUmVnaW9uIHByb3BlcnR5IG9uIEN1c3RvbWVyIGlzIGEgc3RyaW5nLlxyXG4gICAgICByZWdpb25Qcm9wZXJ0eS52YWxpZGF0b3JzLnB1c2goVmFsaWRhdG9yLnN0cmluZygpKTtcclxuICBAbWV0aG9kIHN0cmluZ1xyXG4gIEBzdGF0aWNcclxuICBAcmV0dXJuIHtWYWxpZGF0b3J9IEEgbmV3IFZhbGlkYXRvclxyXG4gICoqL1xyXG4gIHB1YmxpYyBzdGF0aWMgc3RyaW5nID0gZnVuY3Rpb24gKCkge1xyXG4gICAgbGV0IHZhbEZuID0gZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICBpZiAodiA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcclxuICAgICAgcmV0dXJuICh0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIik7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0b3IoXCJzdHJpbmdcIiwgdmFsRm4pO1xyXG4gIH07XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBHdWlkIGRhdGEgdHlwZSBWYWxpZGF0b3IuXHJcbiAgQGV4YW1wbGVcclxuICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhIHByZWV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgICAgIHZhciBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICAgICAgdmFyIGN1c3RvbWVySWRQcm9wZXJ0eSAtIGN1c3RUeXBlLmdldFByb3BlcnR5KFwiQ3VzdG9tZXJJRFwiKTtcclxuICAgICAgLy8gVmFsaWRhdGVzIHRoYXQgdGhlIHZhbHVlIG9mIHRoZSBDdXN0b21lcklEIHByb3BlcnR5IG9uIEN1c3RvbWVyIGlzIGEgR3VpZC5cclxuICAgICAgY3VzdG9tZXJJZFByb3BlcnR5LnZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3IuZ3VpZCgpKTtcclxuICBAbWV0aG9kIGd1aWRcclxuICBAc3RhdGljXHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIGd1aWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICBsZXQgdmFsRm4gPSBmdW5jdGlvbiAodjogYW55KSB7XHJcbiAgICAgIGlmICh2ID09IG51bGwpIHJldHVybiB0cnVlO1xyXG4gICAgICByZXR1cm4gY29yZS5pc0d1aWQodik7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0b3IoXCJndWlkXCIsIHZhbEZuKTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgSVNPIDg2MDEgZHVyYXRpb24gc3RyaW5nICBWYWxpZGF0b3IuXHJcbiAgQGV4YW1wbGVcclxuICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhIHByZWV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgICAgIHZhciBldmVudFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiRXZlbnRcIik7XHJcbiAgICAgIHZhciBlbGFwc2VkVGltZVByb3BlcnR5IC0gZXZlbnRUeXBlLmdldFByb3BlcnR5KFwiRWxhcHNlZFRpbWVcIik7XHJcbiAgICAgIC8vIFZhbGlkYXRlcyB0aGF0IHRoZSB2YWx1ZSBvZiB0aGUgRWxhcHNlZFRpbWUgcHJvcGVydHkgb24gQ3VzdG9tZXIgaXMgYSBkdXJhdGlvbi5cclxuICAgICAgZWxhcHNlZFRpbWVQcm9wZXJ0eS52YWxpZGF0b3JzLnB1c2goVmFsaWRhdG9yLmR1cmF0aW9uKCkpO1xyXG4gIEBtZXRob2QgZHVyYXRpb25cclxuICBAc3RhdGljXHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIGR1cmF0aW9uID0gZnVuY3Rpb24gKCkge1xyXG4gICAgbGV0IHZhbEZuID0gZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICBpZiAodiA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcclxuICAgICAgcmV0dXJuIGNvcmUuaXNEdXJhdGlvbih2KTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRvcihcImR1cmF0aW9uXCIsIHZhbEZuKTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgc3RhbmRhcmQgbnVtZXJpYyBkYXRhIHR5cGUgVmFsaWRhdG9yLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgICB2YXIgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gICAgICB2YXIgZnJlaWdodFByb3BlcnR5IC0gb3JkZXJUeXBlLmdldFByb3BlcnR5KFwiRnJlaWdodFwiKTtcclxuICAgICAgLy8gVmFsaWRhdGVzIHRoYXQgdGhlIHZhbHVlIG9mIHRoZSBGcmVpZ2h0IHByb3BlcnR5IG9uIE9yZGVyIGlzIGEgbnVtYmVyLlxyXG4gICAgICBmcmVpZ2h0UHJvcGVydHkudmFsaWRhdG9ycy5wdXNoKFZhbGlkYXRvci5udW1iZXIoKSk7XHJcbiAgQG1ldGhvZCBudW1iZXJcclxuICBAc3RhdGljXHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuXHJcbiAgICAvLyBUT0RPOiBtYXkgbmVlZCB0byBoYXZlIHNlcGVyYXRlIGxvZ2ljIGZvciBzaW5nbGUuXHJcbiAgcHVibGljIHN0YXRpYyBudW1iZXIgPSBmdW5jdGlvbihjb250ZXh0PzogYW55KSB7XHJcbiAgICBsZXQgdmFsRm4gPSBmdW5jdGlvbiAodjogYW55LCBjdHg6IGFueSkge1xyXG4gICAgICBpZiAodiA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcclxuICAgICAgaWYgKHR5cGVvZiB2ID09PSBcInN0cmluZ1wiICYmIGN0eCAmJiBjdHguYWxsb3dTdHJpbmcpIHtcclxuICAgICAgICB2ID0gcGFyc2VGbG9hdCh2KTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gKHR5cGVvZiB2ID09PSBcIm51bWJlclwiICYmICFpc05hTih2KSk7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0b3IoXCJudW1iZXJcIiwgdmFsRm4sIGNvbnRleHQpO1xyXG4gIH07XHJcbiAgcHVibGljIHN0YXRpYyBkb3VibGUgPSBWYWxpZGF0b3IubnVtYmVyO1xyXG4gIHB1YmxpYyBzdGF0aWMgc2luZ2xlID0gVmFsaWRhdG9yLm51bWJlcjtcclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIHN0YW5kYXJkIGxhcmdlIGludGVnZXIgZGF0YSB0eXBlIC0gNjQgYml0IC0gVmFsaWRhdG9yLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgICB2YXIgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gICAgICB2YXIgZnJlaWdodFByb3BlcnR5IC0gb3JkZXJUeXBlLmdldFByb3BlcnR5KFwiRnJlaWdodFwiKTtcclxuICAgICAgLy8gVmFsaWRhdGVzIHRoYXQgdGhlIHZhbHVlIG9mIHRoZSBGcmVpZ2h0IHByb3BlcnR5IG9uIE9yZGVyIGlzIHdpdGhpbiB0aGUgcmFuZ2Ugb2YgYSA2NCBiaXQgaW50ZWdlci5cclxuICAgICAgZnJlaWdodFByb3BlcnR5LnZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3IuaW50NjQoKSk7XHJcbiAgQG1ldGhvZCBpbnQ2NFxyXG4gIEBzdGF0aWNcclxuICBAcmV0dXJuIHtWYWxpZGF0b3J9IEEgbmV3IFZhbGlkYXRvclxyXG4gICoqL1xyXG4gIHB1YmxpYyBzdGF0aWMgaW50ZWdlciA9IGZ1bmN0aW9uKGNvbnRleHQ6IGFueSkge1xyXG4gICAgbGV0IHZhbEZuID0gZnVuY3Rpb24gKHY6IGFueSwgY3R4OiBhbnkpIHtcclxuICAgICAgaWYgKHYgPT0gbnVsbCkgcmV0dXJuIHRydWU7XHJcbiAgICAgIGlmICh0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIiAmJiBjdHggJiYgY3R4LmFsbG93U3RyaW5nKSB7XHJcbiAgICAgICAgdiA9IHBhcnNlSW50KHYsIDEwKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gKHR5cGVvZiB2ID09PSBcIm51bWJlclwiKSAmJiAoIWlzTmFOKHYpKSAmJiBNYXRoLmZsb29yKHYpID09PSB2O1xyXG4gICAgfTtcclxuICAgIHJldHVybiBuZXcgVmFsaWRhdG9yKFwiaW50ZWdlclwiLCB2YWxGbiwgY29udGV4dCk7XHJcbiAgfTtcclxuICBwdWJsaWMgc3RhdGljIGludDY0ID0gVmFsaWRhdG9yLmludGVnZXI7XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBzdGFuZGFyZCAzMiBiaXQgaW50ZWdlciBkYXRhIHR5cGUgVmFsaWRhdG9yLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgICB2YXIgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gICAgICB2YXIgZnJlaWdodFByb3BlcnR5IC0gb3JkZXJUeXBlLmdldFByb3BlcnR5KFwiRnJlaWdodFwiKTtcclxuICAgICAgZnJlaWdodFByb3BlcnR5LnZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3IuaW50MzIoKSk7XHJcbiAgQG1ldGhvZCBpbnQzMlxyXG4gIEBzdGF0aWNcclxuICBAcmV0dXJuIHtWYWxpZGF0b3J9IEEgbmV3IFZhbGlkYXRvclxyXG4gICoqL1xyXG4gIHB1YmxpYyBzdGF0aWMgaW50MzIgPSBmdW5jdGlvbihjb250ZXh0OiBhbnkpIHtcclxuICAgIHJldHVybiBpbnRSYW5nZVZhbGlkYXRvckN0b3IoXCJpbnQzMlwiLCBJTlQzMl9NSU4sIElOVDMyX01BWCwgY29udGV4dCkoKTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgc3RhbmRhcmQgMTYgYml0IGludGVnZXIgZGF0YSB0eXBlIFZhbGlkYXRvci5cclxuICBAZXhhbXBsZVxyXG4gICAgICAvLyBBc3N1bWUgZW0xIGlzIGEgcHJlZXhpc3RpbmcgRW50aXR5TWFuYWdlci5cclxuICAgICAgdmFyIG9yZGVyVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJPcmRlclwiKTtcclxuICAgICAgdmFyIGZyZWlnaHRQcm9wZXJ0eSAtIG9yZGVyVHlwZS5nZXRQcm9wZXJ0eShcIkZyZWlnaHRcIik7XHJcbiAgICAgIC8vIFZhbGlkYXRlcyB0aGF0IHRoZSB2YWx1ZSBvZiB0aGUgRnJlaWdodCBwcm9wZXJ0eSBvbiBPcmRlciBpcyB3aXRoaW4gdGhlIHJhbmdlIG9mIGEgMTYgYml0IGludGVnZXIuXHJcbiAgICAgIGZyZWlnaHRQcm9wZXJ0eS52YWxpZGF0b3JzLnB1c2goVmFsaWRhdG9yLmludDE2KCkpO1xyXG4gIEBtZXRob2QgaW50MTZcclxuICBAc3RhdGljXHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIGludDE2ID0gZnVuY3Rpb24oY29udGV4dDogYW55KSB7XHJcbiAgICByZXR1cm4gaW50UmFuZ2VWYWxpZGF0b3JDdG9yKFwiaW50MTZcIiwgSU5UMTZfTUlOLCBJTlQxNl9NQVgsIGNvbnRleHQpKCk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIHN0YW5kYXJkIGJ5dGUgZGF0YSB0eXBlIFZhbGlkYXRvci4gKFRoaXMgaXMgYSBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgMjU1IGluY2x1c2l2ZSBmb3IganMgcHVycG9zZXMpLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgICB2YXIgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gICAgICB2YXIgZnJlaWdodFByb3BlcnR5IC0gb3JkZXJUeXBlLmdldFByb3BlcnR5KFwiRnJlaWdodFwiKTtcclxuICAgICAgLy8gVmFsaWRhdGVzIHRoYXQgdGhlIHZhbHVlIG9mIHRoZSBGcmVpZ2h0IHByb3BlcnR5IG9uIE9yZGVyIGlzIHdpdGhpbiB0aGUgcmFuZ2Ugb2YgYSAxNiBiaXQgaW50ZWdlci5cclxuICAgICAgLy8gUHJvYmFibHkgbm90IGEgdmVyeSBnb29kIHZhbGlkYXRpb24gdG8gcGxhY2Ugb24gdGhlIEZyZWlnaHQgcHJvcGVydHkuXHJcbiAgICAgIHJlZ2lvblByb3BlcnR5LnZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3IuYnl0ZSgpKTtcclxuICBAbWV0aG9kIGJ5dGVcclxuICBAc3RhdGljXHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIGJ5dGUgPSBmdW5jdGlvbihjb250ZXh0OiBhbnkpIHtcclxuICAgIHJldHVybiBpbnRSYW5nZVZhbGlkYXRvckN0b3IoXCJieXRlXCIsIEJZVEVfTUlOLCBCWVRFX01BWCwgY29udGV4dCkoKTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgc3RhbmRhcmQgYm9vbGVhbiBkYXRhIHR5cGUgVmFsaWRhdG9yLlxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgICB2YXIgcHJvZHVjdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiUHJvZHVjdFwiKTtcclxuICAgICAgdmFyIGRpc2NvbnRpbnVlZFByb3BlcnR5IC0gcHJvZHVjdFR5cGUuZ2V0UHJvcGVydHkoXCJEaXNjb250aW51ZWRcIik7XHJcbiAgICAgIC8vIFZhbGlkYXRlcyB0aGF0IHRoZSB2YWx1ZSBvZiB0aGUgRGlzY29udGludWVkIHByb3BlcnR5IG9uIFByb2R1Y3QgaXMgYSBib29sZWFuXHJcbiAgICAgIGRpc2NvbnRpbnVlZFByb3BlcnR5LnZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3IuYm9vbCgpKTtcclxuICBAbWV0aG9kIGJvb2xcclxuICBAc3RhdGljXHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIGJvb2wgPSBmdW5jdGlvbigpIHtcclxuICAgIGxldCB2YWxGbiA9IGZ1bmN0aW9uICh2OiBhbnkpIHtcclxuICAgICAgaWYgKHYgPT0gbnVsbCkgcmV0dXJuIHRydWU7XHJcbiAgICAgIHJldHVybiAodiA9PT0gdHJ1ZSkgfHwgKHYgPT09IGZhbHNlKTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRvcihcImJvb2xcIiwgdmFsRm4pO1xyXG4gIH07XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgbm9uZSA9IGZ1bmN0aW9uKCkge1xyXG4gICAgbGV0IHZhbEZuID0gZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRvcihcIm5vbmVcIiwgdmFsRm4pO1xyXG4gIH07XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBzdGFuZGFyZCBkYXRlIGRhdGEgdHlwZSBWYWxpZGF0b3IuXHJcbiAgQGV4YW1wbGVcclxuICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhIHByZWV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgICAgIHZhciBvcmRlclR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiT3JkZXJcIik7XHJcbiAgICAgIHZhciBvcmRlckRhdGVQcm9wZXJ0eSAtIG9yZGVyVHlwZS5nZXRQcm9wZXJ0eShcIk9yZGVyRGF0ZVwiKTtcclxuICAgICAgLy8gVmFsaWRhdGVzIHRoYXQgdGhlIHZhbHVlIG9mIHRoZSBPcmRlckRhdGUgcHJvcGVydHkgb24gT3JkZXIgaXMgYSBkYXRlXHJcbiAgICAgIC8vIFByb2JhYmx5IG5vdCBhIHZlcnkgZ29vZCB2YWxpZGF0aW9uIHRvIHBsYWNlIG9uIHRoZSBGcmVpZ2h0IHByb3BlcnR5LlxyXG4gICAgICBvcmRlckRhdGVQcm9wZXJ0eS52YWxpZGF0b3JzLnB1c2goVmFsaWRhdG9yLmRhdGUoKSk7XHJcbiAgQG1ldGhvZCBkYXRlXHJcbiAgQHN0YXRpY1xyXG4gIEByZXR1cm4ge1ZhbGlkYXRvcn0gQSBuZXcgVmFsaWRhdG9yXHJcbiAgKiovXHJcbiAgcHVibGljIHN0YXRpYyBkYXRlID0gZnVuY3Rpb24oKSB7XHJcbiAgICBsZXQgdmFsRm4gPSBmdW5jdGlvbiAodjogYW55KSB7XHJcbiAgICAgIGlmICh2ID09IG51bGwpIHJldHVybiB0cnVlO1xyXG4gICAgICBpZiAodHlwZW9mIHYgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgcmV0dXJuICFpc05hTihEYXRlLnBhcnNlKHYpKTtcclxuICAgICAgICAgIC8vIG9sZCBjb2RlXHJcbiAgICAgICAgICAvLyByZXR1cm4gX19pc0RhdGUobmV3IERhdGUodikpO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIGNvcmUuaXNEYXRlKHYpO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0b3IoXCJkYXRlXCIsIHZhbEZuKTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgY3JlZGl0IGNhcmQgbnVtYmVyIHZhbGlkYXRvclxyXG4gIFBlcmZvcm1zIGEgbHVobiBhbGdvcml0aG0gY2hlY2tzdW0gdGVzdCBmb3IgcGxhdXNhYmlsaXR5XHJcbiAgY2F0Y2hlcyBzaW1wbGUgbWlzdGFrZXM7IG9ubHkgc2VydmljZSBrbm93cyBmb3Igc3VyZVxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFzc3VtZSBlbSBpcyBhIHByZWV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgICAgIHZhciBwZXJzb25UeXBlID0gZW0ubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiUGVyc29uXCIpO1xyXG4gICAgICB2YXIgY3JlZGl0Q2FyZFByb3BlcnR5ID0gcGVyc29uVHlwZS5nZXRQcm9wZXJ0eShcImNyZWRpdENhcmRcIik7XHJcbiAgICAgIC8vIFZhbGlkYXRlcyB0aGF0IHRoZSB2YWx1ZSBvZiB0aGUgUGVyc29uLmNyZWRpdENhcmQgcHJvcGVydHkgaXMgY3JlZGl0IGNhcmQuXHJcbiAgICAgIGNyZWRpdENhcmRQcm9wZXJ0eS52YWxpZGF0b3JzLnB1c2goVmFsaWRhdG9yLmNyZWRpdENhcmQoKSk7XHJcbiAgQG1ldGhvZCBjcmVkaXRDYXJkXHJcbiAgQHN0YXRpY1xyXG4gIEBwYXJhbSBbY29udGV4dF0ge09iamVjdH0gb3B0aW9uYWwgcGFyYW1ldGVycyB0byBwYXNzIHRocm91Z2ggdG8gdmFsaWRhdGlvbiBjb25zdHJ1Y3RvclxyXG4gIEByZXR1cm4ge1ZhbGlkYXRvcn0gQSBuZXcgVmFsaWRhdG9yXHJcbiAgKiovXHJcbiAgcHVibGljIHN0YXRpYyBjcmVkaXRDYXJkID0gZnVuY3Rpb24oY29udGV4dD86IGFueSkge1xyXG4gICAgZnVuY3Rpb24gdmFsRm4odjogYW55KSB7XHJcbiAgICAgIGlmICh2ID09IG51bGwgfHwgdiA9PT0gJycpIHJldHVybiB0cnVlO1xyXG4gICAgICBpZiAodHlwZW9mICh2KSAhPT0gJ3N0cmluZycpIHJldHVybiBmYWxzZTtcclxuICAgICAgdiA9IHYucmVwbGFjZSgvKFxcLXxcXHMpL2csIFwiXCIpOyAvLyByZW1vdmUgZGFzaGVzIGFuZCBzcGFjZXNcclxuICAgICAgaWYgKCF2IHx8IC9cXEQvLnRlc3QodikpIHJldHVybiBmYWxzZTsgLy8gYWxsIGRpZ2l0cywgbm90IGVtcHR5XHJcbiAgICAgIHJldHVybiBsdWhuKHYpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0b3IoJ2NyZWRpdENhcmQnLCB2YWxGbiwgY29udGV4dCk7XHJcbiAgfTtcclxuXHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYSByZWd1bGFyIGV4cHJlc3Npb24gdmFsaWRhdG9yOyB0aGUgZXhwcmVzc2lvbiBtdXN0IGJlIHNwZWNpZmllZFxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFkZCB2YWxpZGF0b3IgdG8gYSBwcm9wZXJ0eS4gQXNzdW1lIGVtIGlzIGEgcHJlZXhpc3RpbmcgRW50aXR5TWFuYWdlci5cclxuICAgICAgdmFyIGN1c3RvbWVyVHlwZSA9IGVtLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gICAgICB2YXIgcmVnaW9uUHJvcGVydHkgPSBjdXN0b21lclR5cGUuZ2V0UHJvcGVydHkoXCJSZWdpb25cIik7XHJcbiAgICAgIC8vIFZhbGlkYXRlcyB0aGF0IHRoZSB2YWx1ZSBvZiBDdXN0b21lci5SZWdpb24gaXMgMiBjaGFyIHVwcGVyY2FzZSBhbHBoYS5cclxuICAgICAgcmVnaW9uUHJvcGVydHkudmFsaWRhdG9ycy5wdXNoKFZhbGlkYXRvci5yZWd1bGFyRXhwcmVzc2lvbigge2V4cHJlc3Npb246ICdeW0EtWl17Mn0kJ30gKTtcclxuICBAbWV0aG9kIHJlZ3VsYXJFeHByZXNzaW9uXHJcbiAgQHN0YXRpY1xyXG4gIEBwYXJhbSBjb250ZXh0IHtPYmplY3R9XHJcbiAgQHBhcmFtIGNvbnRleHQuZXhwcmVzc2lvbiB7U3RyaW5nfSBTdHJpbmcgZm9ybSBvZiB0aGUgcmVndWxhciBleHByZXNzaW9uIHRvIGFwcGx5XHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIHJlZ3VsYXJFeHByZXNzaW9uID0gZnVuY3Rpb24oY29udGV4dD86IGFueSkge1xyXG4gICAgZnVuY3Rpb24gdmFsRm4odjogYW55LCBjdHg6IGFueSkge1xyXG4gICAgICAvLyBkbyBub3QgaW52YWxpZGF0ZSBpZiBlbXB0eTsgdXNlIGEgc2VwYXJhdGUgcmVxdWlyZWQgdGVzdFxyXG4gICAgICBpZiAodiA9PSBudWxsIHx8IHYgPT09ICcnKSByZXR1cm4gdHJ1ZTtcclxuICAgICAgaWYgKHR5cGVvZiAodikgIT09ICdzdHJpbmcnKSByZXR1cm4gZmFsc2U7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgbGV0IHJlID0gbmV3IFJlZ0V4cChjdHguZXhwcmVzc2lvbik7XHJcbiAgICAgICAgcmV0dXJuIHJlLnRlc3Qodik7XHJcbiAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgb3IgaW52YWxpZCBleHByZXNzaW9uIHBhcmFtZXRlciB0byByZWdFeHAgdmFsaWRhdG9yJyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBuZXcgVmFsaWRhdG9yKCdyZWd1bGFyRXhwcmVzc2lvbicsIHZhbEZuLCBjb250ZXh0KTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIHRoZSBlbWFpbCBhZGRyZXNzIHZhbGlkYXRvclxyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIEFzc3VtZSBlbSBpcyBhIHByZWV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgICAgIHZhciBwZXJzb25UeXBlID0gZW0ubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiUGVyc29uXCIpO1xyXG4gICAgICB2YXIgZW1haWxQcm9wZXJ0eSA9IHBlcnNvblR5cGUuZ2V0UHJvcGVydHkoXCJlbWFpbFwiKTtcclxuICAgICAgLy8gVmFsaWRhdGVzIHRoYXQgdGhlIHZhbHVlIG9mIHRoZSBQZXJzb24uZW1haWwgcHJvcGVydHkgaXMgYW4gZW1haWwgYWRkcmVzcy5cclxuICAgICAgZW1haWxQcm9wZXJ0eS52YWxpZGF0b3JzLnB1c2goVmFsaWRhdG9yLmVtYWlsQWRkcmVzcygpKTtcclxuICBAbWV0aG9kIGVtYWlsQWRkcmVzc1xyXG4gIEBzdGF0aWNcclxuICBAcGFyYW0gW2NvbnRleHRdIHtPYmplY3R9IG9wdGlvbmFsIHBhcmFtZXRlcnMgdG8gcGFzcyB0aHJvdWdoIHRvIHZhbGlkYXRpb24gY29uc3RydWN0b3JcclxuICBAcmV0dXJuIHtWYWxpZGF0b3J9IEEgbmV3IFZhbGlkYXRvclxyXG4gICoqL1xyXG4gIHB1YmxpYyBzdGF0aWMgZW1haWxBZGRyZXNzID0gZnVuY3Rpb24oY29udGV4dD86IGFueSkge1xyXG4gICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9zcmtpcmtsYW5kL0RhdGFBbm5vdGF0aW9uc0V4dGVuc2lvbnMvYmxvYi9tYXN0ZXIvRGF0YUFubm90YXRpb25zRXh0ZW5zaW9ucy9FbWFpbEF0dHJpYnV0ZS5jc1xyXG4gICAgbGV0IHJlRW1haWxBZGRyZXNzID0gL14oKChbYS16XXxcXGR8WyEjXFwkJSYnXFwqXFwrXFwtXFwvPVxcP1xcXl9ge1xcfH1+XXxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSkrKFxcLihbYS16XXxcXGR8WyEjXFwkJSYnXFwqXFwrXFwtXFwvPVxcP1xcXl9ge1xcfH1+XXxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSkrKSopfCgoXFx4MjIpKCgoKFxceDIwfFxceDA5KSooXFx4MGRcXHgwYSkpPyhcXHgyMHxcXHgwOSkrKT8oKFtcXHgwMS1cXHgwOFxceDBiXFx4MGNcXHgwZS1cXHgxZlxceDdmXXxcXHgyMXxbXFx4MjMtXFx4NWJdfFtcXHg1ZC1cXHg3ZV18W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pfChcXFxcKFtcXHgwMS1cXHgwOVxceDBiXFx4MGNcXHgwZC1cXHg3Zl18W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKSkpKigoKFxceDIwfFxceDA5KSooXFx4MGRcXHgwYSkpPyhcXHgyMHxcXHgwOSkrKT8oXFx4MjIpKSlAKCgoW2Etel18XFxkfFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKXwoKFthLXpdfFxcZHxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSkoW2Etel18XFxkfC18XFwufF98fnxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSkqKFthLXpdfFxcZHxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSkpKVxcLikrKChbYS16XXxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSl8KChbYS16XXxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSkoW2Etel18XFxkfC18XFwufF98fnxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSkqKFthLXpdfFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKSkpXFwuPyQvaTtcclxuICAgIHJldHVybiBtYWtlUmVnRXhwVmFsaWRhdG9yKCdlbWFpbEFkZHJlc3MnLCByZUVtYWlsQWRkcmVzcywgbnVsbCwgY29udGV4dCk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyB0aGUgcGhvbmUgdmFsaWRhdG9yXHJcbiAgUHJvdmlkZXMgYmFzaWMgYXNzZXJ0aW9ucyBvbiB0aGUgZm9ybWF0IGFuZCB3aWxsIGhlbHAgdG8gZWxpbWluYXRlIG1vc3Qgbm9uc2Vuc2UgaW5wdXRcclxuICBNYXRjaGVzOlxyXG4gIEludGVybmF0aW9uYWwgZGlhbGluZyBwcmVmaXg6IHt7fSwgKywgMCwgMDAwMH0gKHdpdGggb3Igd2l0aG91dCBhIHRyYWlsaW5nIGJyZWFrIGNoYXJhY3RlciwgaWYgbm90ICcrJzogWy0vLiBdKVxyXG4gID4gKChcXCspfCgwKFxcZCspP1stLy5cXHNdKSlcclxuICBDb3VudHJ5IGNvZGU6IHt7fSwgMSwgLi4uLCA5OTl9ICh3aXRoIG9yIHdpdGhvdXQgYSB0cmFpbGluZyBicmVhayBjaGFyYWN0ZXI6IFstLy4gXSlcclxuICA+IFsxLTldXFxkeywyfVstLy5cXHNdP1xyXG4gIEFyZWEgY29kZTogeygwKSwgLi4uLCAoMDAwMDAwKSwgMCwgLi4uLCAwMDAwMDB9ICh3aXRoIG9yIHdpdGhvdXQgYSB0cmFpbGluZyBicmVhayBjaGFyYWN0ZXI6IFstLy4gXSlcclxuICA+ICgoXFwoXFxkezEsNn1cXCl8XFxkezEsNn0pWy0vLlxcc10/KT9cclxuICBMb2NhbDogezAsIC4uLn0rICh3aXRoIG9yIHdpdGhvdXQgYSB0cmFpbGluZyBicmVhayBjaGFyYWN0ZXI6IFstLy4gXSlcclxuICA+IChcXGQrWy0vLlxcc10/KStcXGQrXHJcbiAgQGV4YW1wbGVcclxuICAgICAgLy8gQXNzdW1lIGVtIGlzIGEgcHJlZXhpc3RpbmcgRW50aXR5TWFuYWdlci5cclxuICAgICAgdmFyIGN1c3RvbWVyVHlwZSA9IGVtLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gICAgICB2YXIgcGhvbmVQcm9wZXJ0eSA9IGN1c3RvbWVyVHlwZS5nZXRQcm9wZXJ0eShcInBob25lXCIpO1xyXG4gICAgICAvLyBWYWxpZGF0ZXMgdGhhdCB0aGUgdmFsdWUgb2YgdGhlIEN1c3RvbWVyLnBob25lIHByb3BlcnR5IGlzIHBob25lLlxyXG4gICAgICBwaG9uZVByb3BlcnR5LnZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3IucGhvbmUoKSk7XHJcbiAgQG1ldGhvZCBwaG9uZVxyXG4gIEBzdGF0aWNcclxuICBAcGFyYW0gW2NvbnRleHRdIHtPYmplY3R9IG9wdGlvbmFsIHBhcmFtZXRlcnMgdG8gcGFzcyB0aHJvdWdoIHRvIHZhbGlkYXRpb24gY29uc3RydWN0b3JcclxuICBAcmV0dXJuIHtWYWxpZGF0b3J9IEEgbmV3IFZhbGlkYXRvclxyXG4gICoqL1xyXG4gIHB1YmxpYyBzdGF0aWMgcGhvbmUgPSBmdW5jdGlvbiAoY29udGV4dD86IGFueSkge1xyXG4gICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9zcmtpcmtsYW5kL0RhdGFBbm5vdGF0aW9uc0V4dGVuc2lvbnMvYmxvYi9tYXN0ZXIvRGF0YUFubm90YXRpb25zRXh0ZW5zaW9ucy9FeHByZXNzaW9ucy5jc1xyXG4gICAgbGV0IHJlUGhvbmUgPSAvXigoXFwrfCgwKFxcZCspP1stLy5cXHNdPykpWzEtOV1cXGR7MCwyfVstLy5cXHNdPyk/KChcXChcXGR7MSw2fVxcKXxcXGR7MSw2fSlbLS8uXFxzXT8pPyhcXGQrWy0vLlxcc10/KStcXGQrJC87XHJcbiAgICByZXR1cm4gbWFrZVJlZ0V4cFZhbGlkYXRvcigncGhvbmUnLCByZVBob25lLCBudWxsLCBjb250ZXh0KTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICBSZXR1cm5zIHRoZSBVUkwgKHByb3RvY29sIHJlcXVpcmVkKSB2YWxpZGF0b3JcclxuICBAZXhhbXBsZVxyXG4gICAgICAvLyBBc3N1bWUgZW0gaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgICB2YXIgcGVyc29uVHlwZSA9IGVtLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIlBlcnNvblwiKTtcclxuICAgICAgdmFyIHdlYnNpdGVQcm9wZXJ0eSA9IHBlcnNvblR5cGUuZ2V0UHJvcGVydHkoXCJ3ZWJzaXRlXCIpO1xyXG4gICAgICAvLyBWYWxpZGF0ZXMgdGhhdCB0aGUgdmFsdWUgb2YgdGhlIFBlcnNvbi53ZWJzaXRlIHByb3BlcnR5IGlzIGEgVVJMLlxyXG4gICAgICB3ZWJzaXRlUHJvcGVydHkudmFsaWRhdG9ycy5wdXNoKFZhbGlkYXRvci51cmwoKSk7XHJcbiAgQG1ldGhvZCB1cmxcclxuICBAc3RhdGljXHJcbiAgQHBhcmFtIFtjb250ZXh0XSB7T2JqZWN0fSBvcHRpb25hbCBwYXJhbWV0ZXJzIHRvIHBhc3MgdGhyb3VnaCB0byB2YWxpZGF0aW9uIGNvbnN0cnVjdG9yXHJcbiAgQHJldHVybiB7VmFsaWRhdG9yfSBBIG5ldyBWYWxpZGF0b3JcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIHVybCA9IGZ1bmN0aW9uIChjb250ZXh0PzogYW55KSB7XHJcbiAgICAvL1NlZSBodHRwczovL2dpdGh1Yi5jb20vc3JraXJrbGFuZC9EYXRhQW5ub3RhdGlvbnNFeHRlbnNpb25zL2Jsb2IvbWFzdGVyL0RhdGFBbm5vdGF0aW9uc0V4dGVuc2lvbnMvVXJsQXR0cmlidXRlLmNzXHJcbiAgICBsZXQgcmVVcmxQcm90b2NvbFJlcXVpcmVkID0gL14oaHR0cHM/fGZ0cCk6XFwvXFwvKCgoKFthLXpBLVpdfFxcZHwtfFxcLnxffH58W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pfCglW1xcZGEtZkEtRl17Mn0pfFshXFwkJidcXChcXClcXCpcXCssOz1dfDopKkApPygoKFxcZHxbMS05XVxcZHwxXFxkXFxkfDJbMC00XVxcZHwyNVswLTVdKVxcLihcXGR8WzEtOV1cXGR8MVxcZFxcZHwyWzAtNF1cXGR8MjVbMC01XSlcXC4oXFxkfFsxLTldXFxkfDFcXGRcXGR8MlswLTRdXFxkfDI1WzAtNV0pXFwuKFxcZHxbMS05XVxcZHwxXFxkXFxkfDJbMC00XVxcZHwyNVswLTVdKSl8KFthLXpBLVpdW1xcLWEtekEtWjAtOV0qKXwoKChbYS16QS1aXXxcXGR8W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pfCgoW2EtekEtWl18XFxkfFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKShbYS16QS1aXXxcXGR8LXxcXC58X3x+fFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKSooW2EtekEtWl18XFxkfFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKSkpXFwuKSsoKFthLXpBLVpdfFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKXwoKFthLXpBLVpdfFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKShbYS16QS1aXXxcXGR8LXxcXC58X3x+fFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKSooW2EtekEtWl18W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKSlcXC4/KSg6XFxkKik/KShcXC8oKChbYS16QS1aXXxcXGR8LXxcXC58X3x+fFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKXwoJVtcXGRhLWZBLUZdezJ9KXxbIVxcJCYnXFwoXFwpXFwqXFwrLDs9XXw6fEApKyhcXC8oKFthLXpBLVpdfFxcZHwtfFxcLnxffH58W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pfCglW1xcZGEtZkEtRl17Mn0pfFshXFwkJidcXChcXClcXCpcXCssOz1dfDp8QCkqKSopPyk/KFxcPygoKFthLXpBLVpdfFxcZHwtfFxcLnxffH58W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pfCglW1xcZGEtZkEtRl17Mn0pfFshXFwkJidcXChcXClcXCpcXCssOz1dfDp8QCl8W1xcdUUwMDAtXFx1RjhGRl18XFwvfFxcPykqKT8oXFwjKCgoW2EtekEtWl18XFxkfC18XFwufF98fnxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSl8KCVbXFxkYS1mQS1GXXsyfSl8WyFcXCQmJ1xcKFxcKVxcKlxcKyw7PV18OnxAKXxcXC98XFw/KSopPyQvO1xyXG4gICAgcmV0dXJuIG1ha2VSZWdFeHBWYWxpZGF0b3IoJ3VybCcsIHJlVXJsUHJvdG9jb2xSZXF1aXJlZCwgbnVsbCwgY29udGV4dCk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgQ3JlYXRlcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB2YWxpZGF0b3Igd2l0aCBhIGZpeGVkIGV4cHJlc3Npb24uXHJcbiAgTWFueSBvZiB0aGUgc3RvY2sgdmFsaWRhdG9ycyBhcmUgYnVpbHQgd2l0aCB0aGlzIGZhY3RvcnkgbWV0aG9kLlxyXG4gIFRoZWlyIGV4cHJlc3Npb25zIGFyZSBvZnRlbiBkZXJpdmVkIGZyb21cclxuICBodHRwczovL2dpdGh1Yi5jb20vc3JraXJrbGFuZC9EYXRhQW5ub3RhdGlvbnNFeHRlbnNpb25zL2Jsb2IvbWFzdGVyL0RhdGFBbm5vdGF0aW9uc0V4dGVuc2lvbnNcclxuICBZb3UgY2FuIHRyeSBtYW55IG9mIHRoZW0gYXQgaHR0cDovL2RhdGFhbm5vdGF0aW9uc2V4dGVuc2lvbnMub3JnL1xyXG4gIEBleGFtcGxlXHJcbiAgICAgIC8vIE1ha2UgYSB6aXBjb2RlIHZhbGlkYXRvclxyXG4gICAgICBmdW5jdGlvbiB6aXBWYWxpZGF0b3IgPSBWYWxpZGF0b3IubWFrZVJlZ0V4cFZhbGlkYXRvcihcclxuICAgICAgXCJ6aXBWYWwsXHJcbiAgICAgIC9eXFxkezV9KFtcXC1dXFxkezR9KT8kLyxcclxuICAgICAgXCJUaGUgJWRpc3BsYXlOYW1lJSAnJXZhbHVlJScgaXMgbm90IGEgdmFsaWQgVS5TLiB6aXBjb2RlXCIpO1xyXG4gICAgICAvLyBSZWdpc3RlciBpdC5cclxuICAgICAgVmFsaWRhdG9yLnJlZ2lzdGVyKHppcFZhbGlkYXRvcik7XHJcbiAgICAgIC8vIEFkZCBpdCB0byBhIGRhdGEgcHJvcGVydHkuIEFzc3VtZSBlbSBpcyBhIHByZWV4aXN0aW5nIEVudGl0eU1hbmFnZXIuXHJcbiAgICAgIHZhciBjdXN0VHlwZSA9IGVtLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gICAgICB2YXIgemlwUHJvcGVydHkgPSBjdXN0VHlwZS5nZXRQcm9wZXJ0eShcIlBvc3RhbENvZGVcIik7XHJcbiAgICAgIHppcFByb3BlcnR5LnZhbGlkYXRvcnMucHVzaCh6aXBWYWxpZGF0b3IpO1xyXG4gIEBtZXRob2QgbWFrZVJlZ0V4cFZhbGlkYXRvclxyXG4gIEBzdGF0aWNcclxuICBAcGFyYW0gdmFsaWRhdG9yTmFtZSB7U3RyaW5nfSBuYW1lIG9mIHRoaXMgdmFsaWRhdG9yXHJcbiAgQHBhcmFtIGV4cHJlc3Npb24ge1N0cmluZyB8IFJlZ0V4cH0gcmVndWxhciBleHByZXNzaW9uIHRvIGFwcGx5XHJcbiAgQHBhcmFtIFtkZWZhdWx0TWVzc2FnZV0ge1N0cmluZ30gZGVmYXVsdCBtZXNzYWdlIGZvciBmYWlsZWQgdmFsaWRhdGlvbnNcclxuICBAcGFyYW0gW2NvbnRleHRdIHtPYmplY3R9IG9wdGlvbmFsIHBhcmFtZXRlcnMgdG8gcGFzcyB0aHJvdWdoIHRvIHZhbGlkYXRpb24gY29uc3RydWN0b3JcclxuICBAcmV0dXJuIHtWYWxpZGF0b3J9IEEgbmV3IFZhbGlkYXRvclxyXG4gICoqL1xyXG4gIHB1YmxpYyBzdGF0aWMgbWFrZVJlZ0V4cFZhbGlkYXRvciA9IG1ha2VSZWdFeHBWYWxpZGF0b3I7XHJcblxyXG59XHJcblZhbGlkYXRvci5wcm90b3R5cGUuXyR0eXBlTmFtZSA9IFwiVmFsaWRhdG9yXCI7XHJcblxyXG4vLyByZWdpc3RlciBhbGwgdmFsaWRhdG9yc1xyXG5FcnJvclsneCddID0gY29yZS5vYmplY3RGb3JFYWNoKFZhbGlkYXRvciwgZnVuY3Rpb24gKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XHJcbiAgaWYgKHR5cGVvZiAodmFsdWUpICE9PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgIHJldHVybjtcclxuICB9XHJcbiAgaWYgKGtleSA9PT0gXCJmcm9tSlNPTlwiIHx8IGtleSA9PT0gXCJyZWdpc3RlclwiIHx8XHJcbiAgICAgIGtleSA9PT0gXCJyZWdpc3RlckZhY3RvcnlcIiB8fCBrZXkgPT09IFwibWFrZVJlZ0V4cFZhbGlkYXRvclwiKSB7XHJcbiAgICByZXR1cm47XHJcbiAgfVxyXG5cclxuICBjb25maWcucmVnaXN0ZXJGdW5jdGlvbih2YWx1ZSwgXCJWYWxpZGF0b3IuXCIgKyBrZXkpO1xyXG59KTtcclxuXHJcbmZ1bmN0aW9uIGZvcm1hdFRlbXBsYXRlKHRlbXBsYXRlOiBzdHJpbmcsIHZhcnM6IE9iamVjdCwgb3duUHJvcGVydGllc09ubHk6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gIGlmICghdmFycykgcmV0dXJuIHRlbXBsYXRlO1xyXG4gIHJldHVybiB0ZW1wbGF0ZS5yZXBsYWNlKC8lKFteJV0rKSUvZywgZnVuY3Rpb24gKF8sIGtleSkge1xyXG4gICAgbGV0IHZhbE9yRm46IGFueTtcclxuICAgIGlmIChvd25Qcm9wZXJ0aWVzT25seSkge1xyXG4gICAgICB2YWxPckZuID0gdmFycy5oYXNPd25Qcm9wZXJ0eShrZXkpID8gdmFyc1trZXldIDogJyc7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB2YWxPckZuID0gdmFyc1trZXldO1xyXG4gICAgfVxyXG4gICAgaWYgKHZhbE9yRm4gIT0gbnVsbCkge1xyXG4gICAgICBpZiAoY29yZS5pc0Z1bmN0aW9uKHZhbE9yRm4pKSB7XHJcbiAgICAgICAgcmV0dXJuIHZhbE9yRm4odmFycyk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIHZhbE9yRm47XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiBcIlwiO1xyXG4gICAgfVxyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBpbnRSYW5nZVZhbGlkYXRvckN0b3IodmFsaWRhdG9yTmFtZTogc3RyaW5nLCBtaW5WYWx1ZTogbnVtYmVyLCBtYXhWYWx1ZTogbnVtYmVyLCBjb250ZXh0OiBhbnkpIHtcclxuICBjb250ZXh0ID0gY29udGV4dCB8fCB7fTtcclxuICBpZiAobWluVmFsdWUgIT09IHVuZGVmaW5lZCkgeyBjb250ZXh0Lm1pbiA9IG1pblZhbHVlOyB9XHJcbiAgaWYgKG1heFZhbHVlICE9PSB1bmRlZmluZWQpIHsgY29udGV4dC5tYXggPSBtYXhWYWx1ZTsgfVxyXG4gIGxldCB0ZW1wbGF0ZUV4aXN0cyA9IGNvbnRleHQubWVzc2FnZVRlbXBsYXRlIHx8IFZhbGlkYXRvci5tZXNzYWdlVGVtcGxhdGVzW3ZhbGlkYXRvck5hbWVdO1xyXG4gIGlmICghdGVtcGxhdGVFeGlzdHMpIHtcclxuICAgIFZhbGlkYXRvci5tZXNzYWdlVGVtcGxhdGVzW3ZhbGlkYXRvck5hbWVdID0gY29yZS5mb3JtYXRTdHJpbmcoXCInJWRpc3BsYXlOYW1lJScgbXVzdCBiZSBhbiBpbnRlZ2VyIGJldHdlZW4gdGhlIHZhbHVlcyBvZiAlMSBhbmQgJTJcIixcclxuICAgICAgICBtaW5WYWx1ZSwgbWF4VmFsdWUpO1xyXG4gIH1cclxuICByZXR1cm4gZnVuY3Rpb24gKCkge1xyXG4gICAgbGV0IHZhbEZuID0gZnVuY3Rpb24gKHY6IGFueSwgY3R4OiBhbnkpIHtcclxuICAgICAgaWYgKHYgPT0gbnVsbCkgcmV0dXJuIHRydWU7XHJcbiAgICAgIGlmICh0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIiAmJiBjdHggJiYgY3R4LmFsbG93U3RyaW5nKSB7XHJcbiAgICAgICAgdiA9IHBhcnNlSW50KHYsIDApO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICgodHlwZW9mIHYgPT09IFwibnVtYmVyXCIpICYmICghaXNOYU4odikpICYmIE1hdGguZmxvb3IodikgPT09IHYpIHtcclxuICAgICAgICBpZiAobWluVmFsdWUgIT0gbnVsbCAmJiB2IDwgbWluVmFsdWUpIHtcclxuICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKG1heFZhbHVlICE9IG51bGwgJiYgdiA+IG1heFZhbHVlKSB7XHJcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgfTtcclxuICAgIHJldHVybiBuZXcgVmFsaWRhdG9yKHZhbGlkYXRvck5hbWUsIHZhbEZuLCBjb250ZXh0KTtcclxuICB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gbWFrZVJlZ0V4cFZhbGlkYXRvcih2YWxpZGF0b3JOYW1lOiBzdHJpbmcsIGV4cHJlc3Npb246IFJlZ0V4cCwgZGVmYXVsdE1lc3NhZ2U/OiBzdHJpbmcgfCBudWxsLCBjb250ZXh0PzogYW55KSB7XHJcbiAgaWYgKGRlZmF1bHRNZXNzYWdlKSB7XHJcbiAgICBWYWxpZGF0b3IubWVzc2FnZVRlbXBsYXRlc1t2YWxpZGF0b3JOYW1lXSA9IGRlZmF1bHRNZXNzYWdlO1xyXG4gIH1cclxuICBsZXQgcmUgPSAodHlwZW9mIChleHByZXNzaW9uKSA9PT0gJ3N0cmluZycpID8gbmV3IFJlZ0V4cChleHByZXNzaW9uKSA6IGV4cHJlc3Npb247XHJcbiAgbGV0IHZhbEZuID0gZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgLy8gZG8gbm90IGludmFsaWRhdGUgaWYgZW1wdHk7IHVzZSBhIHNlcGFyYXRlIHJlcXVpcmVkIHRlc3RcclxuICAgIGlmICh2ID09IG51bGwgfHwgdiA9PT0gJycpIHJldHVybiB0cnVlO1xyXG4gICAgaWYgKHR5cGVvZiAodikgIT09ICdzdHJpbmcnKSByZXR1cm4gZmFsc2U7XHJcbiAgICByZXR1cm4gcmUudGVzdCh2KTtcclxuICB9O1xyXG4gIHJldHVybiBuZXcgVmFsaWRhdG9yKHZhbGlkYXRvck5hbWUsIHZhbEZuLCBjb250ZXh0KTtcclxufVxyXG5cclxuLy8gaHR0cDovL3Jvc2V0dGFjb2RlLm9yZy93aWtpL0x1aG5fdGVzdF9vZl9jcmVkaXRfY2FyZF9udW1iZXJzI0phdmFTY3JpcHRcclxuXHJcbi8vIGZ1bmN0aW9uIGx1aG4oYTogc3RyaW5nLCBiOiBudW1iZXIsIGM6IG51bWJlciwgZDogbnVtYmVyLCBlOiBudW1iZXIpIHtcclxuLy8gICBmb3IgKGQgPSArYVtiID0gYS5sZW5ndGggLSAxXSwgZSA9IDA7IGItLTsgKSB7XHJcbi8vICAgICBjID0gK2FbYl0sIGQgKz0gKytlICUgMiA/IDIgKiBjICUgMTAgKyAoYyA+IDQpIDogYztcclxuLy8gICB9XHJcbi8vICAgcmV0dXJuICEoZCAlIDEwKTtcclxuLy8gfTtcclxuXHJcbmxldCAgbHVobiA9IChmdW5jdGlvbigpIHtcclxuICBsZXQgbHVobkFyciA9IFswLCAyLCA0LCA2LCA4LCAxLCAzLCA1LCA3LCA5XTtcclxuICByZXR1cm4gZnVuY3Rpb24oc3RyOiBzdHJpbmcpIFx0e1xyXG4gICAgbGV0IGNvdW50ZXIgPSAwO1xyXG4gICAgbGV0IGluY051bTogbnVtYmVyO1xyXG4gICAgbGV0IG9kZCA9IGZhbHNlO1xyXG4gICAgbGV0IHRlbXAgPSBTdHJpbmcoc3RyKS5yZXBsYWNlKC9bXlxcZF0vZywgXCJcIik7XHJcbiAgICBpZiAoIHRlbXAubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2U7XHJcbiAgICBmb3IgKGxldCBpID0gdGVtcC5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgIHtcclxuICAgICAgaW5jTnVtID0gcGFyc2VJbnQodGVtcC5jaGFyQXQoaSksIDEwKTtcclxuICAgICAgY291bnRlciArPSAob2RkID0gIW9kZCkgPyBpbmNOdW0gOiBsdWhuQXJyW2luY051bV07XHJcbiAgICB9XHJcbiAgICByZXR1cm4gKGNvdW50ZXIgJSAxMCA9PT0gMCk7XHJcbiAgfTtcclxufSkoKTtcclxuXHJcbi8qKlxyXG5BIFZhbGlkYXRpb25FcnJvciBpcyB1c2VkIHRvIGRlc2NyaWJlIGEgZmFpbGVkIHZhbGlkYXRpb24uXHJcblxyXG5AY2xhc3MgVmFsaWRhdGlvbkVycm9yXHJcbioqL1xyXG5cclxuLyoqXHJcbkNvbnN0cnVjdHMgYSBuZXcgVmFsaWRhdGlvbkVycm9yXHJcbkBtZXRob2QgPGN0b3I+IFZhbGlkYXRpb25FcnJvclxyXG5cclxuQHBhcmFtIHZhbGlkYXRvciB7VmFsaWRhdG9yIHx8IG51bGx9IFRoZSBWYWxpZGF0b3IgdXNlZCB0byBjcmVhdGUgdGhpcyBlcnJvciwgaWYgYW55LlxyXG5AcGFyYW0gY29udGV4dCB7IENvbnRleHRPYmplY3QgfHwgbnVsbH0gVGhlIENvbnRleHQgb2JqZWN0IHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCB0aGUgVmFsaWRhdG9yIHRvIGNyZWF0ZSB0aGlzIGVycm9yLlxyXG5AcGFyYW0gZXJyb3JNZXNzYWdlIHsgU3RyaW5nfSBUaGUgYWN0dWFsIGVycm9yIG1lc3NhZ2VcclxuQHBhcmFtIFtrZXldIHtTdHJpbmd9IEFuIG9wdGlvbmFsIGtleSB1c2VkIHRvIGRlZmluZSBhIGtleSBmb3IgdGhpcyBlcnJvci4gT25lIHdpbGwgYmUgY3JlYXRlZCBhdXRvbWF0aWNhbGx5IGlmIG5vdCBwcm92aWRlZCBoZXJlLlxyXG4qKi9cclxuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb25FcnJvciB7XHJcbiAgdmFsaWRhdG9yPzogVmFsaWRhdG9yO1xyXG4gIGtleTogc3RyaW5nO1xyXG4gIGNvbnRleHQ6IGFueTtcclxuICBlcnJvck1lc3NhZ2U6IHN0cmluZztcclxuICBwcm9wZXJ0eTogYW55OyAvLyBJUHJvcGVydHlcclxuICBwcm9wZXJ0eU5hbWU6IHN0cmluZztcclxuICBpc1NlcnZlckVycm9yOiBib29sZWFuO1xyXG5cclxuICBjb25zdHJ1Y3Rvcih2YWxpZGF0b3I6IFZhbGlkYXRvciB8IG51bGwsIGNvbnRleHQ6IFZhbGlkYXRpb25Db250ZXh0LCBlcnJvck1lc3NhZ2U6IHN0cmluZywga2V5Pzogc3RyaW5nKSB7XHJcbiAgICAvLyBFcnJvciBpcyB3aXRoIGlzSW5zdGFuY2VPZihWYWxpZGF0b3IpXHJcbiAgICBhc3NlcnRQYXJhbSh2YWxpZGF0b3IsIFwidmFsaWRhdG9yXCIpLmlzT3B0aW9uYWwoKS5pc0luc3RhbmNlT2YoVmFsaWRhdG9yKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oZXJyb3JNZXNzYWdlLCBcImVycm9yTWVzc2FnZVwiKS5pc05vbkVtcHR5U3RyaW5nKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGtleSwgXCJrZXlcIikuaXNPcHRpb25hbCgpLmlzTm9uRW1wdHlTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgdGhpcy52YWxpZGF0b3IgPSB2YWxpZGF0b3IgfHwgdW5kZWZpbmVkO1xyXG4gICAgY29udGV4dCA9IGNvbnRleHQgfHwge307XHJcbiAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xyXG4gICAgdGhpcy5lcnJvck1lc3NhZ2UgPSBlcnJvck1lc3NhZ2U7XHJcblxyXG4gICAgdGhpcy5wcm9wZXJ0eSA9IGNvbnRleHQucHJvcGVydHk7XHJcbiAgICB0aGlzLnByb3BlcnR5TmFtZSA9IGNvbnRleHQucHJvcGVydHlOYW1lIHx8IChjb250ZXh0LnByb3BlcnR5ICYmIGNvbnRleHQucHJvcGVydHkubmFtZSk7XHJcblxyXG4gICAgaWYgKGtleSkge1xyXG4gICAgICB0aGlzLmtleSA9IGtleTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMua2V5ID0gVmFsaWRhdGlvbkVycm9yLmdldEtleSh2YWxpZGF0b3IgfHwgZXJyb3JNZXNzYWdlLCB0aGlzLnByb3BlcnR5TmFtZSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmlzU2VydmVyRXJyb3IgPSBmYWxzZTtcclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICBUaGUgVmFsaWRhdG9yIGFzc29jaWF0ZWQgd2l0aCB0aGlzIFZhbGlkYXRpb25FcnJvci5cclxuXHJcbiAgX19yZWFkT25seV9fXHJcbiAgQHByb3BlcnR5IHZhbGlkYXRvciB7VmFsaWRhdG9yfVxyXG4gICoqL1xyXG5cclxuICAvKipcclxuICBBICdjb250ZXh0JyBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMgVmFsaWRhdGlvbkVycm9yLlxyXG5cclxuICBfX3JlYWRPbmx5X19cclxuICBAcHJvcGVydHkgY29udGV4dCB7T2JqZWN0fVxyXG4gICoqL1xyXG5cclxuICAvKipcclxuICBUaGUgRGF0YVByb3BlcnR5IG9yIE5hdmlnYXRpb25Qcm9wZXJ0eSBhc3NvY2lhdGVkIHdpdGggdGhpcyBWYWxpZGF0aW9uRXJyb3IuXHJcblxyXG4gIF9fcmVhZE9ubHlfX1xyXG4gIEBwcm9wZXJ0eSBwcm9wZXJ0eSB7RGF0YVByb3BlcnR5fE5hdmlnYXRpb25Qcm9wZXJ0eX1cclxuICAqKi9cclxuXHJcbiAgLyoqXHJcbiAgVGhlIHByb3BlcnR5IG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgVmFsaWRhdGlvbkVycm9yLiBUaGlzIHdpbGwgYmUgYSBcInByb3BlcnR5IHBhdGhcIiBmb3IgYW55IHByb3BlcnRpZXMgb2YgYSBjb21wbGV4IG9iamVjdC5cclxuXHJcbiAgX19yZWFkT25seV9fXHJcbiAgQHByb3BlcnR5IHByb3BlcnR5TmFtZSB7U3RyaW5nfVxyXG4gICoqL1xyXG5cclxuICAvKipcclxuICBUaGUgZXJyb3IgbWVzc2FnZSBhc3NvY2lhdGVkIHdpdGggdGhlIFZhbGlkYXRpb25FcnJvci5cclxuXHJcbiAgX19yZWFkT25seV9fXHJcbiAgQHByb3BlcnR5IGVycm9yTWVzc2FnZSB7c3RyaW5nfVxyXG4gICoqL1xyXG5cclxuICAvKipcclxuICBUaGUga2V5IGJ5IHdoaWNoIHRoaXMgdmFsaWRhdGlvbiBlcnJvciBtYXkgYmUgcmVtb3ZlZCBmcm9tIGEgY29sbGVjdGlvbiBvZiBWYWxpZGF0aW9uRXJyb3JzLlxyXG5cclxuICBfX3JlYWRPbmx5X19cclxuICBAcHJvcGVydHkga2V5IHtzdHJpbmd9XHJcbiAgKiovXHJcblxyXG4gIC8qKlxyXG4gIFdoZXRoZXIgdGhpcyBpcyBhIHNlcnZlciBlcnJvci5cclxuXHJcbiAgX19yZWFkT25seV9fXHJcbiAgQHByb3BlcnR5IGlzU2VydmVyRXJyb3Ige2Jvb2x9XHJcbiAgKiovXHJcblxyXG5cclxuICAvKipcclxuICBDb21wb3NlcyBhIFZhbGlkYXRpb25FcnJvciAna2V5JyBnaXZlbiBhIHZhbGlkYXRvciBvciBhbiBlcnJvck5hbWUgYW5kIGFuIG9wdGlvbmFsIHByb3BlcnR5TmFtZVxyXG4gIEBtZXRob2QgZ2V0S2V5XHJcbiAgQHN0YXRpY1xyXG4gIEBwYXJhbSB2YWxpZGF0b3Ige1ZhbGlkYXRvck9yRXJyb3JLZXl9IEEgVmFsaWRhdG9yIG9yIGFuIFwiZXJyb3IgbmFtZVwiIGlmIG5vIHZhbGlkYXRvciBpcyBhdmFpbGFibGUuXHJcbiAgQHBhcmFtIFtwcm9wZXJ0eU5hbWVdIEEgcHJvcGVydHkgbmFtZVxyXG4gIEByZXR1cm4ge1N0cmluZ30gQSBWYWxpZGF0aW9uRXJyb3IgJ2tleSdcclxuICAqKi9cclxuICBwdWJsaWMgc3RhdGljIGdldEtleSh2YWxpZGF0b3JPckVycm9yTmFtZTogVmFsaWRhdG9yIHwgc3RyaW5nLCBwcm9wZXJ0eU5hbWU/OiBzdHJpbmcpIHtcclxuICAgIGxldCBuYW1lID0gKHR5cGVvZiB2YWxpZGF0b3JPckVycm9yTmFtZSA9PT0gJ3N0cmluZycpID8gdmFsaWRhdG9yT3JFcnJvck5hbWUgOiB2YWxpZGF0b3JPckVycm9yTmFtZS5uYW1lO1xyXG4gICAgcmV0dXJuIG5hbWUgKyAocHJvcGVydHlOYW1lID8gXCI6XCIgKyBwcm9wZXJ0eU5hbWUgOiBcIlwiKTtcclxuICB9XHJcblxyXG59XHJcblxyXG5cclxuIl19