breeze-client 2.1.3-mjs → 2.1.4

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/README.md +18 -5
  2. package/adapter-ajax-angularjs/{index.d.ts → breeze-client-adapter-ajax-angularjs.d.ts} +0 -1
  3. package/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.metadata.json +1 -0
  4. package/adapter-ajax-angularjs/package.json +13 -0
  5. package/adapter-ajax-fetch/{index.d.ts → breeze-client-adapter-ajax-fetch.d.ts} +0 -1
  6. package/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.metadata.json +1 -0
  7. package/adapter-ajax-fetch/package.json +13 -0
  8. package/adapter-ajax-httpclient/{index.d.ts → breeze-client-adapter-ajax-httpclient.d.ts} +0 -1
  9. package/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.metadata.json +1 -0
  10. package/adapter-ajax-httpclient/package.json +13 -0
  11. package/adapter-ajax-jquery/{index.d.ts → breeze-client-adapter-ajax-jquery.d.ts} +0 -1
  12. package/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.metadata.json +1 -0
  13. package/adapter-ajax-jquery/package.json +13 -0
  14. package/adapter-ajax-post/{index.d.ts → breeze-client-adapter-ajax-post.d.ts} +0 -1
  15. package/adapter-ajax-post/breeze-client-adapter-ajax-post.metadata.json +1 -0
  16. package/adapter-ajax-post/package.json +13 -0
  17. package/adapter-data-service-odata/{index.d.ts → breeze-client-adapter-data-service-odata.d.ts} +0 -1
  18. package/adapter-data-service-odata/breeze-client-adapter-data-service-odata.metadata.json +1 -0
  19. package/adapter-data-service-odata/package.json +13 -0
  20. package/adapter-data-service-webapi/{index.d.ts → breeze-client-adapter-data-service-webapi.d.ts} +0 -1
  21. package/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.metadata.json +1 -0
  22. package/adapter-data-service-webapi/package.json +13 -0
  23. package/adapter-model-library-backing-store/{index.d.ts → breeze-client-adapter-model-library-backing-store.d.ts} +0 -1
  24. package/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.metadata.json +1 -0
  25. package/adapter-model-library-backing-store/package.json +13 -0
  26. package/adapter-model-library-ko/{index.d.ts → breeze-client-adapter-model-library-ko.d.ts} +0 -1
  27. package/adapter-model-library-ko/breeze-client-adapter-model-library-ko.metadata.json +1 -0
  28. package/adapter-model-library-ko/package.json +13 -0
  29. package/adapter-uri-builder-json/{index.d.ts → breeze-client-adapter-uri-builder-json.d.ts} +0 -1
  30. package/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.metadata.json +1 -0
  31. package/adapter-uri-builder-json/package.json +13 -0
  32. package/adapter-uri-builder-odata/{index.d.ts → breeze-client-adapter-uri-builder-odata.d.ts} +0 -1
  33. package/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.metadata.json +1 -0
  34. package/adapter-uri-builder-odata/package.json +13 -0
  35. package/breeze-client.d.ts +8 -0
  36. package/breeze-client.metadata.json +1 -0
  37. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js +190 -0
  38. package/bundles/breeze-client-adapter-ajax-angularjs.umd.js.map +1 -0
  39. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js +2 -0
  40. package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js.map +1 -0
  41. package/bundles/breeze-client-adapter-ajax-fetch.umd.js +190 -0
  42. package/bundles/breeze-client-adapter-ajax-fetch.umd.js.map +1 -0
  43. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js +2 -0
  44. package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js.map +1 -0
  45. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js +195 -0
  46. package/bundles/breeze-client-adapter-ajax-httpclient.umd.js.map +1 -0
  47. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js +2 -0
  48. package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js.map +1 -0
  49. package/bundles/breeze-client-adapter-ajax-jquery.umd.js +115 -0
  50. package/bundles/breeze-client-adapter-ajax-jquery.umd.js.map +1 -0
  51. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js +2 -0
  52. package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js.map +1 -0
  53. package/bundles/breeze-client-adapter-ajax-post.umd.js +92 -0
  54. package/bundles/breeze-client-adapter-ajax-post.umd.js.map +1 -0
  55. package/bundles/breeze-client-adapter-ajax-post.umd.min.js +2 -0
  56. package/bundles/breeze-client-adapter-ajax-post.umd.min.js.map +1 -0
  57. package/bundles/breeze-client-adapter-data-service-odata.umd.js +743 -0
  58. package/bundles/breeze-client-adapter-data-service-odata.umd.js.map +1 -0
  59. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js +16 -0
  60. package/bundles/breeze-client-adapter-data-service-odata.umd.min.js.map +1 -0
  61. package/bundles/breeze-client-adapter-data-service-webapi.umd.js +326 -0
  62. package/bundles/breeze-client-adapter-data-service-webapi.umd.js.map +1 -0
  63. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js +16 -0
  64. package/bundles/breeze-client-adapter-data-service-webapi.umd.min.js.map +1 -0
  65. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js +280 -0
  66. package/bundles/breeze-client-adapter-model-library-backing-store.umd.js.map +1 -0
  67. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js +2 -0
  68. package/bundles/breeze-client-adapter-model-library-backing-store.umd.min.js.map +1 -0
  69. package/bundles/breeze-client-adapter-model-library-ko.umd.js +252 -0
  70. package/bundles/breeze-client-adapter-model-library-ko.umd.js.map +1 -0
  71. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js +2 -0
  72. package/bundles/breeze-client-adapter-model-library-ko.umd.min.js.map +1 -0
  73. package/bundles/breeze-client-adapter-uri-builder-json.umd.js +96 -0
  74. package/bundles/breeze-client-adapter-uri-builder-json.umd.js.map +1 -0
  75. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js +2 -0
  76. package/bundles/breeze-client-adapter-uri-builder-json.umd.min.js.map +1 -0
  77. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js +262 -0
  78. package/bundles/breeze-client-adapter-uri-builder-odata.umd.js.map +1 -0
  79. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js +2 -0
  80. package/bundles/breeze-client-adapter-uri-builder-odata.umd.min.js.map +1 -0
  81. package/bundles/breeze-client-mixin-get-entity-graph.umd.js +258 -0
  82. package/bundles/breeze-client-mixin-get-entity-graph.umd.js.map +1 -0
  83. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js +2 -0
  84. package/bundles/breeze-client-mixin-get-entity-graph.umd.min.js.map +1 -0
  85. package/bundles/breeze-client-mixin-save-queuing.umd.js +579 -0
  86. package/bundles/breeze-client-mixin-save-queuing.umd.js.map +1 -0
  87. package/bundles/breeze-client-mixin-save-queuing.umd.min.js +16 -0
  88. package/bundles/breeze-client-mixin-save-queuing.umd.min.js.map +1 -0
  89. package/bundles/breeze-client.umd.js +14098 -0
  90. package/bundles/breeze-client.umd.js.map +1 -0
  91. package/bundles/breeze-client.umd.min.js +16 -0
  92. package/bundles/breeze-client.umd.min.js.map +1 -0
  93. package/esm2015/adapter-ajax-angularjs/adapter-ajax-angularjs.js +130 -0
  94. package/esm2015/adapter-ajax-angularjs/adapter-core.js +49 -0
  95. package/esm2015/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +5 -0
  96. package/esm2015/adapter-ajax-fetch/adapter-ajax-fetch.js +130 -0
  97. package/esm2015/adapter-ajax-fetch/adapter-core.js +49 -0
  98. package/esm2015/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +5 -0
  99. package/esm2015/adapter-ajax-httpclient/adapter-ajax-httpclient.js +137 -0
  100. package/esm2015/adapter-ajax-httpclient/adapter-core.js +49 -0
  101. package/esm2015/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +5 -0
  102. package/esm2015/adapter-ajax-jquery/adapter-ajax-jquery.js +103 -0
  103. package/esm2015/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +5 -0
  104. package/esm2015/adapter-ajax-post/adapter-ajax-post.js +77 -0
  105. package/esm2015/adapter-ajax-post/breeze-client-adapter-ajax-post.js +5 -0
  106. package/esm2015/adapter-data-service-odata/adapter-core.js +49 -0
  107. package/esm2015/adapter-data-service-odata/adapter-data-service-odata.js +459 -0
  108. package/esm2015/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +5 -0
  109. package/esm2015/adapter-data-service-webapi/adapter-data-service-webapi.js +93 -0
  110. package/esm2015/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +5 -0
  111. package/esm2015/adapter-model-library-backing-store/adapter-model-library-backing-store.js +268 -0
  112. package/esm2015/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +5 -0
  113. package/esm2015/adapter-model-library-ko/adapter-model-library-ko.js +240 -0
  114. package/esm2015/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +5 -0
  115. package/esm2015/adapter-uri-builder-json/adapter-core.js +49 -0
  116. package/esm2015/adapter-uri-builder-json/adapter-uri-builder-json.js +36 -0
  117. package/esm2015/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +5 -0
  118. package/esm2015/adapter-uri-builder-odata/adapter-core.js +49 -0
  119. package/esm2015/adapter-uri-builder-odata/adapter-uri-builder-odata.js +192 -0
  120. package/esm2015/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +5 -0
  121. package/esm2015/breeze-client.js +9 -0
  122. package/esm2015/index.js +2 -0
  123. package/esm2015/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +5 -0
  124. package/esm2015/mixin-get-entity-graph/mixin-get-entity-graph.js +269 -0
  125. package/esm2015/mixin-save-queuing/breeze-client-mixin-save-queuing.js +5 -0
  126. package/esm2015/mixin-save-queuing/mixin-save-queuing.js +400 -0
  127. package/esm2015/src/abstract-data-service-adapter.js +296 -0
  128. package/esm2015/src/array.js +4 -0
  129. package/esm2015/src/assert-param.js +312 -0
  130. package/esm2015/src/breeze.js +85 -0
  131. package/esm2015/src/complex-array.js +119 -0
  132. package/esm2015/src/config.js +223 -0
  133. package/esm2015/src/core.js +709 -0
  134. package/esm2015/src/csdl-metadata-parser.js +385 -0
  135. package/esm2015/src/data-service.js +203 -0
  136. package/esm2015/src/data-type.js +444 -0
  137. package/esm2015/src/default-property-interceptor.js +460 -0
  138. package/esm2015/src/entity-action.js +45 -0
  139. package/esm2015/src/entity-aspect.js +806 -0
  140. package/esm2015/src/entity-group.js +187 -0
  141. package/esm2015/src/entity-key.js +116 -0
  142. package/esm2015/src/entity-manager.js +2094 -0
  143. package/esm2015/src/entity-metadata.js +2109 -0
  144. package/esm2015/src/entity-query.js +996 -0
  145. package/esm2015/src/entity-state.js +99 -0
  146. package/esm2015/src/enum.js +141 -0
  147. package/esm2015/src/event.js +256 -0
  148. package/esm2015/src/interface-registry.js +41 -0
  149. package/esm2015/src/key-generator.js +108 -0
  150. package/esm2015/src/local-query-comparison-options.js +65 -0
  151. package/esm2015/src/mapping-context.js +405 -0
  152. package/esm2015/src/naming-convention.js +88 -0
  153. package/esm2015/src/observable-array.js +185 -0
  154. package/esm2015/src/predicate.js +1235 -0
  155. package/esm2015/src/primitive-array.js +87 -0
  156. package/esm2015/src/query-options.js +152 -0
  157. package/esm2015/src/relation-array.js +175 -0
  158. package/esm2015/src/save-options.js +41 -0
  159. package/esm2015/src/unattached-children-map.js +58 -0
  160. package/esm2015/src/validate.js +991 -0
  161. package/esm2015/src/validation-options.js +64 -0
  162. package/esm5/adapter-ajax-angularjs/adapter-ajax-angularjs.js +132 -0
  163. package/esm5/adapter-ajax-angularjs/adapter-core.js +49 -0
  164. package/esm5/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.js +5 -0
  165. package/esm5/adapter-ajax-fetch/adapter-ajax-fetch.js +132 -0
  166. package/esm5/adapter-ajax-fetch/adapter-core.js +49 -0
  167. package/esm5/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.js +5 -0
  168. package/esm5/adapter-ajax-httpclient/adapter-ajax-httpclient.js +139 -0
  169. package/esm5/adapter-ajax-httpclient/adapter-core.js +49 -0
  170. package/esm5/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.js +5 -0
  171. package/esm5/adapter-ajax-jquery/adapter-ajax-jquery.js +105 -0
  172. package/esm5/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.js +5 -0
  173. package/esm5/adapter-ajax-post/adapter-ajax-post.js +81 -0
  174. package/esm5/adapter-ajax-post/breeze-client-adapter-ajax-post.js +5 -0
  175. package/esm5/adapter-data-service-odata/adapter-core.js +49 -0
  176. package/esm5/adapter-data-service-odata/adapter-data-service-odata.js +466 -0
  177. package/esm5/adapter-data-service-odata/breeze-client-adapter-data-service-odata.js +5 -0
  178. package/esm5/adapter-data-service-webapi/adapter-data-service-webapi.js +98 -0
  179. package/esm5/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +5 -0
  180. package/esm5/adapter-model-library-backing-store/adapter-model-library-backing-store.js +270 -0
  181. package/esm5/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +5 -0
  182. package/esm5/adapter-model-library-ko/adapter-model-library-ko.js +242 -0
  183. package/esm5/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +5 -0
  184. package/esm5/adapter-uri-builder-json/adapter-core.js +49 -0
  185. package/esm5/adapter-uri-builder-json/adapter-uri-builder-json.js +38 -0
  186. package/esm5/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +5 -0
  187. package/esm5/adapter-uri-builder-odata/adapter-core.js +49 -0
  188. package/esm5/adapter-uri-builder-odata/adapter-uri-builder-odata.js +197 -0
  189. package/esm5/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +5 -0
  190. package/esm5/breeze-client.js +9 -0
  191. package/esm5/index.js +2 -0
  192. package/esm5/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +5 -0
  193. package/esm5/mixin-get-entity-graph/mixin-get-entity-graph.js +269 -0
  194. package/esm5/mixin-save-queuing/breeze-client-mixin-save-queuing.js +5 -0
  195. package/esm5/mixin-save-queuing/mixin-save-queuing.js +412 -0
  196. package/esm5/src/abstract-data-service-adapter.js +302 -0
  197. package/esm5/src/array.js +4 -0
  198. package/esm5/src/assert-param.js +317 -0
  199. package/esm5/src/breeze.js +85 -0
  200. package/esm5/src/complex-array.js +119 -0
  201. package/esm5/src/config.js +228 -0
  202. package/esm5/src/core.js +717 -0
  203. package/esm5/src/csdl-metadata-parser.js +385 -0
  204. package/esm5/src/data-service.js +207 -0
  205. package/esm5/src/data-type.js +451 -0
  206. package/esm5/src/default-property-interceptor.js +460 -0
  207. package/esm5/src/entity-action.js +52 -0
  208. package/esm5/src/entity-aspect.js +812 -0
  209. package/esm5/src/entity-group.js +189 -0
  210. package/esm5/src/entity-key.js +118 -0
  211. package/esm5/src/entity-manager.js +2112 -0
  212. package/esm5/src/entity-metadata.js +2144 -0
  213. package/esm5/src/entity-query.js +1023 -0
  214. package/esm5/src/entity-state.js +106 -0
  215. package/esm5/src/enum.js +144 -0
  216. package/esm5/src/event.js +259 -0
  217. package/esm5/src/interface-registry.js +43 -0
  218. package/esm5/src/key-generator.js +111 -0
  219. package/esm5/src/local-query-comparison-options.js +67 -0
  220. package/esm5/src/mapping-context.js +407 -0
  221. package/esm5/src/naming-convention.js +90 -0
  222. package/esm5/src/observable-array.js +201 -0
  223. package/esm5/src/predicate.js +1300 -0
  224. package/esm5/src/primitive-array.js +87 -0
  225. package/esm5/src/query-options.js +167 -0
  226. package/esm5/src/relation-array.js +175 -0
  227. package/esm5/src/save-options.js +43 -0
  228. package/esm5/src/unattached-children-map.js +60 -0
  229. package/esm5/src/validate.js +996 -0
  230. package/esm5/src/validation-options.js +66 -0
  231. package/fesm2015/{breeze-client-adapter-ajax-angularjs.mjs → breeze-client-adapter-ajax-angularjs.js} +1 -1
  232. package/fesm2015/breeze-client-adapter-ajax-angularjs.js.map +1 -0
  233. package/fesm2015/{breeze-client-adapter-ajax-fetch.mjs → breeze-client-adapter-ajax-fetch.js} +3 -5
  234. package/fesm2015/breeze-client-adapter-ajax-fetch.js.map +1 -0
  235. package/fesm2015/{breeze-client-adapter-ajax-httpclient.mjs → breeze-client-adapter-ajax-httpclient.js} +1 -1
  236. package/fesm2015/breeze-client-adapter-ajax-httpclient.js.map +1 -0
  237. package/fesm2015/{breeze-client-adapter-ajax-jquery.mjs → breeze-client-adapter-ajax-jquery.js} +2 -2
  238. package/fesm2015/breeze-client-adapter-ajax-jquery.js.map +1 -0
  239. package/{fesm2020/breeze-client-adapter-ajax-post.mjs → fesm2015/breeze-client-adapter-ajax-post.js} +1 -1
  240. package/fesm2015/breeze-client-adapter-ajax-post.js.map +1 -0
  241. package/fesm2015/{breeze-client-adapter-data-service-odata.mjs → breeze-client-adapter-data-service-odata.js} +22 -20
  242. package/fesm2015/breeze-client-adapter-data-service-odata.js.map +1 -0
  243. package/fesm2015/{breeze-client-adapter-data-service-webapi.mjs → breeze-client-adapter-data-service-webapi.js} +13 -13
  244. package/fesm2015/breeze-client-adapter-data-service-webapi.js.map +1 -0
  245. package/{fesm2020/breeze-client-adapter-model-library-backing-store.mjs → fesm2015/breeze-client-adapter-model-library-backing-store.js} +13 -13
  246. package/fesm2015/breeze-client-adapter-model-library-backing-store.js.map +1 -0
  247. package/{fesm2020/breeze-client-adapter-model-library-ko.mjs → fesm2015/breeze-client-adapter-model-library-ko.js} +13 -13
  248. package/fesm2015/breeze-client-adapter-model-library-ko.js.map +1 -0
  249. package/{fesm2020/breeze-client-adapter-uri-builder-json.mjs → fesm2015/breeze-client-adapter-uri-builder-json.js} +8 -8
  250. package/fesm2015/breeze-client-adapter-uri-builder-json.js.map +1 -0
  251. package/{fesm2020/breeze-client-adapter-uri-builder-odata.mjs → fesm2015/breeze-client-adapter-uri-builder-odata.js} +86 -85
  252. package/fesm2015/breeze-client-adapter-uri-builder-odata.js.map +1 -0
  253. package/fesm2015/{breeze-client-mixin-get-entity-graph.mjs → breeze-client-mixin-get-entity-graph.js} +1 -1
  254. package/fesm2015/breeze-client-mixin-get-entity-graph.js.map +1 -0
  255. package/fesm2015/{breeze-client-mixin-save-queuing.mjs → breeze-client-mixin-save-queuing.js} +1 -1
  256. package/fesm2015/breeze-client-mixin-save-queuing.js.map +1 -0
  257. package/fesm2015/{breeze-client.mjs → breeze-client.js} +418 -409
  258. package/fesm2015/breeze-client.js.map +1 -0
  259. package/{fesm2020/breeze-client-adapter-ajax-angularjs.mjs → fesm5/breeze-client-adapter-ajax-angularjs.js} +42 -41
  260. package/fesm5/breeze-client-adapter-ajax-angularjs.js.map +1 -0
  261. package/{fesm2020/breeze-client-adapter-ajax-fetch.mjs → fesm5/breeze-client-adapter-ajax-fetch.js} +43 -44
  262. package/fesm5/breeze-client-adapter-ajax-fetch.js.map +1 -0
  263. package/{fesm2020/breeze-client-adapter-ajax-httpclient.mjs → fesm5/breeze-client-adapter-ajax-httpclient.js} +44 -43
  264. package/fesm5/breeze-client-adapter-ajax-httpclient.js.map +1 -0
  265. package/{fesm2020/breeze-client-adapter-ajax-jquery.mjs → fesm5/breeze-client-adapter-ajax-jquery.js} +19 -18
  266. package/fesm5/breeze-client-adapter-ajax-jquery.js.map +1 -0
  267. package/{fesm2015/breeze-client-adapter-ajax-post.mjs → fesm5/breeze-client-adapter-ajax-post.js} +11 -8
  268. package/fesm5/breeze-client-adapter-ajax-post.js.map +1 -0
  269. package/{fesm2020/breeze-client-adapter-data-service-odata.mjs → fesm5/breeze-client-adapter-data-service-odata.js} +134 -126
  270. package/fesm5/breeze-client-adapter-data-service-odata.js.map +1 -0
  271. package/{fesm2020/breeze-client-adapter-data-service-webapi.mjs → fesm5/breeze-client-adapter-data-service-webapi.js} +42 -38
  272. package/fesm5/breeze-client-adapter-data-service-webapi.js.map +1 -0
  273. package/{fesm2015/breeze-client-adapter-model-library-backing-store.mjs → fesm5/breeze-client-adapter-model-library-backing-store.js} +64 -63
  274. package/fesm5/breeze-client-adapter-model-library-backing-store.js.map +1 -0
  275. package/{fesm2015/breeze-client-adapter-model-library-ko.mjs → fesm5/breeze-client-adapter-model-library-ko.js} +58 -57
  276. package/fesm5/breeze-client-adapter-model-library-ko.js.map +1 -0
  277. package/fesm5/breeze-client-adapter-uri-builder-json.js +92 -0
  278. package/fesm5/breeze-client-adapter-uri-builder-json.js.map +1 -0
  279. package/fesm5/breeze-client-adapter-uri-builder-odata.js +250 -0
  280. package/fesm5/breeze-client-adapter-uri-builder-odata.js.map +1 -0
  281. package/{fesm2020/breeze-client-mixin-get-entity-graph.mjs → fesm5/breeze-client-mixin-get-entity-graph.js} +45 -45
  282. package/fesm5/breeze-client-mixin-get-entity-graph.js.map +1 -0
  283. package/{fesm2020/breeze-client-mixin-save-queuing.mjs → fesm5/breeze-client-mixin-save-queuing.js} +126 -116
  284. package/fesm5/breeze-client-mixin-save-queuing.js.map +1 -0
  285. package/{fesm2020/breeze-client.mjs → fesm5/breeze-client.js} +3630 -3414
  286. package/fesm5/breeze-client.js.map +1 -0
  287. package/mixin-get-entity-graph/{index.d.ts → breeze-client-mixin-get-entity-graph.d.ts} +0 -1
  288. package/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.metadata.json +1 -0
  289. package/mixin-get-entity-graph/package.json +13 -0
  290. package/mixin-save-queuing/{index.d.ts → breeze-client-mixin-save-queuing.d.ts} +0 -1
  291. package/mixin-save-queuing/breeze-client-mixin-save-queuing.metadata.json +1 -0
  292. package/mixin-save-queuing/package.json +13 -0
  293. package/package.json +12 -126
  294. package/src/entity-metadata.d.ts +4 -6
  295. package/src/entity-query.d.ts +1 -1
  296. package/esm2020/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +0 -130
  297. package/esm2020/adapter-ajax-angularjs/adapter-core.mjs +0 -49
  298. package/esm2020/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +0 -5
  299. package/esm2020/adapter-ajax-fetch/adapter-ajax-fetch.mjs +0 -132
  300. package/esm2020/adapter-ajax-fetch/adapter-core.mjs +0 -49
  301. package/esm2020/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +0 -5
  302. package/esm2020/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +0 -137
  303. package/esm2020/adapter-ajax-httpclient/adapter-core.mjs +0 -49
  304. package/esm2020/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +0 -5
  305. package/esm2020/adapter-ajax-jquery/adapter-ajax-jquery.mjs +0 -103
  306. package/esm2020/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +0 -5
  307. package/esm2020/adapter-ajax-post/adapter-ajax-post.mjs +0 -77
  308. package/esm2020/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +0 -5
  309. package/esm2020/adapter-data-service-odata/adapter-core.mjs +0 -49
  310. package/esm2020/adapter-data-service-odata/adapter-data-service-odata.mjs +0 -456
  311. package/esm2020/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +0 -5
  312. package/esm2020/adapter-data-service-webapi/adapter-data-service-webapi.mjs +0 -93
  313. package/esm2020/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +0 -5
  314. package/esm2020/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +0 -268
  315. package/esm2020/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +0 -5
  316. package/esm2020/adapter-model-library-ko/adapter-model-library-ko.mjs +0 -240
  317. package/esm2020/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +0 -5
  318. package/esm2020/adapter-uri-builder-json/adapter-core.mjs +0 -49
  319. package/esm2020/adapter-uri-builder-json/adapter-uri-builder-json.mjs +0 -36
  320. package/esm2020/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +0 -5
  321. package/esm2020/adapter-uri-builder-odata/adapter-core.mjs +0 -49
  322. package/esm2020/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +0 -190
  323. package/esm2020/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +0 -5
  324. package/esm2020/breeze-client.mjs +0 -5
  325. package/esm2020/index.mjs +0 -2
  326. package/esm2020/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +0 -5
  327. package/esm2020/mixin-get-entity-graph/mixin-get-entity-graph.mjs +0 -269
  328. package/esm2020/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +0 -5
  329. package/esm2020/mixin-save-queuing/mixin-save-queuing.mjs +0 -400
  330. package/esm2020/src/abstract-data-service-adapter.mjs +0 -296
  331. package/esm2020/src/array.mjs +0 -4
  332. package/esm2020/src/assert-param.mjs +0 -312
  333. package/esm2020/src/breeze.mjs +0 -85
  334. package/esm2020/src/complex-array.mjs +0 -117
  335. package/esm2020/src/config.mjs +0 -223
  336. package/esm2020/src/core.mjs +0 -707
  337. package/esm2020/src/csdl-metadata-parser.mjs +0 -385
  338. package/esm2020/src/data-service.mjs +0 -203
  339. package/esm2020/src/data-type.mjs +0 -444
  340. package/esm2020/src/default-property-interceptor.mjs +0 -460
  341. package/esm2020/src/entity-action.mjs +0 -45
  342. package/esm2020/src/entity-aspect.mjs +0 -806
  343. package/esm2020/src/entity-group.mjs +0 -187
  344. package/esm2020/src/entity-key.mjs +0 -116
  345. package/esm2020/src/entity-manager.mjs +0 -2094
  346. package/esm2020/src/entity-metadata.mjs +0 -2109
  347. package/esm2020/src/entity-query.mjs +0 -996
  348. package/esm2020/src/entity-state.mjs +0 -99
  349. package/esm2020/src/enum.mjs +0 -141
  350. package/esm2020/src/event.mjs +0 -256
  351. package/esm2020/src/interface-registry.mjs +0 -41
  352. package/esm2020/src/key-generator.mjs +0 -108
  353. package/esm2020/src/local-query-comparison-options.mjs +0 -65
  354. package/esm2020/src/mapping-context.mjs +0 -405
  355. package/esm2020/src/naming-convention.mjs +0 -88
  356. package/esm2020/src/observable-array.mjs +0 -183
  357. package/esm2020/src/predicate.mjs +0 -1232
  358. package/esm2020/src/primitive-array.mjs +0 -85
  359. package/esm2020/src/query-options.mjs +0 -152
  360. package/esm2020/src/relation-array.mjs +0 -173
  361. package/esm2020/src/save-options.mjs +0 -41
  362. package/esm2020/src/unattached-children-map.mjs +0 -58
  363. package/esm2020/src/validate.mjs +0 -988
  364. package/esm2020/src/validation-options.mjs +0 -64
  365. package/fesm2015/breeze-client-adapter-ajax-angularjs.mjs.map +0 -1
  366. package/fesm2015/breeze-client-adapter-ajax-fetch.mjs.map +0 -1
  367. package/fesm2015/breeze-client-adapter-ajax-httpclient.mjs.map +0 -1
  368. package/fesm2015/breeze-client-adapter-ajax-jquery.mjs.map +0 -1
  369. package/fesm2015/breeze-client-adapter-ajax-post.mjs.map +0 -1
  370. package/fesm2015/breeze-client-adapter-data-service-odata.mjs.map +0 -1
  371. package/fesm2015/breeze-client-adapter-data-service-webapi.mjs.map +0 -1
  372. package/fesm2015/breeze-client-adapter-model-library-backing-store.mjs.map +0 -1
  373. package/fesm2015/breeze-client-adapter-model-library-ko.mjs.map +0 -1
  374. package/fesm2015/breeze-client-adapter-uri-builder-json.mjs +0 -91
  375. package/fesm2015/breeze-client-adapter-uri-builder-json.mjs.map +0 -1
  376. package/fesm2015/breeze-client-adapter-uri-builder-odata.mjs +0 -245
  377. package/fesm2015/breeze-client-adapter-uri-builder-odata.mjs.map +0 -1
  378. package/fesm2015/breeze-client-mixin-get-entity-graph.mjs.map +0 -1
  379. package/fesm2015/breeze-client-mixin-save-queuing.mjs.map +0 -1
  380. package/fesm2015/breeze-client.mjs.map +0 -1
  381. package/fesm2020/breeze-client-adapter-ajax-angularjs.mjs.map +0 -1
  382. package/fesm2020/breeze-client-adapter-ajax-fetch.mjs.map +0 -1
  383. package/fesm2020/breeze-client-adapter-ajax-httpclient.mjs.map +0 -1
  384. package/fesm2020/breeze-client-adapter-ajax-jquery.mjs.map +0 -1
  385. package/fesm2020/breeze-client-adapter-ajax-post.mjs.map +0 -1
  386. package/fesm2020/breeze-client-adapter-data-service-odata.mjs.map +0 -1
  387. package/fesm2020/breeze-client-adapter-data-service-webapi.mjs.map +0 -1
  388. package/fesm2020/breeze-client-adapter-model-library-backing-store.mjs.map +0 -1
  389. package/fesm2020/breeze-client-adapter-model-library-ko.mjs.map +0 -1
  390. package/fesm2020/breeze-client-adapter-uri-builder-json.mjs.map +0 -1
  391. package/fesm2020/breeze-client-adapter-uri-builder-odata.mjs.map +0 -1
  392. package/fesm2020/breeze-client-mixin-get-entity-graph.mjs.map +0 -1
  393. package/fesm2020/breeze-client-mixin-save-queuing.mjs.map +0 -1
  394. package/fesm2020/breeze-client.mjs.map +0 -1
@@ -0,0 +1,1023 @@
1
+ import { __extends, __read, __spread } from "tslib";
2
+ import { core } from './core';
3
+ import { assertParam } from './assert-param';
4
+ import { DataType } from './data-type';
5
+ import { EntityAspect } from './entity-aspect';
6
+ import { EntityKey } from './entity-key';
7
+ import { BreezeEnum } from './enum';
8
+ import { DataService } from './data-service';
9
+ import { EntityType } from './entity-metadata';
10
+ import { QueryOptions } from './query-options';
11
+ import { Predicate } from './predicate';
12
+ /**
13
+ An EntityQuery instance is used to query entities either from a remote datasource or from a local [[EntityManager]].
14
+
15
+ EntityQueries are immutable - this means that all EntityQuery methods that return an EntityQuery actually create a new EntityQuery. This means that
16
+ EntityQueries can be 'modified' without affecting any current instances.
17
+ @dynamic
18
+ **/
19
+ var EntityQuery = /** @class */ (function () {
20
+ /** Constructor
21
+ > let query = new EntityQuery("Customers")
22
+
23
+ Usually this constructor will be followed by calls to filtering, ordering or selection methods
24
+ > let query = new EntityQuery("Customers")
25
+ > .where("CompanyName", "startsWith", "C")
26
+ > .orderBy("Region");
27
+ @param resourceName - either a resource name or a serialized EntityQuery ( created by [[EntityQuery.toJSON]])
28
+ **/
29
+ function EntityQuery(resourceName) {
30
+ if (resourceName != null && (typeof resourceName !== 'string')) {
31
+ return fromJSON(this, resourceName);
32
+ }
33
+ // TODO: cast as string below needed for early versions of TypeDoc - but not for regular compile - check later
34
+ this.resourceName = resourceName;
35
+ this.fromEntityType = undefined;
36
+ this.wherePredicate = undefined;
37
+ this.orderByClause = undefined;
38
+ this.selectClause = undefined;
39
+ this.skipCount = undefined;
40
+ this.takeCount = undefined;
41
+ this.expandClause = undefined;
42
+ this.parameters = {};
43
+ this.inlineCountEnabled = false;
44
+ this.noTrackingEnabled = false;
45
+ // default is to get queryOptions and dataService from the entityManager.
46
+ // this.queryOptions = new QueryOptions();
47
+ // this.dataService = new DataService();
48
+ this.entityManager = undefined;
49
+ }
50
+ /**
51
+ Specifies the resource to query for this EntityQuery.
52
+ > let query = new EntityQuery()
53
+ > .from("Customers");
54
+
55
+ is the same as
56
+ > let query = new EntityQuery("Customers");
57
+ @param resourceName - The resource to query.
58
+ **/
59
+ EntityQuery.prototype.from = function (resourceName) {
60
+ // TODO: think about allowing entityType as well
61
+ assertParam(resourceName, "resourceName").isString().check();
62
+ return clone(this, "resourceName", resourceName);
63
+ };
64
+ /**
65
+ This is a static version of the "from" method and it creates a 'base' entityQuery for the specified resource name.
66
+ > let query = EntityQuery.from("Customers");
67
+
68
+ is the same as
69
+ > let query = new EntityQuery("Customers");
70
+ @param resourceName - The resource to query.
71
+ **/
72
+ EntityQuery.from = function (resourceName) {
73
+ assertParam(resourceName, "resourceName").isString().check();
74
+ return new EntityQuery(resourceName);
75
+ };
76
+ /**
77
+ Specifies the top level EntityType that this query will return. Only needed when a query returns a json result that does not include type information,
78
+ or when using a resource name that is not associated to an EntityType.
79
+ > let query = new EntityQuery()
80
+ > .from("MyCustomMethod")
81
+ > .toType("Customer")
82
+ @param entityType - The top level EntityType that this query will return.
83
+ @summary If the json result consists of more than a simple entity or array of entities, consider using a [[JsonResultsAdapter]] instead.
84
+ **/
85
+ EntityQuery.prototype.toType = function (entityType) {
86
+ assertParam(entityType, "entityType").isString().or().isInstanceOf(EntityType).check();
87
+ return clone(this, "resultEntityType", entityType);
88
+ };
89
+ /**
90
+ Returns a new query with an added filter criteria; Can be called multiple times which means to 'and' with any existing
91
+ Predicate or can be called with null to clear all predicates.
92
+ > let query = new EntityQuery("Customers")
93
+ > .where("CompanyName", "startsWith", "C");
94
+
95
+ This can also be expressed using an explicit [[FilterQueryOp]] as
96
+ > let query = new EntityQuery("Customers")
97
+ > .where("CompanyName", FilterQueryOp.StartsWith, "C");
98
+
99
+ or a preconstructed [[Predicate]] may be used
100
+ > let pred = new Predicate("CompanyName", FilterQueryOp.StartsWith, "C");
101
+ > let query = new EntityQuery("Customers").where(pred);
102
+
103
+ Predicates are often useful when you want to combine multiple conditions in a single filter, such as
104
+ > let pred = Predicate.create("CompanyName", "startswith", "C").and("Region", FilterQueryOp.Equals, null);
105
+ > let query = new EntityQuery("Customers")
106
+ > .where(pred);
107
+
108
+ More complicated queries can make use of nested property paths
109
+ > let query = new EntityQuery("Products")
110
+ > .where("Category.CategoryName", "startswith", "S");
111
+
112
+ or OData functions - A list of valid OData functions can be found within the [[Predicate]] documentation.
113
+
114
+ > let query = new EntityQuery("Customers")
115
+ > .where("toLower(CompanyName)", "startsWith", "c");
116
+
117
+ or to be even more baroque
118
+ > let query = new EntityQuery("Customers")
119
+ > .where("toUpper(substring(CompanyName, 1, 2))", FilterQueryOp.Equals, "OM");
120
+ @param predicate - Can be either
121
+ - a single [[Predicate]]
122
+
123
+ - the parameters to create a 'simple' Predicate
124
+ - - a property name, a property path with '.' as path seperators or a property expression {String}
125
+ - - an operator - [[FilterQueryOp]] or it's string representation. Case is ignored
126
+ when if a string is provided and any string that matches one of the FilterQueryOp aliases will be accepted.
127
+ - - a value {Object} - This will be treated as either a property expression or a literal depending on context.
128
+ In general, if the value can be interpreted as a property expression it will be, otherwise it will be treated as a literal.
129
+ In most cases this works well, but you can also force the interpretation by making the value argument itself an object
130
+ with a 'value' property and an 'isLiteral' property set to either true or false.
131
+ Breeze also tries to infer the dataType of any literal based on context, if this fails you can force this inference by making the value argument
132
+ an object with a 'value' property and a 'dataType'property set to one of the DataType enumeration instances.
133
+
134
+ - a null or undefined ( this causes any existing where clause to be removed)
135
+ **/
136
+ EntityQuery.prototype.where = function () {
137
+ var args = [];
138
+ for (var _i = 0; _i < arguments.length; _i++) {
139
+ args[_i] = arguments[_i];
140
+ }
141
+ var wherePredicate;
142
+ if (args.length > 0 && args[0] != null) {
143
+ wherePredicate = Predicate.create.apply(Predicate, __spread(args));
144
+ if (this.fromEntityType)
145
+ wherePredicate._validate(this.fromEntityType);
146
+ if (this.wherePredicate) {
147
+ wherePredicate = this.wherePredicate.and(wherePredicate);
148
+ }
149
+ }
150
+ return clone(this, "wherePredicate", wherePredicate);
151
+ };
152
+ /**
153
+ Returns a new query that orders the results of the query by property name. By default sorting occurs is ascending order, but sorting in descending order is supported as well.
154
+ OrderBy clauses may be chained.
155
+ > let query = new EntityQuery("Customers")
156
+ > .orderBy("CompanyName");
157
+
158
+ or to sort across multiple properties
159
+ > let query = new EntityQuery("Customers")
160
+ > .orderBy("Region, CompanyName");
161
+
162
+ Nested property paths are also supported
163
+ > let query = new EntityQuery("Products")
164
+ > .orderBy("Category.CategoryName");
165
+
166
+ Sorting in descending order is supported via the addition of ' desc' to the end of any property path.
167
+ > let query = new EntityQuery("Customers")
168
+ > .orderBy("CompanyName desc");
169
+
170
+ or
171
+ > let query = new EntityQuery("Customers")
172
+ > .orderBy("Region desc, CompanyName desc");
173
+ @param propertyPaths - A comma-separated (',') string of property paths or an array of property paths.
174
+ Each property path can optionally end with " desc" to force a descending sort order. If 'propertyPaths' is either null or omitted then all ordering is removed.
175
+ @param isDescending - If specified, overrides all of the embedded 'desc' tags in the previously specified property paths.
176
+ **/
177
+ EntityQuery.prototype.orderBy = function (propertyPaths, isDescending) {
178
+ // propertyPaths: can pass in create("A.X,B") or create("A.X desc, B") or create("A.X desc,B", true])
179
+ // isDesc parameter trumps isDesc in propertyName.
180
+ var orderByClause = propertyPaths == null ? null : new OrderByClause(normalizePropertyPaths(propertyPaths), isDescending);
181
+ if (this.orderByClause && orderByClause) {
182
+ orderByClause = new OrderByClause([this.orderByClause, orderByClause]);
183
+ }
184
+ return clone(this, "orderByClause", orderByClause);
185
+ };
186
+ /**
187
+ Returns a new query that orders the results of the query by property name in descending order.
188
+ > let query = new EntityQuery("Customers")
189
+ > .orderByDesc("CompanyName");
190
+
191
+ or to sort across multiple properties
192
+ > let query = new EntityQuery("Customers")
193
+ > .orderByDesc("Region, CompanyName");
194
+
195
+ Nested property paths are also supported
196
+ > let query = new EntityQuery("Products")
197
+ > .orderByDesc("Category.CategoryName");
198
+ @param propertyPaths - A comma-separated (',') string of property paths or an array of property paths.
199
+ If 'propertyPaths' is either null or omitted then all ordering is removed.
200
+ **/
201
+ EntityQuery.prototype.orderByDesc = function (propertyPaths) {
202
+ return this.orderBy(propertyPaths, true);
203
+ };
204
+ /**
205
+ Returns a new query that selects a list of properties from the results of the original query and returns the values of just these properties. This
206
+ will be referred to as a projection.
207
+ If the result of this selection "projection" contains entities, these entities will automatically be added to EntityManager's cache and will
208
+ be made 'observable'.
209
+ Any simple properties, i.e. strings, numbers or dates within a projection will not be cached are will NOT be made 'observable'.
210
+
211
+ Simple data properties can be projected
212
+ > let query = new EntityQuery("Customers")
213
+ > .where("CompanyName", "startsWith", "C")
214
+ > .select("CompanyName");
215
+
216
+ This will return an array of objects each with a single "CompanyName" property of type string.
217
+ A similar query could return a navigation property instead
218
+ > let query = new EntityQuery("Customers")
219
+ > .where("CompanyName", "startsWith", "C")
220
+ > .select("Orders");
221
+
222
+ where the result would be an array of objects each with a single "Orders" property that would itself be an array of "Order" entities.
223
+ Composite projections are also possible:
224
+ > let query = new EntityQuery("Customers")
225
+ > .where("CompanyName", "startsWith", "C")
226
+ > .select("CompanyName, Orders");
227
+
228
+ As well as projections involving nested property paths
229
+ > let query = EntityQuery("Orders")
230
+ > .where("Customer.CompanyName", "startsWith", "C")
231
+ > .select("Customer.CompanyName, Customer, OrderDate");
232
+ @param propertyPaths - A comma-separated (',') string of property paths or an array of property paths.
233
+ If 'propertyPaths' is either null or omitted then any existing projection on the query is removed.
234
+ **/
235
+ EntityQuery.prototype.select = function (propertyPaths) {
236
+ var selectClause = propertyPaths == null ? null : new SelectClause(normalizePropertyPaths(propertyPaths));
237
+ return clone(this, "selectClause", selectClause);
238
+ };
239
+ /**
240
+ Returns a new query that skips the specified number of entities when returning results.
241
+ Any existing 'skip' can be cleared by calling 'skip' with no arguments.
242
+ > let query = new EntityQuery("Customers")
243
+ > .where("CompanyName", "startsWith", "C")
244
+ > .skip(5);
245
+ @param count - The number of entities to skip over. If omitted or null any existing skip count on the query is removed.
246
+ **/
247
+ EntityQuery.prototype.skip = function (count) {
248
+ assertParam(count, "count").isOptional().isNumber().check();
249
+ return clone(this, "skipCount", (count == null) ? null : count);
250
+ };
251
+ /**
252
+ Returns a new query that returns only the specified number of entities when returning results. - Same as 'take'.
253
+ Any existing 'top' can be cleared by calling 'top' with no arguments.
254
+ > let query = new EntityQuery("Customers")
255
+ > .top(5);
256
+ @param count - The number of entities to return.
257
+ If 'count' is either null or omitted then any existing 'top' count on the query is removed.
258
+ **/
259
+ EntityQuery.prototype.top = function (count) {
260
+ return this.take(count);
261
+ };
262
+ /**
263
+ Returns a new query that returns only the specified number of entities when returning results - Same as 'top'.
264
+ Any existing take can be cleared by calling take with no arguments.
265
+ > let query = new EntityQuery("Customers")
266
+ > .take(5);
267
+ @param count - The number of entities to return.
268
+ If 'count' is either null or omitted then any existing 'take' count on the query is removed.
269
+ **/
270
+ EntityQuery.prototype.take = function (count) {
271
+ assertParam(count, "count").isOptional().isNumber().check();
272
+ return clone(this, "takeCount", (count == null) ? null : count);
273
+ };
274
+ /**
275
+ Returns a new query that will return related entities nested within its results. The expand method allows you to identify related entities, via navigation property
276
+ names such that a graph of entities may be retrieved with a single request. Any filtering occurs before the results are 'expanded'.
277
+ > let query = new EntityQuery("Customers")
278
+ > .where("CompanyName", "startsWith", "C")
279
+ > .expand("Orders");
280
+
281
+ will return the filtered customers each with its "Orders" properties fully resolved.
282
+ Multiple paths may be specified by separating the paths by a ','
283
+ > let query = new EntityQuery("Orders")
284
+ > .expand("Customer, Employee")
285
+
286
+ and nested property paths my be specified as well
287
+ > let query = new EntityQuery("Orders")
288
+ > .expand("Customer, OrderDetails, OrderDetails.Product")
289
+ @param propertyPaths - A comma-separated list of navigation property names or an array of navigation property names. Each Navigation Property name can be followed
290
+ by a '.' and another navigation property name to enable identifying a multi-level relationship.
291
+ If 'propertyPaths' is either null or omitted then any existing 'expand' clause on the query is removed.
292
+ **/
293
+ EntityQuery.prototype.expand = function (propertyPaths) {
294
+ var expandClause = propertyPaths == null ? null : new ExpandClause(normalizePropertyPaths(propertyPaths));
295
+ return clone(this, "expandClause", expandClause);
296
+ };
297
+ /**
298
+ Returns a new query that includes a collection of parameters to pass to the server.
299
+ > let query = EntityQuery.from("EmployeesFilteredByCountryAndBirthdate")
300
+ > .withParameters({ BirthDate: "1/1/1960", Country: "USA" });
301
+
302
+ will call the 'EmployeesFilteredByCountryAndBirthdate' method on the server and pass in 2 parameters. This
303
+ query will be uri encoded as
304
+ > {serviceApi}/EmployeesFilteredByCountryAndBirthdate?birthDate=1%2F1%2F1960&country=USA
305
+
306
+ Parameters may also be mixed in with other query criteria.
307
+ > let query = EntityQuery.from("EmployeesFilteredByCountryAndBirthdate")
308
+ > .withParameters({ BirthDate: "1/1/1960", Country: "USA" })
309
+ > .where("LastName", "startsWith", "S")
310
+ > .orderBy("BirthDate");
311
+ @param parameters - A parameters object where the keys are the parameter names and the values are the parameter values.
312
+ **/
313
+ EntityQuery.prototype.withParameters = function (parameters) {
314
+ assertParam(parameters, "parameters").isObject().check();
315
+ return clone(this, "parameters", parameters);
316
+ };
317
+ /**
318
+ Returns a query with the 'inlineCount' capability either enabled or disabled. With 'inlineCount' enabled, an additional 'inlineCount' property
319
+ will be returned with the query results that will contain the number of entities that would have been returned by this
320
+ query with only the 'where'/'filter' clauses applied, i.e. without any 'skip'/'take' operators applied. For local queries this clause is ignored.
321
+ > let query = new EntityQuery("Customers")
322
+ > .take(20)
323
+ > .orderBy("CompanyName")
324
+ > .inlineCount(true);
325
+
326
+ will return the first 20 customers as well as a count of all of the customers in the remote store.
327
+ @param enabled - (default = true) Whether or not inlineCount capability should be enabled. If this parameter is omitted, true is assumed.
328
+ **/
329
+ EntityQuery.prototype.inlineCount = function (enabled) {
330
+ assertParam(enabled, "enabled").isBoolean().isOptional().check();
331
+ enabled = (enabled === undefined) ? true : !!enabled;
332
+ return clone(this, "inlineCountEnabled", enabled);
333
+ };
334
+ EntityQuery.prototype.useNameOnServer = function (usesNameOnServer) {
335
+ assertParam(usesNameOnServer, "usesNameOnServer").isBoolean().isOptional().check();
336
+ usesNameOnServer = (usesNameOnServer === undefined) ? true : !!usesNameOnServer;
337
+ return clone(this, "usesNameOnServer", usesNameOnServer);
338
+ };
339
+ /**
340
+ Returns a query with the 'noTracking' capability either enabled or disabled. With 'noTracking' enabled, the results of this query
341
+ will not be coerced into entities but will instead look like raw javascript projections. i.e. simple javascript objects.
342
+ > let query = new EntityQuery("Customers")
343
+ > .take(20)
344
+ > .orderBy("CompanyName")
345
+ > .noTracking(true);
346
+ @param enabled - (default = true) Whether or not the noTracking capability should be enabled. If this parameter is omitted, true is assumed.
347
+ **/
348
+ EntityQuery.prototype.noTracking = function (enabled) {
349
+ assertParam(enabled, "enabled").isBoolean().isOptional().check();
350
+ enabled = (enabled === undefined) ? true : !!enabled;
351
+ return clone(this, "noTrackingEnabled", enabled);
352
+ };
353
+ /**
354
+ Returns a copy of this EntityQuery with the specified [[EntityManager]], [[DataService]],
355
+ [[JsonResultsAdapter]], [[MergeStrategy]] or [[FetchStrategy]] applied.
356
+ > // 'using' can be used to return a new query with a specified EntityManager.
357
+ > let em = new EntityManager(serviceName);
358
+ > let query = new EntityQuery("Orders")
359
+ > .using(em);
360
+
361
+ or with a specified [[MergeStrategy]]
362
+ > let em = new EntityManager(serviceName);
363
+ > let query = new EntityQuery("Orders")
364
+ > .using(MergeStrategy.PreserveChanges);
365
+
366
+ or with a specified [[FetchStrategy]]
367
+ > let em = new EntityManager(serviceName);
368
+ > let query = new EntityQuery("Orders")
369
+ > .using(FetchStrategy.FromLocalCache);
370
+ @param obj - The object to update in creating a new EntityQuery from an existing one.
371
+ **/
372
+ EntityQuery.prototype.using = function (obj) {
373
+ if (!obj)
374
+ return this;
375
+ var eq = clone(this);
376
+ processUsing(eq, {
377
+ "entityManager": null,
378
+ "dataService": null,
379
+ "queryOptions": null,
380
+ "fetchStrategy": function (eq, val) {
381
+ eq.queryOptions = (eq.queryOptions || new QueryOptions()).using(val);
382
+ },
383
+ "mergeStrategy": function (eq, val) {
384
+ eq.queryOptions = (eq.queryOptions || new QueryOptions()).using(val);
385
+ },
386
+ "jsonResultsAdapter": function (eq, val) {
387
+ eq.dataService = (eq.dataService || new DataService()).using({ jsonResultsAdapter: val });
388
+ }
389
+ }, obj);
390
+ return eq;
391
+ };
392
+ /**
393
+ Executes this query. This method requires that an EntityManager has been previously specified via the "using" method.
394
+
395
+ This method can be called using a 'promises' syntax ( recommended)
396
+ > let em = new EntityManager(serviceName);
397
+ > let query = new EntityQuery("Orders").using(em);
398
+ > query.execute().then( function(data) {
399
+ > ... query results processed here
400
+ > }).catch( function(err) {
401
+ > ... query failure processed here
402
+ > });
403
+
404
+ or with callbacks
405
+ > let em = new EntityManager(serviceName);
406
+ > let query = new EntityQuery("Orders").using(em);
407
+ > query.execute(
408
+ > function(data) {
409
+ > let orders = data.results;
410
+ > ... query results processed here
411
+ > },
412
+ > function(err) {
413
+ > ... query failure processed here
414
+ > });
415
+
416
+ Either way this method is the same as calling the EntityManager 'execute' method.
417
+ > let em = new EntityManager(serviceName);
418
+ > let query = new EntityQuery("Orders");
419
+ > em.executeQuery(query).then( function(data) {
420
+ > let orders = data.results;
421
+ > ... query results processed here
422
+ > }).catch( function(err) {
423
+ > ... query failure processed here
424
+ > });
425
+
426
+ @param callback - Function called on success.
427
+ @param errorCallback - Function called on failure.
428
+ @return Promise
429
+ **/
430
+ EntityQuery.prototype.execute = function (callback, errorCallback) {
431
+ if (!this.entityManager) {
432
+ throw new Error("An EntityQuery must have its EntityManager property set before calling 'execute'");
433
+ }
434
+ return this.entityManager.executeQuery(this, callback, errorCallback);
435
+ };
436
+ /**
437
+ Executes this query against the local cache. This method requires that an EntityManager have been previously specified via the "using" method.
438
+ > // assume em is an entityManager already filled with order entities;
439
+ > let query = new EntityQuery("Orders").using(em);
440
+ > let orders = query.executeLocally();
441
+
442
+ Note that calling this method is the same as calling [[EntityManager.executeQueryLocally]].
443
+ **/
444
+ EntityQuery.prototype.executeLocally = function () {
445
+ if (!this.entityManager) {
446
+ throw new Error("An EntityQuery must have its EntityManager property set before calling 'executeLocally'");
447
+ }
448
+ return this.entityManager.executeQueryLocally(this);
449
+ };
450
+ EntityQuery.prototype.toJSON = function () {
451
+ return this.toJSONExt();
452
+ };
453
+ /** Typically only for use when building UriBuilderAdapters.
454
+ @hidden @internal
455
+ */
456
+ EntityQuery.prototype.toJSONExt = function (context) {
457
+ context = context || {};
458
+ context.entityType = context.entityType || this.fromEntityType;
459
+ context.propertyPathFn = context.toNameOnServer ? context.entityType.clientPropertyPathToServer.bind(context.entityType) : core.identity;
460
+ var toJSONExtFn = function (v) {
461
+ return v ? v.toJSONExt(context) : undefined;
462
+ };
463
+ return core.toJson(this, {
464
+ "from,resourceName": null,
465
+ "toType,resultEntityType": function (v) {
466
+ // resultEntityType can be either a string or an entityType
467
+ return v ? (typeof v === 'string' ? v : v.name) : undefined;
468
+ },
469
+ "where,wherePredicate": toJSONExtFn,
470
+ "orderBy,orderByClause": toJSONExtFn,
471
+ "select,selectClause": toJSONExtFn,
472
+ "expand,expandClause": toJSONExtFn,
473
+ "skip,skipCount": null,
474
+ "take,takeCount": null,
475
+ parameters: function (v) {
476
+ return core.isEmpty(v) ? undefined : v;
477
+ },
478
+ "inlineCount,inlineCountEnabled": false,
479
+ "noTracking,noTrackingEnabled": false,
480
+ queryOptions: null
481
+ });
482
+ };
483
+ /**
484
+ Static method that creates an EntityQuery that will allow 'requerying' an entity or a collection of entities by primary key. This can be useful
485
+ to force a requery of selected entities, or to restrict an existing collection of entities according to some filter.
486
+
487
+ Works for a single entity or an array of entities of the SAME type.
488
+ Does not work for an array of entities of different types.
489
+ > // assuming 'customers' is an array of 'Customer' entities retrieved earlier.
490
+ > let customersQuery = EntityQuery.fromEntities(customers);
491
+
492
+ The resulting query can, of course, be extended
493
+ > // assuming 'customers' is an array of 'Customer' entities retrieved earlier.
494
+ > let customersQuery = EntityQuery.fromEntities(customers)
495
+ > .where("Region", FilterQueryOp.NotEquals, null);
496
+
497
+ Single entities can requeried as well.
498
+ > // assuming 'customer' is a 'Customer' entity retrieved earlier.
499
+ > let customerQuery = EntityQuery.fromEntities(customer);
500
+
501
+ will create a query that will return an array containing a single customer entity.
502
+ @param entities - The entities for which we want to create an EntityQuery.
503
+ **/
504
+ EntityQuery.fromEntities = function (entities) {
505
+ assertParam(entities, "entities").isEntity().or().isNonEmptyArray().isEntity().check();
506
+ var ents = (Array.isArray(entities)) ? entities : [entities];
507
+ var firstEntity = ents[0];
508
+ var type = firstEntity.entityType;
509
+ if (ents.some(function (e) {
510
+ return e.entityType !== type;
511
+ })) {
512
+ throw new Error("All 'fromEntities' must be the same type; at least one is not of type " +
513
+ type.name);
514
+ }
515
+ var q = new EntityQuery(type.defaultResourceName);
516
+ var preds = ents.map(function (entity) {
517
+ return buildPredicate(entity);
518
+ });
519
+ var pred = Predicate.or(preds);
520
+ q = q.where(pred);
521
+ var em = firstEntity.entityAspect.entityManager;
522
+ if (em) {
523
+ q = q.using(em);
524
+ }
525
+ return q;
526
+ };
527
+ /**
528
+ Creates an EntityQuery for the specified [[EntityKey]].
529
+ > let empType = metadataStore.getEntityType("Employee");
530
+ > let entityKey = new EntityKey(empType, 1);
531
+ > let query = EntityQuery.fromEntityKey(entityKey);
532
+
533
+ or
534
+ > // 'employee' is a previously queried employee
535
+ > let entityKey = employee.entityAspect.getKey();
536
+ > let query = EntityQuery.fromEntityKey(entityKey);
537
+ @param entityKey - The [[EntityKey]] for which a query will be created.
538
+ **/
539
+ EntityQuery.fromEntityKey = function (entityKey) {
540
+ assertParam(entityKey, "entityKey").isInstanceOf(EntityKey).check();
541
+ var q = new EntityQuery(entityKey.entityType.defaultResourceName);
542
+ var pred = buildKeyPredicate(entityKey);
543
+ q = q.where(pred).toType(entityKey.entityType);
544
+ return q;
545
+ };
546
+ // protected methods
547
+ /** @hidden @internal */
548
+ EntityQuery.prototype._getFromEntityType = function (metadataStore, throwErrorIfNotFound) {
549
+ // Uncomment next two lines if we make this method public.
550
+ // assertParam(metadataStore, "metadataStore").isInstanceOf(MetadataStore).check();
551
+ // assertParam(throwErrorIfNotFound, "throwErrorIfNotFound").isBoolean().isOptional().check();
552
+ var entityType = this.fromEntityType;
553
+ if (entityType)
554
+ return entityType;
555
+ var resourceName = this.resourceName;
556
+ if (!resourceName) {
557
+ throw new Error("There is no resourceName for this query");
558
+ }
559
+ if (metadataStore.isEmpty()) {
560
+ if (throwErrorIfNotFound) {
561
+ throw new Error("There is no metadata available for this query. " +
562
+ "Are you querying the local cache before you've fetched metadata?");
563
+ }
564
+ else {
565
+ return undefined;
566
+ }
567
+ }
568
+ var entityTypeName = metadataStore.getEntityTypeNameForResourceName(resourceName);
569
+ if (entityTypeName) {
570
+ entityType = metadataStore._getStructuralType(entityTypeName);
571
+ }
572
+ else {
573
+ entityType = this._getToEntityType(metadataStore, true);
574
+ }
575
+ if (!entityType) {
576
+ if (throwErrorIfNotFound) {
577
+ throw new Error(core.formatString("Cannot find an entityType for resourceName: '%1'. ", resourceName) + core.strings.TO_TYPE);
578
+ }
579
+ else {
580
+ return undefined;
581
+ }
582
+ }
583
+ this.fromEntityType = entityType;
584
+ return entityType;
585
+ };
586
+ /** @hidden @internal */
587
+ EntityQuery.prototype._getToEntityType = function (metadataStore, skipFromCheck) {
588
+ // skipFromCheck is to avoid recursion if called from _getFromEntityType;
589
+ if (this.resultEntityType instanceof EntityType) {
590
+ return this.resultEntityType;
591
+ }
592
+ else if (this.resultEntityType) {
593
+ // resultEntityType is a string
594
+ this.resultEntityType = metadataStore._getStructuralType(this.resultEntityType, false);
595
+ return this.resultEntityType;
596
+ }
597
+ else {
598
+ // resolve it, if possible, via the resourceName
599
+ // do not cache this value in this case
600
+ // cannot determine the resultEntityType if a selectClause is present.
601
+ // return skipFromCheck ? null : (!this.selectClause) && this._getFromEntityType(metadataStore, false);
602
+ if (skipFromCheck || this.selectClause) {
603
+ return undefined;
604
+ }
605
+ else {
606
+ this._getFromEntityType(metadataStore, false);
607
+ }
608
+ }
609
+ };
610
+ /** @hidden @internal */
611
+ // for testing
612
+ EntityQuery.prototype._toUri = function (em) {
613
+ var ds = DataService.resolve([em.dataService]);
614
+ return ds.uriBuilder.buildUri(this, em.metadataStore);
615
+ };
616
+ /**
617
+ Creates an EntityQuery for the specified entity and [[NavigationProperty]].
618
+ > // 'employee' is a previously queried employee
619
+ > let ordersNavProp = employee.entityType.getProperty("Orders");
620
+ > let query = EntityQuery.fromEntityNavigation(employee, ordersNavProp);
621
+
622
+ will return a query for the "Orders" of the specified 'employee'.
623
+ @param entity - The Entity whose navigation property will be queried.
624
+ @param navigationProperty - The [[NavigationProperty]] or name of the NavigationProperty to be queried.
625
+ **/
626
+ EntityQuery.fromEntityNavigation = function (entity, navigationProperty) {
627
+ assertParam(entity, "entity").isEntity().check();
628
+ var navProperty = entity.entityType._checkNavProperty(navigationProperty);
629
+ var q = new EntityQuery(navProperty.entityType.defaultResourceName);
630
+ var pred = buildNavigationPredicate(entity, navProperty);
631
+ if (pred == null) {
632
+ throw new Error("Unable to create a NavigationQuery for navigationProperty: " + navProperty.name);
633
+ }
634
+ q = q.where(pred);
635
+ var em = entity.entityAspect.entityManager;
636
+ return em ? q.using(em) : q;
637
+ };
638
+ return EntityQuery;
639
+ }());
640
+ export { EntityQuery };
641
+ EntityQuery.prototype._$typeName = "EntityQuery";
642
+ // private functions
643
+ function fromJSON(eq, json) {
644
+ core.toJson(json, {
645
+ "resourceName,from": null,
646
+ // just the name comes back and will be resolved later
647
+ "resultEntityType,toType": null,
648
+ "wherePredicate,where": function (v) {
649
+ return v ? new Predicate(v) : undefined;
650
+ },
651
+ "orderByClause,orderBy": function (v) {
652
+ return v ? new OrderByClause(v) : undefined;
653
+ },
654
+ "selectClause,select": function (v) {
655
+ return v ? new SelectClause(v) : undefined;
656
+ },
657
+ "expandClause,expand": function (v) {
658
+ return v ? new ExpandClause(v) : undefined;
659
+ },
660
+ "skipCount,skip": null,
661
+ "takeCount,take": null,
662
+ parameters: function (v) {
663
+ return core.isEmpty(v) ? undefined : v;
664
+ },
665
+ "inlineCountEnabled,inlineCount": false,
666
+ "noTrackingEnabled,noTracking": false,
667
+ queryOptions: function (v) {
668
+ return v ? QueryOptions.fromJSON(v) : undefined;
669
+ }
670
+ }, eq);
671
+ return eq;
672
+ }
673
+ function clone(eq, propName, value) {
674
+ // immutable queries mean that we don't need to clone if no change in value.
675
+ if (propName) {
676
+ if (eq[propName] === value)
677
+ return eq;
678
+ }
679
+ // copying QueryOptions is safe because they are are immutable;
680
+ var copy = core.extend(new EntityQuery(), eq, [
681
+ "resourceName",
682
+ "fromEntityType",
683
+ "wherePredicate",
684
+ "orderByClause",
685
+ "selectClause",
686
+ "skipCount",
687
+ "takeCount",
688
+ "expandClause",
689
+ "inlineCountEnabled",
690
+ "noTrackingEnabled",
691
+ "usesNameOnServer",
692
+ "queryOptions",
693
+ "entityManager",
694
+ "dataService",
695
+ "resultEntityType"
696
+ ]);
697
+ copy.parameters = core.extend({}, eq.parameters);
698
+ if (propName) {
699
+ copy[propName] = value;
700
+ }
701
+ return copy;
702
+ }
703
+ function processUsing(eq, map, value, propertyName) {
704
+ var typeName = value._$typeName || ((value instanceof BreezeEnum) && value.constructor.name);
705
+ var key = typeName && typeName.substr(0, 1).toLowerCase() + typeName.substr(1);
706
+ if (propertyName && key !== propertyName) {
707
+ throw new Error("Invalid value for property: " + propertyName);
708
+ }
709
+ if (key) {
710
+ var fn = map[key];
711
+ if (fn === undefined) {
712
+ throw new Error("Invalid config property: " + key);
713
+ }
714
+ else if (fn === null) {
715
+ eq[key] = value;
716
+ }
717
+ else {
718
+ fn(eq, value);
719
+ }
720
+ }
721
+ else {
722
+ core.objectForEach(value, function (propName, val) {
723
+ processUsing(eq, map, val, propName);
724
+ });
725
+ }
726
+ }
727
+ function normalizePropertyPaths(propertyPaths) {
728
+ assertParam(propertyPaths, "propertyPaths").isOptional().isString().or().isArray().isString().check();
729
+ if (typeof propertyPaths === 'string') {
730
+ propertyPaths = propertyPaths.split(",");
731
+ }
732
+ propertyPaths = propertyPaths.map(function (pp) {
733
+ return pp.trim();
734
+ });
735
+ return propertyPaths;
736
+ }
737
+ function buildPredicate(entity) {
738
+ var entityType = entity.entityType;
739
+ var predParts = entityType.keyProperties.map(function (kp) {
740
+ return Predicate.create(kp.name, FilterQueryOp.Equals, entity.getProperty(kp.name));
741
+ });
742
+ var pred = Predicate.and(predParts);
743
+ return pred;
744
+ }
745
+ function buildKeyPredicate(entityKey) {
746
+ var keyProps = entityKey.entityType.keyProperties;
747
+ var preds = core.arrayZip(keyProps, entityKey.values, function (kp, v) {
748
+ return Predicate.create(kp.name, FilterQueryOp.Equals, v);
749
+ });
750
+ var pred = Predicate.and(preds);
751
+ return pred;
752
+ }
753
+ function buildNavigationPredicate(entity, navigationProperty) {
754
+ if (navigationProperty.isScalar) {
755
+ if (navigationProperty.foreignKeyNames.length === 0)
756
+ return null;
757
+ var relatedKeyValues = navigationProperty.foreignKeyNames.map(function (fkName) {
758
+ return entity.getProperty(fkName);
759
+ });
760
+ var entityKey = new EntityKey(navigationProperty.entityType, relatedKeyValues);
761
+ return buildKeyPredicate(entityKey);
762
+ }
763
+ else {
764
+ var inverseNp = navigationProperty.inverse;
765
+ var foreignKeyNames = inverseNp ? inverseNp.foreignKeyNames : navigationProperty.invForeignKeyNames;
766
+ if (foreignKeyNames.length === 0)
767
+ return null;
768
+ var keyValues = entity.entityAspect.getKey().values;
769
+ var predParts = core.arrayZip(foreignKeyNames, keyValues, function (fkName, kv) {
770
+ return Predicate.create(fkName, FilterQueryOp.Equals, kv);
771
+ });
772
+ return Predicate.and(predParts);
773
+ }
774
+ }
775
+ /**
776
+ FilterQueryOp is an 'Enum' containing all of the valid [[Predicate]]
777
+ filter operators for an [[EntityQuery]].
778
+ **/
779
+ var FilterQueryOp = /** @class */ (function (_super) {
780
+ __extends(FilterQueryOp, _super);
781
+ function FilterQueryOp() {
782
+ return _super !== null && _super.apply(this, arguments) || this;
783
+ }
784
+ /** Aliases: "eq", "==" **/
785
+ FilterQueryOp.Equals = new FilterQueryOp({ operator: "eq" });
786
+ /** Aliases: "ne", "!=" **/
787
+ FilterQueryOp.NotEquals = new FilterQueryOp({ operator: "ne" });
788
+ /** Aliases: "gt", ">" **/
789
+ FilterQueryOp.GreaterThan = new FilterQueryOp({ operator: "gt" });
790
+ /** Aliases: "lt", "<" **/
791
+ FilterQueryOp.LessThan = new FilterQueryOp({ operator: "lt" });
792
+ /** Aliases: "ge", ">=" **/
793
+ FilterQueryOp.GreaterThanOrEqual = new FilterQueryOp({ operator: "ge" });
794
+ /** Aliases: "le", "<=" **/
795
+ FilterQueryOp.LessThanOrEqual = new FilterQueryOp({ operator: "le" });
796
+ /** String operation: Is a string a substring of another string. Aliases: "substringof" **/
797
+ FilterQueryOp.Contains = new FilterQueryOp({ operator: "contains" });
798
+ /** No aliases */
799
+ FilterQueryOp.StartsWith = new FilterQueryOp({ operator: "startswith" });
800
+ /** No aliases */
801
+ FilterQueryOp.EndsWith = new FilterQueryOp({ operator: "endswith" });
802
+ /** Aliases: "some" **/
803
+ FilterQueryOp.Any = new FilterQueryOp({ operator: "any" });
804
+ /** Aliases: "every" **/
805
+ FilterQueryOp.All = new FilterQueryOp({ operator: "all" });
806
+ /** No aliases */
807
+ FilterQueryOp.In = new FilterQueryOp({ operator: "in" });
808
+ /** No aliases */
809
+ FilterQueryOp.IsTypeOf = new FilterQueryOp({ operator: "isof" });
810
+ return FilterQueryOp;
811
+ }(BreezeEnum));
812
+ export { FilterQueryOp };
813
+ FilterQueryOp.prototype._$typeName = "FilterQueryOp";
814
+ Error['x'] = FilterQueryOp.resolveSymbols();
815
+ /**
816
+ BooleanQueryOp is an 'Enum' containing all of the valid boolean
817
+ operators for an [[EntityQuery]].
818
+ **/
819
+ var BooleanQueryOp = /** @class */ (function (_super) {
820
+ __extends(BooleanQueryOp, _super);
821
+ function BooleanQueryOp() {
822
+ return _super !== null && _super.apply(this, arguments) || this;
823
+ }
824
+ BooleanQueryOp.And = new BooleanQueryOp({ operator: "and" });
825
+ BooleanQueryOp.Or = new BooleanQueryOp({ operator: "or" });
826
+ BooleanQueryOp.Not = new BooleanQueryOp({ operator: "not" });
827
+ return BooleanQueryOp;
828
+ }(BreezeEnum));
829
+ export { BooleanQueryOp };
830
+ BooleanQueryOp.prototype._$typeName = "BooleanQueryOp";
831
+ Error['x'] = BooleanQueryOp.resolveSymbols();
832
+ /** For use by breeze plugin authors only. The class is used in most [[IUriBuilderAdapter]] implementations
833
+ @adapter (see [[IUriBuilderAdapter]])
834
+ @hidden
835
+
836
+ An OrderByClause is a description of the properties and direction that the result
837
+ of a query should be sorted in. OrderByClauses are immutable, which means that any
838
+ method that would modify an OrderByClause actually returns a new OrderByClause.
839
+
840
+ For example for an Employee object with properties of 'Company' and 'LastName' the following would be valid expressions:
841
+ > let obc = new OrderByClause("Company.CompanyName, LastName")
842
+
843
+ or
844
+ > let obc = new OrderByClause("Company.CompanyName desc, LastName")
845
+
846
+ or
847
+ > let obc = new OrderByClause("Company.CompanyName, LastName", true);
848
+ */
849
+ var OrderByClause = /** @class */ (function () {
850
+ function OrderByClause(propertyPaths, isDesc) {
851
+ if (propertyPaths.length === 0) {
852
+ throw new Error("OrderByClause cannot be empty");
853
+ }
854
+ // you can also pass in an array of orderByClauses
855
+ if (propertyPaths[0] instanceof OrderByClause) {
856
+ var clauses = propertyPaths;
857
+ this.items = core.arrayFlatMap(clauses, function (c) { return c.items; });
858
+ // this.items = Array.prototype.concat.apply(clauses[0].items, clauses.slice(1).map(core.pluck("items")));
859
+ // this.items = Array.prototype.concat.apply([], clauses.map(core.pluck("items")));
860
+ }
861
+ else {
862
+ this.items = propertyPaths.map(function (pp) {
863
+ return new OrderByItem(pp, isDesc);
864
+ });
865
+ }
866
+ }
867
+ OrderByClause.prototype.validate = function (entityType) {
868
+ if (entityType == null || entityType.isAnonymous)
869
+ return;
870
+ this.items.forEach(function (item) {
871
+ item.validate(entityType);
872
+ });
873
+ };
874
+ OrderByClause.prototype.getComparer = function (entityType) {
875
+ var orderByFuncs = this.items.map(function (obc) {
876
+ return obc.getComparer(entityType);
877
+ });
878
+ return function (entity1, entity2) {
879
+ for (var i = 0; i < orderByFuncs.length; i++) {
880
+ var result = orderByFuncs[i](entity1, entity2);
881
+ if (result !== 0) {
882
+ return result;
883
+ }
884
+ }
885
+ return 0;
886
+ };
887
+ };
888
+ OrderByClause.prototype.toJSONExt = function (context) {
889
+ return this.items.map(function (item) {
890
+ return context.propertyPathFn(item.propertyPath) + (item.isDesc ? " desc" : "");
891
+ });
892
+ };
893
+ return OrderByClause;
894
+ }());
895
+ export { OrderByClause };
896
+ /** @hidden @internal */
897
+ var OrderByItem = /** @class */ (function () {
898
+ function OrderByItem(propertyPath, isDesc) {
899
+ if (!(typeof propertyPath === 'string')) {
900
+ throw new Error("propertyPath is not a string");
901
+ }
902
+ propertyPath = propertyPath.trim();
903
+ var parts = propertyPath.split(' ');
904
+ // parts[0] is the propertyPath; [1] would be whether descending or not.
905
+ // if (parts.length > 1 && isDesc !== true && isDesc !== false) {
906
+ if (parts.length > 1 && isDesc == null) {
907
+ isDesc = core.stringStartsWith(parts[1].toLowerCase(), "desc");
908
+ if (!isDesc) {
909
+ // isDesc is false but check to make sure its intended.
910
+ var isAsc = core.stringStartsWith(parts[1].toLowerCase(), "asc");
911
+ if (!isAsc) {
912
+ throw new Error("the second word in the propertyPath must begin with 'desc' or 'asc'");
913
+ }
914
+ }
915
+ }
916
+ this.propertyPath = parts[0];
917
+ this.isDesc = isDesc || false;
918
+ }
919
+ OrderByItem.prototype.validate = function (entityType) {
920
+ if (entityType == null || entityType.isAnonymous)
921
+ return;
922
+ // will throw an exception on bad propertyPath
923
+ this.lastProperty = entityType.getProperty(this.propertyPath, true);
924
+ return this.lastProperty;
925
+ };
926
+ OrderByItem.prototype.getComparer = function (entityType) {
927
+ var propDataType;
928
+ var isCaseSensitive;
929
+ if (!this.lastProperty)
930
+ this.validate(entityType);
931
+ if (this.lastProperty) {
932
+ propDataType = this.lastProperty.dataType;
933
+ isCaseSensitive = this.lastProperty.parentType.metadataStore.localQueryComparisonOptions.isCaseSensitive;
934
+ }
935
+ var propertyPath = this.propertyPath;
936
+ var isDesc = this.isDesc;
937
+ return function (entity1, entity2) {
938
+ var value1 = EntityAspect.getPropertyPathValue(entity1, propertyPath);
939
+ var value2 = EntityAspect.getPropertyPathValue(entity2, propertyPath);
940
+ var dataType = propDataType || (value1 && DataType.fromValue(value1)) || DataType.fromValue(value2);
941
+ if (dataType === DataType.String) {
942
+ if (isCaseSensitive) {
943
+ value1 = value1 || "";
944
+ value2 = value2 || "";
945
+ }
946
+ else {
947
+ value1 = (value1 || "").toLowerCase();
948
+ value2 = (value2 || "").toLowerCase();
949
+ }
950
+ }
951
+ else {
952
+ var normalize = DataType.getComparableFn(dataType);
953
+ value1 = normalize(value1);
954
+ value2 = normalize(value2);
955
+ }
956
+ if (value1 === value2) {
957
+ return 0;
958
+ }
959
+ else if (value1 > value2 || value2 === undefined) {
960
+ return isDesc ? -1 : 1;
961
+ }
962
+ else {
963
+ return isDesc ? 1 : -1;
964
+ }
965
+ };
966
+ };
967
+ return OrderByItem;
968
+ }());
969
+ export { OrderByItem };
970
+ /** For use by breeze plugin authors only. The class is used in most [[IUriBuilderAdapter]] implementations
971
+ @adapter (see [[IUriBuilderAdapter]])
972
+ @hidden
973
+ **/
974
+ var SelectClause = /** @class */ (function () {
975
+ function SelectClause(propertyPaths) {
976
+ this.propertyPaths = propertyPaths;
977
+ this._pathNames = propertyPaths.map(function (pp) {
978
+ return pp.replace(".", "_");
979
+ });
980
+ }
981
+ SelectClause.prototype.validate = function (entityType) {
982
+ if (entityType == null || entityType.isAnonymous)
983
+ return; // can't validate yet
984
+ // will throw an exception on bad propertyPath
985
+ this.propertyPaths.forEach(function (path) {
986
+ entityType.getProperty(path, true);
987
+ });
988
+ };
989
+ SelectClause.prototype.toFunction = function ( /* config */) {
990
+ var that = this;
991
+ return function (entity) {
992
+ var result = {};
993
+ that.propertyPaths.forEach(function (path, i) {
994
+ result[that._pathNames[i]] = EntityAspect.getPropertyPathValue(entity, path);
995
+ });
996
+ return result;
997
+ };
998
+ };
999
+ SelectClause.prototype.toJSONExt = function (context) {
1000
+ return this.propertyPaths.map(function (pp) {
1001
+ return context.propertyPathFn(pp);
1002
+ });
1003
+ };
1004
+ return SelectClause;
1005
+ }());
1006
+ export { SelectClause };
1007
+ /** For use by breeze plugin authors only. The class is used in most [[IUriBuilderAdapter]] implementations
1008
+ @adapter (see [[IUriBuilderAdapter]])
1009
+ @hidden
1010
+ **/
1011
+ var ExpandClause = /** @class */ (function () {
1012
+ function ExpandClause(propertyPaths) {
1013
+ this.propertyPaths = propertyPaths;
1014
+ }
1015
+ ExpandClause.prototype.toJSONExt = function (context) {
1016
+ return this.propertyPaths.map(function (pp) {
1017
+ return context.propertyPathFn(pp);
1018
+ });
1019
+ };
1020
+ return ExpandClause;
1021
+ }());
1022
+ export { ExpandClause };
1023
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LXF1ZXJ5LmpzIiwic291cmNlUm9vdCI6Im5nOi8vYnJlZXplLWNsaWVudC8iLCJzb3VyY2VzIjpbInNyYy9lbnRpdHktcXVlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQTJCLE1BQU0sUUFBUSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxZQUFZLEVBQVUsTUFBTSxpQkFBaUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDcEMsT0FBTyxFQUFFLFdBQVcsRUFBc0IsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRSxPQUFPLEVBQWlCLFVBQVUsRUFBc0MsTUFBTSxtQkFBbUIsQ0FBQztBQUNsRyxPQUFPLEVBQUUsWUFBWSxFQUFnQyxNQUFNLGlCQUFpQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFXeEM7Ozs7OztHQU1HO0FBQ0g7SUF3Q0U7Ozs7Ozs7O09BUUc7SUFDSCxxQkFBWSxZQUE4QjtRQUN4QyxJQUFJLFlBQVksSUFBSSxJQUFJLElBQUksQ0FBQyxPQUFPLFlBQVksS0FBSyxRQUFRLENBQUMsRUFBRTtZQUM5RCxPQUFPLFFBQVEsQ0FBQyxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUM7U0FDckM7UUFDRCw4R0FBOEc7UUFDOUcsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFzQixDQUFDO1FBQzNDLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO1FBQy9CLElBQUksQ0FB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YSxDQUFDLE9BQU8sQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDO2dCQUMxQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDL0UsQ0FBQyxDQUFDLENBQUM7WUFDSCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQsZ0NBQVMsR0FBVCxVQUFVLE9BQStCO1FBQ3ZDLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFO1lBQ3hDLE9BQU8sT0FBTyxDQUFDLGNBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDSCxtQkFBQztBQUFELENBQUMsQUFwQ0QsSUFvQ0M7O0FBRUQ7OztHQUdHO0FBQ0g7SUFHRSxzQkFBWSxhQUF1QjtRQUNqQyxJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQztJQUNyQyxDQUFDO0lBRUQsZ0NBQVMsR0FBVCxVQUFVLE9BQStCO1FBQ3ZDLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFO1lBQ3hDLE9BQU8sT0FBTyxDQUFDLGNBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFSCxtQkFBQztBQUFELENBQUMsQUFiRCxJQWFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29yZSwgQ2FsbGJhY2ssIEVycm9yQ2FsbGJhY2sgfSBmcm9tICcuL2NvcmUnO1xyXG5pbXBvcnQgeyBhc3NlcnRQYXJhbSB9IGZyb20gJy4vYXNzZXJ0LXBhcmFtJztcclxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuL2RhdGEtdHlwZSc7XHJcbmltcG9ydCB7IEVudGl0eUFzcGVjdCwgRW50aXR5IH0gZnJvbSAnLi9lbnRpdHktYXNwZWN0JztcclxuaW1wb3J0IHsgRW50aXR5S2V5IH0gZnJvbSAnLi9lbnRpdHkta2V5JztcclxuaW1wb3J0IHsgQnJlZXplRW51bSB9IGZyb20gJy4vZW51bSc7XHJcbmltcG9ydCB7IERhdGFTZXJ2aWNlLCBKc29uUmVzdWx0c0FkYXB0ZXIgfSBmcm9tICcuL2RhdGEtc2VydmljZSc7XHJcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIsIFF1ZXJ5UmVzdWx0IH0gZnJvbSAnLi9lbnRpdHktbWFuYWdlcic7XHJcbmltcG9ydCB7IE1ldGFkYXRhU3RvcmUsIEVudGl0eVR5cGUsIE5hdmlnYXRpb25Qcm9wZXJ0eSwgRW50aXR5UHJvcGVydHkgfSBmcm9tICcuL2VudGl0eS1tZXRhZGF0YSc7XHJcbmltcG9ydCB7IFF1ZXJ5T3B0aW9ucywgTWVyZ2VTdHJhdGVneSwgRmV0Y2hTdHJhdGVneSB9IGZyb20gJy4vcXVlcnktb3B0aW9ucyc7XHJcbmltcG9ydCB7IFByZWRpY2F0ZSB9IGZyb20gJy4vcHJlZGljYXRlJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUmVjdXJzaXZlQXJyYXk8VD4ge1xyXG4gIFtpOiBudW1iZXJdOiBUIHwgUmVjdXJzaXZlQXJyYXk8VD47XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5UXVlcnlKc29uQ29udGV4dCB7XHJcbiAgZW50aXR5VHlwZT86IEVudGl0eVR5cGU7XHJcbiAgcHJvcGVydHlQYXRoRm4/OiBGdW5jdGlvbjsgLy8gVE9ET1xyXG4gIHRvTmFtZU9uU2VydmVyPzogYm9vbGVhbjtcclxufVxyXG4vKipcclxuQW4gRW50aXR5UXVlcnkgaW5zdGFuY2UgaXMgdXNlZCB0byBxdWVyeSBlbnRpdGllcyBlaXRoZXIgZnJvbSBhIHJlbW90ZSBkYXRhc291cmNlIG9yIGZyb20gYSBsb2NhbCBbW0VudGl0eU1hbmFnZXJdXS5cclxuXHJcbkVudGl0eVF1ZXJpZXMgYXJlIGltbXV0YWJsZSAtIHRoaXMgbWVhbnMgdGhhdCBhbGwgRW50aXR5UXVlcnkgbWV0aG9kcyB0aGF0IHJldHVybiBhbiBFbnRpdHlRdWVyeSBhY3R1YWxseSBjcmVhdGUgYSBuZXcgRW50aXR5UXVlcnkuICBUaGlzIG1lYW5zIHRoYXRcclxuRW50aXR5UXVlcmllcyBjYW4gYmUgJ21vZGlmaWVkJyB3aXRob3V0IGFmZmVjdGluZyBhbnkgY3VycmVudCBpbnN0YW5jZXMuXHJcbkBkeW5hbWljXHJcbioqL1xyXG5leHBvcnQgY2xhc3MgRW50aXR5UXVlcnkge1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF8kdHlwZU5hbWU6IHN0cmluZzsgLy8gYWN0dWFsbHkgcGxhY2VkIG9uIHByb3RvdHlwZVxyXG4gIC8vIHRvcCA9IHRoaXMudGFrZTsgLy8gVE9ETzogY29uc2lkZXJcclxuICAvKiogVGhlIHJlc291cmNlIG5hbWUgdXNlZCBieSB0aGlzIHF1ZXJ5LiBfX1JlYWQgT25seV9fICovXHJcbiAgcmVzb3VyY2VOYW1lPzogc3RyaW5nO1xyXG4gIC8qKiBUaGUgW1tFbnRpdHlUeXBlXV0gdGhhdCBpcyBhc3NvY2lhdGVkIHdpdGggdGhlICdmcm9tJyBjbGF1c2UgKCByZXNvdXJjZU5hbWUpIG9mIHRoZSBxdWVyeS4gIFRoaXMgaXMgb25seSBndWFyYW50ZWVkIHRvIGJlIGJlIHNldCBBRlRFUiB0aGUgcXVlcnlcclxuICBoYXMgYmVlbiBleGVjdXRlZCBiZWNhdXNlIGl0IGRlcGVuZHMgb24gdGhlIFtbTWV0YWRhdGFTdG9yZV1dIGFzc29jaWF0ZWQgd2l0aCB0aGUgW1tFbnRpdHlNYW5hZ2VyXV0gdGhhdCB0aGUgcXVlcnkgd2FzIGV4ZWN1dGVkIGFnYWluc3QuXHJcbiAgVGhpcyB2YWx1ZSBtYXkgYmUgbnVsbCBpZiB0aGUgZW50aXR5VHlwZSBjYW5ub3QgYmUgYXNzb2NpYXRlZCB3aXRoIGEgcmVzb3VyY2VOYW1lLiBfX1JlYWQgT25seV9fICovXHJcbiAgZnJvbUVudGl0eVR5cGU/OiBFbnRpdHlUeXBlO1xyXG4gIC8qKiBUaGUgJ3doZXJlJyBbW1ByZWRpY2F0ZV1dIHVzZWQgYnkgdGhpcyBxdWVyeS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIHdoZXJlUHJlZGljYXRlOiBQcmVkaWNhdGU7IC8vIFRPRE9cclxuICAvKiogVGhlIFtbT3JkZXJCeUNsYXVzZV1dIHVzZWQgYnkgdGhpcyBxdWVyeS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIG9yZGVyQnlDbGF1c2U/OiBPcmRlckJ5Q2xhdXNlO1xyXG4gIC8qKiBUaGUgW1tFeHBhbmRDbGF1c2VdXSB1c2VkIGJ5IHRoaXMgcXVlcnkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBleHBhbmRDbGF1c2U/OiBFeHBhbmRDbGF1c2U7XHJcbiAgLyoqIFRoZSBbW1NlbGVjdENsYXVzZV1dIHVzZWQgYnkgdGhpcyBxdWVyeS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIHNlbGVjdENsYXVzZT86IFNlbGVjdENsYXVzZTtcclxuICAvKiogVGhlIG51bWJlciBvZiBlbnRpdGllcyB0byAnc2tpcCcgZm9yIHRoaXMgcXVlcnkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBza2lwQ291bnQ/OiBudW1iZXI7XHJcbiAgLyoqIFRoZSBudW1iZXIgb2YgZW50aXRpZXMgdG8gJ3Rha2UnIGZvciB0aGlzIHF1ZXJ5LiBfX1JlYWQgT25seV9fICovXHJcbiAgdGFrZUNvdW50PzogbnVtYmVyO1xyXG4gIC8qKiBBbnkgYWRkaXRpb25hbCBwYXJhbWV0ZXJzIHRoYXQgd2VyZSBhZGRlZCB0byB0aGUgcXVlcnkgdmlhIHRoZSAnd2l0aFBhcmFtZXRlcnMnIG1ldGhvZC4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIHBhcmFtZXRlcnM6IE9iamVjdDtcclxuICAvKiogV2hldGhlciBhbiBpbmxpbmUgY291bnQgaXMgcmV0dXJuZWQgZm9yIHRoaXMgcXVlcnkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBpbmxpbmVDb3VudEVuYWJsZWQ6IGJvb2xlYW47XHJcbiAgLyoqIFdoZXRoZXIgZW50aXR5IHRyYWNraW5nIGhhcyBiZWVuIGRpc2FibGVkIGZvciB0aGlzIHF1ZXJ5LiBfX1JlYWQgT25seV9fICovXHJcbiAgbm9UcmFja2luZ0VuYWJsZWQ6IGJvb2xlYW47XHJcbiAgLyoqIFRoZSBbW1F1ZXJ5T3B0aW9uc11dIGZvciB0aGlzIHF1ZXJ5LiBfX1JlYWQgT25seV9fICAqKi9cclxuICAvLyBkZWZhdWx0IGlzIHRvIGdldCBxdWVyeU9wdGlvbnMgYW5kIGRhdGFTZXJ2aWNlIGZyb20gdGhlIGVudGl0eU1hbmFnZXIuXHJcbiAgcXVlcnlPcHRpb25zPzogUXVlcnlPcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tEYXRhU2VydmljZV1dIGZvciB0aGlzIHF1ZXJ5LiBfX1JlYWQgT25seV9fICAqKi9cclxuICBkYXRhU2VydmljZT86IERhdGFTZXJ2aWNlO1xyXG4gIC8qKiBUaGUgW1tFbnRpdHlNYW5hZ2VyXV0gZm9yIHRoaXMgcXVlcnkuIFRoaXMgbWF5IGJlIG51bGwgYW5kIGNhbiBiZSBzZXQgdmlhIHRoZSAndXNpbmcnIG1ldGhvZC4gICoqL1xyXG4gIGVudGl0eU1hbmFnZXI/OiBFbnRpdHlNYW5hZ2VyO1xyXG4gIC8qKiAgVGhlIGVudGl0eVR5cGUgdGhhdCB3aWxsIGJlIHJldHVybmVkIGJ5IHRoaXMgcXVlcnkuIFxyXG4gIFRoaXMgcHJvcGVydHkgd2lsbCBvbmx5IGJlIHNldCBpZiB0aGUgJ3RvVHlwZScgbWV0aG9kIHdhcyBjYWxsZWQuIF9fUmVhZCBPbmx5X18gKi9cclxuICByZXN1bHRFbnRpdHlUeXBlOiBFbnRpdHlUeXBlIHwgc3RyaW5nO1xyXG4gIHVzZXNOYW1lT25TZXJ2ZXI/OiBib29sZWFuO1xyXG5cclxuICAvKiogQ29uc3RydWN0b3JcclxuICA+ICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKVxyXG5cclxuICBVc3VhbGx5IHRoaXMgY29uc3RydWN0b3Igd2lsbCBiZSBmb2xsb3dlZCBieSBjYWxscyB0byBmaWx0ZXJpbmcsIG9yZGVyaW5nIG9yIHNlbGVjdGlvbiBtZXRob2RzXHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKVxyXG4gID4gICAgICAgIC53aGVyZShcIkNvbXBhbnlOYW1lXCIsIFwic3RhcnRzV2l0aFwiLCBcIkNcIilcclxuICA+ICAgICAgICAub3JkZXJCeShcIlJlZ2lvblwiKTtcclxuICBAcGFyYW0gcmVzb3VyY2VOYW1lIC0gZWl0aGVyIGEgcmVzb3VyY2UgbmFtZSBvciBhIHNlcmlhbGl6ZWQgRW50aXR5UXVlcnkgKCBjcmVhdGVkIGJ5IFtbRW50aXR5UXVlcnkudG9KU09OXV0pXHJcbiAgKiovXHJcbiAgY29uc3RydWN0b3IocmVzb3VyY2VOYW1lPzogc3RyaW5nIHwgT2JqZWN0KSB7XHJcbiAgICBpZiAocmVzb3VyY2VOYW1lICE9IG51bGwgJiYgKHR5cGVvZiByZXNvdXJjZU5hbWUgIT09ICdzdHJpbmcnKSkge1xyXG4gICAgICByZXR1cm4gZnJvbUpTT04odGhpcywgcmVzb3VyY2VOYW1lKTtcclxuICAgIH1cclxuICAgIC8vIFRPRE86IGNhc3QgYXMgc3RyaW5nIGJlbG93IG5lZWRlZCBmb3IgZWFybHkgdmVyc2lvbnMgb2YgVHlwZURvYyAtIGJ1dCBub3QgZm9yIHJlZ3VsYXIgY29tcGlsZSAtIGNoZWNrIGxhdGVyXHJcbiAgICB0aGlzLnJlc291cmNlTmFtZSA9IHJlc291cmNlTmFtZSBhcyBzdHJpbmc7XHJcbiAgICB0aGlzLmZyb21FbnRpdHlUeXBlID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy53aGVyZVByZWRpY2F0ZSA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMub3JkZXJCeUNsYXVzZSA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuc2VsZWN0Q2xhdXNlID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5za2lwQ291bnQgPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLnRha2VDb3VudCA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuZXhwYW5kQ2xhdXNlID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5wYXJhbWV0ZXJzID0ge307XHJcbiAgICB0aGlzLmlubGluZUNvdW50RW5hYmxlZCA9IGZhbHNlO1xyXG4gICAgdGhpcy5ub1RyYWNraW5nRW5hYmxlZCA9IGZhbHNlO1xyXG4gICAgLy8gZGVmYXVsdCBpcyB0byBnZXQgcXVlcnlPcHRpb25zIGFuZCBkYXRhU2VydmljZSBmcm9tIHRoZSBlbnRpdHlNYW5hZ2VyLlxyXG4gICAgLy8gdGhpcy5xdWVyeU9wdGlvbnMgPSBuZXcgUXVlcnlPcHRpb25zKCk7XHJcbiAgICAvLyB0aGlzLmRhdGFTZXJ2aWNlID0gbmV3IERhdGFTZXJ2aWNlKCk7XHJcbiAgICB0aGlzLmVudGl0eU1hbmFnZXIgPSB1bmRlZmluZWQ7XHJcblxyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gIFNwZWNpZmllcyB0aGUgcmVzb3VyY2UgdG8gcXVlcnkgZm9yIHRoaXMgRW50aXR5UXVlcnkuXHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeSgpXHJcbiAgPiAgICAgICAgLmZyb20oXCJDdXN0b21lcnNcIik7XHJcblxyXG4gIGlzIHRoZSBzYW1lIGFzXHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKTtcclxuICBAcGFyYW0gcmVzb3VyY2VOYW1lIC0gVGhlIHJlc291cmNlIHRvIHF1ZXJ5LlxyXG4gICoqL1xyXG4gIGZyb20ocmVzb3VyY2VOYW1lOiBzdHJpbmcpIHtcclxuICAgIC8vIFRPRE86IHRoaW5rIGFib3V0IGFsbG93aW5nIGVudGl0eVR5cGUgYXMgd2VsbFxyXG4gICAgYXNzZXJ0UGFyYW0ocmVzb3VyY2VOYW1lLCBcInJlc291cmNlTmFtZVwiKS5pc1N0cmluZygpLmNoZWNrKCk7XHJcbiAgICByZXR1cm4gY2xvbmUodGhpcywgXCJyZXNvdXJjZU5hbWVcIiwgcmVzb3VyY2VOYW1lKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFRoaXMgaXMgYSBzdGF0aWMgdmVyc2lvbiBvZiB0aGUgXCJmcm9tXCIgbWV0aG9kIGFuZCBpdCBjcmVhdGVzIGEgJ2Jhc2UnIGVudGl0eVF1ZXJ5IGZvciB0aGUgc3BlY2lmaWVkIHJlc291cmNlIG5hbWUuXHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IEVudGl0eVF1ZXJ5LmZyb20oXCJDdXN0b21lcnNcIik7XHJcblxyXG4gIGlzIHRoZSBzYW1lIGFzXHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKTtcclxuICBAcGFyYW0gcmVzb3VyY2VOYW1lIC0gVGhlIHJlc291cmNlIHRvIHF1ZXJ5LlxyXG4gICoqL1xyXG4gIHN0YXRpYyBmcm9tKHJlc291cmNlTmFtZTogc3RyaW5nKSB7XHJcbiAgICBhc3NlcnRQYXJhbShyZXNvdXJjZU5hbWUsIFwicmVzb3VyY2VOYW1lXCIpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICAgIHJldHVybiBuZXcgRW50aXR5UXVlcnkocmVzb3VyY2VOYW1lKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFNwZWNpZmllcyB0aGUgdG9wIGxldmVsIEVudGl0eVR5cGUgdGhhdCB0aGlzIHF1ZXJ5IHdpbGwgcmV0dXJuLiAgT25seSBuZWVkZWQgd2hlbiBhIHF1ZXJ5IHJldHVybnMgYSBqc29uIHJlc3VsdCB0aGF0IGRvZXMgbm90IGluY2x1ZGUgdHlwZSBpbmZvcm1hdGlvbixcclxuICBvciB3aGVuIHVzaW5nIGEgcmVzb3VyY2UgbmFtZSB0aGF0IGlzIG5vdCBhc3NvY2lhdGVkIHRvIGFuIEVudGl0eVR5cGUuXHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeSgpXHJcbiAgPiAgICAgICAgLmZyb20oXCJNeUN1c3RvbU1ldGhvZFwiKVxyXG4gID4gICAgICAgIC50b1R5cGUoXCJDdXN0b21lclwiKVxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlIC0gVGhlIHRvcCBsZXZlbCBFbnRpdHlUeXBlIHRoYXQgdGhpcyBxdWVyeSB3aWxsIHJldHVybi5cclxuICBAc3VtbWFyeSBJZiB0aGUganNvbiByZXN1bHQgY29uc2lzdHMgb2YgbW9yZSB0aGFuIGEgc2ltcGxlIGVudGl0eSBvciBhcnJheSBvZiBlbnRpdGllcywgY29uc2lkZXIgdXNpbmcgYSBbW0pzb25SZXN1bHRzQWRhcHRlcl1dIGluc3RlYWQuXHJcbiAgKiovXHJcbiAgdG9UeXBlKGVudGl0eVR5cGU6IHN0cmluZyB8IEVudGl0eVR5cGUpIHtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eVR5cGUsIFwiZW50aXR5VHlwZVwiKS5pc1N0cmluZygpLm9yKCkuaXNJbnN0YW5jZU9mKEVudGl0eVR5cGUpLmNoZWNrKCk7XHJcbiAgICByZXR1cm4gY2xvbmUodGhpcywgXCJyZXN1bHRFbnRpdHlUeXBlXCIsIGVudGl0eVR5cGUpO1xyXG4gIH1cclxuXHJcblxyXG4gIHdoZXJlKHByZWRpY2F0ZT86IFByZWRpY2F0ZSk6IEVudGl0eVF1ZXJ5O1xyXG4gIHdoZXJlKHByZWRpY2F0ZTogT2JqZWN0KTogRW50aXR5UXVlcnk7XHJcbiAgd2hlcmUocHJvcGVydHk6IHN0cmluZywgb3BlcmF0b3I6IHN0cmluZywgdmFsdWU6IGFueSk6IEVudGl0eVF1ZXJ5O1xyXG4gIHdoZXJlKHByb3BlcnR5OiBzdHJpbmcsIG9wZXJhdG9yOiBGaWx0ZXJRdWVyeU9wLCB2YWx1ZTogYW55KTogRW50aXR5UXVlcnk7XHJcbiAgd2hlcmUocHJvcGVydHk6IHN0cmluZywgZmlsdGVyb3A6IEZpbHRlclF1ZXJ5T3AsIHByb3BlcnR5Mjogc3RyaW5nLCBmaWx0ZXJvcDI6IEZpbHRlclF1ZXJ5T3AsIHZhbHVlOiBhbnkpOiBFbnRpdHlRdWVyeTsgIC8vIGZvciBhbnkvYWxsIGNsYXVzZXNcclxuICB3aGVyZShwcm9wZXJ0eTogc3RyaW5nLCBmaWx0ZXJvcDogc3RyaW5nLCBwcm9wZXJ0eTI6IHN0cmluZywgZmlsdGVyb3AyOiBzdHJpbmcsIHZhbHVlOiBhbnkpOiBFbnRpdHlRdWVyeTsgIC8vIGZvciBhbnkvYWxsIGNsYXVzZXNcclxuICB3aGVyZShwcm9wZXJ0eTogc3RyaW5nLCBmaWx0ZXJvcDogc3RyaW5nLCBwcm9wZXJ0eTI6IHN0cmluZywgZmlsdGVyb3AyOiBzdHJpbmcsIHByb3BlcnR5Mzogc3RyaW5nLCBmaWx0ZXJvcDM6IHN0cmluZywgdmFsdWU6IGFueSk6IEVudGl0eVF1ZXJ5OyAgLy8gZm9yIGFueS9hbGwgY2xhdXNlc1xyXG4gIHdoZXJlKGFuQXJyYXk6IFJlY3Vyc2l2ZUFycmF5PHN0cmluZyB8IG51bWJlciB8IEZpbHRlclF1ZXJ5T3AgfCBQcmVkaWNhdGU+KTogRW50aXR5UXVlcnk7XHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIG5ldyBxdWVyeSB3aXRoIGFuIGFkZGVkIGZpbHRlciBjcml0ZXJpYTsgQ2FuIGJlIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyB3aGljaCBtZWFucyB0byAnYW5kJyB3aXRoIGFueSBleGlzdGluZ1xyXG4gIFByZWRpY2F0ZSBvciBjYW4gYmUgY2FsbGVkIHdpdGggbnVsbCB0byBjbGVhciBhbGwgcHJlZGljYXRlcy5cclxuICA+ICAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiQ3VzdG9tZXJzXCIpXHJcbiAgPiAgICAgICAgICAud2hlcmUoXCJDb21wYW55TmFtZVwiLCBcInN0YXJ0c1dpdGhcIiwgXCJDXCIpO1xyXG5cclxuICBUaGlzIGNhbiBhbHNvIGJlIGV4cHJlc3NlZCB1c2luZyBhbiBleHBsaWNpdCBbW0ZpbHRlclF1ZXJ5T3BdXSBhc1xyXG4gID4gICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJDdXN0b21lcnNcIilcclxuICA+ICAgICAgICAgIC53aGVyZShcIkNvbXBhbnlOYW1lXCIsIEZpbHRlclF1ZXJ5T3AuU3RhcnRzV2l0aCwgXCJDXCIpO1xyXG5cclxuICBvciBhIHByZWNvbnN0cnVjdGVkIFtbUHJlZGljYXRlXV0gbWF5IGJlIHVzZWRcclxuICA+ICAgICAgbGV0IHByZWQgPSBuZXcgUHJlZGljYXRlKFwiQ29tcGFueU5hbWVcIiwgRmlsdGVyUXVlcnlPcC5TdGFydHNXaXRoLCBcIkNcIik7XHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKS53aGVyZShwcmVkKTtcclxuXHJcbiAgUHJlZGljYXRlcyBhcmUgb2Z0ZW4gdXNlZnVsIHdoZW4geW91IHdhbnQgdG8gY29tYmluZSBtdWx0aXBsZSBjb25kaXRpb25zIGluIGEgc2luZ2xlIGZpbHRlciwgc3VjaCBhc1xyXG4gID4gICAgICBsZXQgcHJlZCA9IFByZWRpY2F0ZS5jcmVhdGUoXCJDb21wYW55TmFtZVwiLCBcInN0YXJ0c3dpdGhcIiwgXCJDXCIpLmFuZChcIlJlZ2lvblwiLCBGaWx0ZXJRdWVyeU9wLkVxdWFscywgbnVsbCk7XHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKVxyXG4gID4gICAgICAgICAgLndoZXJlKHByZWQpO1xyXG5cclxuICBNb3JlIGNvbXBsaWNhdGVkIHF1ZXJpZXMgY2FuIG1ha2UgdXNlIG9mIG5lc3RlZCBwcm9wZXJ0eSBwYXRoc1xyXG4gID4gICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJQcm9kdWN0c1wiKVxyXG4gID4gICAgICAgICAgLndoZXJlKFwiQ2F0ZWdvcnkuQ2F0ZWdvcnlOYW1lXCIsIFwic3RhcnRzd2l0aFwiLCBcIlNcIik7XHJcblxyXG4gIG9yIE9EYXRhIGZ1bmN0aW9ucyAtIEEgbGlzdCBvZiB2YWxpZCBPRGF0YSBmdW5jdGlvbnMgY2FuIGJlIGZvdW5kIHdpdGhpbiB0aGUgW1tQcmVkaWNhdGVdXSBkb2N1bWVudGF0aW9uLlxyXG4gIFxyXG4gID4gICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJDdXN0b21lcnNcIilcclxuICA+ICAgICAgICAgIC53aGVyZShcInRvTG93ZXIoQ29tcGFueU5hbWUpXCIsIFwic3RhcnRzV2l0aFwiLCBcImNcIik7XHJcblxyXG4gIG9yIHRvIGJlIGV2ZW4gbW9yZSBiYXJvcXVlXHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKVxyXG4gID4gICAgICAgICAgLndoZXJlKFwidG9VcHBlcihzdWJzdHJpbmcoQ29tcGFueU5hbWUsIDEsIDIpKVwiLCBGaWx0ZXJRdWVyeU9wLkVxdWFscywgXCJPTVwiKTtcclxuICBAcGFyYW0gcHJlZGljYXRlIC0gIENhbiBiZSBlaXRoZXJcclxuICAgIC0gYSBzaW5nbGUgW1tQcmVkaWNhdGVdXVxyXG5cclxuICAgIC0gdGhlIHBhcmFtZXRlcnMgdG8gY3JlYXRlIGEgJ3NpbXBsZScgUHJlZGljYXRlXHJcbiAgICAtIC0gIGEgcHJvcGVydHkgbmFtZSwgYSBwcm9wZXJ0eSBwYXRoIHdpdGggJy4nIGFzIHBhdGggc2VwZXJhdG9ycyBvciBhIHByb3BlcnR5IGV4cHJlc3Npb24ge1N0cmluZ31cclxuICAgIC0gLSAgYW4gb3BlcmF0b3IgLSBbW0ZpbHRlclF1ZXJ5T3BdXSBvciBpdCdzIHN0cmluZyByZXByZXNlbnRhdGlvbi4gQ2FzZSBpcyBpZ25vcmVkXHJcbiAgICB3aGVuIGlmIGEgc3RyaW5nIGlzIHByb3ZpZGVkIGFuZCBhbnkgc3RyaW5nIHRoYXQgbWF0Y2hlcyBvbmUgb2YgdGhlIEZpbHRlclF1ZXJ5T3AgYWxpYXNlcyB3aWxsIGJlIGFjY2VwdGVkLlxyXG4gICAgLSAtICBhIHZhbHVlIHtPYmplY3R9IC0gVGhpcyB3aWxsIGJlIHRyZWF0ZWQgYXMgZWl0aGVyIGEgcHJvcGVydHkgZXhwcmVzc2lvbiBvciBhIGxpdGVyYWwgZGVwZW5kaW5nIG9uIGNvbnRleHQuICBcclxuICAgIEluIGdlbmVyYWwsIGlmIHRoZSB2YWx1ZSBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgYSBwcm9wZXJ0eSBleHByZXNzaW9uIGl0IHdpbGwgYmUsIG90aGVyd2lzZSBpdCB3aWxsIGJlIHRyZWF0ZWQgYXMgYSBsaXRlcmFsLlxyXG4gICAgSW4gbW9zdCBjYXNlcyB0aGlzIHdvcmtzIHdlbGwsIGJ1dCB5b3UgY2FuIGFsc28gZm9yY2UgdGhlIGludGVycHJldGF0aW9uIGJ5IG1ha2luZyB0aGUgdmFsdWUgYXJndW1lbnQgaXRzZWxmIGFuIG9iamVjdCBcclxuICAgIHdpdGggYSAndmFsdWUnIHByb3BlcnR5IGFuZCBhbiAnaXNMaXRlcmFsJyBwcm9wZXJ0eSBzZXQgdG8gZWl0aGVyIHRydWUgb3IgZmFsc2UuXHJcbiAgICBCcmVlemUgYWxzbyB0cmllcyB0byBpbmZlciB0aGUgZGF0YVR5cGUgb2YgYW55IGxpdGVyYWwgYmFzZWQgb24gY29udGV4dCwgaWYgdGhpcyBmYWlscyB5b3UgY2FuIGZvcmNlIHRoaXMgaW5mZXJlbmNlIGJ5IG1ha2luZyB0aGUgdmFsdWUgYXJndW1lbnQgXHJcbiAgICBhbiBvYmplY3Qgd2l0aCBhICd2YWx1ZScgcHJvcGVydHkgYW5kIGEgJ2RhdGFUeXBlJ3Byb3BlcnR5IHNldCB0byBvbmUgb2YgdGhlIERhdGFUeXBlIGVudW1lcmF0aW9uIGluc3RhbmNlcy5cclxuXHJcbiAgICAtIGEgbnVsbCBvciB1bmRlZmluZWQgKCB0aGlzIGNhdXNlcyBhbnkgZXhpc3Rpbmcgd2hlcmUgY2xhdXNlIHRvIGJlIHJlbW92ZWQpXHJcbiAgKiovXHJcbiAgd2hlcmUoLi4uYXJnczogYW55W10pIHtcclxuICAgIGxldCB3aGVyZVByZWRpY2F0ZTogUHJlZGljYXRlIHwgdW5kZWZpbmVkO1xyXG4gICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdICE9IG51bGwpIHtcclxuICAgICAgd2hlcmVQcmVkaWNhdGUgPSBQcmVkaWNhdGUuY3JlYXRlKC4uLjxhbnk+YXJncyk7XHJcbiAgICAgIGlmICh0aGlzLmZyb21FbnRpdHlUeXBlKSB3aGVyZVByZWRpY2F0ZS5fdmFsaWRhdGUodGhpcy5mcm9tRW50aXR5VHlwZSk7XHJcbiAgICAgIGlmICh0aGlzLndoZXJlUHJlZGljYXRlKSB7XHJcbiAgICAgICAgd2hlcmVQcmVkaWNhdGUgPSB0aGlzLndoZXJlUHJlZGljYXRlLmFuZCh3aGVyZVByZWRpY2F0ZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBjbG9uZSh0aGlzLCBcIndoZXJlUHJlZGljYXRlXCIsIHdoZXJlUHJlZGljYXRlKTtcclxuICB9XHJcblxyXG5cclxuICBvcmRlckJ5KHByb3BlcnR5UGF0aHM/OiBzdHJpbmcsIGlzRGVzY2VuZGluZz86IGJvb2xlYW4pOiBFbnRpdHlRdWVyeTtcclxuICBvcmRlckJ5KHByb3BlcnR5UGF0aHM6IHN0cmluZ1tdLCBpc0Rlc2NlbmRpbmc/OiBib29sZWFuKTogRW50aXR5UXVlcnk7XHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIG5ldyBxdWVyeSB0aGF0IG9yZGVycyB0aGUgcmVzdWx0cyBvZiB0aGUgcXVlcnkgYnkgcHJvcGVydHkgbmFtZS4gIEJ5IGRlZmF1bHQgc29ydGluZyBvY2N1cnMgaXMgYXNjZW5kaW5nIG9yZGVyLCBidXQgc29ydGluZyBpbiBkZXNjZW5kaW5nIG9yZGVyIGlzIHN1cHBvcnRlZCBhcyB3ZWxsLlxyXG4gIE9yZGVyQnkgY2xhdXNlcyBtYXkgYmUgY2hhaW5lZC5cclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJDdXN0b21lcnNcIilcclxuICA+ICAgICAgICAub3JkZXJCeShcIkNvbXBhbnlOYW1lXCIpO1xyXG5cclxuICBvciB0byBzb3J0IGFjcm9zcyBtdWx0aXBsZSBwcm9wZXJ0aWVzXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiQ3VzdG9tZXJzXCIpXHJcbiAgPiAgICAgICAgLm9yZGVyQnkoXCJSZWdpb24sIENvbXBhbnlOYW1lXCIpO1xyXG5cclxuICBOZXN0ZWQgcHJvcGVydHkgcGF0aHMgYXJlIGFsc28gc3VwcG9ydGVkXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiUHJvZHVjdHNcIilcclxuICA+ICAgICAgICAub3JkZXJCeShcIkNhdGVnb3J5LkNhdGVnb3J5TmFtZVwiKTtcclxuXHJcbiAgU29ydGluZyBpbiBkZXNjZW5kaW5nIG9yZGVyIGlzIHN1cHBvcnRlZCB2aWEgdGhlIGFkZGl0aW9uIG9mICcgZGVzYycgdG8gdGhlIGVuZCBvZiBhbnkgcHJvcGVydHkgcGF0aC5cclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJDdXN0b21lcnNcIilcclxuICA+ICAgICAgICAub3JkZXJCeShcIkNvbXBhbnlOYW1lIGRlc2NcIik7XHJcblxyXG4gIG9yXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiQ3VzdG9tZXJzXCIpXHJcbiAgPiAgICAgICAgLm9yZGVyQnkoXCJSZWdpb24gZGVzYywgQ29tcGFueU5hbWUgZGVzY1wiKTtcclxuICBAcGFyYW0gcHJvcGVydHlQYXRocyAtIEEgY29tbWEtc2VwYXJhdGVkICgnLCcpIHN0cmluZyBvZiBwcm9wZXJ0eSBwYXRocyBvciBhbiBhcnJheSBvZiBwcm9wZXJ0eSBwYXRocy5cclxuICBFYWNoIHByb3BlcnR5IHBhdGggY2FuIG9wdGlvbmFsbHkgZW5kIHdpdGggXCIgZGVzY1wiIHRvIGZvcmNlIGEgZGVzY2VuZGluZyBzb3J0IG9yZGVyLiBJZiAncHJvcGVydHlQYXRocycgaXMgZWl0aGVyIG51bGwgb3Igb21pdHRlZCB0aGVuIGFsbCBvcmRlcmluZyBpcyByZW1vdmVkLlxyXG4gIEBwYXJhbSBpc0Rlc2NlbmRpbmcgLSBJZiBzcGVjaWZpZWQsIG92ZXJyaWRlcyBhbGwgb2YgdGhlIGVtYmVkZGVkICdkZXNjJyB0YWdzIGluIHRoZSBwcmV2aW91c2x5IHNwZWNpZmllZCBwcm9wZXJ0eSBwYXRocy5cclxuICAqKi9cclxuICBvcmRlckJ5KHByb3BlcnR5UGF0aHM6IHN0cmluZyB8IHN0cmluZ1tdLCBpc0Rlc2NlbmRpbmc/OiBib29sZWFuKSB7XHJcbiAgICAvLyBwcm9wZXJ0eVBhdGhzOiBjYW4gcGFzcyBpbiBjcmVhdGUoXCJBLlgsQlwiKSBvciBjcmVhdGUoXCJBLlggZGVzYywgQlwiKSBvciBjcmVhdGUoXCJBLlggZGVzYyxCXCIsIHRydWVdKVxyXG4gICAgLy8gaXNEZXNjIHBhcmFtZXRlciB0cnVtcHMgaXNEZXNjIGluIHByb3BlcnR5TmFtZS5cclxuICAgIGxldCBvcmRlckJ5Q2xhdXNlID0gcHJvcGVydHlQYXRocyA9PSBudWxsID8gbnVsbCA6IG5ldyBPcmRlckJ5Q2xhdXNlKG5vcm1hbGl6ZVByb3BlcnR5UGF0aHMocHJvcGVydHlQYXRocyksIGlzRGVzY2VuZGluZyk7XHJcbiAgICBpZiAodGhpcy5vcmRlckJ5Q2xhdXNlICYmIG9yZGVyQnlDbGF1c2UpIHtcclxuICAgICAgb3JkZXJCeUNsYXVzZSA9IG5ldyBPcmRlckJ5Q2xhdXNlKFt0aGlzLm9yZGVyQnlDbGF1c2UsIG9yZGVyQnlDbGF1c2VdKTtcclxuICAgIH1cclxuICAgIHJldHVybiBjbG9uZSh0aGlzLCBcIm9yZGVyQnlDbGF1c2VcIiwgb3JkZXJCeUNsYXVzZSk7XHJcbiAgfVxyXG5cclxuXHJcbiAgb3JkZXJCeURlc2MocHJvcGVydHlQYXRoczogc3RyaW5nKTogRW50aXR5UXVlcnk7XHJcbiAgb3JkZXJCeURlc2MocHJvcGVydHlQYXRoczogc3RyaW5nW10pOiBFbnRpdHlRdWVyeTtcclxuICAvKipcclxuICBSZXR1cm5zIGEgbmV3IHF1ZXJ5IHRoYXQgb3JkZXJzIHRoZSByZXN1bHRzIG9mIHRoZSBxdWVyeSBieSBwcm9wZXJ0eSBuYW1lIGluIGRlc2NlbmRpbmcgb3JkZXIuXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiQ3VzdG9tZXJzXCIpXHJcbiAgPiAgICAgICAgLm9yZGVyQnlEZXNjKFwiQ29tcGFueU5hbWVcIik7XHJcblxyXG4gIG9yIHRvIHNvcnQgYWNyb3NzIG11bHRpcGxlIHByb3BlcnRpZXNcclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJDdXN0b21lcnNcIilcclxuICA+ICAgICAgICAub3JkZXJCeURlc2MoXCJSZWdpb24sIENvbXBhbnlOYW1lXCIpO1xyXG5cclxuICBOZXN0ZWQgcHJvcGVydHkgcGF0aHMgYXJlIGFsc28gc3VwcG9ydGVkXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiUHJvZHVjdHNcIilcclxuICA+ICAgICAgICAub3JkZXJCeURlc2MoXCJDYXRlZ29yeS5DYXRlZ29yeU5hbWVcIik7XHJcbiAgQHBhcmFtIHByb3BlcnR5UGF0aHMgLSBBIGNvbW1hLXNlcGFyYXRlZCAoJywnKSBzdHJpbmcgb2YgcHJvcGVydHkgcGF0aHMgb3IgYW4gYXJyYXkgb2YgcHJvcGVydHkgcGF0aHMuXHJcbiAgSWYgJ3Byb3BlcnR5UGF0aHMnIGlzIGVpdGhlciBudWxsIG9yIG9taXR0ZWQgdGhlbiBhbGwgb3JkZXJpbmcgaXMgcmVtb3ZlZC5cclxuICAqKi9cclxuICBvcmRlckJ5RGVzYyhwcm9wZXJ0eVBhdGhzOiBzdHJpbmcgfCBzdHJpbmdbXSkge1xyXG4gICAgcmV0dXJuIHRoaXMub3JkZXJCeShwcm9wZXJ0eVBhdGhzIGFzIGFueSwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgbmV3IHF1ZXJ5IHRoYXQgc2VsZWN0cyBhIGxpc3Qgb2YgcHJvcGVydGllcyBmcm9tIHRoZSByZXN1bHRzIG9mIHRoZSBvcmlnaW5hbCBxdWVyeSBhbmQgcmV0dXJucyB0aGUgdmFsdWVzIG9mIGp1c3QgdGhlc2UgcHJvcGVydGllcy4gVGhpc1xyXG4gIHdpbGwgYmUgcmVmZXJyZWQgdG8gYXMgYSBwcm9qZWN0aW9uLlxyXG4gIElmIHRoZSByZXN1bHQgb2YgdGhpcyBzZWxlY3Rpb24gXCJwcm9qZWN0aW9uXCIgY29udGFpbnMgZW50aXRpZXMsIHRoZXNlIGVudGl0aWVzIHdpbGwgYXV0b21hdGljYWxseSBiZSBhZGRlZCB0byBFbnRpdHlNYW5hZ2VyJ3MgY2FjaGUgYW5kIHdpbGxcclxuICBiZSBtYWRlICdvYnNlcnZhYmxlJy5cclxuICBBbnkgc2ltcGxlIHByb3BlcnRpZXMsIGkuZS4gc3RyaW5ncywgbnVtYmVycyBvciBkYXRlcyB3aXRoaW4gYSBwcm9qZWN0aW9uIHdpbGwgbm90IGJlIGNhY2hlZCBhcmUgd2lsbCBOT1QgYmUgbWFkZSAnb2JzZXJ2YWJsZScuXHJcbiAgXHJcbiAgU2ltcGxlIGRhdGEgcHJvcGVydGllcyBjYW4gYmUgcHJvamVjdGVkXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiQ3VzdG9tZXJzXCIpXHJcbiAgPiAgICAgICAgIC53aGVyZShcIkNvbXBhbnlOYW1lXCIsIFwic3RhcnRzV2l0aFwiLCBcIkNcIilcclxuICA+ICAgICAgICAgLnNlbGVjdChcIkNvbXBhbnlOYW1lXCIpO1xyXG5cclxuICBUaGlzIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIG9iamVjdHMgZWFjaCB3aXRoIGEgc2luZ2xlIFwiQ29tcGFueU5hbWVcIiBwcm9wZXJ0eSBvZiB0eXBlIHN0cmluZy5cclxuICBBIHNpbWlsYXIgcXVlcnkgY291bGQgcmV0dXJuIGEgbmF2aWdhdGlvbiBwcm9wZXJ0eSBpbnN0ZWFkXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiQ3VzdG9tZXJzXCIpXHJcbiAgPiAgICAgICAgLndoZXJlKFwiQ29tcGFueU5hbWVcIiwgXCJzdGFydHNXaXRoXCIsIFwiQ1wiKVxyXG4gID4gICAgICAgIC5zZWxlY3QoXCJPcmRlcnNcIik7XHJcblxyXG4gIHdoZXJlIHRoZSByZXN1bHQgd291bGQgYmUgYW4gYXJyYXkgb2Ygb2JqZWN0cyBlYWNoIHdpdGggYSBzaW5nbGUgXCJPcmRlcnNcIiBwcm9wZXJ0eSB0aGF0IHdvdWxkIGl0c2VsZiBiZSBhbiBhcnJheSBvZiBcIk9yZGVyXCIgZW50aXRpZXMuXHJcbiAgQ29tcG9zaXRlIHByb2plY3Rpb25zIGFyZSBhbHNvIHBvc3NpYmxlOlxyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKVxyXG4gID4gICAgICAgIC53aGVyZShcIkNvbXBhbnlOYW1lXCIsIFwic3RhcnRzV2l0aFwiLCBcIkNcIilcclxuICA+ICAgICAgICAuc2VsZWN0KFwiQ29tcGFueU5hbWUsIE9yZGVyc1wiKTtcclxuXHJcbiAgQXMgd2VsbCBhcyBwcm9qZWN0aW9ucyBpbnZvbHZpbmcgbmVzdGVkIHByb3BlcnR5IHBhdGhzXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gRW50aXR5UXVlcnkoXCJPcmRlcnNcIilcclxuICA+ICAgICAgICAud2hlcmUoXCJDdXN0b21lci5Db21wYW55TmFtZVwiLCBcInN0YXJ0c1dpdGhcIiwgXCJDXCIpXHJcbiAgPiAgICAgICAgLnNlbGVjdChcIkN1c3RvbWVyLkNvbXBhbnlOYW1lLCBDdXN0b21lciwgT3JkZXJEYXRlXCIpO1xyXG4gIEBwYXJhbSBwcm9wZXJ0eVBhdGhzIC0gQSBjb21tYS1zZXBhcmF0ZWQgKCcsJykgc3RyaW5nIG9mIHByb3BlcnR5IHBhdGhzIG9yIGFuIGFycmF5IG9mIHByb3BlcnR5IHBhdGhzLlxyXG4gIElmICdwcm9wZXJ0eVBhdGhzJyBpcyBlaXRoZXIgbnVsbCBvciBvbWl0dGVkIHRoZW4gYW55IGV4aXN0aW5nIHByb2plY3Rpb24gb24gdGhlIHF1ZXJ5IGlzIHJlbW92ZWQuXHJcbiAgKiovXHJcbiAgc2VsZWN0KHByb3BlcnR5UGF0aHM/OiBzdHJpbmcgfCBzdHJpbmdbXSkge1xyXG4gICAgbGV0IHNlbGVjdENsYXVzZSA9IHByb3BlcnR5UGF0aHMgPT0gbnVsbCA/IG51bGwgOiBuZXcgU2VsZWN0Q2xhdXNlKG5vcm1hbGl6ZVByb3BlcnR5UGF0aHMocHJvcGVydHlQYXRocykpO1xyXG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIFwic2VsZWN0Q2xhdXNlXCIsIHNlbGVjdENsYXVzZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgbmV3IHF1ZXJ5IHRoYXQgc2tpcHMgdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgZW50aXRpZXMgd2hlbiByZXR1cm5pbmcgcmVzdWx0cy5cclxuICBBbnkgZXhpc3RpbmcgJ3NraXAnIGNhbiBiZSBjbGVhcmVkIGJ5IGNhbGxpbmcgJ3NraXAnIHdpdGggbm8gYXJndW1lbnRzLlxyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKVxyXG4gID4gICAgICAgLndoZXJlKFwiQ29tcGFueU5hbWVcIiwgXCJzdGFydHNXaXRoXCIsIFwiQ1wiKVxyXG4gID4gICAgICAgLnNraXAoNSk7XHJcbiAgQHBhcmFtIGNvdW50IC0gVGhlIG51bWJlciBvZiBlbnRpdGllcyB0byBza2lwIG92ZXIuIElmIG9taXR0ZWQgb3IgbnVsbCBhbnkgZXhpc3Rpbmcgc2tpcCBjb3VudCBvbiB0aGUgcXVlcnkgaXMgcmVtb3ZlZC5cclxuICAqKi9cclxuICBza2lwKGNvdW50PzogbnVtYmVyKSB7XHJcbiAgICBhc3NlcnRQYXJhbShjb3VudCwgXCJjb3VudFwiKS5pc09wdGlvbmFsKCkuaXNOdW1iZXIoKS5jaGVjaygpO1xyXG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIFwic2tpcENvdW50XCIsIChjb3VudCA9PSBudWxsKSA/IG51bGwgOiBjb3VudCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgbmV3IHF1ZXJ5IHRoYXQgcmV0dXJucyBvbmx5IHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIGVudGl0aWVzIHdoZW4gcmV0dXJuaW5nIHJlc3VsdHMuIC0gU2FtZSBhcyAndGFrZScuXHJcbiAgQW55IGV4aXN0aW5nICd0b3AnIGNhbiBiZSBjbGVhcmVkIGJ5IGNhbGxpbmcgJ3RvcCcgd2l0aCBubyBhcmd1bWVudHMuXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiQ3VzdG9tZXJzXCIpXHJcbiAgPiAgICAgICAgLnRvcCg1KTtcclxuICBAcGFyYW0gY291bnQgLSBUaGUgbnVtYmVyIG9mIGVudGl0aWVzIHRvIHJldHVybi5cclxuICBJZiAnY291bnQnIGlzIGVpdGhlciBudWxsIG9yIG9taXR0ZWQgdGhlbiBhbnkgZXhpc3RpbmcgJ3RvcCcgY291bnQgb24gdGhlIHF1ZXJ5IGlzIHJlbW92ZWQuXHJcbiAgKiovXHJcbiAgdG9wKGNvdW50PzogbnVtYmVyKSB7XHJcbiAgICByZXR1cm4gdGhpcy50YWtlKGNvdW50KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBuZXcgcXVlcnkgdGhhdCByZXR1cm5zIG9ubHkgdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgZW50aXRpZXMgd2hlbiByZXR1cm5pbmcgcmVzdWx0cyAtIFNhbWUgYXMgJ3RvcCcuXHJcbiAgQW55IGV4aXN0aW5nIHRha2UgY2FuIGJlIGNsZWFyZWQgYnkgY2FsbGluZyB0YWtlIHdpdGggbm8gYXJndW1lbnRzLlxyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKVxyXG4gID4gICAgICAgIC50YWtlKDUpO1xyXG4gIEBwYXJhbSBjb3VudCAtIFRoZSBudW1iZXIgb2YgZW50aXRpZXMgdG8gcmV0dXJuLlxyXG4gIElmICdjb3VudCcgaXMgZWl0aGVyIG51bGwgb3Igb21pdHRlZCB0aGVuIGFueSBleGlzdGluZyAndGFrZScgY291bnQgb24gdGhlIHF1ZXJ5IGlzIHJlbW92ZWQuXHJcbiAgKiovXHJcbiAgdGFrZShjb3VudD86IG51bWJlcikge1xyXG4gICAgYXNzZXJ0UGFyYW0oY291bnQsIFwiY291bnRcIikuaXNPcHRpb25hbCgpLmlzTnVtYmVyKCkuY2hlY2soKTtcclxuICAgIHJldHVybiBjbG9uZSh0aGlzLCBcInRha2VDb3VudFwiLCAoY291bnQgPT0gbnVsbCkgPyBudWxsIDogY291bnQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIG5ldyBxdWVyeSB0aGF0IHdpbGwgcmV0dXJuIHJlbGF0ZWQgZW50aXRpZXMgbmVzdGVkIHdpdGhpbiBpdHMgcmVzdWx0cy4gVGhlIGV4cGFuZCBtZXRob2QgYWxsb3dzIHlvdSB0byBpZGVudGlmeSByZWxhdGVkIGVudGl0aWVzLCB2aWEgbmF2aWdhdGlvbiBwcm9wZXJ0eVxyXG4gIG5hbWVzIHN1Y2ggdGhhdCBhIGdyYXBoIG9mIGVudGl0aWVzIG1heSBiZSByZXRyaWV2ZWQgd2l0aCBhIHNpbmdsZSByZXF1ZXN0LiBBbnkgZmlsdGVyaW5nIG9jY3VycyBiZWZvcmUgdGhlIHJlc3VsdHMgYXJlICdleHBhbmRlZCcuXHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiQ3VzdG9tZXJzXCIpXHJcbiAgPiAgICAgICAgLndoZXJlKFwiQ29tcGFueU5hbWVcIiwgXCJzdGFydHNXaXRoXCIsIFwiQ1wiKVxyXG4gID4gICAgICAgIC5leHBhbmQoXCJPcmRlcnNcIik7XHJcblxyXG4gIHdpbGwgcmV0dXJuIHRoZSBmaWx0ZXJlZCBjdXN0b21lcnMgZWFjaCB3aXRoIGl0cyBcIk9yZGVyc1wiIHByb3BlcnRpZXMgZnVsbHkgcmVzb2x2ZWQuXHJcbiAgTXVsdGlwbGUgcGF0aHMgbWF5IGJlIHNwZWNpZmllZCBieSBzZXBhcmF0aW5nIHRoZSBwYXRocyBieSBhICcsJ1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKVxyXG4gID4gICAgICAgIC5leHBhbmQoXCJDdXN0b21lciwgRW1wbG95ZWVcIilcclxuXHJcbiAgYW5kIG5lc3RlZCBwcm9wZXJ0eSBwYXRocyBteSBiZSBzcGVjaWZpZWQgYXMgd2VsbFxyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKVxyXG4gID4gICAgICAgIC5leHBhbmQoXCJDdXN0b21lciwgT3JkZXJEZXRhaWxzLCBPcmRlckRldGFpbHMuUHJvZHVjdFwiKVxyXG4gIEBwYXJhbSBwcm9wZXJ0eVBhdGhzIC0gQSBjb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBuYXZpZ2F0aW9uIHByb3BlcnR5IG5hbWVzIG9yIGFuIGFycmF5IG9mIG5hdmlnYXRpb24gcHJvcGVydHkgbmFtZXMuIEVhY2ggTmF2aWdhdGlvbiBQcm9wZXJ0eSBuYW1lIGNhbiBiZSBmb2xsb3dlZFxyXG4gIGJ5IGEgJy4nIGFuZCBhbm90aGVyIG5hdmlnYXRpb24gcHJvcGVydHkgbmFtZSB0byBlbmFibGUgaWRlbnRpZnlpbmcgYSBtdWx0aS1sZXZlbCByZWxhdGlvbnNoaXAuXHJcbiAgSWYgJ3Byb3BlcnR5UGF0aHMnIGlzIGVpdGhlciBudWxsIG9yIG9taXR0ZWQgdGhlbiBhbnkgZXhpc3RpbmcgJ2V4cGFuZCcgY2xhdXNlIG9uIHRoZSBxdWVyeSBpcyByZW1vdmVkLlxyXG4gICoqL1xyXG4gIGV4cGFuZChwcm9wZXJ0eVBhdGhzPzogc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICAgIGxldCBleHBhbmRDbGF1c2UgPSBwcm9wZXJ0eVBhdGhzID09IG51bGwgPyBudWxsIDogbmV3IEV4cGFuZENsYXVzZShub3JtYWxpemVQcm9wZXJ0eVBhdGhzKHByb3BlcnR5UGF0aHMpKTtcclxuICAgIHJldHVybiBjbG9uZSh0aGlzLCBcImV4cGFuZENsYXVzZVwiLCBleHBhbmRDbGF1c2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIG5ldyBxdWVyeSB0aGF0IGluY2x1ZGVzIGEgY29sbGVjdGlvbiBvZiBwYXJhbWV0ZXJzIHRvIHBhc3MgdG8gdGhlIHNlcnZlci5cclxuICA+ICAgICBsZXQgcXVlcnkgPSBFbnRpdHlRdWVyeS5mcm9tKFwiRW1wbG95ZWVzRmlsdGVyZWRCeUNvdW50cnlBbmRCaXJ0aGRhdGVcIilcclxuICA+ICAgICAgICAud2l0aFBhcmFtZXRlcnMoeyBCaXJ0aERhdGU6IFwiMS8xLzE5NjBcIiwgQ291bnRyeTogXCJVU0FcIiB9KTtcclxuICAgXHJcbiAgd2lsbCBjYWxsIHRoZSAnRW1wbG95ZWVzRmlsdGVyZWRCeUNvdW50cnlBbmRCaXJ0aGRhdGUnIG1ldGhvZCBvbiB0aGUgc2VydmVyIGFuZCBwYXNzIGluIDIgcGFyYW1ldGVycy4gVGhpc1xyXG4gIHF1ZXJ5IHdpbGwgYmUgdXJpIGVuY29kZWQgYXNcclxuICA+ICAgICAge3NlcnZpY2VBcGl9L0VtcGxveWVlc0ZpbHRlcmVkQnlDb3VudHJ5QW5kQmlydGhkYXRlP2JpcnRoRGF0ZT0xJTJGMSUyRjE5NjAmY291bnRyeT1VU0FcclxuXHJcbiAgUGFyYW1ldGVycyBtYXkgYWxzbyBiZSBtaXhlZCBpbiB3aXRoIG90aGVyIHF1ZXJ5IGNyaXRlcmlhLlxyXG4gID4gICAgIGxldCBxdWVyeSA9IEVudGl0eVF1ZXJ5LmZyb20oXCJFbXBsb3llZXNGaWx0ZXJlZEJ5Q291bnRyeUFuZEJpcnRoZGF0ZVwiKVxyXG4gID4gICAgICAgIC53aXRoUGFyYW1ldGVycyh7IEJpcnRoRGF0ZTogXCIxLzEvMTk2MFwiLCBDb3VudHJ5OiBcIlVTQVwiIH0pXHJcbiAgPiAgICAgICAgLndoZXJlKFwiTGFzdE5hbWVcIiwgXCJzdGFydHNXaXRoXCIsIFwiU1wiKVxyXG4gID4gICAgICAgIC5vcmRlckJ5KFwiQmlydGhEYXRlXCIpO1xyXG4gIEBwYXJhbSBwYXJhbWV0ZXJzIC0gQSBwYXJhbWV0ZXJzIG9iamVjdCB3aGVyZSB0aGUga2V5cyBhcmUgdGhlIHBhcmFtZXRlciBuYW1lcyBhbmQgdGhlIHZhbHVlcyBhcmUgdGhlIHBhcmFtZXRlciB2YWx1ZXMuXHJcbiAgKiovXHJcbiAgd2l0aFBhcmFtZXRlcnMocGFyYW1ldGVyczogT2JqZWN0KSB7XHJcbiAgICBhc3NlcnRQYXJhbShwYXJhbWV0ZXJzLCBcInBhcmFtZXRlcnNcIikuaXNPYmplY3QoKS5jaGVjaygpO1xyXG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIFwicGFyYW1ldGVyc1wiLCBwYXJhbWV0ZXJzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYSBxdWVyeSB3aXRoIHRoZSAnaW5saW5lQ291bnQnIGNhcGFiaWxpdHkgZWl0aGVyIGVuYWJsZWQgb3IgZGlzYWJsZWQuICBXaXRoICdpbmxpbmVDb3VudCcgZW5hYmxlZCwgYW4gYWRkaXRpb25hbCAnaW5saW5lQ291bnQnIHByb3BlcnR5XHJcbiAgd2lsbCBiZSByZXR1cm5lZCB3aXRoIHRoZSBxdWVyeSByZXN1bHRzIHRoYXQgd2lsbCBjb250YWluIHRoZSBudW1iZXIgb2YgZW50aXRpZXMgdGhhdCB3b3VsZCBoYXZlIGJlZW4gcmV0dXJuZWQgYnkgdGhpc1xyXG4gIHF1ZXJ5IHdpdGggb25seSB0aGUgJ3doZXJlJy8nZmlsdGVyJyBjbGF1c2VzIGFwcGxpZWQsIGkuZS4gd2l0aG91dCBhbnkgJ3NraXAnLyd0YWtlJyBvcGVyYXRvcnMgYXBwbGllZC4gRm9yIGxvY2FsIHF1ZXJpZXMgdGhpcyBjbGF1c2UgaXMgaWdub3JlZC5cclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJDdXN0b21lcnNcIilcclxuICA+ICAgICAgICAudGFrZSgyMClcclxuICA+ICAgICAgICAub3JkZXJCeShcIkNvbXBhbnlOYW1lXCIpXHJcbiAgPiAgICAgICAgLmlubGluZUNvdW50KHRydWUpO1xyXG5cclxuICB3aWxsIHJldHVybiB0aGUgZmlyc3QgMjAgY3VzdG9tZXJzIGFzIHdlbGwgYXMgYSBjb3VudCBvZiBhbGwgb2YgdGhlIGN1c3RvbWVycyBpbiB0aGUgcmVtb3RlIHN0b3JlLlxyXG4gIEBwYXJhbSBlbmFibGVkIC0gKGRlZmF1bHQgPSB0cnVlKSBXaGV0aGVyIG9yIG5vdCBpbmxpbmVDb3VudCBjYXBhYmlsaXR5IHNob3VsZCBiZSBlbmFibGVkLiBJZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkLCB0cnVlIGlzIGFzc3VtZWQuXHJcbiAgKiovXHJcbiAgaW5saW5lQ291bnQoZW5hYmxlZD86IGJvb2xlYW4pIHtcclxuICAgIGFzc2VydFBhcmFtKGVuYWJsZWQsIFwiZW5hYmxlZFwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGVuYWJsZWQgPSAoZW5hYmxlZCA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiAhIWVuYWJsZWQ7XHJcbiAgICByZXR1cm4gY2xvbmUodGhpcywgXCJpbmxpbmVDb3VudEVuYWJsZWRcIiwgZW5hYmxlZCk7XHJcbiAgfVxyXG5cclxuICB1c2VOYW1lT25TZXJ2ZXIodXNlc05hbWVPblNlcnZlcj86IGJvb2xlYW4pIHtcclxuICAgIGFzc2VydFBhcmFtKHVzZXNOYW1lT25TZXJ2ZXIsIFwidXNlc05hbWVPblNlcnZlclwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIHVzZXNOYW1lT25TZXJ2ZXIgPSAodXNlc05hbWVPblNlcnZlciA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiAhIXVzZXNOYW1lT25TZXJ2ZXI7XHJcbiAgICByZXR1cm4gY2xvbmUodGhpcywgXCJ1c2VzTmFtZU9uU2VydmVyXCIsIHVzZXNOYW1lT25TZXJ2ZXIpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIHF1ZXJ5IHdpdGggdGhlICdub1RyYWNraW5nJyBjYXBhYmlsaXR5IGVpdGhlciBlbmFibGVkIG9yIGRpc2FibGVkLiAgV2l0aCAnbm9UcmFja2luZycgZW5hYmxlZCwgdGhlIHJlc3VsdHMgb2YgdGhpcyBxdWVyeVxyXG4gIHdpbGwgbm90IGJlIGNvZXJjZWQgaW50byBlbnRpdGllcyBidXQgd2lsbCBpbnN0ZWFkIGxvb2sgbGlrZSByYXcgamF2YXNjcmlwdCBwcm9qZWN0aW9ucy4gaS5lLiBzaW1wbGUgamF2YXNjcmlwdCBvYmplY3RzLlxyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIkN1c3RvbWVyc1wiKVxyXG4gID4gICAgICAgICAudGFrZSgyMClcclxuICA+ICAgICAgICAgLm9yZGVyQnkoXCJDb21wYW55TmFtZVwiKVxyXG4gID4gICAgICAgICAubm9UcmFja2luZyh0cnVlKTtcclxuICBAcGFyYW0gZW5hYmxlZCAtIChkZWZhdWx0ID0gdHJ1ZSkgV2hldGhlciBvciBub3QgdGhlIG5vVHJhY2tpbmcgY2FwYWJpbGl0eSBzaG91bGQgYmUgZW5hYmxlZC4gSWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCwgdHJ1ZSBpcyBhc3N1bWVkLlxyXG4gICoqL1xyXG4gIG5vVHJhY2tpbmcoZW5hYmxlZD86IGJvb2xlYW4pIHtcclxuICAgIGFzc2VydFBhcmFtKGVuYWJsZWQsIFwiZW5hYmxlZFwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGVuYWJsZWQgPSAoZW5hYmxlZCA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiAhIWVuYWJsZWQ7XHJcbiAgICByZXR1cm4gY2xvbmUodGhpcywgXCJub1RyYWNraW5nRW5hYmxlZFwiLCBlbmFibGVkKTtcclxuICB9XHJcblxyXG4gIHVzaW5nKG9iajogRW50aXR5TWFuYWdlcik6IEVudGl0eVF1ZXJ5O1xyXG4gIHVzaW5nKG9iajogRGF0YVNlcnZpY2UpOiBFbnRpdHlRdWVyeTtcclxuICB1c2luZyhvYmo6IEpzb25SZXN1bHRzQWRhcHRlcik6IEVudGl0eVF1ZXJ5O1xyXG4gIHVzaW5nKG9iajogUXVlcnlPcHRpb25zKTogRW50aXR5UXVlcnk7XHJcbiAgdXNpbmcob2JqOiBNZXJnZVN0cmF0ZWd5KTogRW50aXR5UXVlcnk7XHJcbiAgdXNpbmcob2JqOiBGZXRjaFN0cmF0ZWd5KTogRW50aXR5UXVlcnk7XHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIGNvcHkgb2YgdGhpcyBFbnRpdHlRdWVyeSB3aXRoIHRoZSBzcGVjaWZpZWQgW1tFbnRpdHlNYW5hZ2VyXV0sIFtbRGF0YVNlcnZpY2VdXSxcclxuICBbW0pzb25SZXN1bHRzQWRhcHRlcl1dLCBbW01lcmdlU3RyYXRlZ3ldXSBvciBbW0ZldGNoU3RyYXRlZ3ldXSBhcHBsaWVkLlxyXG4gID4gICAgICAvLyAndXNpbmcnIGNhbiBiZSB1c2VkIHRvIHJldHVybiBhIG5ldyBxdWVyeSB3aXRoIGEgc3BlY2lmaWVkIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKHNlcnZpY2VOYW1lKTtcclxuICA+ICAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiT3JkZXJzXCIpXHJcbiAgPiAgICAgICAgLnVzaW5nKGVtKTtcclxuXHJcbiAgb3Igd2l0aCBhIHNwZWNpZmllZCBbW01lcmdlU3RyYXRlZ3ldXVxyXG4gID4gICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcihzZXJ2aWNlTmFtZSk7XHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKVxyXG4gID4gICAgICAgIC51c2luZyhNZXJnZVN0cmF0ZWd5LlByZXNlcnZlQ2hhbmdlcyk7XHJcblxyXG4gIG9yIHdpdGggYSBzcGVjaWZpZWQgW1tGZXRjaFN0cmF0ZWd5XV1cclxuICA+ICAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJPcmRlcnNcIilcclxuICA+ICAgICAgICAudXNpbmcoRmV0Y2hTdHJhdGVneS5Gcm9tTG9jYWxDYWNoZSk7XHJcbiAgQHBhcmFtIG9iaiAtIFRoZSBvYmplY3QgdG8gdXBkYXRlIGluIGNyZWF0aW5nIGEgbmV3IEVudGl0eVF1ZXJ5IGZyb20gYW4gZXhpc3Rpbmcgb25lLlxyXG4gICoqL1xyXG4gIHVzaW5nKG9iajogYW55KSB7XHJcbiAgICBpZiAoIW9iaikgcmV0dXJuIHRoaXM7XHJcbiAgICBsZXQgZXEgPSBjbG9uZSh0aGlzKTtcclxuICAgIHByb2Nlc3NVc2luZyhlcSwge1xyXG4gICAgICBcImVudGl0eU1hbmFnZXJcIjogbnVsbCxcclxuICAgICAgXCJkYXRhU2VydmljZVwiOiBudWxsLFxyXG4gICAgICBcInF1ZXJ5T3B0aW9uc1wiOiBudWxsLFxyXG4gICAgICBcImZldGNoU3RyYXRlZ3lcIjogKGVxOiBFbnRpdHlRdWVyeSwgdmFsOiBhbnkpID0+IHtcclxuICAgICAgICBlcS5xdWVyeU9wdGlvbnMgPSAoZXEucXVlcnlPcHRpb25zIHx8IG5ldyBRdWVyeU9wdGlvbnMoKSkudXNpbmcodmFsKTtcclxuICAgICAgfSxcclxuICAgICAgXCJtZXJnZVN0cmF0ZWd5XCI6IChlcTogRW50aXR5UXVlcnksIHZhbDogYW55KSA9PiB7XHJcbiAgICAgICAgZXEucXVlcnlPcHRpb25zID0gKGVxLnF1ZXJ5T3B0aW9ucyB8fCBuZXcgUXVlcnlPcHRpb25zKCkpLnVzaW5nKHZhbCk7XHJcbiAgICAgIH0sXHJcbiAgICAgIFwianNvblJlc3VsdHNBZGFwdGVyXCI6IChlcTogRW50aXR5UXVlcnksIHZhbDogYW55KSA9PiB7XHJcbiAgICAgICAgZXEuZGF0YVNlcnZpY2UgPSAoZXEuZGF0YVNlcnZpY2UgfHwgbmV3IERhdGFTZXJ2aWNlKCkpLnVzaW5nKHsganNvblJlc3VsdHNBZGFwdGVyOiB2YWwgfSk7XHJcbiAgICAgIH1cclxuICAgIH0sIG9iaik7XHJcbiAgICByZXR1cm4gZXE7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBFeGVjdXRlcyB0aGlzIHF1ZXJ5LiAgVGhpcyBtZXRob2QgcmVxdWlyZXMgdGhhdCBhbiBFbnRpdHlNYW5hZ2VyIGhhcyBiZWVuIHByZXZpb3VzbHkgc3BlY2lmaWVkIHZpYSB0aGUgXCJ1c2luZ1wiIG1ldGhvZC5cclxuICBcclxuICBUaGlzIG1ldGhvZCBjYW4gYmUgY2FsbGVkIHVzaW5nIGEgJ3Byb21pc2VzJyBzeW50YXggKCByZWNvbW1lbmRlZClcclxuICA+ICAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJPcmRlcnNcIikudXNpbmcoZW0pO1xyXG4gID4gICAgICBxdWVyeS5leGVjdXRlKCkudGhlbiggZnVuY3Rpb24oZGF0YSkge1xyXG4gID4gICAgICAgICAgLi4uIHF1ZXJ5IHJlc3VsdHMgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICAgfSkuY2F0Y2goIGZ1bmN0aW9uKGVycikge1xyXG4gID4gICAgICAgICAgLi4uIHF1ZXJ5IGZhaWx1cmUgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICAgfSk7XHJcblxyXG4gIG9yIHdpdGggY2FsbGJhY2tzXHJcbiAgPiAgICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKHNlcnZpY2VOYW1lKTtcclxuICA+ICAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiT3JkZXJzXCIpLnVzaW5nKGVtKTtcclxuICA+ICAgICAgcXVlcnkuZXhlY3V0ZShcclxuICA+ICAgICAgICBmdW5jdGlvbihkYXRhKSB7XHJcbiAgPiAgICAgICAgICAgICAgICAgICAgbGV0IG9yZGVycyA9IGRhdGEucmVzdWx0cztcclxuICA+ICAgICAgICAgICAgICAgICAgICAuLi4gcXVlcnkgcmVzdWx0cyBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgICAgICAgICAgICAgfSxcclxuICA+ICAgICAgICBmdW5jdGlvbihlcnIpIHtcclxuICA+ICAgICAgICAgICAgICAgICAgICAuLi4gcXVlcnkgZmFpbHVyZSBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgICAgICAgICAgICAgfSk7XHJcblxyXG4gIEVpdGhlciB3YXkgdGhpcyBtZXRob2QgaXMgdGhlIHNhbWUgYXMgY2FsbGluZyB0aGUgRW50aXR5TWFuYWdlciAnZXhlY3V0ZScgbWV0aG9kLlxyXG4gID4gICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcihzZXJ2aWNlTmFtZSk7XHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKTtcclxuICA+ICAgICAgZW0uZXhlY3V0ZVF1ZXJ5KHF1ZXJ5KS50aGVuKCBmdW5jdGlvbihkYXRhKSB7XHJcbiAgPiAgICAgICAgIGxldCBvcmRlcnMgPSBkYXRhLnJlc3VsdHM7XHJcbiAgPiAgICAgICAgICAuLi4gcXVlcnkgcmVzdWx0cyBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgICB9KS5jYXRjaCggZnVuY3Rpb24oZXJyKSB7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSBmYWlsdXJlIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgIH0pO1xyXG5cclxuICBAcGFyYW0gY2FsbGJhY2sgLSAgRnVuY3Rpb24gY2FsbGVkIG9uIHN1Y2Nlc3MuXHJcbiAgQHBhcmFtIGVycm9yQ2FsbGJhY2sgLSBGdW5jdGlvbiBjYWxsZWQgb24gZmFpbHVyZS5cclxuICBAcmV0dXJuIFByb21pc2VcclxuICAqKi9cclxuICBleGVjdXRlKGNhbGxiYWNrPzogQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s/OiBFcnJvckNhbGxiYWNrKTogUHJvbWlzZTxRdWVyeVJlc3VsdD4ge1xyXG4gICAgaWYgKCF0aGlzLmVudGl0eU1hbmFnZXIpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQW4gRW50aXR5UXVlcnkgbXVzdCBoYXZlIGl0cyBFbnRpdHlNYW5hZ2VyIHByb3BlcnR5IHNldCBiZWZvcmUgY2FsbGluZyAnZXhlY3V0ZSdcIik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5lbnRpdHlNYW5hZ2VyLmV4ZWN1dGVRdWVyeSh0aGlzLCBjYWxsYmFjaywgZXJyb3JDYWxsYmFjayk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBFeGVjdXRlcyB0aGlzIHF1ZXJ5IGFnYWluc3QgdGhlIGxvY2FsIGNhY2hlLiAgVGhpcyBtZXRob2QgcmVxdWlyZXMgdGhhdCBhbiBFbnRpdHlNYW5hZ2VyIGhhdmUgYmVlbiBwcmV2aW91c2x5IHNwZWNpZmllZCB2aWEgdGhlIFwidXNpbmdcIiBtZXRob2QuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbSBpcyBhbiBlbnRpdHlNYW5hZ2VyIGFscmVhZHkgZmlsbGVkIHdpdGggb3JkZXIgZW50aXRpZXM7XHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKS51c2luZyhlbSk7XHJcbiAgPiAgICAgIGxldCBvcmRlcnMgPSBxdWVyeS5leGVjdXRlTG9jYWxseSgpO1xyXG5cclxuICBOb3RlIHRoYXQgY2FsbGluZyB0aGlzIG1ldGhvZCBpcyB0aGUgc2FtZSBhcyBjYWxsaW5nIFtbRW50aXR5TWFuYWdlci5leGVjdXRlUXVlcnlMb2NhbGx5XV0uXHJcbiAgKiovXHJcbiAgZXhlY3V0ZUxvY2FsbHkoKSB7XHJcbiAgICBpZiAoIXRoaXMuZW50aXR5TWFuYWdlcikge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBbiBFbnRpdHlRdWVyeSBtdXN0IGhhdmUgaXRzIEVudGl0eU1hbmFnZXIgcHJvcGVydHkgc2V0IGJlZm9yZSBjYWxsaW5nICdleGVjdXRlTG9jYWxseSdcIik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5lbnRpdHlNYW5hZ2VyLmV4ZWN1dGVRdWVyeUxvY2FsbHkodGhpcyk7XHJcbiAgfVxyXG5cclxuICB0b0pTT04oKSB7XHJcbiAgICByZXR1cm4gdGhpcy50b0pTT05FeHQoKTtcclxuICB9XHJcblxyXG4gIC8qKiBUeXBpY2FsbHkgb25seSBmb3IgdXNlIHdoZW4gYnVpbGRpbmcgVXJpQnVpbGRlckFkYXB0ZXJzLiAgXHJcbiAgQGhpZGRlbiBAaW50ZXJuYWwgIFxyXG4gICovXHJcbiAgdG9KU09ORXh0KGNvbnRleHQ/OiBFbnRpdHlRdWVyeUpzb25Db250ZXh0KSB7XHJcbiAgICBjb250ZXh0ID0gY29udGV4dCB8fCB7fTtcclxuICAgIGNvbnRleHQuZW50aXR5VHlwZSA9IGNvbnRleHQuZW50aXR5VHlwZSB8fCB0aGlzLmZyb21FbnRpdHlUeXBlO1xyXG4gICAgY29udGV4dC5wcm9wZXJ0eVBhdGhGbiA9IGNvbnRleHQudG9OYW1lT25TZXJ2ZXIgPyBjb250ZXh0LmVudGl0eVR5cGUhLmNsaWVudFByb3BlcnR5UGF0aFRvU2VydmVyLmJpbmQoY29udGV4dC5lbnRpdHlUeXBlKSA6IGNvcmUuaWRlbnRpdHk7XHJcblxyXG4gICAgbGV0IHRvSlNPTkV4dEZuID0gZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICByZXR1cm4gdiA/IHYudG9KU09ORXh0KGNvbnRleHQpIDogdW5kZWZpbmVkO1xyXG4gICAgfTtcclxuICAgIHJldHVybiBjb3JlLnRvSnNvbih0aGlzLCB7XHJcbiAgICAgIFwiZnJvbSxyZXNvdXJjZU5hbWVcIjogbnVsbCxcclxuICAgICAgXCJ0b1R5cGUscmVzdWx0RW50aXR5VHlwZVwiOiBmdW5jdGlvbiAodjogYW55KSB7XHJcbiAgICAgICAgLy8gcmVzdWx0RW50aXR5VHlwZSBjYW4gYmUgZWl0aGVyIGEgc3RyaW5nIG9yIGFuIGVudGl0eVR5cGVcclxuICAgICAgICByZXR1cm4gdiA/ICh0eXBlb2YgdiA9PT0gJ3N0cmluZycgPyB2IDogdi5uYW1lKSA6IHVuZGVmaW5lZDtcclxuICAgICAgfSxcclxuICAgICAgXCJ3aGVyZSx3aGVyZVByZWRpY2F0ZVwiOiB0b0pTT05FeHRGbixcclxuICAgICAgXCJvcmRlckJ5LG9yZGVyQnlDbGF1c2VcIjogdG9KU09ORXh0Rm4sXHJcbiAgICAgIFwic2VsZWN0LHNlbGVjdENsYXVzZVwiOiB0b0pTT05FeHRGbixcclxuICAgICAgXCJleHBhbmQsZXhwYW5kQ2xhdXNlXCI6IHRvSlNPTkV4dEZuLFxyXG4gICAgICBcInNraXAsc2tpcENvdW50XCI6IG51bGwsXHJcbiAgICAgIFwidGFrZSx0YWtlQ291bnRcIjogbnVsbCxcclxuICAgICAgcGFyYW1ldGVyczogZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICAgIHJldHVybiBjb3JlLmlzRW1wdHkodikgPyB1bmRlZmluZWQgOiB2O1xyXG4gICAgICB9LFxyXG4gICAgICBcImlubGluZUNvdW50LGlubGluZUNvdW50RW5hYmxlZFwiOiBmYWxzZSxcclxuICAgICAgXCJub1RyYWNraW5nLG5vVHJhY2tpbmdFbmFibGVkXCI6IGZhbHNlLFxyXG4gICAgICBxdWVyeU9wdGlvbnM6IG51bGxcclxuICAgIH0pO1xyXG5cclxuICB9XHJcblxyXG4gIHN0YXRpYyBmcm9tRW50aXRpZXMoZW50aXR5OiBFbnRpdHkpOiBFbnRpdHlRdWVyeTtcclxuICBzdGF0aWMgZnJvbUVudGl0aWVzKGVudGl0aWVzOiBFbnRpdHlbXSk6IEVudGl0eVF1ZXJ5O1xyXG4gIC8qKlxyXG4gIFN0YXRpYyBtZXRob2QgdGhhdCBjcmVhdGVzIGFuIEVudGl0eVF1ZXJ5IHRoYXQgd2lsbCBhbGxvdyAncmVxdWVyeWluZycgYW4gZW50aXR5IG9yIGEgY29sbGVjdGlvbiBvZiBlbnRpdGllcyBieSBwcmltYXJ5IGtleS4gVGhpcyBjYW4gYmUgdXNlZnVsXHJcbiAgdG8gZm9yY2UgYSByZXF1ZXJ5IG9mIHNlbGVjdGVkIGVudGl0aWVzLCBvciB0byByZXN0cmljdCBhbiBleGlzdGluZyBjb2xsZWN0aW9uIG9mIGVudGl0aWVzIGFjY29yZGluZyB0byBzb21lIGZpbHRlci5cclxuXHJcbiAgV29ya3MgZm9yIGEgc2luZ2xlIGVudGl0eSBvciBhbiBhcnJheSBvZiBlbnRpdGllcyBvZiB0aGUgU0FNRSB0eXBlLlxyXG4gIERvZXMgbm90IHdvcmsgZm9yIGFuIGFycmF5IG9mIGVudGl0aWVzIG9mIGRpZmZlcmVudCB0eXBlcy5cclxuICA+ICAgICAgLy8gYXNzdW1pbmcgJ2N1c3RvbWVycycgaXMgYW4gYXJyYXkgb2YgJ0N1c3RvbWVyJyBlbnRpdGllcyByZXRyaWV2ZWQgZWFybGllci5cclxuICA+ICAgICAgbGV0IGN1c3RvbWVyc1F1ZXJ5ID0gRW50aXR5UXVlcnkuZnJvbUVudGl0aWVzKGN1c3RvbWVycyk7XHJcblxyXG4gIFRoZSByZXN1bHRpbmcgcXVlcnkgY2FuLCBvZiBjb3Vyc2UsIGJlIGV4dGVuZGVkXHJcbiAgPiAgICAgIC8vIGFzc3VtaW5nICdjdXN0b21lcnMnIGlzIGFuIGFycmF5IG9mICdDdXN0b21lcicgZW50aXRpZXMgcmV0cmlldmVkIGVhcmxpZXIuXHJcbiAgPiAgICAgIGxldCBjdXN0b21lcnNRdWVyeSA9IEVudGl0eVF1ZXJ5LmZyb21FbnRpdGllcyhjdXN0b21lcnMpXHJcbiAgPiAgICAgICAgLndoZXJlKFwiUmVnaW9uXCIsIEZpbHRlclF1ZXJ5T3AuTm90RXF1YWxzLCBudWxsKTtcclxuXHJcbiAgU2luZ2xlIGVudGl0aWVzIGNhbiByZXF1ZXJpZWQgYXMgd2VsbC5cclxuICA+ICAgICAgLy8gYXNzdW1pbmcgJ2N1c3RvbWVyJyBpcyBhICdDdXN0b21lcicgZW50aXR5IHJldHJpZXZlZCBlYXJsaWVyLlxyXG4gID4gICAgICBsZXQgY3VzdG9tZXJRdWVyeSA9IEVudGl0eVF1ZXJ5LmZyb21FbnRpdGllcyhjdXN0b21lcik7XHJcblxyXG4gIHdpbGwgY3JlYXRlIGEgcXVlcnkgdGhhdCB3aWxsIHJldHVybiBhbiBhcnJheSBjb250YWluaW5nIGEgc2luZ2xlIGN1c3RvbWVyIGVudGl0eS5cclxuICBAcGFyYW0gZW50aXRpZXMgLSBUaGUgZW50aXRpZXMgZm9yIHdoaWNoIHdlIHdhbnQgdG8gY3JlYXRlIGFuIEVudGl0eVF1ZXJ5LlxyXG4gICoqL1xyXG4gIHN0YXRpYyBmcm9tRW50aXRpZXMoZW50aXRpZXM6IEVudGl0eSB8IEVudGl0eVtdKSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdGllcywgXCJlbnRpdGllc1wiKS5pc0VudGl0eSgpLm9yKCkuaXNOb25FbXB0eUFycmF5KCkuaXNFbnRpdHkoKS5jaGVjaygpO1xyXG4gICAgbGV0IGVudHMgPSAoQXJyYXkuaXNBcnJheShlbnRpdGllcykpID8gZW50aXRpZXMgOiBbZW50aXRpZXNdO1xyXG5cclxuICAgIGxldCBmaXJzdEVudGl0eSA9IGVudHNbMF07XHJcbiAgICBsZXQgdHlwZSA9IGZpcnN0RW50aXR5LmVudGl0eVR5cGU7XHJcbiAgICBpZiAoZW50cy5zb21lKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIHJldHVybiBlLmVudGl0eVR5cGUgIT09IHR5cGU7XHJcbiAgICB9KSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBbGwgJ2Zyb21FbnRpdGllcycgbXVzdCBiZSB0aGUgc2FtZSB0eXBlOyBhdCBsZWFzdCBvbmUgaXMgbm90IG9mIHR5cGUgXCIgK1xyXG4gICAgICAgIHR5cGUubmFtZSk7XHJcbiAgICB9XHJcbiAgICBsZXQgcSA9IG5ldyBFbnRpdHlRdWVyeSh0eXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUpO1xyXG4gICAgbGV0IHByZWRzID0gZW50cy5tYXAoZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgICByZXR1cm4gYnVpbGRQcmVkaWNhdGUoZW50aXR5KTtcclxuICAgIH0pO1xyXG4gICAgbGV0IHByZWQgPSBQcmVkaWNhdGUub3IocHJlZHMpO1xyXG4gICAgcSA9IHEud2hlcmUocHJlZCk7XHJcbiAgICBsZXQgZW0gPSBmaXJzdEVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5TWFuYWdlcjtcclxuICAgIGlmIChlbSkge1xyXG4gICAgICBxID0gcS51c2luZyhlbSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIENyZWF0ZXMgYW4gRW50aXR5UXVlcnkgZm9yIHRoZSBzcGVjaWZpZWQgW1tFbnRpdHlLZXldXS5cclxuICA+ICAgICAgbGV0IGVtcFR5cGUgPSBtZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJFbXBsb3llZVwiKTtcclxuICA+ICAgICAgbGV0IGVudGl0eUtleSA9IG5ldyBFbnRpdHlLZXkoZW1wVHlwZSwgMSk7XHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IEVudGl0eVF1ZXJ5LmZyb21FbnRpdHlLZXkoZW50aXR5S2V5KTtcclxuXHJcbiAgb3JcclxuICA+ICAgICAgLy8gJ2VtcGxveWVlJyBpcyBhIHByZXZpb3VzbHkgcXVlcmllZCBlbXBsb3llZVxyXG4gID4gICAgICBsZXQgZW50aXR5S2V5ID0gZW1wbG95ZWUuZW50aXR5QXNwZWN0LmdldEtleSgpO1xyXG4gID4gICAgICBsZXQgcXVlcnkgPSBFbnRpdHlRdWVyeS5mcm9tRW50aXR5S2V5KGVudGl0eUtleSk7XHJcbiAgQHBhcmFtIGVudGl0eUtleSAtIFRoZSBbW0VudGl0eUtleV1dIGZvciB3aGljaCBhIHF1ZXJ5IHdpbGwgYmUgY3JlYXRlZC5cclxuICAqKi9cclxuICBzdGF0aWMgZnJvbUVudGl0eUtleShlbnRpdHlLZXk6IEVudGl0eUtleSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5S2V5LCBcImVudGl0eUtleVwiKS5pc0luc3RhbmNlT2YoRW50aXR5S2V5KS5jaGVjaygpO1xyXG4gICAgbGV0IHEgPSBuZXcgRW50aXR5UXVlcnkoZW50aXR5S2V5LmVudGl0eVR5cGUuZGVmYXVsdFJlc291cmNlTmFtZSk7XHJcbiAgICBsZXQgcHJlZCA9IGJ1aWxkS2V5UHJlZGljYXRlKGVudGl0eUtleSk7XHJcbiAgICBxID0gcS53aGVyZShwcmVkKS50b1R5cGUoZW50aXR5S2V5LmVudGl0eVR5cGUpO1xyXG4gICAgcmV0dXJuIHE7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBDcmVhdGVzIGFuIEVudGl0eVF1ZXJ5IGZvciB0aGUgc3BlY2lmaWVkIGVudGl0eSBhbmQgW1tOYXZpZ2F0aW9uUHJvcGVydHldXS5cclxuICA+ICAgICAgLy8gJ2VtcGxveWVlJyBpcyBhIHByZXZpb3VzbHkgcXVlcmllZCBlbXBsb3llZVxyXG4gID4gICAgICBsZXQgb3JkZXJzTmF2UHJvcCA9IGVtcGxveWVlLmVudGl0eVR5cGUuZ2V0UHJvcGVydHkoXCJPcmRlcnNcIik7XHJcbiAgPiAgICAgIGxldCBxdWVyeSA9IEVudGl0eVF1ZXJ5LmZyb21FbnRpdHlOYXZpZ2F0aW9uKGVtcGxveWVlLCBvcmRlcnNOYXZQcm9wKTtcclxuXHJcbiAgd2lsbCByZXR1cm4gYSBxdWVyeSBmb3IgdGhlIFwiT3JkZXJzXCIgb2YgdGhlIHNwZWNpZmllZCAnZW1wbG95ZWUnLlxyXG4gIEBwYXJhbSBlbnRpdHkgLSBUaGUgRW50aXR5IHdob3NlIG5hdmlnYXRpb24gcHJvcGVydHkgd2lsbCBiZSBxdWVyaWVkLlxyXG4gIEBwYXJhbSBuYXZpZ2F0aW9uUHJvcGVydHkgLSBUaGUgW1tOYXZpZ2F0aW9uUHJvcGVydHldXSBvciBuYW1lIG9mIHRoZSBOYXZpZ2F0aW9uUHJvcGVydHkgdG8gYmUgcXVlcmllZC5cclxuICAqKi9cclxuICBzdGF0aWMgZnJvbUVudGl0eU5hdmlnYXRpb24gPSBmdW5jdGlvbiAoZW50aXR5OiBFbnRpdHksIG5hdmlnYXRpb25Qcm9wZXJ0eTogTmF2aWdhdGlvblByb3BlcnR5IHwgc3RyaW5nKSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHksIFwiZW50aXR5XCIpLmlzRW50aXR5KCkuY2hlY2soKTtcclxuICAgIGxldCBuYXZQcm9wZXJ0eSA9IGVudGl0eS5lbnRpdHlUeXBlLl9jaGVja05hdlByb3BlcnR5KG5hdmlnYXRpb25Qcm9wZXJ0eSk7XHJcbiAgICBsZXQgcSA9IG5ldyBFbnRpdHlRdWVyeShuYXZQcm9wZXJ0eS5lbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUpO1xyXG4gICAgbGV0IHByZWQgPSBidWlsZE5hdmlnYXRpb25QcmVkaWNhdGUoZW50aXR5LCBuYXZQcm9wZXJ0eSk7XHJcbiAgICBpZiAocHJlZCA9PSBudWxsKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBjcmVhdGUgYSBOYXZpZ2F0aW9uUXVlcnkgZm9yIG5hdmlnYXRpb25Qcm9wZXJ0eTogXCIgKyBuYXZQcm9wZXJ0eS5uYW1lICk7XHJcbiAgICB9XHJcbiAgICBxID0gcS53aGVyZShwcmVkKTtcclxuICAgIGxldCBlbSA9IGVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5TWFuYWdlcjtcclxuICAgIHJldHVybiBlbSA/IHEudXNpbmcoZW0pIDogcTtcclxuICB9O1xyXG5cclxuICAvLyBwcm90ZWN0ZWQgbWV0aG9kc1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9nZXRGcm9tRW50aXR5VHlwZShtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlLCB0aHJvd0Vycm9ySWZOb3RGb3VuZD86IGJvb2xlYW4pIHtcclxuICAgIC8vIFVuY29tbWVudCBuZXh0IHR3byBsaW5lcyBpZiB3ZSBtYWtlIHRoaXMgbWV0aG9kIHB1YmxpYy5cclxuICAgIC8vIGFzc2VydFBhcmFtKG1ldGFkYXRhU3RvcmUsIFwibWV0YWRhdGFTdG9yZVwiKS5pc0luc3RhbmNlT2YoTWV0YWRhdGFTdG9yZSkuY2hlY2soKTtcclxuICAgIC8vIGFzc2VydFBhcmFtKHRocm93RXJyb3JJZk5vdEZvdW5kLCBcInRocm93RXJyb3JJZk5vdEZvdW5kXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgbGV0IGVudGl0eVR5cGUgPSB0aGlzLmZyb21FbnRpdHlUeXBlO1xyXG4gICAgaWYgKGVudGl0eVR5cGUpIHJldHVybiBlbnRpdHlUeXBlO1xyXG5cclxuICAgIGxldCByZXNvdXJjZU5hbWUgPSB0aGlzLnJlc291cmNlTmFtZTtcclxuICAgIGlmICghcmVzb3VyY2VOYW1lKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZXJlIGlzIG5vIHJlc291cmNlTmFtZSBmb3IgdGhpcyBxdWVyeVwiKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAobWV0YWRhdGFTdG9yZS5pc0VtcHR5KCkpIHtcclxuICAgICAgaWYgKHRocm93RXJyb3JJZk5vdEZvdW5kKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlcmUgaXMgbm8gbWV0YWRhdGEgYXZhaWxhYmxlIGZvciB0aGlzIHF1ZXJ5LiBcIiArXHJcbiAgICAgICAgICBcIkFyZSB5b3UgcXVlcnlpbmcgdGhlIGxvY2FsIGNhY2hlIGJlZm9yZSB5b3UndmUgZmV0Y2hlZCBtZXRhZGF0YT9cIik7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBlbnRpdHlUeXBlTmFtZSA9IG1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZU5hbWVGb3JSZXNvdXJjZU5hbWUocmVzb3VyY2VOYW1lKTtcclxuICAgIGlmIChlbnRpdHlUeXBlTmFtZSkge1xyXG4gICAgICBlbnRpdHlUeXBlID0gbWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUoZW50aXR5VHlwZU5hbWUpIGFzIEVudGl0eVR5cGU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBlbnRpdHlUeXBlID0gdGhpcy5fZ2V0VG9FbnRpdHlUeXBlKG1ldGFkYXRhU3RvcmUsIHRydWUpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghZW50aXR5VHlwZSkge1xyXG4gICAgICBpZiAodGhyb3dFcnJvcklmTm90Rm91bmQpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoY29yZS5mb3JtYXRTdHJpbmcoXCJDYW5ub3QgZmluZCBhbiBlbnRpdHlUeXBlIGZvciByZXNvdXJjZU5hbWU6ICclMScuIFwiLCByZXNvdXJjZU5hbWUpICsgY29yZS5zdHJpbmdzLlRPX1RZUEUpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmZyb21FbnRpdHlUeXBlID0gZW50aXR5VHlwZTtcclxuICAgIHJldHVybiBlbnRpdHlUeXBlO1xyXG5cclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9nZXRUb0VudGl0eVR5cGUobWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSwgc2tpcEZyb21DaGVjaz86IGJvb2xlYW4pOiBFbnRpdHlUeXBlIHwgdW5kZWZpbmVkIHtcclxuICAgIC8vIHNraXBGcm9tQ2hlY2sgaXMgdG8gYXZvaWQgcmVjdXJzaW9uIGlmIGNhbGxlZCBmcm9tIF9nZXRGcm9tRW50aXR5VHlwZTtcclxuICAgIGlmICh0aGlzLnJlc3VsdEVudGl0eVR5cGUgaW5zdGFuY2VvZiBFbnRpdHlUeXBlKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLnJlc3VsdEVudGl0eVR5cGU7XHJcbiAgICB9IGVsc2UgaWYgKHRoaXMucmVzdWx0RW50aXR5VHlwZSkge1xyXG4gICAgICAvLyByZXN1bHRFbnRpdHlUeXBlIGlzIGEgc3RyaW5nXHJcbiAgICAgIHRoaXMucmVzdWx0RW50aXR5VHlwZSA9IG1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKHRoaXMucmVzdWx0RW50aXR5VHlwZSwgZmFsc2UpIGFzIEVudGl0eVR5cGU7XHJcbiAgICAgIHJldHVybiB0aGlzLnJlc3VsdEVudGl0eVR5cGU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyByZXNvbHZlIGl0LCBpZiBwb3NzaWJsZSwgdmlhIHRoZSByZXNvdXJjZU5hbWVcclxuICAgICAgLy8gZG8gbm90IGNhY2hlIHRoaXMgdmFsdWUgaW4gdGhpcyBjYXNlXHJcbiAgICAgIC8vIGNhbm5vdCBkZXRlcm1pbmUgdGhlIHJlc3VsdEVudGl0eVR5cGUgaWYgYSBzZWxlY3RDbGF1c2UgaXMgcHJlc2VudC5cclxuICAgICAgLy8gcmV0dXJuIHNraXBGcm9tQ2hlY2sgPyBudWxsIDogKCF0aGlzLnNlbGVjdENsYXVzZSkgJiYgdGhpcy5fZ2V0RnJvbUVudGl0eVR5cGUobWV0YWRhdGFTdG9yZSwgZmFsc2UpO1xyXG4gICAgICBpZiAoc2tpcEZyb21DaGVjayB8fCB0aGlzLnNlbGVjdENsYXVzZSkge1xyXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5fZ2V0RnJvbUVudGl0eVR5cGUobWV0YWRhdGFTdG9yZSwgZmFsc2UpO1xyXG4gICAgICB9XHJcblxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgLy8gZm9yIHRlc3RpbmdcclxuICBfdG9VcmkoZW06IEVudGl0eU1hbmFnZXIpIHtcclxuICAgIGxldCBkcyA9IERhdGFTZXJ2aWNlLnJlc29sdmUoW2VtLmRhdGFTZXJ2aWNlXSk7XHJcbiAgICByZXR1cm4gZHMhLnVyaUJ1aWxkZXIhLmJ1aWxkVXJpKHRoaXMsIGVtLm1ldGFkYXRhU3RvcmUpO1xyXG4gIH1cclxuXHJcbn1cclxuRW50aXR5UXVlcnkucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIkVudGl0eVF1ZXJ5XCI7XHJcblxyXG4vLyBwcml2YXRlIGZ1bmN0aW9uc1xyXG5cclxuZnVuY3Rpb24gZnJvbUpTT04oZXE6IEVudGl0eVF1ZXJ5LCBqc29uOiBPYmplY3QpIHtcclxuICBjb3JlLnRvSnNvbihqc29uLCB7XHJcbiAgICBcInJlc291cmNlTmFtZSxmcm9tXCI6IG51bGwsXHJcbiAgICAvLyBqdXN0IHRoZSBuYW1lIGNvbWVzIGJhY2sgYW5kIHdpbGwgYmUgcmVzb2x2ZWQgbGF0ZXJcclxuICAgIFwicmVzdWx0RW50aXR5VHlwZSx0b1R5cGVcIjogbnVsbCxcclxuICAgIFwid2hlcmVQcmVkaWNhdGUsd2hlcmVcIjogZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICByZXR1cm4gdiA/IG5ldyBQcmVkaWNhdGUodikgOiB1bmRlZmluZWQ7XHJcbiAgICB9LFxyXG4gICAgXCJvcmRlckJ5Q2xhdXNlLG9yZGVyQnlcIjogZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICByZXR1cm4gdiA/IG5ldyBPcmRlckJ5Q2xhdXNlKHYpIDogdW5kZWZpbmVkO1xyXG4gICAgfSxcclxuICAgIFwic2VsZWN0Q2xhdXNlLHNlbGVjdFwiOiBmdW5jdGlvbiAodjogYW55KSB7XHJcbiAgICAgIHJldHVybiB2ID8gbmV3IFNlbGVjdENsYXVzZSh2KSA6IHVuZGVmaW5lZDtcclxuICAgIH0sXHJcbiAgICBcImV4cGFuZENsYXVzZSxleHBhbmRcIjogZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICByZXR1cm4gdiA/IG5ldyBFeHBhbmRDbGF1c2UodikgOiB1bmRlZmluZWQ7XHJcbiAgICB9LFxyXG4gICAgXCJza2lwQ291bnQsc2tpcFwiOiBudWxsLFxyXG4gICAgXCJ0YWtlQ291bnQsdGFrZVwiOiBudWxsLFxyXG4gICAgcGFyYW1ldGVyczogZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICByZXR1cm4gY29yZS5pc0VtcHR5KHYpID8gdW5kZWZpbmVkIDogdjtcclxuICAgIH0sXHJcbiAgICBcImlubGluZUNvdW50RW5hYmxlZCxpbmxpbmVDb3VudFwiOiBmYWxzZSxcclxuICAgIFwibm9UcmFja2luZ0VuYWJsZWQsbm9UcmFja2luZ1wiOiBmYWxzZSxcclxuICAgIHF1ZXJ5T3B0aW9uczogZnVuY3Rpb24gKHY6IGFueSkge1xyXG4gICAgICByZXR1cm4gdiA/IFF1ZXJ5T3B0aW9ucy5mcm9tSlNPTih2KSA6IHVuZGVmaW5lZDtcclxuICAgIH1cclxuICB9LCBlcSk7XHJcbiAgcmV0dXJuIGVxO1xyXG59XHJcblxyXG5mdW5jdGlvbiBjbG9uZShlcTogRW50aXR5UXVlcnksIHByb3BOYW1lPzogc3RyaW5nLCB2YWx1ZT86IGFueSkge1xyXG4gIC8vIGltbXV0YWJsZSBxdWVyaWVzIG1lYW4gdGhhdCB3ZSBkb24ndCBuZWVkIHRvIGNsb25lIGlmIG5vIGNoYW5nZSBpbiB2YWx1ZS5cclxuICBpZiAocHJvcE5hbWUpIHtcclxuICAgIGlmIChlcVtwcm9wTmFtZV0gPT09IHZhbHVlKSByZXR1cm4gZXE7XHJcbiAgfVxyXG4gIC8vIGNvcHlpbmcgUXVlcnlPcHRpb25zIGlzIHNhZmUgYmVjYXVzZSB0aGV5IGFyZSBhcmUgaW1tdXRhYmxlO1xyXG4gIGxldCBjb3B5ID0gY29yZS5leHRlbmQobmV3IEVudGl0eVF1ZXJ5KCksIGVxLCBbXHJcbiAgICBcInJlc291cmNlTmFtZVwiLFxyXG4gICAgXCJmcm9tRW50aXR5VHlwZVwiLFxyXG4gICAgXCJ3aGVyZVByZWRpY2F0ZVwiLFxyXG4gICAgXCJvcmRlckJ5Q2xhdXNlXCIsXHJcbiAgICBcInNlbGVjdENsYXVzZVwiLFxyXG4gICAgXCJza2lwQ291bnRcIixcclxuICAgIFwidGFrZUNvdW50XCIsXHJcbiAgICBcImV4cGFuZENsYXVzZVwiLFxyXG4gICAgXCJpbmxpbmVDb3VudEVuYWJsZWRcIixcclxuICAgIFwibm9UcmFja2luZ0VuYWJsZWRcIixcclxuICAgIFwidXNlc05hbWVPblNlcnZlclwiLFxyXG4gICAgXCJxdWVyeU9wdGlvbnNcIixcclxuICAgIFwiZW50aXR5TWFuYWdlclwiLFxyXG4gICAgXCJkYXRhU2VydmljZVwiLFxyXG4gICAgXCJyZXN1bHRFbnRpdHlUeXBlXCJcclxuICBdKSBhcyBFbnRpdHlRdWVyeTtcclxuICBjb3B5LnBhcmFtZXRlcnMgPSBjb3JlLmV4dGVuZCh7fSwgZXEucGFyYW1ldGVycyk7XHJcbiAgaWYgKHByb3BOYW1lKSB7XHJcbiAgICBjb3B5W3Byb3BOYW1lXSA9IHZhbHVlO1xyXG4gIH1cclxuICByZXR1cm4gY29weTtcclxufVxyXG5cclxuZnVuY3Rpb24gcHJvY2Vzc1VzaW5nKGVxOiBFbnRpdHlRdWVyeSwgbWFwOiBPYmplY3QsIHZhbHVlOiBhbnksIHByb3BlcnR5TmFtZT86IHN0cmluZykge1xyXG4gIGxldCB0eXBlTmFtZSA9IHZhbHVlLl8kdHlwZU5hbWUgfHwgKCh2YWx1ZSBpbnN0YW5jZW9mIEJyZWV6ZUVudW0pICYmICh2YWx1ZS5jb25zdHJ1Y3RvciBhcyBhbnkpLm5hbWUpO1xyXG4gIGxldCBrZXkgPSB0eXBlTmFtZSAmJiB0eXBlTmFtZS5zdWJzdHIoMCwgMSkudG9Mb3dlckNhc2UoKSArIHR5cGVOYW1lLnN1YnN0cigxKTtcclxuICBpZiAocHJvcGVydHlOYW1lICYmIGtleSAhPT0gcHJvcGVydHlOYW1lKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHZhbHVlIGZvciBwcm9wZXJ0eTogXCIgKyBwcm9wZXJ0eU5hbWUpO1xyXG4gIH1cclxuICBpZiAoa2V5KSB7XHJcbiAgICBsZXQgZm4gPSBtYXBba2V5XTtcclxuICAgIGlmIChmbiA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgY29uZmlnIHByb3BlcnR5OiBcIiArIGtleSk7XHJcbiAgICB9IGVsc2UgaWYgKGZuID09PSBudWxsKSB7XHJcbiAgICAgIGVxW2tleV0gPSB2YWx1ZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGZuKGVxLCB2YWx1ZSk7XHJcbiAgICB9XHJcbiAgfSBlbHNlIHtcclxuICAgIGNvcmUub2JqZWN0Rm9yRWFjaCh2YWx1ZSwgKHByb3BOYW1lLCB2YWwpID0+IHtcclxuICAgICAgcHJvY2Vzc1VzaW5nKGVxLCBtYXAsIHZhbCwgcHJvcE5hbWUpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBub3JtYWxpemVQcm9wZXJ0eVBhdGhzKHByb3BlcnR5UGF0aHM6IHN0cmluZyB8IHN0cmluZ1tdKSB7XHJcbiAgYXNzZXJ0UGFyYW0ocHJvcGVydHlQYXRocywgXCJwcm9wZXJ0eVBhdGhzXCIpLmlzT3B0aW9uYWwoKS5pc1N0cmluZygpLm9yKCkuaXNBcnJheSgpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICBpZiAodHlwZW9mIHByb3BlcnR5UGF0aHMgPT09ICdzdHJpbmcnKSB7XHJcbiAgICBwcm9wZXJ0eVBhdGhzID0gcHJvcGVydHlQYXRocy5zcGxpdChcIixcIik7XHJcbiAgfVxyXG5cclxuICBwcm9wZXJ0eVBhdGhzID0gcHJvcGVydHlQYXRocy5tYXAoZnVuY3Rpb24gKHBwKSB7XHJcbiAgICByZXR1cm4gcHAudHJpbSgpO1xyXG4gIH0pO1xyXG4gIHJldHVybiBwcm9wZXJ0eVBhdGhzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBidWlsZFByZWRpY2F0ZShlbnRpdHk6IEVudGl0eSkge1xyXG4gIGxldCBlbnRpdHlUeXBlID0gZW50aXR5LmVudGl0eVR5cGU7XHJcbiAgbGV0IHByZWRQYXJ0cyA9IGVudGl0eVR5cGUua2V5UHJvcGVydGllcy5tYXAoZnVuY3Rpb24gKGtwKSB7XHJcbiAgICByZXR1cm4gUHJlZGljYXRlLmNyZWF0ZShrcC5uYW1lLCBGaWx0ZXJRdWVyeU9wLkVxdWFscywgZW50aXR5LmdldFByb3BlcnR5KGtwLm5hbWUpKTtcclxuICB9KTtcclxuICBsZXQgcHJlZCA9IFByZWRpY2F0ZS5hbmQocHJlZFBhcnRzKTtcclxuICByZXR1cm4gcHJlZDtcclxufVxyXG5cclxuZnVuY3Rpb24gYnVpbGRLZXlQcmVkaWNhdGUoZW50aXR5S2V5OiBFbnRpdHlLZXkpIHtcclxuICBsZXQga2V5UHJvcHMgPSBlbnRpdHlLZXkuZW50aXR5VHlwZS5rZXlQcm9wZXJ0aWVzO1xyXG4gIGxldCBwcmVkcyA9IGNvcmUuYXJyYXlaaXAoa2V5UHJvcHMsIGVudGl0eUtleS52YWx1ZXMsIGZ1bmN0aW9uIChrcCwgdikge1xyXG4gICAgcmV0dXJuIFByZWRpY2F0ZS5jcmVhdGUoa3AubmFtZSwgRmlsdGVyUXVlcnlPcC5FcXVhbHMsIHYpO1xyXG4gIH0pO1xyXG4gIGxldCBwcmVkID0gUHJlZGljYXRlLmFuZChwcmVkcyk7XHJcbiAgcmV0dXJuIHByZWQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGJ1aWxkTmF2aWdhdGlvblByZWRpY2F0ZShlbnRpdHk6IEVudGl0eSwgbmF2aWdhdGlvblByb3BlcnR5OiBOYXZpZ2F0aW9uUHJvcGVydHkpIHtcclxuICBpZiAobmF2aWdhdGlvblByb3BlcnR5LmlzU2NhbGFyKSB7XHJcbiAgICBpZiAobmF2aWdhdGlvblByb3BlcnR5LmZvcmVpZ25LZXlOYW1lcy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xyXG4gICAgbGV0IHJlbGF0ZWRLZXlWYWx1ZXMgPSBuYXZpZ2F0aW9uUHJvcGVydHkuZm9yZWlnbktleU5hbWVzLm1hcCgoZmtOYW1lKSA9PiB7XHJcbiAgICAgIHJldHVybiBlbnRpdHkuZ2V0UHJvcGVydHkoZmtOYW1lKTtcclxuICAgIH0pO1xyXG4gICAgbGV0IGVudGl0eUtleSA9IG5ldyBFbnRpdHlLZXkobmF2aWdhdGlvblByb3BlcnR5LmVudGl0eVR5cGUsIHJlbGF0ZWRLZXlWYWx1ZXMpO1xyXG4gICAgcmV0dXJuIGJ1aWxkS2V5UHJlZGljYXRlKGVudGl0eUtleSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIGxldCBpbnZlcnNlTnAgPSBuYXZpZ2F0aW9uUHJvcGVydHkuaW52ZXJzZTtcclxuICAgIGxldCBmb3JlaWduS2V5TmFtZXMgPSBpbnZlcnNlTnAgPyBpbnZlcnNlTnAuZm9yZWlnbktleU5hbWVzIDogbmF2aWdhdGlvblByb3BlcnR5LmludkZvcmVpZ25LZXlOYW1lcztcclxuICAgIGlmIChmb3JlaWduS2V5TmFtZXMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcclxuICAgIGxldCBrZXlWYWx1ZXMgPSBlbnRpdHkuZW50aXR5QXNwZWN0LmdldEtleSgpLnZhbHVlcztcclxuICAgIGxldCBwcmVkUGFydHMgPSBjb3JlLmFycmF5WmlwKGZvcmVpZ25LZXlOYW1lcywga2V5VmFsdWVzLCAoZmtOYW1lLCBrdikgPT4ge1xyXG4gICAgICByZXR1cm4gUHJlZGljYXRlLmNyZWF0ZShma05hbWUsIEZpbHRlclF1ZXJ5T3AuRXF1YWxzLCBrdik7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBQcmVkaWNhdGUuYW5kKHByZWRQYXJ0cyk7XHJcbiAgfVxyXG59XHJcblxyXG4vKiogQmFzZSBjbGFzcyBmb3IgQm9vbGVhblF1ZXJ5T3AgYW5kIEZpbHRlclF1ZXJ5T3AgKi9cclxuZXhwb3J0IGludGVyZmFjZSBRdWVyeU9wIHtcclxuICAvKiogVGhlIG9wZXJhdG9yIGZvciB0aGlzIGVudW0uICovXHJcbiAgb3BlcmF0b3I6IHN0cmluZztcclxufVxyXG5cclxuXHJcblxyXG4vKipcclxuRmlsdGVyUXVlcnlPcCBpcyBhbiAnRW51bScgY29udGFpbmluZyBhbGwgb2YgdGhlIHZhbGlkICBbW1ByZWRpY2F0ZV1dXHJcbmZpbHRlciBvcGVyYXRvcnMgZm9yIGFuIFtbRW50aXR5UXVlcnldXS5cclxuKiovXHJcbmV4cG9ydCBjbGFzcyBGaWx0ZXJRdWVyeU9wIGV4dGVuZHMgQnJlZXplRW51bSBpbXBsZW1lbnRzIFF1ZXJ5T3Age1xyXG4gIC8qKiBUaGUgb3BlcmF0b3IgZm9yIHRoaXMgZW51bS4gKi9cclxuICBvcGVyYXRvcjogc3RyaW5nO1xyXG5cclxuICAvKiogQWxpYXNlczogXCJlcVwiLCBcIj09XCIgKiovXHJcbiAgc3RhdGljIEVxdWFscyA9IG5ldyBGaWx0ZXJRdWVyeU9wKHsgb3BlcmF0b3I6IFwiZXFcIiB9KTtcclxuICAvKiogIEFsaWFzZXM6IFwibmVcIiwgXCIhPVwiICAqKi9cclxuICBzdGF0aWMgTm90RXF1YWxzID0gbmV3IEZpbHRlclF1ZXJ5T3AoeyBvcGVyYXRvcjogXCJuZVwiIH0pO1xyXG4gIC8qKiBBbGlhc2VzOiBcImd0XCIsIFwiPlwiICAgKiovXHJcbiAgc3RhdGljIEdyZWF0ZXJUaGFuID0gbmV3IEZpbHRlclF1ZXJ5T3AoeyBvcGVyYXRvcjogXCJndFwiIH0pO1xyXG4gIC8qKiBBbGlhc2VzOiBcImx0XCIsIFwiPFwiICAqKi9cclxuICBzdGF0aWMgTGVzc1RoYW4gPSBuZXcgRmlsdGVyUXVlcnlPcCh7IG9wZXJhdG9yOiBcImx0XCIgfSk7XHJcbiAgLyoqICBBbGlhc2VzOiBcImdlXCIsIFwiPj1cIiAgKiovXHJcbiAgc3RhdGljIEdyZWF0ZXJUaGFuT3JFcXVhbCA9IG5ldyBGaWx0ZXJRdWVyeU9wKHsgb3BlcmF0b3I6IFwiZ2VcIiB9KTtcclxuICAvKiogIEFsaWFzZXM6IFwibGVcIiwgXCI8PVwiICAqKi9cclxuICBzdGF0aWMgTGVzc1RoYW5PckVxdWFsID0gbmV3IEZpbHRlclF1ZXJ5T3AoeyBvcGVyYXRvcjogXCJsZVwiIH0pO1xyXG4gIC8qKiAgU3RyaW5nIG9wZXJhdGlvbjogSXMgYSBzdHJpbmcgYSBzdWJzdHJpbmcgb2YgYW5vdGhlciBzdHJpbmcuICBBbGlhc2VzOiBcInN1YnN0cmluZ29mXCIgICAqKi9cclxuICBzdGF0aWMgQ29udGFpbnMgPSBuZXcgRmlsdGVyUXVlcnlPcCh7IG9wZXJhdG9yOiBcImNvbnRhaW5zXCIgfSk7XHJcbiAgLyoqIE5vIGFsaWFzZXMgKi9cclxuICBzdGF0aWMgU3RhcnRzV2l0aCA9IG5ldyBGaWx0ZXJRdWVyeU9wKHsgb3BlcmF0b3I6IFwic3RhcnRzd2l0aFwiIH0pO1xyXG4gIC8qKiBObyBhbGlhc2VzICovXHJcbiAgc3RhdGljIEVuZHNXaXRoID0gbmV3IEZpbHRlclF1ZXJ5T3AoeyBvcGVyYXRvcjogXCJlbmRzd2l0aFwiIH0pO1xyXG4gIC8qKiAgQWxpYXNlczogXCJzb21lXCIgICoqL1xyXG4gIHN0YXRpYyBBbnkgPSBuZXcgRmlsdGVyUXVlcnlPcCh7IG9wZXJhdG9yOiBcImFueVwiIH0pO1xyXG4gIC8qKiAgQWxpYXNlczogXCJldmVyeVwiICAqKi9cclxuICBzdGF0aWMgQWxsID0gbmV3IEZpbHRlclF1ZXJ5T3AoeyBvcGVyYXRvcjogXCJhbGxcIiB9KTtcclxuICAvKiogTm8gYWxpYXNlcyAqL1xyXG4gIHN0YXRpYyBJbiA9IG5ldyBGaWx0ZXJRdWVyeU9wKHsgb3BlcmF0b3I6IFwiaW5cIiB9KTtcclxuICAvKiogTm8gYWxpYXNlcyAqL1xyXG4gIHN0YXRpYyBJc1R5cGVPZiA9IG5ldyBGaWx0ZXJRdWVyeU9wKHsgb3BlcmF0b3I6IFwiaXNvZlwiIH0pO1xyXG59XHJcbkZpbHRlclF1ZXJ5T3AucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIkZpbHRlclF1ZXJ5T3BcIjtcclxuRXJyb3JbJ3gnXSA9IEZpbHRlclF1ZXJ5T3AucmVzb2x2ZVN5bWJvbHMoKTtcclxuXHJcblxyXG4vKipcclxuIEJvb2xlYW5RdWVyeU9wIGlzIGFuICdFbnVtJyBjb250YWluaW5nIGFsbCBvZiB0aGUgdmFsaWQgIGJvb2xlYW5cclxub3BlcmF0b3JzIGZvciBhbiBbW0VudGl0eVF1ZXJ5XV0uXHJcbioqL1xyXG5leHBvcnQgY2xhc3MgQm9vbGVhblF1ZXJ5T3AgZXh0ZW5kcyBCcmVlemVFbnVtIGltcGxlbWVudHMgUXVlcnlPcCB7XHJcbiAgLyoqIFRoZSBvcGVyYXRvciBmb3IgdGhpcyBlbnVtLiAqL1xyXG4gIG9wZXJhdG9yOiBzdHJpbmc7XHJcblxyXG4gIHN0YXRpYyBBbmQgPSBuZXcgQm9vbGVhblF1ZXJ5T3AoeyBvcGVyYXRvcjogXCJhbmRcIiB9KTtcclxuICBzdGF0aWMgT3IgPSBuZXcgQm9vbGVhblF1ZXJ5T3AoeyBvcGVyYXRvcjogXCJvclwiIH0pO1xyXG4gIHN0YXRpYyBOb3QgPSBuZXcgQm9vbGVhblF1ZXJ5T3AoeyBvcGVyYXRvcjogXCJub3RcIiB9KTtcclxuXHJcbn1cclxuQm9vbGVhblF1ZXJ5T3AucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIkJvb2xlYW5RdWVyeU9wXCI7XHJcbkVycm9yWyd4J10gPSBCb29sZWFuUXVlcnlPcC5yZXNvbHZlU3ltYm9scygpO1xyXG5cclxuXHJcbi8qKiBGb3IgdXNlIGJ5IGJyZWV6ZSBwbHVnaW4gYXV0aG9ycyBvbmx5LiAgVGhlIGNsYXNzIGlzIHVzZWQgaW4gbW9zdCBbW0lVcmlCdWlsZGVyQWRhcHRlcl1dIGltcGxlbWVudGF0aW9uc1xyXG5AYWRhcHRlciAoc2VlIFtbSVVyaUJ1aWxkZXJBZGFwdGVyXV0pICAgIFxyXG5AaGlkZGVuXHJcblxyXG5BbiBPcmRlckJ5Q2xhdXNlIGlzIGEgZGVzY3JpcHRpb24gb2YgdGhlIHByb3BlcnRpZXMgYW5kIGRpcmVjdGlvbiB0aGF0IHRoZSByZXN1bHRcclxub2YgYSBxdWVyeSBzaG91bGQgYmUgc29ydGVkIGluLiAgT3JkZXJCeUNsYXVzZXMgYXJlIGltbXV0YWJsZSwgd2hpY2ggbWVhbnMgdGhhdCBhbnlcclxubWV0aG9kIHRoYXQgd291bGQgbW9kaWZ5IGFuIE9yZGVyQnlDbGF1c2UgYWN0dWFsbHkgcmV0dXJucyBhIG5ldyBPcmRlckJ5Q2xhdXNlLlxyXG5cclxuRm9yIGV4YW1wbGUgZm9yIGFuIEVtcGxveWVlIG9iamVjdCB3aXRoIHByb3BlcnRpZXMgb2YgJ0NvbXBhbnknIGFuZCAnTGFzdE5hbWUnIHRoZSBmb2xsb3dpbmcgd291bGQgYmUgdmFsaWQgZXhwcmVzc2lvbnM6XHJcbj4gICAgIGxldCBvYmMgPSBuZXcgT3JkZXJCeUNsYXVzZShcIkNvbXBhbnkuQ29tcGFueU5hbWUsIExhc3ROYW1lXCIpXHJcblxyXG5vclxyXG4+ICAgICBsZXQgb2JjID0gbmV3IE9yZGVyQnlDbGF1c2UoXCJDb21wYW55LkNvbXBhbnlOYW1lIGRlc2MsIExhc3ROYW1lXCIpXHJcblxyXG5vclxyXG4+ICAgICBsZXQgb2JjID0gbmV3IE9yZGVyQnlDbGF1c2UoXCJDb21wYW55LkNvbXBhbnlOYW1lLCBMYXN0TmFtZVwiLCB0cnVlKTtcclxuKi9cclxuZXhwb3J0IGNsYXNzIE9yZGVyQnlDbGF1c2Uge1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIGl0ZW1zOiBPcmRlckJ5SXRlbVtdO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcm9wZXJ0eVBhdGhzOiBzdHJpbmdbXSB8IE9yZGVyQnlDbGF1c2VbXSwgaXNEZXNjPzogYm9vbGVhbikge1xyXG4gICAgaWYgKHByb3BlcnR5UGF0aHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk9yZGVyQnlDbGF1c2UgY2Fubm90IGJlIGVtcHR5XCIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHlvdSBjYW4gYWxzbyBwYXNzIGluIGFuIGFycmF5IG9mIG9yZGVyQnlDbGF1c2VzXHJcbiAgICBpZiAocHJvcGVydHlQYXRoc1swXSBpbnN0YW5jZW9mIE9yZGVyQnlDbGF1c2UpIHtcclxuICAgICAgbGV0IGNsYXVzZXMgPSBwcm9wZXJ0eVBhdGhzIGFzIE9yZGVyQnlDbGF1c2VbXTtcclxuICAgICAgdGhpcy5pdGVtcyA9IGNvcmUuYXJyYXlGbGF0TWFwKGNsYXVzZXMsIGMgPT4gYy5pdGVtcyk7XHJcbiAgICAgIC8vIHRoaXMuaXRlbXMgPSBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KGNsYXVzZXNbMF0uaXRlbXMsIGNsYXVzZXMuc2xpY2UoMSkubWFwKGNvcmUucGx1Y2soXCJpdGVtc1wiKSkpO1xyXG4gICAgICAvLyB0aGlzLml0ZW1zID0gQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShbXSwgY2xhdXNlcy5tYXAoY29yZS5wbHVjayhcIml0ZW1zXCIpKSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLml0ZW1zID0gKHByb3BlcnR5UGF0aHMgYXMgc3RyaW5nW10pLm1hcChmdW5jdGlvbiAocHApIHtcclxuICAgICAgICByZXR1cm4gbmV3IE9yZGVyQnlJdGVtKHBwLCBpc0Rlc2MpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgfVxyXG5cclxuICB2YWxpZGF0ZShlbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgICBpZiAoZW50aXR5VHlwZSA9PSBudWxsIHx8IGVudGl0eVR5cGUuaXNBbm9ueW1vdXMpIHJldHVybjtcclxuICAgIHRoaXMuaXRlbXMuZm9yRWFjaCgoaXRlbSkgPT4ge1xyXG4gICAgICBpdGVtLnZhbGlkYXRlKGVudGl0eVR5cGUpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBnZXRDb21wYXJlcihlbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgICBsZXQgb3JkZXJCeUZ1bmNzID0gdGhpcy5pdGVtcy5tYXAoZnVuY3Rpb24gKG9iYykge1xyXG4gICAgICByZXR1cm4gb2JjLmdldENvbXBhcmVyKGVudGl0eVR5cGUpO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKGVudGl0eTE6IGFueSwgZW50aXR5MjogYW55KSB7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JkZXJCeUZ1bmNzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgbGV0IHJlc3VsdCA9IG9yZGVyQnlGdW5jc1tpXShlbnRpdHkxLCBlbnRpdHkyKTtcclxuICAgICAgICBpZiAocmVzdWx0ICE9PSAwKSB7XHJcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gMDtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICB0b0pTT05FeHQoY29udGV4dDogRW50aXR5UXVlcnlKc29uQ29udGV4dCkge1xyXG4gICAgcmV0dXJuIHRoaXMuaXRlbXMubWFwKGZ1bmN0aW9uIChpdGVtKSB7XHJcbiAgICAgIHJldHVybiBjb250ZXh0LnByb3BlcnR5UGF0aEZuIShpdGVtLnByb3BlcnR5UGF0aCkgKyAoaXRlbS5pc0Rlc2MgPyBcIiBkZXNjXCIgOiBcIlwiKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbn1cclxuXHJcbi8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgY2xhc3MgT3JkZXJCeUl0ZW0ge1xyXG4gIHByb3BlcnR5UGF0aDogc3RyaW5nO1xyXG4gIGlzRGVzYzogYm9vbGVhbjtcclxuICBsYXN0UHJvcGVydHk6IEVudGl0eVByb3BlcnR5O1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcm9wZXJ0eVBhdGg6IHN0cmluZywgaXNEZXNjPzogYm9vbGVhbikge1xyXG4gICAgaWYgKCEodHlwZW9mIHByb3BlcnR5UGF0aCA9PT0gJ3N0cmluZycpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInByb3BlcnR5UGF0aCBpcyBub3QgYSBzdHJpbmdcIik7XHJcbiAgICB9XHJcbiAgICBwcm9wZXJ0eVBhdGggPSBwcm9wZXJ0eVBhdGgudHJpbSgpO1xyXG5cclxuICAgIGxldCBwYXJ0cyA9IHByb3BlcnR5UGF0aC5zcGxpdCgnICcpO1xyXG4gICAgLy8gcGFydHNbMF0gaXMgdGhlIHByb3BlcnR5UGF0aDsgWzFdIHdvdWxkIGJlIHdoZXRoZXIgZGVzY2VuZGluZyBvciBub3QuXHJcbiAgICAvLyBpZiAocGFydHMubGVuZ3RoID4gMSAmJiBpc0Rlc2MgIT09IHRydWUgJiYgaXNEZXNjICE9PSBmYWxzZSkge1xyXG4gICAgaWYgKHBhcnRzLmxlbmd0aCA+IDEgJiYgaXNEZXNjID09IG51bGwpIHtcclxuICAgICAgaXNEZXNjID0gY29yZS5zdHJpbmdTdGFydHNXaXRoKHBhcnRzWzFdLnRvTG93ZXJDYXNlKCksIFwiZGVzY1wiKTtcclxuICAgICAgaWYgKCFpc0Rlc2MpIHtcclxuICAgICAgICAvLyBpc0Rlc2MgaXMgZmFsc2UgYnV0IGNoZWNrIHRvIG1ha2Ugc3VyZSBpdHMgaW50ZW5kZWQuXHJcbiAgICAgICAgbGV0IGlzQXNjID0gY29yZS5zdHJpbmdTdGFydHNXaXRoKHBhcnRzWzFdLnRvTG93ZXJDYXNlKCksIFwiYXNjXCIpO1xyXG4gICAgICAgIGlmICghaXNBc2MpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRoZSBzZWNvbmQgd29yZCBpbiB0aGUgcHJvcGVydHlQYXRoIG11c3QgYmVnaW4gd2l0aCAnZGVzYycgb3IgJ2FzYydcIik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5wcm9wZXJ0eVBhdGggPSBwYXJ0c1swXTtcclxuICAgIHRoaXMuaXNEZXNjID0gaXNEZXNjIHx8IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgdmFsaWRhdGUoZW50aXR5VHlwZTogRW50aXR5VHlwZSk6IEVudGl0eVByb3BlcnR5IHwgdW5kZWZpbmVkIHtcclxuICAgIGlmIChlbnRpdHlUeXBlID09IG51bGwgfHwgZW50aXR5VHlwZS5pc0Fub255bW91cykgcmV0dXJuO1xyXG4gICAgLy8gd2lsbCB0aHJvdyBhbiBleGNlcHRpb24gb24gYmFkIHByb3BlcnR5UGF0aFxyXG4gICAgdGhpcy5sYXN0UHJvcGVydHkgPSBlbnRpdHlUeXBlLmdldFByb3BlcnR5KHRoaXMucHJvcGVydHlQYXRoLCB0cnVlKSBhcyBFbnRpdHlQcm9wZXJ0eTtcclxuICAgIHJldHVybiB0aGlzLmxhc3RQcm9wZXJ0eTtcclxuICB9XHJcblxyXG4gIGdldENvbXBhcmVyKGVudGl0eVR5cGU6IEVudGl0eVR5cGUpIHtcclxuICAgIGxldCBwcm9wRGF0YVR5cGU6IERhdGFUeXBlO1xyXG4gICAgbGV0IGlzQ2FzZVNlbnNpdGl2ZTogYm9vbGVhbjtcclxuICAgIGlmICghdGhpcy5sYXN0UHJvcGVydHkpIHRoaXMudmFsaWRhdGUoZW50aXR5VHlwZSk7XHJcbiAgICBpZiAodGhpcy5sYXN0UHJvcGVydHkpIHtcclxuICAgICAgcHJvcERhdGFUeXBlID0gKHRoaXMubGFzdFByb3BlcnR5IGFzIGFueSkuZGF0YVR5cGU7XHJcbiAgICAgIGlzQ2FzZVNlbnNpdGl2ZSA9IHRoaXMubGFzdFByb3BlcnR5LnBhcmVudFR5cGUubWV0YWRhdGFTdG9yZS5sb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnMuaXNDYXNlU2Vuc2l0aXZlO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBwcm9wZXJ0eVBhdGggPSB0aGlzLnByb3BlcnR5UGF0aDtcclxuICAgIGxldCBpc0Rlc2MgPSB0aGlzLmlzRGVzYztcclxuXHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKGVudGl0eTE6IGFueSwgZW50aXR5MjogYW55KSB7XHJcbiAgICAgIGxldCB2YWx1ZTEgPSBFbnRpdHlBc3BlY3QuZ2V0UHJvcGVydHlQYXRoVmFsdWUoZW50aXR5MSwgcHJvcGVydHlQYXRoKTtcclxuICAgICAgbGV0IHZhbHVlMiA9IEVudGl0eUFzcGVjdC5nZXRQcm9wZXJ0eVBhdGhWYWx1ZShlbnRpdHkyLCBwcm9wZXJ0eVBhdGgpO1xyXG4gICAgICBsZXQgZGF0YVR5cGUgPSBwcm9wRGF0YVR5cGUgfHwgKHZhbHVlMSAmJiBEYXRhVHlwZS5mcm9tVmFsdWUodmFsdWUxKSkgfHwgRGF0YVR5cGUuZnJvbVZhbHVlKHZhbHVlMik7XHJcbiAgICAgIGlmIChkYXRhVHlwZSA9PT0gRGF0YVR5cGUuU3RyaW5nKSB7XHJcbiAgICAgICAgaWYgKGlzQ2FzZVNlbnNpdGl2ZSkge1xyXG4gICAgICAgICAgdmFsdWUxID0gdmFsdWUxIHx8IFwiXCI7XHJcbiAgICAgICAgICB2YWx1ZTIgPSB2YWx1ZTIgfHwgXCJcIjtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdmFsdWUxID0gKHZhbHVlMSB8fCBcIlwiKS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgICAgdmFsdWUyID0gKHZhbHVlMiB8fCBcIlwiKS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBsZXQgbm9ybWFsaXplID0gRGF0YVR5cGUuZ2V0Q29tcGFyYWJsZUZuKGRhdGFUeXBlKTtcclxuICAgICAgICB2YWx1ZTEgPSBub3JtYWxpemUodmFsdWUxKTtcclxuICAgICAgICB2YWx1ZTIgPSBub3JtYWxpemUodmFsdWUyKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodmFsdWUxID09PSB2YWx1ZTIpIHtcclxuICAgICAgICByZXR1cm4gMDtcclxuICAgICAgfSBlbHNlIGlmICh2YWx1ZTEgPiB2YWx1ZTIgfHwgdmFsdWUyID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICByZXR1cm4gaXNEZXNjID8gLTEgOiAxO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiBpc0Rlc2MgPyAxIDogLTE7XHJcbiAgICAgIH1cclxuICAgIH07XHJcbiAgfVxyXG59XHJcblxyXG4vKiogRm9yIHVzZSBieSBicmVlemUgcGx1Z2luIGF1dGhvcnMgb25seS4gIFRoZSBjbGFzcyBpcyB1c2VkIGluIG1vc3QgW1tJVXJpQnVpbGRlckFkYXB0ZXJdXSBpbXBsZW1lbnRhdGlvbnNcclxuQGFkYXB0ZXIgKHNlZSBbW0lVcmlCdWlsZGVyQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBcclxuKiovXHJcbmV4cG9ydCBjbGFzcyBTZWxlY3RDbGF1c2Uge1xyXG4gIHByb3BlcnR5UGF0aHM6IHN0cmluZ1tdO1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9wYXRoTmFtZXM6IHN0cmluZ1tdO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcm9wZXJ0eVBhdGhzOiBzdHJpbmdbXSkge1xyXG4gICAgdGhpcy5wcm9wZXJ0eVBhdGhzID0gcHJvcGVydHlQYXRocztcclxuICAgIHRoaXMuX3BhdGhOYW1lcyA9IHByb3BlcnR5UGF0aHMubWFwKGZ1bmN0aW9uIChwcCkge1xyXG4gICAgICByZXR1cm4gcHAucmVwbGFjZShcIi5cIiwgXCJfXCIpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICB2YWxpZGF0ZShlbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgICBpZiAoZW50aXR5VHlwZSA9PSBudWxsIHx8IGVudGl0eVR5cGUuaXNBbm9ueW1vdXMpIHJldHVybjsgLy8gY2FuJ3QgdmFsaWRhdGUgeWV0XHJcbiAgICAvLyB3aWxsIHRocm93IGFuIGV4Y2VwdGlvbiBvbiBiYWQgcHJvcGVydHlQYXRoXHJcbiAgICB0aGlzLnByb3BlcnR5UGF0aHMuZm9yRWFjaChmdW5jdGlvbiAocGF0aCkge1xyXG4gICAgICBlbnRpdHlUeXBlLmdldFByb3BlcnR5KHBhdGgsIHRydWUpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICB0b0Z1bmN0aW9uKC8qIGNvbmZpZyAqLykge1xyXG4gICAgbGV0IHRoYXQgPSB0aGlzO1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChlbnRpdHk6IEVudGl0eSkge1xyXG4gICAgICBsZXQgcmVzdWx0ID0ge307XHJcbiAgICAgIHRoYXQucHJvcGVydHlQYXRocy5mb3JFYWNoKGZ1bmN0aW9uIChwYXRoLCBpKSB7XHJcbiAgICAgICAgcmVzdWx0W3RoYXQuX3BhdGhOYW1lc1tpXV0gPSBFbnRpdHlBc3BlY3QuZ2V0UHJvcGVydHlQYXRoVmFsdWUoZW50aXR5LCBwYXRoKTtcclxuICAgICAgfSk7XHJcbiAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgdG9KU09ORXh0KGNvbnRleHQ6IEVudGl0eVF1ZXJ5SnNvbkNvbnRleHQpIHtcclxuICAgIHJldHVybiB0aGlzLnByb3BlcnR5UGF0aHMubWFwKGZ1bmN0aW9uIChwcCkge1xyXG4gICAgICByZXR1cm4gY29udGV4dC5wcm9wZXJ0eVBhdGhGbiEocHApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcblxyXG4vKiogRm9yIHVzZSBieSBicmVlemUgcGx1Z2luIGF1dGhvcnMgb25seS4gIFRoZSBjbGFzcyBpcyB1c2VkIGluIG1vc3QgW1tJVXJpQnVpbGRlckFkYXB0ZXJdXSBpbXBsZW1lbnRhdGlvbnNcclxuQGFkYXB0ZXIgKHNlZSBbW0lVcmlCdWlsZGVyQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBcclxuKiovXHJcbmV4cG9ydCBjbGFzcyBFeHBhbmRDbGF1c2Uge1xyXG4gIHByb3BlcnR5UGF0aHM6IHN0cmluZ1tdO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcm9wZXJ0eVBhdGhzOiBzdHJpbmdbXSkge1xyXG4gICAgdGhpcy5wcm9wZXJ0eVBhdGhzID0gcHJvcGVydHlQYXRocztcclxuICB9XHJcblxyXG4gIHRvSlNPTkV4dChjb250ZXh0OiBFbnRpdHlRdWVyeUpzb25Db250ZXh0KSB7XHJcbiAgICByZXR1cm4gdGhpcy5wcm9wZXJ0eVBhdGhzLm1hcChmdW5jdGlvbiAocHApIHtcclxuICAgICAgcmV0dXJuIGNvbnRleHQucHJvcGVydHlQYXRoRm4hKHBwKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbn1cclxuXHJcblxyXG4iXX0=